消防数据测试

zw
CZ 4 months ago
parent 0859ee768e
commit bcf2bb9877

@ -0,0 +1,60 @@
using System.Collections.Concurrent;
using System.Reflection;
using Autofac;
using Entity.DbModel.Station;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
using HybirdFrameworkCore.Entity;
using HybirdFrameworkCore.Redis;
using HybirdFrameworkCore.Utils;
using HybirdFrameworkDriver.Session;
using HybirdFrameworkDriver.TcpClient;
using log4net;
using Newtonsoft.Json;
using Repository.Station;
using Service.Fire.Codec;
using Service.Fire.Common;
using Service.Fire.Handler;
using SqlSugar;
namespace Service.Fire.Client;
[Scope("InstancePerDependency")]
public class FireClient : TcpClient<IBaseHandler, Decoder, Encoder>
{
/// <summary>
/// 消防设备编号
/// </summary>
public string Sn { get; set; }
private ILog Log()
{
var name = "Fire";
ILog logger = LogManager.GetLogger(name);
Console.WriteLine(name + "-" + logger.GetHashCode());
return logger;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool Connect()
{
base.BaseConnect();
Log().Info("Fire connect succeed");
return Connected;
}
/// <summary>
///
/// </summary>
/// <param name="sn"></param>
/// <param name="destAddr"></param>
public void SessionAttr(string sn)
{
ChannelUtils.AddAttr(Channel, FireConst.FireSn, sn);
ChannelUtils.AddAttr(Channel, FireConst.EqmTypeNo, sn);
ChannelUtils.AddAttr(Channel, FireConst.EqmCode, sn);
}
}

@ -0,0 +1,75 @@
using System.Collections.Concurrent;
using Autofac;
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkDriver.Session;
using log4net;
using Service.Fire.Common;
namespace Service.Fire.Client;
public class FireMgr
{
private static readonly ILog Log = LogManager.GetLogger(typeof(FireMgr));
public static readonly ConcurrentDictionary<string, FireClient> Dictionary = new();
public static void ConnClient()
{
Log.Info($"begin to connect fire");
FireClient client = AppInfo.Container.Resolve<FireClient>();
client.AutoReconnect = true;
client.Sn = FireConst.Sn;
client.LogName = "Fire" + FireConst.EqmCode;
client.ConnectedEventHandler += (sender, b) =>
{
client.SessionAttr(FireConst.Sn);
};
client.InitBootstrap(FireConst.Ip, FireConst.Port);
Task.Run(() =>
{
client.Connect();
client.SessionAttr(FireConst.Sn);
Log.Info($"succeed to connect loading...");
});
AddBySn(FireConst.Sn, client);
Log.Info($"begin to connect fire");
}
public static void AddBySn(string sn, FireClient client)
{
Dictionary[sn] = client;
}
/// <summary>
/// 通过channel获取client
/// </summary>
/// <param name="channel"></param>
/// <param name="sn"></param>
/// <param name="client">获取不到client则为空</param>
/// <returns></returns>
public static bool TryGetClient(IChannel channel, out string sn, out FireClient? client)
{
string? snt = ChannelUtils.GetAttr(channel, FireConst.EqmCode);
if (!string.IsNullOrWhiteSpace(snt))
{
var chargerClient = GetBySn(snt);
if (chargerClient != null)
{
sn = snt;
client = chargerClient;
return true;
}
}
sn = string.Empty;
client = null;
return false;
}
public static FireClient? GetBySn(string sn)
{
Dictionary.TryGetValue(sn, out var o);
return o;
}
}

@ -0,0 +1,152 @@
using System.Diagnostics;
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Utils;
using HybirdFrameworkDriver.Session;
using log4net;
using Newtonsoft.Json;
using Service.Cloud.Msg;
using Service.Fire.Common;
using Service.Fire.Msg;
using Service.Fire.Msg.Fire;
using Service.Fire.Msg.Fire.Req;
namespace Service.Fire.Codec;
public class Decoder : ByteToMessageDecoder
{
private readonly IByteBuffer[] _delimiters = { Unpooled.CopiedBuffer(FireConst.StartChar) };
private ILog Log(string? chargerSn)
{
if (ObjUtils.IsNotNullOrWhiteSpace(chargerSn))
{
return LogManager.GetLogger("Charger" + chargerSn);
}
return LogManager.GetLogger(typeof(Decoder));
}
protected override void Decode(IChannelHandlerContext context, IByteBuffer buffer, List<object> output)
{
string? chargerSn = ChannelUtils.GetAttr(context.Channel, FireConst.FireSn);
IByteBuffer? delimiter = FindDelimiter(buffer);
if (delimiter != null)
{
//分隔符索引
int delimiterIndex = IndexOf(buffer, delimiter);
//帧长索引
int frameLengthIndex = delimiterIndex + delimiter.Capacity + 1;
if (delimiterIndex > 0)
{
buffer.SkipBytes(delimiterIndex);
return;
}
if (buffer.ReadableBytes < frameLengthIndex + 2)
{
// 数据不足,等待更多数据
return;
}
// 读取长度字段
byte frameLength = buffer.GetByte(buffer.ReaderIndex + frameLengthIndex);
//总帧长
int totalFrameLength = delimiterIndex + delimiter.Capacity + 2 + 2 + frameLength;
// 最小总帧长过滤
if (totalFrameLength < 5)
{
return;
}
if (buffer.ReadableBytes < totalFrameLength)
{
// 数据不足,等待更多数据
return;
}
byte[]? data = null;
try
{
ASDU asdu = Parse(buffer, totalFrameLength, delimiter, out data);
Log(chargerSn)
.Info(
$"receive {BitUtls.BytesToHexStr(data)}:{JsonConvert.SerializeObject(asdu)} from {chargerSn}");
output.Add(asdu);
}
catch (Exception e)
{
Log(chargerSn).Error($"decode fail msg={BitUtls.BytesToHexStr(data)}");
}
}
}
private IByteBuffer? FindDelimiter(IByteBuffer buffer)
{
foreach (IByteBuffer delimiter in _delimiters)
{
int delimiterIndex = IndexOf(buffer, delimiter);
if (delimiterIndex >= 0)
{
return delimiter;
}
}
return null;
}
private static int IndexOf(IByteBuffer haystack, IByteBuffer needle)
{
for (int i = haystack.ReaderIndex; i < haystack.WriterIndex; i++)
{
int num = i;
int j;
for (j = 0; j < needle.Capacity && haystack.GetByte(num) == needle.GetByte(j); j++)
{
num++;
if (num == haystack.WriterIndex && j != needle.Capacity - 1)
{
return -1;
}
}
if (j == needle.Capacity)
{
return i - haystack.ReaderIndex;
}
}
return -1;
}
public ASDU Parse(IByteBuffer byteBuffer, int totalFrameLength, IByteBuffer delimiter, out byte[] data)
{
data = new byte[totalFrameLength];
byteBuffer.ReadBytes(data);
int removeIndex = delimiter.Capacity;
ushort cmd = data[2 + removeIndex];
byte[] bytes = new byte[data[2]];
Array.Copy(data, 2 + removeIndex, bytes, 0, bytes.Length);
byte length = data[2];
ASDU asdu = cmd switch
{
0xA1 => ModelConvert.Decode<BroadcastResetReq>(bytes),
0xA2 => ModelConvert.Decode<PollingReq>(bytes),
0xA5 => length switch
{
20 => ModelConvert.Decode<DataNoAddresReq>(bytes),
40 => ModelConvert.Decode<DataReq>(bytes),
_ => new ASDU(),
},
_ => new ASDU(),
};
ASDU.ParseHeader(data, asdu);
return asdu;
}
}

@ -0,0 +1,41 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Utils;
using HybirdFrameworkDriver.Session;
using log4net;
using Newtonsoft.Json;
using Service.Fire.Common;
using Service.Fire.Msg;
namespace Service.Fire.Codec;
public class Encoder: MessageToByteEncoder<APCI>
{
private ILog? Log(string? chargerSn)
{
if (ObjUtils.IsNotNullOrWhiteSpace(chargerSn))
{
return LogManager.GetLogger("fire" + chargerSn);
}
return LogManager.GetLogger(typeof(Encoder));
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="obj"></param>
/// <param name="output"></param>
protected override void Encode(IChannelHandlerContext context, APCI obj, IByteBuffer output)
{
string? sn = ChannelUtils.GetAttr(context.Channel, FireConst.FireSn);
byte[] bytes = obj.ToBytes();
Log(sn)?.Info(
$"send {BitUtls.BytesToHexStr(bytes)}:{JsonConvert.SerializeObject(obj)} to {ChannelUtils.GetAttr(context.Channel, FireConst.FireSn)}");
context.WriteAndFlushAsync(bytes);
}
}

@ -0,0 +1,42 @@
using System.Text;
namespace Service.Fire.Common;
public class CRC16
{
private const ushort Polynomial = 0x1021;
private ushort[] crcTable = new ushort[256];
public CRC16()
{
for (int i = 0; i < 256; i++)
{
ushort value = 0;
ushort temp = (ushort)(i << 8);
for (byte j = 0; j < 8; j++)
{
if (((value ^ temp) & 0x8000) != 0)
{
value = (ushort)((value << 1) ^ Polynomial);
}
else
{
value = (ushort)(value << 1);
}
temp = (ushort)(temp << 1);
}
crcTable[i] = value;
}
}
public ushort ComputeChecksum(byte[] bytes)
{
ushort crc = 0xFFFF; // 初始值
for (int i = 0; i < bytes.Length; i++)
{
byte index = (byte)((crc ^ bytes[i]) & 0xff);
crc = (ushort)((crc >> 8) ^ crcTable[index]);
}
return crc;
}
}

@ -0,0 +1,335 @@
using DotNetty.Common.Utilities;
namespace Service.Fire.Common;
public class FireConst
{
public static readonly AttributeKey<string> FireSn = AttributeKey<string>.ValueOf("fire_sn");//fire
public static readonly AttributeKey<string> EqmTypeNo = AttributeKey<string>.ValueOf("eqm_type_no");//5
public static readonly AttributeKey<string> EqmCode = AttributeKey<string>.ValueOf("eqm_code");//fire
//public static readonly AttributeKey<string> DestAddr = AttributeKey<string>.ValueOf("dest_addr");//
public static readonly byte[] StartChar = { 0xF0 /* ,0xEE*/ };
public static string Ip = "127.0.0.1";
public static int Port = 502;
public static string Sn = "fire";
public static string No = "1";
public static string Code = "5";
/// <summary>
/// 功能属性说明
/// </summary>
/// <param name="bvalue"></param>
/// <returns></returns>
public static string FunctionalAttribute(byte bvalue)
{
switch (bvalue)
{
case 0xC1: return "启动";
case 0xC2: return "故障";
case 0xC3: return "火警";
case 0xC5: return "屏蔽";
case 0xC6: return "其它";
case 0xC7: return "监管";
default: return "";
}
}
/// <summary>
/// 信息类型说明
/// </summary>
/// <param name="bvalue"></param>
/// <returns></returns>
public static string InformationType(byte bvalue)
{
switch (bvalue)
{
case 0x01: return "探头";
case 0x02: return "模块";
case 0x03: return "回路";
case 0x04: return "主电";
case 0x05: return "备电";
case 0x06: return "计算";
case 0x07: return "显示盘";
case 0x08: return "多线";
case 0x09: return "控制器";
case 0x0A: return "网络模";
case 0x0B: return "充电";
case 0x0C: return "系统板";
case 0x1B: return "无线终端";
case 0x1C: return "无线中继器";
case 0x1D: return "气灭终端";
default: return "";
}
}
/// <summary>
/// 设备状态说明
/// </summary>
/// <param name="bvalue"></param>
/// <returns></returns>
public static string DeviceStatus(byte bvalue)
{
switch (bvalue)
{
case 0x00: return "正常";
case 0x01: return "地址丢失";
case 0x02: return "设备错误";
case 0x03: return "重码";
case 0x04: return "动作失败";
case 0x05: return "火警";
case 0x06: return "现场动作";
case 0x07: return "动作成功";
case 0x08: return "开路";
case 0x09: return "故障";
case 0x0A: return "故障恢复";
case 0x0B: return "短路";
case 0x0E: return "多线短路";
case 0x0F: return "多线开路";
case 0x10: return "多线故障";
case 0x11: return "多线正常";
case 0x12: return "自诊断故障";
case 0x13: return "污染";
case 0x14: return "通信故障";
case 0x15: return "通信正常";
case 0x16: return "flash故障";
case 0x17: return "flash故障恢复";
case 0x18: return "多线启动";
case 0x19: return "多线停止";
case 0x1A: return "多线启成功";
case 0x1B: return "多线停成功";
case 0x1C: return "多线现场启";
case 0x1D: return "多线现场停";
case 0x1E: return "多线启失败";
case 0x1F: return "多线停失败";
case 0x21: return "开机";
case 0x22: return "复位";
case 0x23: return "手动转自动";
case 0x24: return "火警确认";
case 0x25: return "预警确认";
case 0x26: return "预警复位";
case 0x28: return "屏蔽";
case 0x29: return "屏蔽解除";
case 0x2A: return "屏蔽";
case 0x2B: return "屏蔽解除";
case 0x2C: return "手动启动";
case 0x2D: return "手动停止";
case 0x2E: return "联动启动";
case 0x2F: return "联动延时";
case 0x30: return "总线短路";
case 0x31: return "24V总线异常";
case 0x32: return "24V总线漏电流异常";
case 0x33: return "总线参考电压异常";
case 0x34: return "5v总线漏电流异常";
case 0x35: return "5V总线电压异常";
case 0x36: return "0V总线电压异常";
case 0x37: return "0V总线漏电流异常";
case 0x38: return "高压中断";
case 0x39: return "总线电压过低";
case 0x3A: return "总线电压过高";
case 0x3B: return "正电流异常";
case 0x3C: return "漏电流异常";
case 0x3D: return "总线负线异常";
case 0x3E: return "总线正线异常";
case 0x3F: return "总线不能上电";
case 0x40: return "总线正常";
case 0x41: return "预警";
case 0x42: return "故障";
case 0x43: return "多线启动";
case 0x44: return "多线停止";
case 0x45: return "多线启成功";
case 0x46: return "多线启失败";
case 0x47: return "多线停成功";
case 0x48: return "多线停失败";
case 0x55: return "气体启动";
case 0x56: return "气体停止";
case 0x7E: return "输入端开路";
case 0x7F: return "输出端开路";
case 0x80: return "输入输出端开路";
case 0x81: return "输入端短路";
case 0x82: return "输出端短路";
case 0x83: return "输入输出端短路";
case 0x8C: return "自检";
case 0x99: return "电池低电压";
case 0x9A: return "终端设备离线";
case 0x9B: return "疏散启动";
case 0x9C: return "底座低电压";
case 0x9D: return "探测器低电压";
case 0x9E: return "中继器离线";
case 0x9F: return "中继器电池低电压";
case 0xA0: return "主电故障";
case 0xA1: return "备电故障";
case 0xA2: return "中继器正常";
case 0xB0: return "手动关门";
case 0xB1: return "联动关门";
case 0xB2: return "现场关门";
case 0xB3: return "关门到位";
case 0xB4: return "关门到位(左)";
case 0xB5: return "关门到位(右)";
case 0xB6: return "现场开门";
case 0xB7: return "开门到位";
case 0xB8: return "现场开门(左)";
case 0xB9: return "现场开门(右)";
case 0xBA: return "现场开门(双)";
case 0xBB: return "开门未到位";
case 0xBC: return "关门未到位";
case 0xEC: return "气体反馈失败";
case 0xED: return "气体现场动作";
default: return "";
}
}
/// <summary>
/// 设备类型说明
/// </summary>
/// <param name="bvalue"></param>
/// <returns></returns>
public static string DeviceType(byte bvalue)
{
switch (bvalue)
{
case 00 : return "离子探头";
case 01 : return "光电探头";
case 02 : return "感温探头";
case 03 : return "烟复合头";
case 04 : return "光复合头";
case 05 : return "三复合头";
case 06 : return "激光探头";
case 07 : return "一氧化碳";
case 08 : return "可燃气体";
case 09 : return "空气采样";
case 10 : return "手动按钮";
case 11 : return "消防栓钮";
case 12 : return "压力开关";
case 13 : return "水流指示";
case 14 : return "信号阀";
case 15 : return "接口模块";
case 16 : return "消防栓泵启";
case 17 : return "消防栓泵停";
case 18 : return "喷淋泵启";
case 19 : return "喷淋泵停";
case 20 : return "泡沫泵启";
case 21 : return "泡沫蹦停";
case 22 : return "备用泵启";
case 23 : return "备用泵停";
case 24 : return "稳压泵启";
case 25 : return "稳压泵停";
case 26 : return "雨淋泵启";
case 27 : return "雨淋泵停";
case 28 : return "正压风机启";
case 29 : return "正压风机停";
case 30 : return "排烟风机启";
case 31 : return "排烟风机停";
case 32 : return "干粉系统启";
case 33 : return "干粉系统停";
case 34 : return "新风机启";
case 35 : return "新风机停";
case 36 : return "发电机";
case 37 : return "消防泵故障";
case 38 : return "喷淋泵故障";
case 39 : return "稳压泵故障";
case 40 : return "水冷却";
case 41 : return "泡沫喷淋";
case 42 : return "送风机启";
case 43 : return "送风机停";
case 44 : return "讯响器";
case 45 : return "试验阀";
case 46 : return "消防栓灯";
case 47 : return "泡沫阀";
case 48 : return "空调";
case 49 : return "消防广播";
case 50 : return "消防警铃";
case 51 : return "防火门";
case 52 : return "防火阀";
case 53 : return "排烟阀";
case 54 : return "电梯";
case 55 : return "疏散指示";
case 56 : return "事故照明";
case 57 : return "非消防电";
case 58 : return "水幕";
case 59 : return "送风口";
case 60 : return "挡烟垂壁";
case 61 : return "雨淋阀";
case 62 : return "湿式阀";
case 63 : return "水冷却泵";
case 64 : return "卷帘半降";
case 65 : return "卷帘全降";
case 66 : return "排风机启";
case 67 : return "排烟风机";
case 68 : return "气体灭火器";
case 69 : return "气体灭火停";
case 70 : return "备用设备启";
case 71 : return "备用设备停";
case 72 : return "码座离子";
case 73 : return "码座光电";
case 74 : return "码座感温";
case 75 : return "低倍泡沫";
case 76 : return "高倍泡沫";
case 77 : return "水雾";
case 78 : return "普通光电";
case 79 : return "普通温感";
case 80 : return "气体报警";
case 81 : return "气体喷放";
case 82 : return "气体故障";
case 83 : return "气体失重";
case 84 : return "高水位";
case 85 : return "低水位";
case 86 : return "电话模块";
case 87 : return "总线电话";
case 88 : return "总线显示盘";
case 89 : return "声光报警器";
case 90 : return "气体灭火盘";
case 91 : return "显示盘";
case 92 : return "探测器";
case 93 : return "模块";
case 94 : return "启停按钮";
case 100 : return "输入2";
case 101 : return "面板按钮";
case 102 : return "传感器";
case 103 : return "漏电传感器";
case 104 : return "温度传感器";
case 105 : return "电流传感器";
case 106 : return "FS8110";
case 107 : return "FS8120";
case 108 : return "FS8130";
case 109 : return "FS8150";
case 110 : return "面板启动";
case 111 : return "面板停止";
case 112 : return "总线";
case 113 : return "电源箱";
case 130 : return "电动先关";
case 131 : return "电动后关";
case 132 : return "释放器先放";
case 133 : return "释放器后放";
case 134 : return "门磁左开";
case 135 : return "门磁右开";
case 136 : return "门磁双开";
case 137 : return "火警模块";
case 138 : return "火警输入";
case 139 : return "常闭防火门";
case 140 : return "常开防火门";
default: return "";
}
}
/// <summary>
/// 获取16进制字符串的字节数组
/// </summary>
/// <param name="hexString">hexString 16进制字符串</param>
/// <returns>字节数组</returns>
public static byte[] ToByteByHexStr(string hexString)
{
if (hexString == null)
return null;
hexString = hexString.Replace(" ", "");
if ((hexString.Length % 2) != 0)
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return returnBytes;
}
}

@ -0,0 +1,34 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
using Service.Fire.Client;
using Service.Fire.Common;
using Service.Fire.Msg.Fire.Req;
namespace Service.Fire.Handler;
/// <summary>
/// 发送事件
/// <code>
/// 1保存日志到log
/// </code>
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class DataNoAddresReqHandler : SimpleChannelInboundHandler<DataNoAddresReq>, IBaseHandler
{
private static readonly ILog Log = LogManager.GetLogger(typeof(DataNoAddresReqHandler));
protected override void ChannelRead0(IChannelHandlerContext ctx, DataNoAddresReq msg)
{
if (FireMgr.TryGetClient(ctx.Channel, out var sn, out var client))
{
Log.Info($"receive {msg} from {sn}");
string datatime = (new DateTime(2000 + msg.Years, msg.Month, msg.Day, msg.Hour, msg.Minute, msg.Seconds)).ToString();
string functionalAttribute = FireConst.FunctionalAttribute(msg.FunctionalAttribute);
string informationType = FireConst.InformationType(msg.InformationType);
string deviceStatus = FireConst.DeviceStatus(msg.DeviceStatus);
string deviceType = FireConst.DeviceType(msg.DeviceType);
}
}
}

@ -0,0 +1,57 @@
using System.Text;
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
using Service.Fire.Client;
using Service.Fire.Common;
using Service.Fire.Msg.Fire.Req;
using Service.Fire.Msg.Host.Resp;
namespace Service.Fire.Handler
{
/// <summary>
/// 发送事件
/// <code>
/// 1保存日志到log
/// </code>
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class DataReqHandler : SimpleChannelInboundHandler<DataReq>, IBaseHandler
{
private static readonly ILog Log = LogManager.GetLogger(typeof(PollingReqHandler));
protected override void ChannelRead0(IChannelHandlerContext ctx, DataReq msg)
{
if (FireMgr.TryGetClient(ctx.Channel, out var sn, out var client))
{
Log.Info($"receive {msg} from {sn}");
string datatime =
(new DateTime(2000 + msg.Years, msg.Month, msg.Day, msg.Hour, msg.Minute, msg.Seconds)).ToString();
string functionalAttribute = FireConst.FunctionalAttribute(msg.FunctionalAttribute);
string informationType = FireConst.InformationType(msg.InformationType);
string deviceStatus = FireConst.DeviceStatus(msg.DeviceStatus);
string deviceType = FireConst.DeviceType(msg.DeviceType);
string strDecode = "";
for (int i = 0; i < msg.BytesLocationCode.Length; i++)
{
if (msg.BytesLocationCode[i] != 0)
{
string strhex = msg.BytesLocationCode[i].ToString("X");
strDecode += strhex;
}
else
{
break;
}
}
byte[] bytesVelNo = FireConst.ToByteByHexStr(strDecode);
Encoding gbEcoding = Encoding.GetEncoding("gb2312");
string strVelNo = gbEcoding.GetString(bytesVelNo);
}
}
}
}

@ -0,0 +1,8 @@
using DotNetty.Transport.Channels;
namespace Service.Fire.Handler;
public interface IBaseHandler : IChannelHandler
{
}

@ -0,0 +1,30 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
using Service.Fire.Client;
using Service.Fire.Msg.Fire.Req;
using Service.Fire.Msg.Host.Resp;
namespace Service.Fire.Handler;
/// <summary>
/// 巡检
/// <code>
/// 1保存日志到log
/// </code>
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class PollingReqHandler : SimpleChannelInboundHandler<PollingReq>, IBaseHandler
{
private static readonly ILog Log = LogManager.GetLogger(typeof(PollingReqHandler));
protected override void ChannelRead0(IChannelHandlerContext ctx, PollingReq msg)
{
if (FireMgr.TryGetClient(ctx.Channel, out var sn, out var client))
{
Log.Info($"receive {msg} from {sn}");
ctx.Channel.WriteAndFlushAsync(new PollingResp());
}
}
}

@ -0,0 +1,38 @@
using HybirdFrameworkDriver.Common;
using Service.Fire.Common;
namespace Service.Fire.Msg;
public abstract class APCI : IToBytes
{
/// <summary>
/// 目标地址
/// </summary>
public byte DestAddress { get; set; }
/// <summary>
/// 数据长度
/// </summary>
public byte Length { get; set; }
public byte CrcHight { get; set; }
public byte CrcLow { get; set; }
public byte[] ToBytes()
{
var bodyBytes = GetBytes();
var list = new List<byte>();
list.AddRange(FireConst.StartChar);
list.Add(DestAddress);
list.Add((byte)bodyBytes.Length);
list.AddRange(bodyBytes);
CRC16 CRC16 = new();
//进行CRC校验
list.AddRange(BitConverter.GetBytes(CRC16.ComputeChecksum(list.ToArray())));
return list.ToArray();
}
public abstract byte[] GetBytes();
}

@ -0,0 +1,36 @@
using DotNetty.Buffers;
using HybirdFrameworkCore.Utils;
using Service.Fire.Common;
namespace Service.Fire.Msg.Fire;
public class ASDU : APCI
{
public override byte[] GetBytes()
{
var list = new List<byte>();
list.AddRange(ModelConvert.Encode(this));
return list.ToArray();
}
public static void ParseHeader(byte[] data, ASDU asdu)
{
IByteBuffer byteBuffer = Unpooled.WrappedBuffer(data);
try
{
var start = FireConst.StartChar.Length - 1;
asdu.DestAddress = byteBuffer.GetByte(start + 1);
asdu.Length = byteBuffer.GetByte(start + 2);
}
catch (Exception e)
{
throw e;
}
finally
{
byteBuffer.Release();
}
}
}

@ -0,0 +1,9 @@
namespace Service.Fire.Msg.Fire.Req;
/// <summary>
/// 广播复位
/// </summary>
public class BroadcastResetReq:ASDU
{
}

@ -0,0 +1,119 @@
using HybirdFrameworkCore.Autofac.Attribute;
namespace Service.Fire.Msg.Fire.Req;
public class DataNoAddresReq:ASDU
{
/// <summary>
/// 功能码/命令字
/// </summary>
[Property(0, 8)]
public byte CommandWord { get; set; }
/// <summary>
/// 功能属性
/// </summary>
[Property(8, 8)]
public byte FunctionalAttribute { get; set; }
/// <summary>
/// 信息类型
/// </summary>
[Property(16, 8)]
public byte InformationType { get; set; }
/// <summary>
/// 设备状态
/// </summary>
[Property(24, 8)]
public byte DeviceStatus { get; set; }
/// <summary>
/// 网络号
/// </summary>
[Property(32, 8)]
public byte NetworkNumber { get; set; }
/// <summary>
/// 主从和机号
/// </summary>
[Property(40, 8)]
public byte MasterSlaveAndPhoneNumber { get; set; }
/// <summary>
/// 年
/// </summary>
[Property(48, 8)]
public byte Years { get; set; }
/// <summary>
/// 月
/// </summary>
[Property(56, 8)]
public byte Month { get; set; }
/// <summary>
/// 日
/// </summary>
[Property(64, 8)]
public byte Day { get; set; }
/// <summary>
/// 时
/// </summary>
[Property(72, 8)]
public byte Hour { get; set; }
/// <summary>
/// 分
/// </summary>
[Property(80, 8)]
public byte Minute { get; set; }
/// <summary>
/// 秒
/// </summary>
[Property(88, 8)]
public byte Seconds { get; set; }
/// <summary>
/// 回路
/// </summary>
[Property(96, 8)]
public byte Loop { get; set; }
/// <summary>
/// 地址
/// </summary>
[Property(104, 8)]
public byte Address { get; set; }
/// <summary>
/// 栋
/// </summary>
[Property(112, 8)]
public byte Building { get; set; }
/// <summary>
/// 区
/// </summary>
[Property(120, 8)]
public byte Area { get; set; }
/// <summary>
/// 层
/// </summary>
[Property(128, 8)]
public byte Layer { get; set; }
/// <summary>
/// 号
/// </summary>
[Property(136, 16)]
public ushort No { get; set; }
/// <summary>
/// 设备类型
/// </summary>
[Property(152, 8)]
public byte DeviceType { get; set; }
}

@ -0,0 +1,148 @@
using HybirdFrameworkCore.Autofac.Attribute;
namespace Service.Fire.Msg.Fire.Req;
public class DataReq : ASDU
{
/// <summary>
/// 功能码/命令字
/// </summary>
[Property(0, 8)]
public byte CommandWord { get; set; }
/// <summary>
/// 功能属性
/// 启动 0xC1
/// 故障 0xC2
/// 火警 0xC3
/// 屏蔽 0xC5
/// 其它 0xC6
/// 监管 0xC7
/// </summary>
[Property(8, 8)]
public byte FunctionalAttribute { get; set; }
/// <summary>
/// 信息类型
/// 探头 0x01
/// 模块 0x02
/// 回路 0x03
/// 主电 0x04
/// 备电 0x05
/// 计算机 0x06
/// 显示盘 0x07
/// 多线 0x08
/// 控制器 0x09
/// 网络模块 0x0A
/// 充电 0x0B
/// 系统板 0x0C
/// 无线终端 0x1B
/// 无线中继器 0x1C
/// 气灭终端 0x1D
/// </summary>
[Property(16, 8)]
public byte InformationType { get; set; }
/// <summary>
/// 设备状态
/// </summary>
[Property(24, 8)]
public byte DeviceStatus { get; set; }
/// <summary>
/// 网络号
/// </summary>
[Property(32, 8)]
public byte NetworkNumber { get; set; }
/// <summary>
/// 主从和机号
/// </summary>
[Property(40, 8)]
public byte MasterSlaveAndPhoneNumber { get; set; }
/// <summary>
/// 年
/// </summary>
[Property(48, 8)]
public byte Years { get; set; }
/// <summary>
/// 月
/// </summary>
[Property(56, 8)]
public byte Month { get; set; }
/// <summary>
/// 日
/// </summary>
[Property(64, 8)]
public byte Day { get; set; }
/// <summary>
/// 时
/// </summary>
[Property(72, 8)]
public byte Hour { get; set; }
/// <summary>
/// 分
/// </summary>
[Property(80, 8)]
public byte Minute { get; set; }
/// <summary>
/// 秒
/// </summary>
[Property(88, 8)]
public byte Seconds { get; set; }
/// <summary>
/// 回路
/// </summary>
[Property(96, 8)]
public byte Loop { get; set; }
/// <summary>
/// 地址
/// </summary>
[Property(104, 8)]
public byte Address { get; set; }
/// <summary>
/// 栋
/// </summary>
[Property(112, 8)]
public byte Building { get; set; }
/// <summary>
/// 区
/// </summary>
[Property(120, 8)]
public byte Area { get; set; }
/// <summary>
/// 层
/// </summary>
[Property(128, 8)]
public byte Layer { get; set; }
/// <summary>
/// 号
/// </summary>
[Property(136, 16)]
public ushort No { get; set; }
/// <summary>
/// 设备类型
/// </summary>
[Property(152, 8)]
public byte DeviceType { get; set; }
/// <summary>
/// 位置代码
/// </summary>
[Property(160, 8*20)]
public string LocationCode { get; set; }
[Property(160, 8*20)]
public byte[] BytesLocationCode { get; set; }
}

@ -0,0 +1,20 @@
using HybirdFrameworkCore.Autofac.Attribute;
namespace Service.Fire.Msg.Fire.Req;
/// <summary>
/// 巡检
/// </summary>
public class PollingReq:ASDU
{
/// <summary>
/// 数据段
/// </summary>
[Property(0, 8)]
public byte DataSegment1 { get; set; }
/// <summary>
/// 数据段
/// </summary>
[Property(8, 8)]
public byte DataSegment2 { get; set; }
}

@ -0,0 +1,28 @@
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Fire.Msg.Fire;
namespace Service.Fire.Msg.Host.Resp;
public class PollingResp: ASDU
{
/// <summary>
/// 功能码/命令字
/// </summary>
[Property(0, 8)]
public byte CommandWord { get; set; }
/// <summary>
/// 信息体1
/// </summary>
[Property(8, 8)]
public byte Resp1 { get; set; }
/// <summary>
/// 信息体2
/// </summary>
[Property(16, 8)]
public byte Resp2 { get; set; }
public PollingResp()
{
CommandWord = 0xA2;
}
}

@ -37,6 +37,7 @@
<PackageReference Include="System.ServiceModel.Http" Version="4.8.1" /> <PackageReference Include="System.ServiceModel.Http" Version="4.8.1" />
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.8.1" /> <PackageReference Include="System.ServiceModel.NetTcp" Version="4.8.1" />
<PackageReference Include="System.ServiceModel.Security" Version="4.8.1" /> <PackageReference Include="System.ServiceModel.Security" Version="4.8.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -160,7 +160,7 @@ public class ChargeOrderService : BaseServices<ChargeOrder>
/// <summary> /// <summary>
/// /// 充电订单手动上传云平台
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>

@ -14,6 +14,8 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Service.Cloud.Client; using Service.Cloud.Client;
using Service.Execute; using Service.Execute;
using Service.Fire.Client;
using Service.Fire.Common;
using Service.FireControl.Client; using Service.FireControl.Client;
using Service.Plc.Client; using Service.Plc.Client;
using Service.RealTime; using Service.RealTime;
@ -186,9 +188,15 @@ if (AppSettingsHelper.GetBool("fire", "enable"))
FireControlMgr.Init(); FireControlMgr.Init();
} }
//中卫消防
if (AppSettingsHelper.GetBool("fireZw", "enable"))
{
FireMgr.ConnClient();
}
TaskInit.Init(); TaskInit.Init();
QuartzSchedulerFactory.Init(); QuartzSchedulerFactory.Init();
app.Lifetime.ApplicationStopping.Register(QuartzSchedulerFactory.Shutdown); app.Lifetime.ApplicationStopping.Register(QuartzSchedulerFactory.Shutdown);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
app.Run(); app.Run();

Loading…
Cancel
Save