GWDataCenter常用接口API
# 协议插件开发
本节介绍GWDataCenter包提供的常用接口和应用示例。
# 设备信息字典与测点信息字典
# EquipItemDict
EquipItemDict
在GWDataCenter包的DataCenter类中维护了一个字典类型的静态字段EquipItemDict,所有的设备信息均维护在该字典中,该字典的原型为:
static public Dictionary<int, EquipItem> EquipItemDict;
其中int类型的Key为设备的设备号。
# YCItemDict和YXItemDict
YCItemDict和YXItemDict
同时,在EquipItem类中维护了两个分别用于保存遥测和遥信的字典YCItemDict和YXItemDict。其原型为:
public Dictionary<int, YXItem> YCItemDict;
public Dictionary<int, YXItem> YXItemDict;
其中Key为遥测或者遥信的编号。
可以通过这些字典获取设备测点的实时数据或者获取设备的相关信息。例如可以试用这些字典获取设备测点的实时值,代码示例如下:
object obj = DataCenter.EquipItemDict[131].YCItemDict[1].YCValue;
上述代码的功能为获取设备号为131的设备的1号遥测点的实时数据
object obj = DataCenter.EquipItemDict[132].YXItemDict[3].YXValue;
上述代码的功能为获取设备号为132的设备的3号遥信点的实时数据
# 应用示例:获取设备测点的实时值
在此示例中的协议插件可以将其它设备的测点组合成一个新的设备,为了实现这一需求协议插件需要能够获取其它设备测点的实时值。示例代码如下:
- init()方法
init()方法
初始化方法中仅用到了设备的通讯时间参数做为控制插件刷新的时间间隔,那么也就意味着在使用该协议插件添加产品时,仅需要配置通讯时间参数以及其它必填项即可,例如:可以在通讯时间参数中填入1000,则代表刷新的时间间隔为1秒钟。
int _sleep = 1000;
/// <summary>
/// 初始化方法
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public override bool init(EquipItem item)
{
if (!base.init(item))
{
return false;
}
if (!string.IsNullOrEmpty(item.communication_time_param) && int.TryParse(item.communication_time_param, out _))
{
_sleep = int.Parse(item.communication_time_param);//将强制休眠参数配置在通讯时间参数中。
}
return true;
}
- GetData()方法
GetData()方法
public override CommunicationState GetData(CEquipBase pEquip)
{
Sleep(_sleep);//线程等待,控制刷新间隔
return base.GetData(pEquip);
}
- GetYC()方法
GetYC()方法
GetYC()方法中使用了main_instruction和minor_instruction两个字段分别用来获取了设备编号和测点编号,那么也就意味着在添加产品遥测量时需要在操作命令中配置想要获取设备的设备号,在操作参数中配置设备的遥测号。例如:要配置遥测量显示151号设备的10号测点,则应在遥测量的操作命令中填入151,而在操作参数中填入10。
public override bool GetYC(YcpTableRow r)
{
int equipNo = int.Parse(r.main_instruction);//操作命令中配置设备编号
int ycNo = int.Parse(r.minor_instruction);//操作参数中配置上述设备的遥测编号
SetYCData(r, GetRealData(equipNo, ycNo));
return true;
}
- 在GetYC方法中使用了GetRealData方法,该方法用来获取指定设备号和遥测号的测点的实时值,是本示例中的核心代码,代码示例如下:
代码
/// <summary>
/// 获取设备测点实时值的私有方法
/// </summary>
/// <param name="equipNo">设备编号</param>
/// <param name="ycNo">遥测编号</param>
/// <returns>测点实时值</returns>
private object GetRealData(int equipNo, int ycNo)
{
object realValue = DataCenter.EquipItemDict[equipNo].YCItemDict[ycNo].YCValue;
return realValue;
}
- GetYX()和SetParm()方法在本示例中没有使用到,故保持默认代码即可。
- 协议插件开发完成后可以通过添加产品,再根据产品添加设备,最后在设备列表中查看设备的数据。
添加产品和添加设备
产品配置如下图所示
产品遥测配置如下图所示
产品遥测量配置完成后即可根据此产品添加设备,添加过程此处不再赘述,
在设备列表中查看设备的数据
在上述示例中可以发现EquipItemDict字典、YCItemDict以及YXItemDict三个字典Value的数据类型分别为EquipItem、YXItem、YXItem三个类。这三个类均对应数据库中的表,下面分别给出这三个类的说明以供参考。
# EquipItem 设备类
EquipItem类对应数据库中的Equip表
该类原型如下:
public class EquipItem
{
public string advice_Msg;//通讯故障处理意见,对应“proc_advice”字段
public string alarmMsg;//告警信息,其值为设备名+“out_of_contact”字段
public int AlarmRiseCycle;//报警升级周期。单位分钟
public int attrib;//可配置属性
public bool bCanMonitor; //能否进行监控,与授权文件有关
public bool bCommunicationOk; //通讯是否正常
public bool bInitOk; //初始化是否成功
public string communication_drv;//设备驱动dll,对应“communication_drv”字段
public string communication_param; //通讯参数,对应“communication_param”字段
public string communication_time_param; //通讯时间参数,对应“communication_time_param”
public Database db; //内置可操作的数据库实例
public bool DoSetParm; //标记是否该设备处于设置动作
public string equip_detail; //设备属性,对应“equip_detail”字段
public int iCommFaultRetryCount; //决定通讯失败的重试次数,与communication_time_param 有关
public string PlanNo;//预案号,对应“PlanNo”字段
public string related_video; //报警时的联动视频,对应“related_video”字段。关联的视频通道,可以是单路视频或多通道的组合,云台通道可以带有预置位编号:203,1+203,2(Y1)
public string Reserve1;//保留字段1
public string Reserve2; //保留字段2
public string Reserve3; //保留字段3
public string RestorealarmMsg; //设备故障恢复提示信息,其值为设备名+“contacted”字段
public string restore_wave_file;//报警恢复时的语音文件,对应“event_wav”字段
public List<SafeTimeSpan> SafeTimeSpanList; //安全时段,对应“SafeTime”字段,比如:08:20:00-09:30:00+10:20:00-12:30:00+18:15:20-19:30:00
public SerialPort serialport;//通讯实例。类名称沿用SerialPort,是为了通讯dll不做更改,实际含义并非只是串口,而是代表一个可选择的通讯方式
public Queue SetItemQueue;//正在进行的设置项的队列
public string wave_file;//报警语音文件,对应“event_wav”字段
public Dictionary<int, YCItem> YCItemDict;//YCP点的字典
public Dictionary<int, YXItem> YXItemDict;//YXP点的字典
public string ZiChanID;//资产号,对应“ZiChanID”字段
public int Alarm_scheme { get; }//报警方式,对应“alarm_scheme”字段
public bool bCanConfirm2NormalState { get; set; }//能否通过确认把报警状态恢复为正常,用于不能自动复位的情况。
public bool? Bufang { get; set; }//布防状态。true布防 false撤防
public Assembly Dll { get; }//获取通讯驱动的dll程序集
public string Equip_addr { get; }//设备通讯编号,对应“equip_addr”字段
public string Equip_nm { get; set; }//设备名称,对应“equip_nm”字段
public int iAcc_cyc { get; }//后台调度线程的进入周期,1表示每次都进入,N表示循环N次才进入。增大这个值,可以使设备的通讯变慢。
public int iEquipno { get; }//设备号,对应“equip_no”字段
public bool IsDebug { get; set; }//是否设成调试状态
public int iStano { get; }//站点号,对应“sta_n”字段
public string Local_addr { get; }//通讯地址,比如COM3,对应“local_addr”字段
public string Related_pic { get; }//报警时的联动页面,对应“related_pic”字段
public EquipState State { get; set; }//设备通讯状态
public event EqpStateChangedEventHandler EqpStateChanged;//设备通讯状态发生了改变
public event EventHandler EquipCommError;//通讯故障
public event EventHandler EquipCommOk;//通讯正常
public event EventHandler EquipHaveAlarm;//有报警发生
public event EventHandler EquipNoAlarm;//没有报警发生
public event SetItemNoPermissionEventHandler NoSetItemPermissionEvent;//有不被允许的设置发生
public void AddSetItem(SetItem item);//加入设置项
public void ClearAllEvents();//清除掉本设备的所有事件
public string GetEquipInfo();//获取设备信息
public YCItem GetYCItem(int iYcNo);//获取YCItem
public int GetYCItemAlarmCount();//获取YCItem的报警数量
public int GetYCYXItemCount();//获取YC、YX的测点数
public YXItem GetYXItem(int iYxNo); //获取YXItem
public int GetYXItemAlarmCount();//获取YXItem的报警数量
public bool IsSafeTime();//是否在安全时段
public void SetBufang();//设成布防状态
public void SetChefang();//设成撤防状态
}
说明
其中的设备通讯状态属性State:public EquipState State { get; set; }
,可以通过通讯状态进行设备数量的统计。设备通讯状态属性为EquipState枚举类型。该枚举类型的原型如下:
public enum EquipState
{
NoCommunication = 0,//不通讯或者通讯故障
CommunicationOK = 1,//通讯正常
HaveAlarm = 2,//有报警发生
HaveSetParm = 3,//有设置在处理
Initial = 4,//初始化
CheFang = 5,//撤防
BackUp = 6//处于备份侦听状态中
}
可以通过如下代码判断设备的状态是否为不通讯或者通讯故障(也就是设备离线):
if(DataCenter.EquipItemDict[133].State == EquipState.NoCommunication)
{
//其它功能代码
}
# YCItem 模拟量测点(遥测)类
YCItem类对应数据库中ycp表
public class YCItem
{
public static object m_DefaultValue;//测点未得到通讯数据的默认值
public int AlarmRiseCycle;//报警升级周期,对应“AlarmRiseCycle”字段
public bool bCanMonitor;//是否处于监控之下
public bool bRepeatAlarm; //是否是重复报警
public int DotBitNum; //数值显示的小数位数
public bool IsWuBao;//是否误报
public string main_instruction;//操作命名,对应“main_instruction”字段
public string minor_instruction; //操作参数,对应“minor_instruction”字段
public CurveRecordInterval m_CurveRecordInterval;//曲线记录间隔
public string PlanNo;//预案号,对应“PlanNo”字段
public string related_video;//关联视频,对应“related_video”字段
public string Reserve1;//保留字段1
public string Reserve2; //保留字段2
public string Reserve3; //保留字段3
public string strUnit;//测点单位
public string s_alarm_shield; //屏蔽报警参数:e.g. 2.3+4.2 表示2号设备3号测点 和 4号设备2号测点
public string ZiChanID;//资产号,对应“ZiChanID”字段
public string AlarmMsg { get; }//测点发生报警时的信息
public int Alarm_scheme { get; }//报警方式,对应“alarm_scheme”字段
public bool Bufang { get; set; }//是否布防
public string Comments { get; } //越限事件+处理意见
public bool Curve_rcd { get; }//是否记录曲线,对应“curve_rcd”字段
public Database Db { get; }//内置数据库操作实例
public int Equip_no { get; }//设备号,对应“equip_no”字段
public bool IsAlarm { get; }//是否报警
public int Level { get; }//报警级别,对应“lvl_level”字段
public bool ManualReset { get; set; }//手工复位标志,默认处于非手工状态
public string Proc_advice { get; }//处理意见,对应“proc_advice”字段
public string Related_pic { get; }//关联页面,对应“related_pic”字段
public string Restore_Wave_file { get; }//恢复报警的声音文件,对应“wave_file”字段
public int Sta_n { get; }//站点号,对应“sta_n”字段
public string Wave_file { get; }//声音文件,对应“wave_file”字段
public object YCValue { get; set; }//测点值
public string Yc_nm { get; set; }//测点名称,对应“yc_nm”字段
public int Yc_no { get; }//测点号,对应“yc_no”字段
public event YCAlarmEventHandler Alarmed;//报警事件
public event YCAlarmRestoreEventHandler AlarmRestored;//报警恢复事件
public event YCValueChangedEventHandler ValueChanged;//测点值改变事件
public void ClearAllEvents();//清除所有该测点的事件(实时快照)
public void SetNoAlarm();//把测点设置成不报警状态
}
# YXItem 状态量测点(遥信)类
YXItem类对应数据库中的yxp表
public class YXItem
{
public int AlarmRiseCycle;//报警升级周期,对应“AlarmRiseCycle”字段
public bool bCanMonitor;//是否受监控
public bool bRepeatAlarm; //是否是重复报警
public bool IsWuBao;//是否误报
public string PlanNo;//预案号,对应“PlanNo”字段
public string related_video;//关联视频,对应“related_video”字段
public string Reserve1;//保留字段1,对应“Reserve1”字段
public string Reserve2; //保留字段2,对应“Reserve2”字段
public string Reserve3; //保留字段3,对应“Reserve3”字段
public string s_alarm_shield;// 屏蔽报警参数:e.g. 2.3+4.2 表示2号设备3号测点 和 4号设备2号测点,对应“alarm_shield”字段
public string ZiChanID;//资产号,对应“ZiChanID”字段
public int AlarmLevel { get; }//报警发生时的级别
public string AlarmMsg { get; }//报警信息
public int Alarm_scheme { get; }//报警方式,对应“alarm_scheme”字段
public bool Bufang { get; set; }//是否布防
public string Comments { get; set; }//报警发生时的处理意见
public Database Db { get; }//内置数据库操作实例
public int Equip_no { get; }//设备号,对应“equip_no”字段
public bool IsAlarm { get; set; }//测点是否报警
public int Level_d { get; }//1-0报警级别,对应“level_d”字段
public int Level_r { get; }//0-1报警级别,对应“level_r”字段
public bool ManualReset { get; set; } //手工复位标志,默认处于非手工状态
public string Proc_advice { get; set; }//报警时的处理意见
public string Related_pic { get; }//关联页面,对应“related_pic”字段
public int Restorelevel { get; }//报警恢复时的级别
public string RestoreMsg { get; }//恢复的提示信息
public string Restore_Wave_file { get; }//报警恢复的对应语音文件
public int Sta_n { get; }//站点号,对应“sta_n”字段
public string Wave_file { get; }//语音文件
public string YXState { get; set; }//测点状态
public object YXValue { get; set; }//测点值
public string Yx_nm { get; set; }//测点名称,对应“yx_nm”字段
public int Yx_no { get; }//测点号,对应“yx_no”字段
public event YXAlarmEventHandler Alarmed;//报警事件
public event YXAlarmRestoreEventHandler AlarmRestored;//报警恢复事件
public event YXValueChangedEventHandler ValueChanged;//测点值改变事件
public void ClearAllEvents();//清除所有该测点的事件(实时快照)
public void SetNoAlarm();//把测点设置成非报警状态
}
在IoT平台中设备除了拥有遥测量和遥信量外还拥有设置,通过设置可以向设备下发指令,下面也给出SetItem 设置点类的说明以供参考
# SetItem 设置点类
SetItem类对应数据库中的setparm表。
public class SetItem
{
public bool bCanRepeat;//是否在实时快照中可以重复显示
public bool bRecord;//是否记录在数据库
public bool bShowDlg;//是否弹出确认提示窗口
public string Client_Instance_GUID;//客户端标识
public string Description;//设置项的描述
public bool IsCj;//是否为场景控制
public bool isQRTrigger;//是否是二维码扫码触发
public bool IsWaitSetParm; //该命令是否是等待返回的类型
public int m_SetNo;//设置号,对应“set_no”字段
//构造函数
public SetItem(int Eqpno, string MainInstruct, string MinorInstruct, string Value);
public SetItem(int Eqpno, int Setno, string Value, string myexecutor, bool CanRepeat = false);
public SetItem(int Eqpno, string MainInstruct, string MinorInstruct, string Value, string myexecutor, bool CanRepeat = false);
public SetItem(int Eqpno, string MainInstruct, string MinorInstruct, string Value, string Type, string myexecutor);
public SetItem(int Eqpno, int Setno, string MainInstruct, string MinorInstruct, string Value, string myexecutor, bool CanRepeat = false);
public int EquipNo { get; }//设备号,对应“equip_no”字段
public string Executor { get; set; }//执行用户名
public string MainInstruct { get; }//设置参数,对应“main_instruction”字段
public string MinorInstruct { get; }//设置参数,对应“minor_instruction”字段
public string Type { get; }//设置类型,对应“set_type”参数
public string Value { get; }//设置值,对应“value”字段
public bool? WaitSetParmIsFinish { get; set; } //等待返回的设置是否完成
public void GetRecord();//获取是否记录的状态
public string GetSetItemDesc();//获取设置项的描述
public int GetSetNo();//获取设置号
public string GetSetType();//获取设置类型
}
# 实时快照接口
GWDataCenter包中还提供了MessageService类用于向外部提供添加事件信息的方法,下面主要介绍MessageService类的AddMessage()方法。外部调用该方法一般将事件信息做为系统事件进行处理,因而事件信息将保存在数据库中的SysEvt表,SysEvt表以及实时快照使用的GWSnapshotConfig表、YcYxEvt表、SetEvt表的表结构请参照附录\数据库说明部分的内容,此处不再赘述。
Addmessage()方法的声明如下:
/// <param name="level">报警级别</param>
/// <param name="msgstr">内容</param>
/// <param name="equipno">设备号</param>
/// <param name="CanRepeat">是否可以重复出现</param>
public static void AddMessage(MessageLevel level, string msgstr, int equipno, bool CanRepeat = true)
参数说明:
msgstr:所发生事件的内容
equipno:发生事件的设备的设备号。 注意: 外部调用AddMessage()方法一般做为系统事件去添加,因此equipno参数的值必须为0。因而若需要在事件信息中包含设备号,可以在事件内容中通过以字符串的方式保存。
CANRepeat:是否可以重复出现。这里的重复出现是指是否在实时快照列表中可以重复出现。改参数为可选参数,默认值为true表示在实时快照列表中会重复出现事件信息;若该参数的值为false表示实时快照列表中只会显示最近发生的该事实的信息。
level:事件的报警等级。枚举类型MessageLevel定义如下:
public enum MessageLevel { Wubao = -1, Info = 0, SpecalInfo = 9999, Debug = 10000, SetParm, ZiChan, Warn, Error, Fatal }
该枚举类型共包含9种级别,其中Debug级别做为调试使用,因而Debug级别的事件信息不会出现在实时快照列表中也不会保存在数据中。下面介绍其它8种报警级别。
Fatal:致命错误。显示在实时快照的故障类别,同时事件信息保存在数据库中。
Error:错误。显示在实时快照的故障类别,同时事件信息保存在数据库中。
Warn:警告。显示在实时快照的故障类别,同时事件信息保存在数据库中。
Info:提示信息。显示在实时快照的信息类别,同时事件信息保存在数据库中
ZiChan:资产。显示在实时快照的资产类别,同时事件信息保存在数据库中。
SetParm:设置。显示在实时快照的设置类别,同时事件信息保存在数据库中。
Wubao:误报。不显示在实时快照列表中,但事件信息会保存在数据库中。
SpecalInfo:特殊报警。不显示在实时快照列表中,但事件信息会保存在数据库中。
# 应用示例
通过判断随机数的不同范围产生不同级别的事件信息。示例代码如下:
- init()方法
init()方法
int showData = 0;
int _sleep = 5000;
public override bool init(EquipItem item)
{
if (!string.IsNullOrEmpty(item.communication_time_param) && int.TryParse(item.communication_time_param, out _))
{
_sleep = int.Parse(item.communication_time_param);//设置数据刷新间隔
}
return base.init(item);
}
- GetData()方法
GetData()方法
public override CommunicationState GetData(CEquipBase pEquip)
{
Random random = new Random();
showData = random.Next(-60, 60);
if (showData >= 40)
{
MessageService.AddMessage(MessageLevel.Error, $"{pEquip.Equipitem.iEquipno}:错误", 0, true);
}
else if (showData >= 20)
{
MessageService.AddMessage(MessageLevel.Fatal, $"{pEquip.Equipitem.iEquipno}:致命错误", 0, true);
}
else if (showData >= 0)
{
MessageService.AddMessage(MessageLevel.Wubao, $"{pEquip.Equipitem.iEquipno}:误报", 0, true);
}
else if (showData >= -10)
{
MessageService.AddMessage(MessageLevel.Info, $"{pEquip.Equipitem.iEquipno}:提示信息", 0, false);
}
else if (showData >= -30)
{
MessageService.AddMessage(MessageLevel.Warn, $"{pEquip.Equipitem.iEquipno}:警告", 0, true);
}
else if (showData >= -40)
{
MessageService.AddMessage(MessageLevel.SetParm, $"{pEquip.Equipitem.iEquipno}:设置", 0, true);
}
else if (showData >= -50)
{
MessageService.AddMessage(MessageLevel.SpecalInfo, $"{pEquip.Equipitem.iEquipno}:特殊报警", 0, true);
}
else
{
MessageService.AddMessage(MessageLevel.ZiChan, $"{pEquip.Equipitem.iEquipno}:资产", 0, false);
}
Sleep(_sleep);
return base.GetData(pEquip);
}
- GetYC()方法
GetYC()方法
public override bool GetYC(YcpTableRow r)
{
SetYCData(r, showData);
return true;
}
- GetYX()和SetParm()方法在本示例中没有使用到,故保持默认代码即可。
- 协议插件开发完成后可以通过添加产品,再根据产品添加设备,最后在实时快照和数据库中查看事件信息。
产品配置如下图所示
产品遥测配置如下图所示
实时快照列表中显示的事件信息
数据库SysEvt表中的事件信息
# 读取历史数据接口
GWDataCenter包中的DataCenter类提供了两个静态方法GetChangedDataFromCurveAsync()
和GetStringInfoFromCurveAsync()
分别用于读取数值型历史数据和字符型的历史数据。
# GetChangedDataFromCurveAsync方法
方法声明:
/// <summary>
/// 获取数值型历史数据
/// </summary>
/// <param name="bgn">查询的起始时间</param>
/// <param name="end">查询的结束时间</param>
/// <param name="stano">查询设备的站点号</param>
/// <param name="eqpno">查询设备的设备号</param>
/// <param name="ycyxno">查询设备的测点号</param>
/// <param name="type">查询类型</param>
/// <returns></returns>
public static Task<List<myCurveData>> GetChangedDataFromCurveAsync(DateTime bgn, DateTime end, int stano, int eqpno, int ycyxno, string type);
说明
type的类型有C、X两种,分别对应遥测和遥信。
# 应用示例
获取一个模拟温湿度设备零点的数据。示例代码如下
- init()方法
double zeroData = 0;
int _sleep = 5000;
public override bool init(EquipItem item)
{
if (!base.init(item))
{
return false;
}
if (!string.IsNullOrEmpty(item.communication_time_param) && int.TryParse(item.communication_time_param, out _))
{
_sleep = int.Parse(item.communication_time_param);//设置数据刷新间隔
}
return true;
}
- GetData()方法
public override CommunicationState GetData(CEquipBase pEquip)
{
//此处获取的是遥测点所以type参数的值为C
List<myCurveData> myCurveDatas = DataCenter.GetChangedDataFromCurveAsync(DateTime.Now.Date, DateTime.Now.Date.AddMinutes(1), 1, 130, 1, "C").Result;
if (myCurveDatas != null && myCurveDatas.Count > 0)
{
zeroData = myCurveDatas.OrderBy(u=>u.datetime).FirstOrDefault().value;
}
else
{
zeroData = 0;
}
return base.GetData(pEquip);
}
- GetYC()方法
public override bool GetYC(YcpTableRow r)
{
SetYCData(r, zeroData);
return true;
}
- GetYX()和SetParm()方法在本示例中没有使用到,故保持默认代码即可。
GetStringInfoFromCurveAsync方法
方法声明:
/// <summary>
/// 获取字符型历史数据
/// </summary>
/// <param name="bgn">查询的起始时间</param>
/// <param name="end">查询的结束时间</param>
/// <param name="stano">查询设备的站点号</param>
/// <param name="eqpno">查询设备的设备号</param>
/// <param name="ycyxno">查询设备的测点号</param>
/// <param name="type">查询类型</param>
/// <returns></returns>
public static Task<List<myCurveData4String>> GetStringInfoFromCurveAsync(DateTime bgn, DateTime end, int stano, int eqpno, int ycyxno, string type)
{
}
说明
type的类型有CS、XS、SEQ三类,分别对应遥测、遥信和元组。 因该方法的使用跟获取数值型历史数据类似,参考获取数值型历史数据案例即可。