using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
namespace Rainbow.Entity;
/// <summary>设备在线快照。每分钟从ARP表同步,记录当前活跃IP与MAC映射,是统计映射的核心枢纽表</summary>
[Serializable]
[DataObject]
[Description("设备在线快照。每分钟从ARP表同步,记录当前活跃IP与MAC映射,是统计映射的核心枢纽表")]
[BindIndex("IU_DeviceOnline_IP", true, "IP")]
[BindIndex("IX_DeviceOnline_Mac_IsOnline", false, "Mac,IsOnline")]
[BindIndex("IX_DeviceOnline_DeviceId_IsOnline", false, "DeviceId,IsOnline")]
[BindIndex("IX_DeviceOnline_Interface", false, "Interface")]
[BindIndex("IX_DeviceOnline_LastSeen", false, "LastSeen")]
[BindTable("DeviceOnline", Description = "设备在线快照。每分钟从ARP表同步,记录当前活跃IP与MAC映射,是统计映射的核心枢纽表", ConnName = "Rainbow", DbType = DatabaseType.None)]
public partial class DeviceOnline
{
#region 属性
private Int64 _Id;
/// <summary>编号。雪花ID,保留历史快照</summary>
[DisplayName("编号")]
[Description("编号。雪花ID,保留历史快照")]
[DataObjectField(true, false, false, 0)]
[BindColumn("Id", "编号。雪花ID,保留历史快照", "", DataScale = "time")]
public Int64 Id { get => _Id; set { if (OnPropertyChanging("Id", value)) { _Id = value; OnPropertyChanged("Id"); } } }
private String? _IP;
/// <summary>IP地址。当前活跃IP,IPv4/IPv6。统计时优先从此表按IP查DeviceId</summary>
[DisplayName("IP地址")]
[Description("IP地址。当前活跃IP,IPv4/IPv6。统计时优先从此表按IP查DeviceId")]
[DataObjectField(false, false, true, 45)]
[BindColumn("IP", "IP地址。当前活跃IP,IPv4/IPv6。统计时优先从此表按IP查DeviceId", "")]
public String? IP { get => _IP; set { if (OnPropertyChanging("IP", value)) { _IP = value; OnPropertyChanged("IP"); } } }
private String? _Mac;
/// <summary>MAC地址。ARP解析得到,是设备唯一标识。映射第一优先级:MAC精确匹配Device表</summary>
[DisplayName("MAC地址")]
[Description("MAC地址。ARP解析得到,是设备唯一标识。映射第一优先级:MAC精确匹配Device表")]
[DataObjectField(false, false, true, 17)]
[BindColumn("Mac", "MAC地址。ARP解析得到,是设备唯一标识。映射第一优先级:MAC精确匹配Device表", "")]
public String? Mac { get => _Mac; set { if (OnPropertyChanging("Mac", value)) { _Mac = value; OnPropertyChanged("Mac"); } } }
private String? _HostName;
/// <summary>主机名。DHCP/mDNS上报,如'XiaoMing-PC'。用于人工识别设备</summary>
[DisplayName("主机名")]
[Description("主机名。DHCP/mDNS上报,如'XiaoMing-PC'。用于人工识别设备")]
[DataObjectField(false, false, true, 100)]
[BindColumn("HostName", "主机名。DHCP/mDNS上报,如'XiaoMing-PC'。用于人工识别设备", "")]
public String? HostName { get => _HostName; set { if (OnPropertyChanging("HostName", value)) { _HostName = value; OnPropertyChanged("HostName"); } } }
private Int32 _DeviceId;
/// <summary>关联设备。通过MAC查Device表得到,首次未知=0,后续自动关联</summary>
[DisplayName("关联设备")]
[Description("关联设备。通过MAC查Device表得到,首次未知=0,后续自动关联")]
[DataObjectField(false, false, false, 0)]
[BindColumn("DeviceId", "关联设备。通过MAC查Device表得到,首次未知=0,后续自动关联", "")]
public Int32 DeviceId { get => _DeviceId; set { if (OnPropertyChanging("DeviceId", value)) { _DeviceId = value; OnPropertyChanged("DeviceId"); } } }
private String? _Interface;
/// <summary>所在网口。如eth0/br-lan/wlan0。同IP在不同网口=不同设备,用于多网段隔离</summary>
[DisplayName("所在网口")]
[Description("所在网口。如eth0/br-lan/wlan0。同IP在不同网口=不同设备,用于多网段隔离")]
[DataObjectField(false, false, true, 20)]
[BindColumn("Interface", "所在网口。如eth0/br-lan/wlan0。同IP在不同网口=不同设备,用于多网段隔离", "")]
public String? Interface { get => _Interface; set { if (OnPropertyChanging("Interface", value)) { _Interface = value; OnPropertyChanged("Interface"); } } }
private DateTime _LeaseExpire;
/// <summary>DHCP租约过期。过期后IP可能被回收分配给其他设备,是IP漂移的预警信号</summary>
[DisplayName("DHCP租约过期")]
[Description("DHCP租约过期。过期后IP可能被回收分配给其他设备,是IP漂移的预警信号")]
[DataObjectField(false, false, true, 0)]
[BindColumn("LeaseExpire", "DHCP租约过期。过期后IP可能被回收分配给其他设备,是IP漂移的预警信号", "")]
public DateTime LeaseExpire { get => _LeaseExpire; set { if (OnPropertyChanging("LeaseExpire", value)) { _LeaseExpire = value; OnPropertyChanged("LeaseExpire"); } } }
private String? _PrevMac;
/// <summary>前一MAC。IP漂移时的旧MAC,审计关键:本次MAC≠上次MAC→IP已换设备→触发DeviceHistory事件</summary>
[DisplayName("前一MAC")]
[Description("前一MAC。IP漂移时的旧MAC,审计关键:本次MAC≠上次MAC→IP已换设备→触发DeviceHistory事件")]
[DataObjectField(false, false, true, 17)]
[BindColumn("PrevMac", "前一MAC。IP漂移时的旧MAC,审计关键:本次MAC≠上次MAC→IP已换设备→触发DeviceHistory事件", "")]
public String? PrevMac { get => _PrevMac; set { if (OnPropertyChanging("PrevMac", value)) { _PrevMac = value; OnPropertyChanged("PrevMac"); } } }
private Int32 _PrevDeviceId;
/// <summary>前一设备ID。IP漂移时旧设备关联。事后统计可按PrevDeviceId修正历史数据</summary>
[DisplayName("前一设备ID")]
[Description("前一设备ID。IP漂移时旧设备关联。事后统计可按PrevDeviceId修正历史数据")]
[DataObjectField(false, false, false, 0)]
[BindColumn("PrevDeviceId", "前一设备ID。IP漂移时旧设备关联。事后统计可按PrevDeviceId修正历史数据", "")]
public Int32 PrevDeviceId { get => _PrevDeviceId; set { if (OnPropertyChanging("PrevDeviceId", value)) { _PrevDeviceId = value; OnPropertyChanged("PrevDeviceId"); } } }
private DateTime _MacChangedTime;
/// <summary>MAC变更时间。IP漂移发生的精确时刻,用于精确定位漂移窗口</summary>
[DisplayName("MAC变更时间")]
[Description("MAC变更时间。IP漂移发生的精确时刻,用于精确定位漂移窗口")]
[DataObjectField(false, false, true, 0)]
[BindColumn("MacChangedTime", "MAC变更时间。IP漂移发生的精确时刻,用于精确定位漂移窗口", "")]
public DateTime MacChangedTime { get => _MacChangedTime; set { if (OnPropertyChanging("MacChangedTime", value)) { _MacChangedTime = value; OnPropertyChanged("MacChangedTime"); } } }
private DateTime _FirstSeen;
/// <summary>首次出现。本次会话首次在ARP表中出现的时间,即上线时刻</summary>
[DisplayName("首次出现")]
[Description("首次出现。本次会话首次在ARP表中出现的时间,即上线时刻")]
[DataObjectField(false, false, true, 0)]
[BindColumn("FirstSeen", "首次出现。本次会话首次在ARP表中出现的时间,即上线时刻", "")]
public DateTime FirstSeen { get => _FirstSeen; set { if (OnPropertyChanging("FirstSeen", value)) { _FirstSeen = value; OnPropertyChanged("FirstSeen"); } } }
private DateTime _LastSeen;
/// <summary>最后活跃。每分钟更新。LastSeen超过2分钟未更新→设备已下线→触发Offline事件</summary>
[DisplayName("最后活跃")]
[Description("最后活跃。每分钟更新。LastSeen超过2分钟未更新→设备已下线→触发Offline事件")]
[DataObjectField(false, false, true, 0)]
[BindColumn("LastSeen", "最后活跃。每分钟更新。LastSeen超过2分钟未更新→设备已下线→触发Offline事件", "")]
public DateTime LastSeen { get => _LastSeen; set { if (OnPropertyChanging("LastSeen", value)) { _LastSeen = value; OnPropertyChanged("LastSeen"); } } }
private Int32 _OnlineSeconds;
/// <summary>本日在线秒数。每分钟+60,用于快速展示今日在线时长,无需查DeviceHistory</summary>
[DisplayName("本日在线秒数")]
[Description("本日在线秒数。每分钟+60,用于快速展示今日在线时长,无需查DeviceHistory")]
[DataObjectField(false, false, false, 0)]
[BindColumn("OnlineSeconds", "本日在线秒数。每分钟+60,用于快速展示今日在线时长,无需查DeviceHistory", "", ItemType = "TimeSpan")]
public Int32 OnlineSeconds { get => _OnlineSeconds; set { if (OnPropertyChanging("OnlineSeconds", value)) { _OnlineSeconds = value; OnPropertyChanged("OnlineSeconds"); } } }
private Boolean _IsOnline;
/// <summary>是否在线。LastSeen在2分钟以内=True。用于仪表盘实时在线数统计和告警</summary>
[DisplayName("是否在线")]
[Description("是否在线。LastSeen在2分钟以内=True。用于仪表盘实时在线数统计和告警")]
[DataObjectField(false, false, false, 0)]
[BindColumn("IsOnline", "是否在线。LastSeen在2分钟以内=True。用于仪表盘实时在线数统计和告警", "")]
public Boolean IsOnline { get => _IsOnline; set { if (OnPropertyChanging("IsOnline", value)) { _IsOnline = value; OnPropertyChanged("IsOnline"); } } }
private Int64 _RxBytes;
/// <summary>本日累计接收字节。从iptables计数器累加。异常暴增→大流量下载或视频播放</summary>
[DisplayName("本日累计接收字节")]
[Description("本日累计接收字节。从iptables计数器累加。异常暴增→大流量下载或视频播放")]
[DataObjectField(false, false, false, 0)]
[BindColumn("RxBytes", "本日累计接收字节。从iptables计数器累加。异常暴增→大流量下载或视频播放", "")]
public Int64 RxBytes { get => _RxBytes; set { if (OnPropertyChanging("RxBytes", value)) { _RxBytes = value; OnPropertyChanged("RxBytes"); } } }
private Int64 _TxBytes;
/// <summary>本日累计发送字节。上行>下行→P2P上传或直播推流,需关注是否异常</summary>
[DisplayName("本日累计发送字节")]
[Description("本日累计发送字节。上行>下行→P2P上传或直播推流,需关注是否异常")]
[DataObjectField(false, false, false, 0)]
[BindColumn("TxBytes", "本日累计发送字节。上行>下行→P2P上传或直播推流,需关注是否异常", "")]
public Int64 TxBytes { get => _TxBytes; set { if (OnPropertyChanging("TxBytes", value)) { _TxBytes = value; OnPropertyChanged("TxBytes"); } } }
private DateTime _CreateTime;
/// <summary>创建时间</summary>
[Category("扩展")]
[DisplayName("创建时间")]
[Description("创建时间")]
[DataObjectField(false, false, true, 0)]
[BindColumn("CreateTime", "创建时间", "")]
public DateTime CreateTime { get => _CreateTime; set { if (OnPropertyChanging("CreateTime", value)) { _CreateTime = value; OnPropertyChanged("CreateTime"); } } }
private DateTime _UpdateTime;
/// <summary>更新时间。每次采集同步时更新</summary>
[Category("扩展")]
[DisplayName("更新时间")]
[Description("更新时间。每次采集同步时更新")]
[DataObjectField(false, false, true, 0)]
[BindColumn("UpdateTime", "更新时间。每次采集同步时更新", "")]
public DateTime UpdateTime { get => _UpdateTime; set { if (OnPropertyChanging("UpdateTime", value)) { _UpdateTime = value; OnPropertyChanged("UpdateTime"); } } }
#endregion
#region 获取/设置 字段值
/// <summary>获取/设置 字段值</summary>
/// <param name="name">字段名</param>
/// <returns></returns>
public override Object? this[String name]
{
get => name switch
{
"Id" => _Id,
"IP" => _IP,
"Mac" => _Mac,
"HostName" => _HostName,
"DeviceId" => _DeviceId,
"Interface" => _Interface,
"LeaseExpire" => _LeaseExpire,
"PrevMac" => _PrevMac,
"PrevDeviceId" => _PrevDeviceId,
"MacChangedTime" => _MacChangedTime,
"FirstSeen" => _FirstSeen,
"LastSeen" => _LastSeen,
"OnlineSeconds" => _OnlineSeconds,
"IsOnline" => _IsOnline,
"RxBytes" => _RxBytes,
"TxBytes" => _TxBytes,
"CreateTime" => _CreateTime,
"UpdateTime" => _UpdateTime,
_ => base[name]
};
set
{
switch (name)
{
case "Id": _Id = value.ToLong(); break;
case "IP": _IP = Convert.ToString(value); break;
case "Mac": _Mac = Convert.ToString(value); break;
case "HostName": _HostName = Convert.ToString(value); break;
case "DeviceId": _DeviceId = value.ToInt(); break;
case "Interface": _Interface = Convert.ToString(value); break;
case "LeaseExpire": _LeaseExpire = value.ToDateTime(); break;
case "PrevMac": _PrevMac = Convert.ToString(value); break;
case "PrevDeviceId": _PrevDeviceId = value.ToInt(); break;
case "MacChangedTime": _MacChangedTime = value.ToDateTime(); break;
case "FirstSeen": _FirstSeen = value.ToDateTime(); break;
case "LastSeen": _LastSeen = value.ToDateTime(); break;
case "OnlineSeconds": _OnlineSeconds = value.ToInt(); break;
case "IsOnline": _IsOnline = value.ToBoolean(); break;
case "RxBytes": _RxBytes = value.ToLong(); break;
case "TxBytes": _TxBytes = value.ToLong(); break;
case "CreateTime": _CreateTime = value.ToDateTime(); break;
case "UpdateTime": _UpdateTime = value.ToDateTime(); break;
default: base[name] = value; break;
}
}
}
#endregion
#region 关联映射
/// <summary>关联设备</summary>
[XmlIgnore, IgnoreDataMember, ScriptIgnore]
public Device? Device => Extends.Get(nameof(Device), k => Device.FindById(DeviceId));
/// <summary>关联设备</summary>
[Map(nameof(DeviceId), typeof(Device), "Id")]
public String? DeviceName => Device?.Name;
#endregion
#region 扩展查询
/// <summary>根据编号查找</summary>
/// <param name="id">编号</param>
/// <returns>实体对象</returns>
public static DeviceOnline? FindById(Int64 id)
{
if (id < 0) return null;
return Find(_.Id == id);
}
/// <summary>根据IP地址查找</summary>
/// <param name="ip">IP地址</param>
/// <returns>实体对象</returns>
public static DeviceOnline? FindByIP(String? ip)
{
if (ip == null) return null;
return Find(_.IP == ip);
}
/// <summary>根据所在网口查找</summary>
/// <param name="@interface">所在网口</param>
/// <returns>实体列表</returns>
public static IList<DeviceOnline> FindAllByInterface(String? @interface)
{
if (@interface == null) return [];
return FindAll(_.Interface == @interface);
}
#endregion
#region 高级查询
/// <summary>高级查询</summary>
/// <param name="ip">IP地址。当前活跃IP,IPv4/IPv6。统计时优先从此表按IP查DeviceId</param>
/// <param name="mac">MAC地址。ARP解析得到,是设备唯一标识。映射第一优先级:MAC精确匹配Device表</param>
/// <param name="deviceId">关联设备。通过MAC查Device表得到,首次未知=0,后续自动关联</param>
/// <param name="@interface">所在网口。如eth0/br-lan/wlan0。同IP在不同网口=不同设备,用于多网段隔离</param>
/// <param name="lastSeen">最后活跃。每分钟更新。LastSeen超过2分钟未更新→设备已下线→触发Offline事件</param>
/// <param name="isOnline">是否在线。LastSeen在2分钟以内=True。用于仪表盘实时在线数统计和告警</param>
/// <param name="start">编号开始</param>
/// <param name="end">编号结束</param>
/// <param name="key">关键字</param>
/// <param name="page">分页参数信息。可携带统计和数据权限扩展查询等信息</param>
/// <returns>实体列表</returns>
public static IList<DeviceOnline> Search(String? ip, String? mac, Int32 deviceId, String? @interface, DateTime lastSeen, Boolean? isOnline, DateTime start, DateTime end, String key, PageParameter page)
{
var exp = new WhereExpression();
if (!ip.IsNullOrEmpty()) exp &= _.IP == ip;
if (!mac.IsNullOrEmpty()) exp &= _.Mac == mac;
if (deviceId >= 0) exp &= _.DeviceId == deviceId;
if (!@interface.IsNullOrEmpty()) exp &= _.Interface == @interface;
if (isOnline != null) exp &= _.IsOnline == isOnline;
exp &= _.Id.Between(start, end, Meta.Factory.Snow);
if (!key.IsNullOrEmpty()) exp &= SearchWhereByKeys(key);
return FindAll(exp, page);
}
#endregion
#region 数据清理
/// <summary>清理指定时间段内的数据</summary>
/// <param name="start">开始时间。未指定时清理小于指定时间的所有数据</param>
/// <param name="end">结束时间</param>
/// <param name="maximumRows">最大删除行数。清理历史数据时,避免一次性删除过多导致数据库IO跟不上,0表示所有</param>
/// <returns>清理行数</returns>
public static Int32 DeleteWith(DateTime start, DateTime end, Int32 maximumRows = 0)
{
return Delete(_.Id.Between(start, end, Meta.Factory.Snow), maximumRows);
}
#endregion
#region 字段名
/// <summary>取得设备在线快照字段信息的快捷方式</summary>
public partial class _
{
/// <summary>编号。雪花ID,保留历史快照</summary>
public static readonly Field Id = FindByName("Id");
/// <summary>IP地址。当前活跃IP,IPv4/IPv6。统计时优先从此表按IP查DeviceId</summary>
public static readonly Field IP = FindByName("IP");
/// <summary>MAC地址。ARP解析得到,是设备唯一标识。映射第一优先级:MAC精确匹配Device表</summary>
public static readonly Field Mac = FindByName("Mac");
/// <summary>主机名。DHCP/mDNS上报,如'XiaoMing-PC'。用于人工识别设备</summary>
public static readonly Field HostName = FindByName("HostName");
/// <summary>关联设备。通过MAC查Device表得到,首次未知=0,后续自动关联</summary>
public static readonly Field DeviceId = FindByName("DeviceId");
/// <summary>所在网口。如eth0/br-lan/wlan0。同IP在不同网口=不同设备,用于多网段隔离</summary>
public static readonly Field Interface = FindByName("Interface");
/// <summary>DHCP租约过期。过期后IP可能被回收分配给其他设备,是IP漂移的预警信号</summary>
public static readonly Field LeaseExpire = FindByName("LeaseExpire");
/// <summary>前一MAC。IP漂移时的旧MAC,审计关键:本次MAC≠上次MAC→IP已换设备→触发DeviceHistory事件</summary>
public static readonly Field PrevMac = FindByName("PrevMac");
/// <summary>前一设备ID。IP漂移时旧设备关联。事后统计可按PrevDeviceId修正历史数据</summary>
public static readonly Field PrevDeviceId = FindByName("PrevDeviceId");
/// <summary>MAC变更时间。IP漂移发生的精确时刻,用于精确定位漂移窗口</summary>
public static readonly Field MacChangedTime = FindByName("MacChangedTime");
/// <summary>首次出现。本次会话首次在ARP表中出现的时间,即上线时刻</summary>
public static readonly Field FirstSeen = FindByName("FirstSeen");
/// <summary>最后活跃。每分钟更新。LastSeen超过2分钟未更新→设备已下线→触发Offline事件</summary>
public static readonly Field LastSeen = FindByName("LastSeen");
/// <summary>本日在线秒数。每分钟+60,用于快速展示今日在线时长,无需查DeviceHistory</summary>
public static readonly Field OnlineSeconds = FindByName("OnlineSeconds");
/// <summary>是否在线。LastSeen在2分钟以内=True。用于仪表盘实时在线数统计和告警</summary>
public static readonly Field IsOnline = FindByName("IsOnline");
/// <summary>本日累计接收字节。从iptables计数器累加。异常暴增→大流量下载或视频播放</summary>
public static readonly Field RxBytes = FindByName("RxBytes");
/// <summary>本日累计发送字节。上行>下行→P2P上传或直播推流,需关注是否异常</summary>
public static readonly Field TxBytes = FindByName("TxBytes");
/// <summary>创建时间</summary>
public static readonly Field CreateTime = FindByName("CreateTime");
/// <summary>更新时间。每次采集同步时更新</summary>
public static readonly Field UpdateTime = FindByName("UpdateTime");
static Field FindByName(String name) => Meta.Table.FindByName(name)!;
}
/// <summary>取得设备在线快照字段名称的快捷方式</summary>
public partial class __
{
/// <summary>编号。雪花ID,保留历史快照</summary>
public const String Id = "Id";
/// <summary>IP地址。当前活跃IP,IPv4/IPv6。统计时优先从此表按IP查DeviceId</summary>
public const String IP = "IP";
/// <summary>MAC地址。ARP解析得到,是设备唯一标识。映射第一优先级:MAC精确匹配Device表</summary>
public const String Mac = "Mac";
/// <summary>主机名。DHCP/mDNS上报,如'XiaoMing-PC'。用于人工识别设备</summary>
public const String HostName = "HostName";
/// <summary>关联设备。通过MAC查Device表得到,首次未知=0,后续自动关联</summary>
public const String DeviceId = "DeviceId";
/// <summary>所在网口。如eth0/br-lan/wlan0。同IP在不同网口=不同设备,用于多网段隔离</summary>
public const String Interface = "Interface";
/// <summary>DHCP租约过期。过期后IP可能被回收分配给其他设备,是IP漂移的预警信号</summary>
public const String LeaseExpire = "LeaseExpire";
/// <summary>前一MAC。IP漂移时的旧MAC,审计关键:本次MAC≠上次MAC→IP已换设备→触发DeviceHistory事件</summary>
public const String PrevMac = "PrevMac";
/// <summary>前一设备ID。IP漂移时旧设备关联。事后统计可按PrevDeviceId修正历史数据</summary>
public const String PrevDeviceId = "PrevDeviceId";
/// <summary>MAC变更时间。IP漂移发生的精确时刻,用于精确定位漂移窗口</summary>
public const String MacChangedTime = "MacChangedTime";
/// <summary>首次出现。本次会话首次在ARP表中出现的时间,即上线时刻</summary>
public const String FirstSeen = "FirstSeen";
/// <summary>最后活跃。每分钟更新。LastSeen超过2分钟未更新→设备已下线→触发Offline事件</summary>
public const String LastSeen = "LastSeen";
/// <summary>本日在线秒数。每分钟+60,用于快速展示今日在线时长,无需查DeviceHistory</summary>
public const String OnlineSeconds = "OnlineSeconds";
/// <summary>是否在线。LastSeen在2分钟以内=True。用于仪表盘实时在线数统计和告警</summary>
public const String IsOnline = "IsOnline";
/// <summary>本日累计接收字节。从iptables计数器累加。异常暴增→大流量下载或视频播放</summary>
public const String RxBytes = "RxBytes";
/// <summary>本日累计发送字节。上行>下行→P2P上传或直播推流,需关注是否异常</summary>
public const String TxBytes = "TxBytes";
/// <summary>创建时间</summary>
public const String CreateTime = "CreateTime";
/// <summary>更新时间。每次采集同步时更新</summary>
public const String UpdateTime = "UpdateTime";
}
#endregion
}
|