diff --git a/Ems.CollectService.Analysis/BufferAnalysis.cs b/Ems.CollectService.Analysis/BufferAnalysis.cs new file mode 100644 index 0000000..98e721c --- /dev/null +++ b/Ems.CollectService.Analysis/BufferAnalysis.cs @@ -0,0 +1,838 @@ +using Ems.CollectService.Common; +using Ems.CollectService.Entity; +using Ems.CollectService.Entity.dto; +using Ems.CollectService.SqlSugarCore; +using NetTaste; +using NLog; +using SqlSugar; +using System; +using System.Data.SqlTypes; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Sockets; + +namespace Ems.CollectService.Analysis +{ + public sealed class BufferAnalysis + { + private Logger logger = LogManager.GetCurrentClassLogger(); + + private MsgUtil msgUtil = MsgUtil.Instance; + + //private SqlSugarClient baseService = SqlGenerator.GetMySqlInstance(); + + private static readonly Lazy lazy = new Lazy(() => new BufferAnalysis()); + + public static BufferAnalysis Instance + { + get + { + return lazy.Value; + } + } + + private BufferAnalysis() { } + + /// + /// 登录指令 + /// + /// + /// + /// + /// + public bool LoginMessageHandling(SocketClient client, byte[] buffer, int count) + { + byte[] array = new byte[2]; + var flag = ""; + try + { + string DeviceType = ""; + byte[] bDeviceType = new byte[1]; + byte[] bDeviceID = new byte[2]; + Array.Copy(buffer, 1, bDeviceType, 0, 1); + Array.Copy(buffer, 2, bDeviceID, 0, 2); + + DeviceType = Encoding.ASCII.GetString(buffer, 1, 1); + DeviceType += msgUtil.ConverToString(bDeviceID); + + flag = msgUtil.ConverToString(bDeviceType); + flag += msgUtil.ConverToString(bDeviceID); + + MessagePack messagePack = new MessagePack(); + messagePack.m_EnergyType = buffer[1]; + Array.Copy(buffer, 2, messagePack.m_Meteraddr, 0, 2); + Array.Copy(buffer, 4, messagePack.m_Msta, 0, 2); + messagePack.m_StartFlag = buffer[6]; + messagePack.m_MessageType = 161; + Array.Copy(buffer, 2, array, 0, 2); + string text = Encoding.ASCII.GetString(buffer, 1, 1) + msgUtil.ConverToString(array); + + if (SendMessageToClient(client, messagePack)) + { + logger.Info($"向客户端:{client.ID};地址:{client.GetIPPort()};回复登录指令成功"); + client.ResetID(flag.ToString()); + + if(client.ID.Length >= 4 ) + { + string clientId = string.Format("E{0}", client.ID.ToString().Substring(2, client.ID.ToString().Length - 2)); + UpdateCollectDeviceOnLineState(clientId, 1); + } + + return true; + } + + return false; + } + catch (Exception ex) + { + logger.Error($"LoginMessageHandling登录指令解析异常:{ex.Message}"); + return false; + } + } + + /// + /// 心跳指令 + /// + /// + /// + /// + /// + public bool HeartMessageHandlingAsync(SocketClient client, byte[] buffer, int count) + { + try + { + var flag = ""; + byte[] SendMessage = new byte[12]; + string DeviceType = ""; + byte[] bDeviceType = new byte[1]; + byte[] bDeviceID = new byte[2]; + Array.Copy(buffer, 1, bDeviceType, 0, 1); + Array.Copy(buffer, 2, bDeviceID, 0, 2); + + DeviceType = Encoding.ASCII.GetString(buffer, 1, 1); + DeviceType += msgUtil.ConverToString(bDeviceID); + + flag = msgUtil.ConverToString(bDeviceType); + flag += msgUtil.ConverToString(bDeviceID); + + logger.Debug($"收到客户端:{client.ID};地址:{client.GetIPPort()}心跳指令"); + MessagePack SendMessagePackInfo = new MessagePack(); + SendMessagePackInfo.m_EnergyType = buffer[1]; + Array.Copy(buffer, 2, SendMessagePackInfo.m_Meteraddr, 0, 2); + Array.Copy(buffer, 4, SendMessagePackInfo.m_Msta, 0, 2); + SendMessagePackInfo.m_StartFlag = buffer[6]; + SendMessagePackInfo.m_MessageType = (byte)CallbackSendData._HeartBeat; + if(SendMessageAsync(client, SendMessagePackInfo)) + { + logger.Debug($"向客户端:{client.ID};地址:{client.GetIPPort()};回复心跳指令成功"); + return true; + } + else + { + logger.Debug($"向客户端:{client.ID};地址:{client.GetIPPort()};回复心跳指令失败"); + return false; + } + } + catch (Exception ex) + { + logger.Error($"HeartMessageHandlingAsync心跳指令解析异常:{ex.Message}"); + return false; + } + } + + /// + /// 电力仪表 + /// + /// + /// + /// + /// + public void EDataMessageHandlingAsync(SocketClient socketClient, byte[] buffer, int count, int collectType) + { + int DataLength = 58 + 12; + var flag = "";//发送指定客户端标记 + string DeviceType = ""; + byte[] bDeviceType = new byte[1]; + byte[] bDeviceID = new byte[2]; + + string m_BarcodeGroupCount = "";//表长度16进制字符串 + byte[] b_BarcodeGroupCount = new byte[2]; + int i_BarcodeGroupCount = 0; + + try + { + //发送电力仪表应答帧 + MessagePack SendMessagePackInfo = new MessagePack(); + SendMessagePackInfo.m_EnergyType = buffer[1]; + Array.Copy(buffer, 2, SendMessagePackInfo.m_Meteraddr, 0, 2); + Array.Copy(buffer, 4, SendMessagePackInfo.m_Msta, 0, 2); + SendMessagePackInfo.m_StartFlag = buffer[6]; + SendMessagePackInfo.m_MessageType = (byte)CallbackSendData._ERealFlag; + SendMessageAsync(socketClient, SendMessagePackInfo); + + Array.Copy(buffer, 1, bDeviceType, 0, 1); + Array.Copy(buffer, 2, bDeviceID, 0, 2); + DeviceType = Encoding.ASCII.GetString(buffer, 1, 1); + flag = msgUtil.ConverToString(bDeviceType) + msgUtil.ConverToString(bDeviceID); + //LogInfo.Debug("》》》收到采集终端[" + DeviceType + "]下属电表数据指令!\r\n"); + Array.Copy(buffer, 8, b_BarcodeGroupCount, 0, 2); + m_BarcodeGroupCount = Convert.ToString(msgUtil.bytesToHexStr(b_BarcodeGroupCount, b_BarcodeGroupCount.Length));//获取仪表数量 + i_BarcodeGroupCount = Convert.ToInt32("0x" + m_BarcodeGroupCount, 16); + int iFirstMeterID = 10; + uint u_Control; //控制码 + byte[] b_MeterID = new byte[2]; + byte[] b_UA = new byte[4]; + byte[] b_UB = new byte[4]; + byte[] b_UC = new byte[4]; + byte[] b_IA = new byte[4]; + byte[] b_IB = new byte[4]; + byte[] b_IC = new byte[4]; + byte[] b_ZXYGZ = new byte[4]; + byte[] b_GLYS = new byte[4]; + float f_UA; + float f_UB; + float f_UC; + float f_IA; + float f_IB; + float f_IC; + float f_ZXYGZ; + float f_GLYS; + + #region 有功功率、无功功率参数定义 Add By Wenjy 2023-03-23 + byte[] b_YGGL = new byte[4]; + float f_YGGL; + byte[] b_WGGL = new byte[4]; + float f_WGGL; + #endregion + + for (int i = 0; i < i_BarcodeGroupCount / DataLength; i++) + { + int nParamCount = 11; //表参数个数 + RecordDnbInstant recordDnbInstant = new RecordDnbInstant(); + Array.Copy(buffer, iFirstMeterID, b_MeterID, 0, b_MeterID.Length); + + var collectDeviceId = Encoding.ASCII.GetString(buffer, 1, 1) + msgUtil.ConverToString(bDeviceID); + var MeterID_1 = "00" + Convert.ToInt32(b_MeterID[0]).ToString(); + MeterID_1 = MeterID_1.Substring(MeterID_1.Length - 2, 2); + var MeterID_2 = "00" + Convert.ToInt32(b_MeterID[1]).ToString(); + MeterID_2 = MeterID_2.Substring(MeterID_2.Length - 2, 2); + DeviceType = collectDeviceId + "_" + MeterID_1 + MeterID_2; + //LogInfo.Debug("MeterID_1:" + MeterID_1 + "b_MeterID[0]:" + Convert.ToInt32(b_MeterID[0]) + ";" + "MeterID_2:" + MeterID_2 + "b_MeterID[1]" + Convert.ToInt32(b_MeterID[1])); + logger.Info("》》》循环解析[" + (i + 1) + "]个电力仪表[" + DeviceType + "]电力数据!\r\n"); + + int i_pointer = 12 + i * DataLength; + recordDnbInstant.monitorId = DeviceType; + + if (i_pointer == 0) + { + return; + } + string logInfoStr = ""; + while (i_pointer < 10 + (i + 1) * DataLength) + { + + u_Control = (uint)(buffer[i_pointer] * 0x100 + buffer[i_pointer + 1]); + logInfoStr += $"仪表编号:{recordDnbInstant.monitorId}"; + switch (u_Control) + { + case EMS_COMM_PARAMS.AU: + //A相电压 + Array.Copy(buffer, i_pointer + 2 + 2, b_UA, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_UA, 2, 2); + f_UA = BitConverter.ToSingle(b_UA.Reverse().ToArray(), 0); + + logInfoStr += $";电力仪表的A相电压:{f_UA}"; + if (double.IsNaN(f_UA)) + { + //此处判断a为NaN + recordDnbInstant.vA = 0; + } + else + { + recordDnbInstant.vA = Convert.ToDecimal(f_UA); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.BU: + //B相电压 + Array.Copy(buffer, i_pointer + 2 + 2, b_UB, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_UB, 2, 2); + f_UB = BitConverter.ToSingle(b_UB.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的B相电压:{f_UB}"; + if (double.IsNaN(f_UB)) + { + //此处判断a为NaN + recordDnbInstant.vB = 0; + } + else + { + recordDnbInstant.vB = Convert.ToDecimal(f_UB); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.CU: + //C相电压 + Array.Copy(buffer, i_pointer + 2 + 2, b_UC, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_UC, 2, 2); + f_UC = BitConverter.ToSingle(b_UC.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的C相电压:{f_UC}"; + if (double.IsNaN(f_UC)) + { + //此处判断a为NaN + recordDnbInstant.vC = 0; + } + else + { + recordDnbInstant.vC = Convert.ToDecimal(f_UC); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.AI: + //A相电流 + Array.Copy(buffer, i_pointer + 2 + 2, b_IA, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_IA, 2, 2); + f_IA = BitConverter.ToSingle(b_IA.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的A相电流:{f_IA}"; + if (double.IsNaN(f_IA)) + { + //此处判断a为NaN + recordDnbInstant.iA = 0; + } + else + { + recordDnbInstant.iA = Convert.ToDecimal(f_IA); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.BI: + //B相电流 + Array.Copy(buffer, i_pointer + 2 + 2, b_IB, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_IB, 2, 2); + f_IB = BitConverter.ToSingle(b_IB.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的B相电流:{f_IB}"; + if (double.IsNaN(f_IB)) + { + //此处判断a为NaN + recordDnbInstant.iB = 0; + } + else + { + recordDnbInstant.iB = Convert.ToDecimal(f_IB); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.CI: + //C相电流 + Array.Copy(buffer, i_pointer + 2 + 2, b_IC, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_IC, 2, 2); + f_IC = BitConverter.ToSingle(b_IC.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的C相电流:{f_IC}"; + if (double.IsNaN(f_IC)) + { + //此处判断a为NaN + recordDnbInstant.iC = 0; + } + else + { + recordDnbInstant.iC = Convert.ToDecimal(f_IC); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.ZXYGZ: + //正向有功总 + Array.Copy(buffer, i_pointer + 2 + 2, b_ZXYGZ, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_ZXYGZ, 2, 2); + f_ZXYGZ = BitConverter.ToSingle(b_ZXYGZ.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的正向有功总:{f_ZXYGZ}"; + if (double.IsNaN(f_ZXYGZ)) + { + //此处判断a为NaN + recordDnbInstant.zxyg = 0; + } + else + { + recordDnbInstant.zxyg = Convert.ToDecimal(f_ZXYGZ); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.GLYS: + //功率因数 + Array.Copy(buffer, i_pointer + 2 + 2, b_GLYS, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_GLYS, 2, 2); + f_GLYS = BitConverter.ToSingle(b_GLYS.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的功率因数:{f_GLYS}"; + if (double.IsNaN(f_GLYS)) + { + //此处判断a为NaN + recordDnbInstant.glys = 0; + } + else + { + recordDnbInstant.glys = Convert.ToDecimal(f_GLYS); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.YGGL: + Array.Copy(buffer, i_pointer + 2 + 2, b_YGGL, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_YGGL, 2, 2); + f_YGGL = BitConverter.ToSingle(b_YGGL.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的有功功率:{f_YGGL}"; + if (double.IsNaN(f_YGGL)) + { + //此处判断a为NaN + recordDnbInstant.activePower = 0; + } + else + { + recordDnbInstant.activePower = Convert.ToDecimal(f_YGGL / 1000); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.WGGL: + Array.Copy(buffer, i_pointer + 2 + 2, b_WGGL, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_WGGL, 2, 2); + f_WGGL = BitConverter.ToSingle(b_WGGL.Reverse().ToArray(), 0); + logInfoStr += $";电力仪表的无功功率:{f_WGGL}"; + if (double.IsNaN(f_WGGL)) + { + //此处判断a为NaN + recordDnbInstant.reactivePower = 0; + } + else + { + recordDnbInstant.reactivePower = Convert.ToDecimal(f_WGGL); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.CJSJ: + //采集时间 + string strDateTime = "20" + buffer[i_pointer + 2 + 5].ToString("x2") + + "-" + buffer[i_pointer + 2 + 4].ToString("x2") + + "-" + buffer[i_pointer + 2 + 3].ToString("x2") + + " " + buffer[i_pointer + 2 + 2].ToString("x2") + + ":" + buffer[i_pointer + 2 + 1].ToString("x2") + + ":" + buffer[i_pointer + 2].ToString("x2"); + logInfoStr += $";终端时间:{strDateTime}"; + recordDnbInstant.collectTime = Convert.ToDateTime(strDateTime); + i_pointer += 8; + nParamCount--; + break; + } + } + if (nParamCount == 0) + { + logger.Info($"仪表:{recordDnbInstant.monitorId};解析完成数据:{logInfoStr}"); + recordDnbInstant.collectType = collectType; + recordDnbInstant.recordTime = DateTime.Now; + //var info = await baseService.Insertable(recordDnbInstant).ExecuteCommandAsync(); + var info = SqlSugarHelper.Db.Insertable(recordDnbInstant).ExecuteCommand(); + if (info > 0) + { + logger.Info($"仪表:{recordDnbInstant.monitorId}数据保存成功"); + } + } + iFirstMeterID += 70; + }//end for + + + } + catch (Exception ex) + { + logger.Error($"EDataMessageHandlingAsync电力仪表数据解析异常:{ex.Message}"); + } + + } + + /// + /// 水表数据 + /// + /// + /// + /// + /// + public void SDataMessageHandling(SocketClient socketClient, byte[] buffer, int length, int collectType) + { + int DataLength = 58; + var flag = "";//发送指定客户端标记 + string DeviceType = ""; + byte[] bDeviceType = new byte[1]; + byte[] bDeviceID = new byte[2]; + + string m_BarcodeGroupCount = "";//表长度16进制字符串 + byte[] b_BarcodeGroupCount = new byte[2]; + int i_BarcodeGroupCount = 0; + + try + { + //发送蒸汽、压缩空气、水仪表应答帧 + MessagePack SendMessagePackInfo = new MessagePack(); + SendMessagePackInfo.m_EnergyType = buffer[1]; + Array.Copy(buffer, 2, SendMessagePackInfo.m_Meteraddr, 0, 2); + Array.Copy(buffer, 4, SendMessagePackInfo.m_Msta, 0, 2); + SendMessagePackInfo.m_StartFlag = buffer[6]; + SendMessagePackInfo.m_MessageType = (byte)CallbackSendData._SRealFlag; + SendMessageAsync(socketClient, SendMessagePackInfo); + + Array.Copy(buffer, 1, bDeviceType, 0, 1); + Array.Copy(buffer, 2, bDeviceID, 0, 2); + DeviceType = Encoding.ASCII.GetString(buffer, 1, 1); + flag = msgUtil.ConverToString(bDeviceType) + msgUtil.ConverToString(bDeviceID); + //LogInfo.Debug("》》》收到采集终端[" + DeviceType + "]下属电表数据指令!\r\n"); + Array.Copy(buffer, 8, b_BarcodeGroupCount, 0, 2); + m_BarcodeGroupCount = Convert.ToString(msgUtil.bytesToHexStr(b_BarcodeGroupCount, b_BarcodeGroupCount.Length));//获取仪表数量 + i_BarcodeGroupCount = Convert.ToInt32("0x" + m_BarcodeGroupCount, 16); + int iFirstMeterID = 10; + uint u_Control; //控制码 + byte[] b_MeterID = new byte[2]; + byte[] b_Press = new byte[4]; + byte[] b_Temperature = new byte[4]; + byte[] b_Frequency = new byte[4]; + byte[] b_FluxInstantValue = new byte[4]; + byte[] b_FluxEyeableTotalValue = new byte[4]; + byte[] b_HeatInstantValue = new byte[4]; + byte[] b_HeatToftalValue = new byte[4]; + byte[] b_Density = new byte[4]; + float f_Press; + float f_Temperature; + float f_Frequency; + float f_FluxInstantValue; + float f_FluxEyeableTotalValue; + float f_HeatInstantValue; + float f_HeatToftalValue; + float f_Density; + + for (int i = 0; i < i_BarcodeGroupCount / DataLength; i++) + { + int nParamCount = 9; //表参数个数 + RecordWaterInstant recordWaterInstant = new RecordWaterInstant(); + Array.Copy(buffer, iFirstMeterID, b_MeterID, 0, b_MeterID.Length); + + + var collectDeviceId = Encoding.ASCII.GetString(buffer, 1, 1) + msgUtil.ConverToString(bDeviceID); + var MeterID_1 = "00" + Convert.ToInt32(b_MeterID[0]).ToString(); + MeterID_1 = MeterID_1.Substring(MeterID_1.Length - 2, 2); + var MeterID_2 = "00" + Convert.ToInt32(b_MeterID[1]).ToString(); + MeterID_2 = MeterID_2.Substring(MeterID_2.Length - 2, 2); + DeviceType = collectDeviceId + "_" + MeterID_1 + MeterID_2; + + logger.Info("》》》循环解析第[" + (i + 1) + "]个蒸汽、压缩空气、水仪表[" + DeviceType + "]数据!\r\n"); + + int i_pointer = 12 + i * DataLength; + recordWaterInstant.monitorId = DeviceType; + if (i_pointer == 0) + { + return; + } + string logInfoStr = ""; + while (i_pointer < 10 + (i + 1) * DataLength) + { + u_Control = (uint)(buffer[i_pointer] * 0x100 + buffer[i_pointer + 1]); + logInfoStr+=$"仪表编号:{recordWaterInstant.monitorId}"; + switch (u_Control) + { + case EMS_COMM_PARAMS.Press: + //压力值 + Array.Copy(buffer, i_pointer + 2 + 2, b_Press, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_Press, 2, 2); + f_Press = BitConverter.ToSingle(b_Press.Reverse().ToArray(), 0); + logInfoStr += $";压力值:{f_Press}"; + if (float.IsNaN(f_Press)) + { + //recordWaterInstant.press = 0; + + } + else + { + //recordWaterInstant.press = Convert.ToDecimal(f_Press); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.STemperature: + //温度值 + Array.Copy(buffer, i_pointer + 2 + 2, b_Temperature, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_Temperature, 2, 2); + f_Temperature = BitConverter.ToSingle(b_Temperature.Reverse().ToArray(), 0); + logInfoStr += $";温度值:{f_Temperature}"; + if (float.IsNaN(f_Temperature)) + { + //recordWaterInstant.temperature = 0; + + } + else + { + //recordWaterInstant.temperature = Convert.ToDecimal(f_Temperature); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.Frequency: + //频率值 + Array.Copy(buffer, i_pointer + 2 + 2, b_Frequency, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_Frequency, 2, 2); + f_Frequency = BitConverter.ToSingle(b_Frequency.Reverse().ToArray(), 0); + logInfoStr += $";频率值:{f_Frequency}"; + if (float.IsNaN(f_Frequency)) + { + //recordWaterInstant.frequency = 0; + + } + else + { + //recordWaterInstant.frequency = Convert.ToDecimal(f_Frequency); + } + + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.FluxInstantValue: + //瞬时流值 + Array.Copy(buffer, i_pointer + 2 + 2, b_FluxInstantValue, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_FluxInstantValue, 2, 2); + f_FluxInstantValue = BitConverter.ToSingle(b_FluxInstantValue.Reverse().ToArray(), 0); + logInfoStr += $";瞬时流值:{f_FluxInstantValue}"; + if (float.IsNaN(f_FluxInstantValue)) + { + recordWaterInstant.fluxFlow = 0; + + } + else + { + recordWaterInstant.fluxFlow = Convert.ToDecimal(f_FluxInstantValue); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.FluxEyeableTotalValue: + //累计流量值 + Array.Copy(buffer, i_pointer + 2 + 2, b_FluxEyeableTotalValue, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_FluxEyeableTotalValue, 2, 2); + f_FluxEyeableTotalValue = BitConverter.ToSingle(b_FluxEyeableTotalValue.Reverse().ToArray(), 0); + + logInfoStr += $";累计流量值:{f_FluxEyeableTotalValue}"; + if (float.IsNaN(f_FluxEyeableTotalValue)) + { + recordWaterInstant.waterFlow = 0; + + } + else + { + recordWaterInstant.waterFlow = Convert.ToDecimal(f_FluxEyeableTotalValue); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.HeatInstantValue: + //瞬时热量 + Array.Copy(buffer, i_pointer + 2 + 2, b_HeatInstantValue, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_HeatInstantValue, 2, 2); + f_HeatInstantValue = BitConverter.ToSingle(b_HeatInstantValue.Reverse().ToArray(), 0); + logInfoStr += $";瞬时热量:{f_HeatInstantValue}"; + if (float.IsNaN(f_HeatInstantValue)) + { + //recordWaterInstant.heatInstantValue = 0; + + } + else + { + //recordWaterInstant.heatInstantValue = Convert.ToDecimal(f_HeatInstantValue); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.HeatToftalValue: + //累计热量值 + Array.Copy(buffer, i_pointer + 2 + 2, b_HeatToftalValue, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_HeatToftalValue, 2, 2); + f_HeatToftalValue = BitConverter.ToSingle(b_HeatToftalValue.Reverse().ToArray(), 0); + logInfoStr += $";累计热量值:{f_HeatToftalValue}"; + if (float.IsNaN(f_HeatToftalValue)) + { + //recordWaterInstant.heatToftalValue = 0; + + } + else + { + //recordWaterInstant.heatToftalValue = Convert.ToDecimal(f_HeatToftalValue); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.Density: + //密度值 + Array.Copy(buffer, i_pointer + 2 + 2, b_Density, 0, 2); + Array.Copy(buffer, i_pointer + 2, b_Density, 2, 2); + f_Density = BitConverter.ToSingle(b_Density.Reverse().ToArray(), 0); + logInfoStr += $";密度值:{f_Density}"; + if (float.IsNaN(f_Density)) + { + //recordWaterInstant.density = 0; + + } + else + { + //recordWaterInstant.density = Convert.ToDecimal(f_Density); + } + i_pointer += 6; + nParamCount--; + break; + case EMS_COMM_PARAMS.CJSJ: + //采集时间 + string strDateTime = "20" + buffer[i_pointer + 2 + 5].ToString("x2") + + "-" + buffer[i_pointer + 2 + 4].ToString("x2") + + "-" + buffer[i_pointer + 2 + 3].ToString("x2") + + " " + buffer[i_pointer + 2 + 2].ToString("x2") + + ":" + buffer[i_pointer + 2 + 1].ToString("x2") + + ":" + buffer[i_pointer + 2].ToString("x2"); + logInfoStr += $";终端时间:{strDateTime}"; + recordWaterInstant.collectTime = Convert.ToDateTime(strDateTime); + i_pointer += 8; + nParamCount--; + break; + } + } + if (nParamCount == 0) + { + logger.Info($"仪表:{recordWaterInstant.monitorId};解析完成数据:{logInfoStr}"); + recordWaterInstant.collectType = collectType; + recordWaterInstant.recordTime = DateTime.Now; + //var info = await baseService.Insertable(recordWaterInstant).ExecuteCommandAsync(); + + var info = SqlSugarHelper.Db.Insertable(recordWaterInstant).ExecuteCommand(); + if (info > 0) + { + logger.Info($"仪表:{recordWaterInstant.monitorId}数据保存成功"); + } + } + iFirstMeterID += 58; + }//end for + + + } + catch (Exception ex) + { + logger.Info($"SDataMessageHandling水表数据解析异常:{ex}"); + } + } + + /// + /// 修改终端连接状态 + /// + /// 终端编号 + /// 终端状态:0-离线;1-在线 + public void UpdateCollectDeviceOnLineState(string collectId, int onLineFlag) + { + try + { + int result = SqlSugarHelper.Db.Updateable() + .SetColumns(it => new BaseCollectDeviceInfo() { OnlineState = onLineFlag, UpdateTime = DateTime.Now }).Where(it => it.CollectDeviceId == collectId).ExecuteCommand(); + if (result > 0) + { + logger.Trace(string.Format("》》》终端:{0};状态修改成功:{1}", collectId, onLineFlag == 1 ? "在线" : "离线")); + + } + else + { + logger.Trace(string.Format("终端:{0};状态修改失败", collectId)); + } + } + catch (Exception ex) + { + logger.Error(string.Format("UpdateCollectDeviceOnLineState修改终端状态异常:{0}", ex.Message)); + + } + } + + public bool SendMessageToClient(SocketClient client, MessagePack pMessagePack) + { + ushort num = 0; + try + { + byte[] SendBuffer = new byte[12]; + SendBuffer[num] = pMessagePack.m_BeginChar; + num = (ushort)(num + 1); + SendBuffer[num] = pMessagePack.m_EnergyType; + num = (ushort)(num + 1); + Array.Copy(pMessagePack.m_Meteraddr, 0, SendBuffer, num, pMessagePack.m_Meteraddr.Length); + num = (ushort)(num + 2); + Array.Copy(pMessagePack.m_Msta, 0, SendBuffer, num, pMessagePack.m_Msta.Length); + num = (ushort)(num + 2); + SendBuffer[num] = pMessagePack.m_StartFlag; + num = (ushort)(num + 1); + SendBuffer[num] = pMessagePack.m_MessageType; + num = (ushort)(num + 1); + Array.Copy(pMessagePack.m_PackLen, 0, SendBuffer, num, pMessagePack.m_PackLen.Length); + num = (ushort)(num + 2); + pMessagePack.m_Verify = MsgUtil.CalculateVerify(SendBuffer, SendBuffer.Length - 1)[0]; + SendBuffer[num] = pMessagePack.m_Verify; + num = (ushort)(num + 1); + SendBuffer[num] = pMessagePack.m_EndChar; + logger.Info($"向客户端:{client.ID};地址:{client.GetIPPort()};发送终端消息:{msgUtil.bytesToHexStr(SendBuffer, SendBuffer.Length)}"); + + client.SendAsync(SendBuffer); + return true; + } + catch (Exception ex) + { + logger.Error($"SendMessageToClient异常:{ex.Message}"); + return false; + } + } + + public bool SendMessageAsync(SocketClient client, MessagePack pMessagePack) + { + UInt16 iPos = 0; + string flag = ""; + try + { + byte[] SendBuffer = new byte[12]; + SendBuffer[iPos] = pMessagePack.m_BeginChar; + iPos += 1; + SendBuffer[iPos] = pMessagePack.m_EnergyType; + iPos += 1; + Array.Copy(pMessagePack.m_Meteraddr, 0, SendBuffer, iPos, pMessagePack.m_Meteraddr.Length); + iPos += 2; + Array.Copy(pMessagePack.m_Msta, 0, SendBuffer, iPos, pMessagePack.m_Msta.Length); + iPos += 2; + SendBuffer[iPos] = pMessagePack.m_StartFlag; + iPos += 1; + SendBuffer[iPos] = pMessagePack.m_MessageType; + iPos += 1; + Array.Copy(pMessagePack.m_PackLen, 0, SendBuffer, iPos, pMessagePack.m_PackLen.Length); + iPos += 2; + pMessagePack.m_Verify = MsgUtil.CalculateVerify(SendBuffer, SendBuffer.Length - 1)[0]; + SendBuffer[iPos] = pMessagePack.m_Verify; + iPos += 1; + SendBuffer[iPos] = pMessagePack.m_EndChar; + flag = pMessagePack.m_EnergyType.ToString("X2"); + flag += msgUtil.ConverToString(pMessagePack.m_Meteraddr); + client.Send(SendBuffer); + logger.Info($"向客户端:{client.ID};地址:{client.GetIPPort()};发送终端消息:{msgUtil.bytesToHexStr(SendBuffer, SendBuffer.Length)}"); + return true; + } + catch (Exception ex) + { + logger.Error($"SendMessageAsync异常:{ex.Message}"); + return false; + } + } + } +} diff --git a/Ems.CollectService.Analysis/Ems.CollectService.Analysis.csproj b/Ems.CollectService.Analysis/Ems.CollectService.Analysis.csproj new file mode 100644 index 0000000..8d0a7f3 --- /dev/null +++ b/Ems.CollectService.Analysis/Ems.CollectService.Analysis.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/Ems.CollectService.Common/Ems.CollectService.Common.csproj b/Ems.CollectService.Common/Ems.CollectService.Common.csproj new file mode 100644 index 0000000..d699c23 --- /dev/null +++ b/Ems.CollectService.Common/Ems.CollectService.Common.csproj @@ -0,0 +1,23 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + Never + + + PreserveNewest + + + + diff --git a/Ems.CollectService.Common/INIFile.cs b/Ems.CollectService.Common/INIFile.cs new file mode 100644 index 0000000..5686db0 --- /dev/null +++ b/Ems.CollectService.Common/INIFile.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Ems.CollectService.Common +{ + /// + /// 配置操作类 + /// + public class INIFile + { + public string path; + + public INIFile(string INIPath) + { + path = INIPath; + } + + [DllImport("kernel32")] + private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); + + [DllImport("kernel32")] + private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); + + + [DllImport("kernel32")] + private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath); + + + /// + /// 写INI文件 + /// + /// + /// + /// + public void IniWriteValue(string Section, string Key, string Value) + { + WritePrivateProfileString(Section, Key, Value, this.path); + } + + /// + /// 读取INI文件 + /// + /// + /// + /// + public string IniReadValue(string Section, string Key) + { + StringBuilder temp = new StringBuilder(255); + int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path); + return temp.ToString(); + } + public byte[] IniReadValues(string section, string key) + { + byte[] temp = new byte[255]; + int i = GetPrivateProfileString(section, key, "", temp, 255, this.path); + return temp; + + } + + + /// + /// 删除ini文件下所有段落 + /// + public void ClearAllSection() + { + IniWriteValue(null, null, null); + } + /// + /// 删除ini文件下personal段落下的所有键 + /// + /// + public void ClearSection(string Section) + { + IniWriteValue(Section, null, null); + } + } +} diff --git a/Ems.CollectService.Common/JsonChange.cs b/Ems.CollectService.Common/JsonChange.cs new file mode 100644 index 0000000..62a1b71 --- /dev/null +++ b/Ems.CollectService.Common/JsonChange.cs @@ -0,0 +1,112 @@ +using Nancy.Json; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; +using System.Xml.Linq; + +namespace Ems.CollectService.Common +{ + public sealed class JsonChange + { + + private static readonly Lazy lazy = new Lazy(() => new JsonChange()); + + public static JsonChange Instance + { + get + { + return lazy.Value; + } + } + + private JsonChange() { } + + /// + /// Model 实体转json + /// + /// 可以是单个实体,也可是实体集(即:ToList()) + /// + public string ModeToJson(object Model) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + try + { + string str = serializer.Serialize(Model); + return str; + } + catch (Exception) + { + return ""; + } + } + + /// + /// json实体转Model + /// + /// + /// + /// + public T JsonToMode(string jsonStr) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + try + { + var info = serializer.Deserialize(jsonStr); + return info; + } + catch (Exception) + { + return default(T); + } + } + + /// + /// object转dictionary + /// + /// + /// + public Dictionary objectToDictionary(string jsonData) + { + Dictionary result = new Dictionary(); + + var inf = JsonConvert.DeserializeObject>(jsonData); + + foreach (KeyValuePair item in inf) + { + if (item.Value != null) + { + var type = item.Value.GetType(); + if (type == typeof(JObject)) + { + var info = objectToDictionary(JsonConvert.SerializeObject(item.Value)); + foreach (KeyValuePair ite in info) + { + result.Add(ite.Key, ite.Value); + } + continue; + } + else if (type == typeof(JArray)) + { + JArray array = (JArray)item.Value; + var info = objectToDictionary(JsonConvert.SerializeObject(array[0])); + foreach (KeyValuePair ite in info) + { + result.Add(item.Key + ite.Key, ite.Value); + } + continue; + } + } + + result.Add(item.Key, item.Value); + } + + return result; + } + + + + } +} \ No newline at end of file diff --git a/Ems.CollectService.Common/MsgUtil.cs b/Ems.CollectService.Common/MsgUtil.cs new file mode 100644 index 0000000..b207135 --- /dev/null +++ b/Ems.CollectService.Common/MsgUtil.cs @@ -0,0 +1,510 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace Ems.CollectService.Common +{ + /// + /// 工具类 + /// + public sealed class MsgUtil + { + + private static readonly Lazy lazy = new Lazy(() => new MsgUtil()); + + public static MsgUtil Instance + { + get + { + return lazy.Value; + } + } + + private MsgUtil() { } + + #region 数据解析公共方法 + /// + /// 字节数组转换成结构体 + /// + /// + /// + /// + /// + public static object BytesToStruct(byte[] buf, int len, Type type) + { + object rtn; + IntPtr buffer = Marshal.AllocHGlobal(len); + Marshal.Copy(buf, 0, buffer, len); + try + { + rtn = Marshal.PtrToStructure(buffer, type); + Marshal.FreeHGlobal(buffer); + } + catch (Exception) + { + return null; + } + return rtn; + } + + public string StringToHexString(string s, Encoding encode) + { + + byte[] b = encode.GetBytes(s); //按照指定编码将string编程字节数组 + string result = string.Empty; + for (int i = 0; i < b.Length; i++) //逐字节变为16进制字符,以%隔开 + { + result += "%" + Convert.ToString(b[i], 16); + } + return result; + } + + //// + /// 结构体转byte数组 + /// + /// 要转换的结构体 + /// 转换后的byte数组 + public static byte[] StructToBytes(object structObj) + { + //得到结构体的大小 + int size = Marshal.SizeOf(structObj); + //创建byte数组 + byte[] bytes = new byte[size]; + //分配结构体大小的内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(size); + //将结构体拷到分配好的内存空间 + Marshal.StructureToPtr(structObj, structPtr, false); + //从内存空间拷到byte数组 + Marshal.Copy(structPtr, bytes, 0, size); + //释放内存空间 + Marshal.FreeHGlobal(structPtr); + //返回byte数组 + return bytes; + } + + + #endregion + #region 消息验证方法 + + /// + /// CS和校验 + /// + /// + /// + public byte Check_CS(byte[] Abyte) + { + byte result = new byte(); + try + { + int num = 0; + for (int i = 0; i < Abyte.Length; i++) + { + num = (num + Abyte[i]) % 256; + } + result = (byte)num; + } + catch + { + result = 0; + } + return result; + } + + /// + /// BCC异或取反校验 + /// + /// + /// + public string getBCC(byte[] data) + { + String ret = ""; + byte[] BCC = new byte[1]; + for (int i = 0; i < data.Length; i++) + { + BCC[0] = (byte)(BCC[0] ^ data[i]); + } + String hex = ((~BCC[0]) & 0xFF).ToString("X");//取反操作 + if (hex.Length == 1) + { + hex = '0' + hex; + } + ret += hex.ToUpper(); + return ret; + } + + static int BytesToInt(byte[] b, int length) + { + int temp = 0; + for (int i = 0; i <= length - 1 && i < 4; i++) + { + temp += (int)(b[i] << (i * 8)); + } + return temp; + } + + public static byte[] CalculateVerify(byte[] pMessage, int iLength) + { + UInt16 i; + int iVerify = 0; + + iVerify = pMessage[0]; + for (i = 0; i < iLength - 1; i++) + { + iVerify = iVerify + pMessage[i + 1]; + } + return BitConverter.GetBytes(Convert.ToUInt16(iVerify)); + } + #endregion + public byte[] HexStrTorbytes(string strHex)//e.g. " 01 01" ---> { 0x01, 0x01} + { + strHex = strHex.Replace(" ", ""); + if ((strHex.Length % 2) != 0) + strHex += " "; + byte[] returnBytes = new byte[strHex.Length / 2]; + for (int i = 0; i < returnBytes.Length; i++) + returnBytes[i] = Convert.ToByte(strHex.Substring(i * 2, 2), 16); + return returnBytes; + } + + /// + /// 将字符串强制转换成int,转换失败则返回0 + /// + /// + /// + public int ParseToInt(string str) + { + int returnInt = 0; + + if (str == null || str.Trim().Length < 1) + { + return returnInt; + } + + if (int.TryParse(str, out returnInt)) + { + return returnInt; + } + else + { + return 0; + } + } + + public byte[] HexToString(string Str) + { + byte[] str = new byte[Str.Length / 2]; + for (int i = 0; i < str.Length; i++) + { + int temp = Convert.ToInt32(Str.Substring(i * 2, 2), 16); + str[i] = (byte)temp; + } + return str; + } + public string ConverToString(byte[] data) + { + string str; + StringBuilder stb = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + if ((int)data[i] > 15) + { + stb.Append(Convert.ToString(data[i], 16).ToUpper()); //添加字符串 + } + else //如果是小于0F需要加个零 + { + stb.Append("0" + Convert.ToString(data[i], 16).ToUpper()); + } + } + str = stb.ToString(); + return str; + } + + public string bytesToHexStr(byte[] bytes, int iLen) + { + StringBuilder sb = new StringBuilder(); + if (bytes != null) + { + for (int i = 0; i < iLen; i++) + { + sb.Append(bytes[i].ToString("X2")); + } + } + return sb.ToString(); + } + + /// + /// 从十进制转换到十六进制 + /// + /// + /// + public string Ten2Hex(string ten) + { + ulong tenValue = Convert.ToUInt64(ten); + ulong divValue, resValue; + string hex = ""; + do + { + //divValue = (ulong)Math.Floor(tenValue / 16); + + divValue = (ulong)Math.Floor((decimal)(tenValue / 16)); + + resValue = tenValue % 16; + hex = tenValue2Char(resValue) + hex; + tenValue = divValue; + } + while (tenValue >= 16); + if (tenValue != 0) + hex = tenValue2Char(tenValue) + hex; + return hex; + } + + public static string tenValue2Char(ulong ten) + { + switch (ten) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + return ten.ToString(); + case 10: + return "A"; + case 11: + return "B"; + case 12: + return "C"; + case 13: + return "D"; + case 14: + return "E"; + case 15: + return "F"; + default: + return ""; + } + } + } + + #region 消息公用的头尾 + + /// + /// 能源通讯协议结构体 + /// + + public enum CallbackSendData + { + _LoginIn = 0XA1, + _SetTime = 0X08, + _HeartBeat = 0XA4, + _ERealFlag = 0XB3, + _SRealFlag = 0XB4, + _TRealFlag = 0XB5, + _IRealFlag = 0XB6, + + _EFlag = 0XC3, + _SFlag = 0XC4, + _TFlag = 0XC5, + _IFlag = 0XC6, + } + public struct struFrame + { + //帧开始 + public byte BeginChar_State; + //采集器类型 + public byte Collection_Type; + //采集器地址 + public byte[] Collection_Addr; + //命令序列号 + public byte[] Command_Id; + //起始符 + public byte StartChar_State; + //控制码 + public byte Ctrl_State; + //数据长度 + public byte[] DataLen_State; + //数据域 + public byte[] Data_State; + //校验码 + public byte CSChar_State; + //结束符 + public byte EndChar_State; + //终端类型 + public byte flagDTN; + //逻辑编号 + public byte[] addrDNL; + //主站地址 + public byte flagMSTA; + //帧内序号 + public byte flagISEQ; + //帧序号 + public byte flagFSEQ; + //控制码 + public byte flagCtrl; + //传送方向 + public byte flagCtrlD; + //异常标志 + public byte flagCtrlE; + //功能标志 + public byte flagCtrlF; + //数据长度 + public int lenData; + //数据字符串 + public byte[] strData; + + public object userData; + public string tName; + + public object userData2; + //public bool isCtrl; + //public bool isData; + + public bool isTimeCorrectting; + + }; + + + + /// + /// 头文件 + /// + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct Head + { + public byte start; //起始 + public short addr; //软件地址 + public byte mstaseq; //主站地址与命令序号 + public byte control; //控制码 + public short length; //数据长度 + } + /// + /// 结尾 + /// + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct Tail + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] verifica; //校验码 + public byte end; //结束码 + } + #endregion + #region 与MES通讯协议 + //识别一条EPC数据 125+3 + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct ReadEPC + { + public Head head; + public int num;//合并编号 + public Tail tail; + } + + /// + /// 写入反馈 125+5 + /// + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct RecWrite + { + public Head head; + public int num;//合并编号 + public byte state;//1成功,0失败,2写失败,读成功 + public Tail tail; + } + // + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + + public struct RecDataCell + { + public byte len;//Data长度 + public byte[] data;//len 长度个字节数据 + } + /// + /// 自报数据 125+6 + /// + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + + public struct RecAutoData + { + public Head head; + public int num;//合并编号 + public RecDataCell recDatas;//自报数据 + public Tail tail; + } + + /// + ///心跳 101 + /// + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + + public struct Heart + { + public Head head; + public Tail tail; + } + #endregion + #region 与上层应用层 消息指令 + /// + /// 收到的消息指令 + /// + enum RecAppMsgType + { + _ReadEpc = 125 + 3, + _ReadData = 125 + 4, + _WirteData = 125 + 5, + _AutoSendData, + + _HeartBeat = 101, + _ReadEquipState = 125 + 102, + _SendGetSoftState = 125 + 103, + + } + + /// + /// 发送的消息指令 + /// + enum RetAppMsgType + { + _RetEpc = 125 + 3, + _RetData = 125 + 4, + _RetDataBack = 125 + 5, + _RetAutoSendData, + + _RetEquipState = 125 + 102, + _RetGetSoftState = 125 + 103, + } + #endregion + + + #region 与设备层 适配层消息指令 + //收到设备层消息 + enum RecEquipMsgType + { + _GetEquipInfo = 0X01, //收到适配软件所需设备信息 + _GetSensor = 0x02, //收到适配软件传感器信息 + _EPCinfo = 0x03, //收到设备返回数据 将数据发送MES 并保存数据库 + _SendData = 0x04, //收到读取到的数据 收到数据后,上传给MES,并保存数据库 + _RecGetData = 0x05, //收到写入的数据是否成功反馈 + _RecAutoData = 0x06, //收到设备自报数据 + + _HeartBeat = 101, //心跳 + _EquipState, //设备状态 + } + //发送给设备层消息 + enum RetEquipMsgType + { + _RetEquipInfo = 0X01, //获取适配软件所需设备信息 + _RetSensor = 0x02, //获取适配软件传感器信息 + _GetEPCinfo = 0x03, //向设备发送命令,识别EPC数据 + _GetData = 0x04, //向设备发送命令,读取数据 + _WirteData = 0x05, //向设备发送命令,写入数据 + _RetAutoData = 0x06, //收到设备自爆数据反馈 + + } + #endregion +} diff --git a/Ems.CollectService.Common/NLog.config b/Ems.CollectService.Common/NLog.config new file mode 100644 index 0000000..7ce6fdd --- /dev/null +++ b/Ems.CollectService.Common/NLog.config @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ems.CollectService.Common/StringChange.cs b/Ems.CollectService.Common/StringChange.cs new file mode 100644 index 0000000..4c80e2f --- /dev/null +++ b/Ems.CollectService.Common/StringChange.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; + +namespace Ems.CollectService.Common +{ + public sealed class StringChange + { + + private static readonly Lazy lazy = new Lazy(() => new StringChange()); + + public static StringChange Instance + { + get + { + return lazy.Value; + } + } + + private StringChange() { } + + #region 数据类型转换函数 + + /// + /// 将字符串强制转换成int,转换失败则返回0 + /// + /// + /// + public int ParseToInt(string str) + { + int returnInt = 0; + if (str == null || str.Trim().Length < 1) + { + return returnInt; + } + if (int.TryParse(str, out returnInt)) + { + return returnInt; + } + else + { + return 0; + } + } + + /// + /// char数组转Array + /// + /// + /// + /// + public string CharArrayToString(char[] cha, int len) + { + string str = ""; + for (int i = 0; i < len; i++) + { + str += string.Format("{0}", cha[i]); + } + + return str; + } + + public string HexStringToASCII(string hexstring) + { + byte[] buff = new byte[(hexstring.Length - 8) / 2]; + int index = 0; + for (int i = 0; i < hexstring.Length - 8; i += 2) + { + buff[index] = Convert.ToByte(hexstring.Substring(i, 2), 16); + ++index; + } + string result = Encoding.Default.GetString(buff); + return result; + } + public byte[] Swap16Bytes(byte[] OldU16) + { + byte[] ReturnBytes = new byte[2]; + ReturnBytes[1] = OldU16[0]; + ReturnBytes[0] = OldU16[1]; + return ReturnBytes; + } + + public bool CompareBytes(byte[] byteA, byte[] byteB, int iLen) + { + for (int i = 0; i < iLen; i++) + { + if (byteA[i] != byteB[i]) + { + return false; + } + } + return true; + } + + public string bytesToHexStr(byte[] bytes, int iLen)//e.g. { 0x01, 0x01} ---> " 01 01" + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < iLen; i++) + { + returnStr += bytes[i].ToString("X2"); + } + } + return returnStr; + } + + public byte[] HexStrTorbytes(string strHex)//e.g. " 01 01" ---> { 0x01, 0x01} + { + strHex = strHex.Replace(" ", ""); + if ((strHex.Length % 2) != 0) + strHex += " "; + byte[] returnBytes = new byte[strHex.Length / 2]; + for (int i = 0; i < returnBytes.Length; i++) + returnBytes[i] = Convert.ToByte(strHex.Substring(i * 2, 2), 16); + return returnBytes; + } + + public string StringToHexString(string s, Encoding encode) + { + byte[] b = encode.GetBytes(s); //按照指定编码将string编程字节数组 + string result = string.Empty; + for (int i = 0; i < b.Length; i++) //逐字节变为16进制字符,以%隔开 + { + result += "%" + Convert.ToString(b[i], 16); + } + return result; + } + + public string HexStringToString(string hs, Encoding encode) + { + //以%分割字符串,并去掉空字符 + string[] chars = hs.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries); + byte[] b = new byte[chars.Length]; + //逐个字符变为16进制字节数据 + for (int i = 0; i < chars.Length; i++) + { + b[i] = Convert.ToByte(chars[i], 16); + } + //按照指定编码将字节数组变为字符串 + return encode.GetString(b); + } + + /*public short SwapInt16(this short n) + { + return (short)(((n & 0xff) << 8) | ((n >> 8) & 0xff)); + } + + public ushort SwapUInt16(this ushort n) + { + return (ushort)(((n & 0xff) << 8) | ((n >> 8) & 0xff)); + } + + public int SwapInt32(this int n) + { + return (int)(((SwapInt16((short)n) & 0xffff) << 0x10) | + (SwapInt16((short)(n >> 0x10)) & 0xffff)); + } + + public uint SwapUInt32(this uint n) + { + return (uint)(((SwapUInt16((ushort)n) & 0xffff) << 0x10) | + (SwapUInt16((ushort)(n >> 0x10)) & 0xffff)); + } + + public long SwapInt64(this long n) + { + return (long)(((SwapInt32((int)n) & 0xffffffffL) << 0x20) | + (SwapInt32((int)(n >> 0x20)) & 0xffffffffL)); + } + + public ulong SwapUInt64(this ulong n) + { + return (ulong)(((SwapUInt32((uint)n) & 0xffffffffL) << 0x20) | + (SwapUInt32((uint)(n >> 0x20)) & 0xffffffffL)); + }*/ + public byte[] intToBytesBig(int value) + { + byte[] src = new byte[4]; + src[0] = (byte)((value >> 24) & 0xFF); + src[1] = (byte)((value >> 16) & 0xFF); + src[2] = (byte)((value >> 8) & 0xFF); + src[3] = (byte)(value & 0xFF); + return src; + } + #endregion + + /// 64Base码 + /// 保存路径 + /// 文件名称 + /// + public bool Base64ToImage(string strbase64, string path, string filename) + { + bool Flag = false; + try + { + //base64编码的文本 转为 图片 + //图片名称 + byte[] arr = Convert.FromBase64String(strbase64);//将指定的字符串(它将二进制数据编码为 Base64 数字)转换为等效的 8 位无符号整数数组。 + using (MemoryStream ms = new MemoryStream(arr)) + { + Bitmap bmp = new Bitmap(ms);//加载图像 + if (!Directory.Exists(path))//判断保存目录是否存在 + { + Directory.CreateDirectory(path); + } + bmp.Save((path + "\\" + filename + ".png"), System.Drawing.Imaging.ImageFormat.Png);//将图片以JPEG格式保存在指定目录(可以选择其他图片格式) + ms.Close();//关闭流并释放 + if (File.Exists(path + "\\" + filename + ".png"))//判断是否存在 + { + Flag = true; + } + } + } + catch (Exception ex) + { + Console.WriteLine("图片保存失败:" + ex.Message); + } + return Flag; + } + + /// + /// 获取时间戳 + /// + /// + public long GetTimeStamp() + { + TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds); + } + + public byte[] ConvertFloatToINt(byte[] floatBytes) + { + byte[] intBytes = new byte[floatBytes.Length / 2]; + for (int i = 0; i < intBytes.Length; i++) + { + intBytes[i] = floatBytes[i * 2 + 1]; + } + return intBytes; + } + + //CRC异或校验 + public byte CalculateVerify(byte[] pMessage, int iLength) + { + UInt16 i; + byte iVerify = 0; + + iVerify = pMessage[0]; + for (i = 1; i < iLength; i++) + { + iVerify = (byte)(iVerify ^ pMessage[i]); + } + return iVerify; + } + + public int HexStringToNegative(string strNumber) + { + + int iNegate = 0; + int iNumber = Convert.ToInt32(strNumber, 16); + if (iNumber > 127) + { + int iComplement = iNumber - 1; + string strNegate = string.Empty; + char[] binchar = Convert.ToString(iComplement, 2).PadLeft(8, '0').ToArray(); + foreach (char ch in binchar) + { + if (Convert.ToInt32(ch) == 48) + { + strNegate += "1"; + } + else + { + strNegate += "0"; + } + } + iNegate = -Convert.ToInt32(strNegate, 2); + } + return iNegate; + } + } +} diff --git a/Ems.CollectService.Entity/BaseCollectDeviceInfo.cs b/Ems.CollectService.Entity/BaseCollectDeviceInfo.cs new file mode 100644 index 0000000..0e58fb6 --- /dev/null +++ b/Ems.CollectService.Entity/BaseCollectDeviceInfo.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Ems.CollectService.Entity +{ + /// + /// 采集设备信息 + /// + [SugarTable("base_collect_device_info")] + public class BaseCollectDeviceInfo + { + /// + /// 自增标识 + /// + [SugarColumn(ColumnName="objid" ,IsPrimaryKey = true ,IsIdentity = true )] + public int Objid { get; set; } + /// + /// 设备编号 + /// + [SugarColumn(ColumnName="collect_device_id" ,IsPrimaryKey = true )] + public string CollectDeviceId { get; set; } + /// + /// 设备名称 + /// + [SugarColumn(ColumnName="collect_device_name" )] + public string CollectDeviceName { get; set; } + /// + /// 生产厂家 + /// + [SugarColumn(ColumnName="manufacturer" )] + public string Manufacturer { get; set; } + /// + /// 生产编号 + /// + [SugarColumn(ColumnName="factory_number" )] + public string FactoryNumber { get; set; } + /// + /// 生产日期 + /// + [SugarColumn(ColumnName="produce_date" )] + public DateTime? ProduceDate { get; set; } + /// + /// 安装位置 + /// + [SugarColumn(ColumnName="address" )] + public string Address { get; set; } + /// + /// 能源类型 + /// + [SugarColumn(ColumnName="energy_type" )] + public int? EnergyType { get; set; } + /// + /// 型号 + /// + [SugarColumn(ColumnName="model" )] + public string Model { get; set; } + /// + /// 地址 + /// + [SugarColumn(ColumnName="ip" )] + public string Ip { get; set; } + /// + /// 备注 + /// + [SugarColumn(ColumnName="remark" )] + public string Remark { get; set; } + /// + /// 终端在线状态 + /// + [SugarColumn(ColumnName="online_state" )] + public int? OnlineState { get; set; } + /// + /// 权限标识(部门) + /// + [SugarColumn(ColumnName="dept_id" )] + public int? DeptId { get; set; } + /// + /// 权限标识(用户) + /// + [SugarColumn(ColumnName="user_id" )] + public int? UserId { get; set; } + /// + /// 创建人 + /// + [SugarColumn(ColumnName="create_by" )] + public string CreateBy { get; set; } + /// + /// 创建时间 + /// + [SugarColumn(ColumnName="create_time" )] + public DateTime? CreateTime { get; set; } + /// + /// 更新人 + /// + [SugarColumn(ColumnName="update_by" )] + public string UpdateBy { get; set; } + /// + /// 更新时间 + /// + [SugarColumn(ColumnName="update_time" )] + public DateTime? UpdateTime { get; set; } + } +} diff --git a/Ems.CollectService.Entity/BaseMonitorInfo.cs b/Ems.CollectService.Entity/BaseMonitorInfo.cs new file mode 100644 index 0000000..21bd6fd --- /dev/null +++ b/Ems.CollectService.Entity/BaseMonitorInfo.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Ems.CollectService.Entity +{ + /// + /// 计量设备信息 + /// + [SugarTable("base_monitor_info")] + public class BaseMonitorInfo + { + /// + /// 自增标识 + /// + [SugarColumn(ColumnName="objid" ,IsPrimaryKey = true ,IsIdentity = true )] + public int Objid { get; set; } + /// + /// 父级编号 + /// + [SugarColumn(ColumnName="parent_id" )] + public string ParentId { get; set; } + /// + /// 计量设备编号 + /// + [SugarColumn(ColumnName="monitor_id" ,IsPrimaryKey = true )] + public string MonitorId { get; set; } + /// + /// 计量设备名称 + /// + [SugarColumn(ColumnName="monitor_name" )] + public string MonitorName { get; set; } + /// + /// 计量设备位置 + /// + [SugarColumn(ColumnName="monitor_addr" )] + public string MonitorAddr { get; set; } + /// + /// 计量设备类型 + /// + [SugarColumn(ColumnName="monitor_type" )] + public int? MonitorType { get; set; } + /// + /// 计量设备状态 + /// + [SugarColumn(ColumnName="monitor_status" )] + public int? MonitorStatus { get; set; } + /// + /// 采集设备编号 + /// + [SugarColumn(ColumnName="collect_device_id" )] + public string CollectDeviceId { get; set; } + /// + /// 祖级列表 + /// + [SugarColumn(ColumnName="ancestors" )] + public string Ancestors { get; set; } + /// + /// 等级 + /// + [SugarColumn(ColumnName="grade" )] + public int? Grade { get; set; } + /// + /// 建筑类型 + /// + [SugarColumn(ColumnName="build_id" )] + public string BuildId { get; set; } + /// + /// 分项类型 + /// + [SugarColumn(ColumnName="subentry_id" )] + public string SubentryId { get; set; } + /// + /// 业态类型 + /// + [SugarColumn(ColumnName="business_id" )] + public string BusinessId { get; set; } + /// + /// 传感器仪表 + /// + [SugarColumn(ColumnName="meter_type_id" )] + public string MeterTypeId { get; set; } + /// + /// 测量器具 + /// + [SugarColumn(ColumnName="meter_id" )] + public string MeterId { get; set; } + /// + /// 修正值 + /// + [SugarColumn(ColumnName="correct_value" )] + public decimal? CorrectValue { get; set; } + /// + /// PT值 + /// + [SugarColumn(ColumnName="pt" )] + public int? Pt { get; set; } + /// + /// CT值 + /// + [SugarColumn(ColumnName="ct" )] + public int? Ct { get; set; } + /// + /// 是否虚拟 + /// 默认值: _utf8mb4'false' + /// + [SugarColumn(ColumnName="is_ammeter" )] + public string IsAmmeter { get; set; } + /// + /// 通断复位 + /// + [SugarColumn(ColumnName="is_key_monitor" )] + public int? IsKeyMonitor { get; set; } + /// + /// 是否断路 + /// + [SugarColumn(ColumnName="is_circuit" )] + public int? IsCircuit { get; set; } + /// + /// 权限标识(部门) + /// + [SugarColumn(ColumnName="dept_id" )] + public int? DeptId { get; set; } + /// + /// 权限标识(用户) + /// + [SugarColumn(ColumnName="user_id" )] + public int? UserId { get; set; } + /// + /// 创建人 + /// + [SugarColumn(ColumnName="create_by" )] + public string CreateBy { get; set; } + /// + /// 创建时间 + /// 默认值: CURRENT_TIMESTAMP + /// + [SugarColumn(ColumnName="create_time" )] + public DateTime? CreateTime { get; set; } + /// + /// 更新人 + /// + [SugarColumn(ColumnName="update_by" )] + public string UpdateBy { get; set; } + /// + /// 更新时间 + /// + [SugarColumn(ColumnName="update_time" )] + public DateTime? UpdateTime { get; set; } + } +} diff --git a/Ems.CollectService.Entity/Ems.CollectService.Entity.csproj b/Ems.CollectService.Entity/Ems.CollectService.Entity.csproj new file mode 100644 index 0000000..2338bdd --- /dev/null +++ b/Ems.CollectService.Entity/Ems.CollectService.Entity.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.1 + + + + + + + + diff --git a/Ems.CollectService.Entity/RecordDnbInstant.cs b/Ems.CollectService.Entity/RecordDnbInstant.cs new file mode 100644 index 0000000..8cbbbc1 --- /dev/null +++ b/Ems.CollectService.Entity/RecordDnbInstant.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Ems.CollectService.Entity +{ + /// + /// 电实时数据 + /// + [SugarTable("record_dnb_instant")] + public class RecordDnbInstant + { + /// + /// 编号 + /// + [SugarColumn(ColumnName="objid" ,IsPrimaryKey = true ,IsIdentity = true )] + public long objid { get; set; } + /// + /// 计量设备编号 + /// + [SugarColumn(ColumnName="monitor_id" )] + public string monitorId { get; set; } + /// + /// 采集时间 + /// + [SugarColumn(ColumnName="collect_time" )] + public DateTime? collectTime { get; set; } + /// + /// A项电压 + /// + [SugarColumn(ColumnName="vA" )] + public decimal? vA { get; set; } + /// + /// B项电压 + /// + [SugarColumn(ColumnName="vB" )] + public decimal? vB { get; set; } + /// + /// C项电压 + /// + [SugarColumn(ColumnName="vC" )] + public decimal? vC { get; set; } + /// + /// A项电流 + /// + [SugarColumn(ColumnName="iA" )] + public decimal? iA { get; set; } + /// + /// B项电流 + /// + [SugarColumn(ColumnName="iB" )] + public decimal? iB { get; set; } + /// + /// C项电流 + /// + [SugarColumn(ColumnName="iC" )] + public decimal? iC { get; set; } + /// + /// 记录时间 + /// + [SugarColumn(ColumnName="record_time" )] + public DateTime? recordTime { get; set; } + /// + /// 功率因数 + /// + [SugarColumn(ColumnName="glys" )] + public decimal? glys { get; set; } + /// + /// 正向有功 + /// + [SugarColumn(ColumnName="zxyg" )] + public decimal? zxyg { get; set; } + /// + /// 有功功率 + /// + [SugarColumn(ColumnName="active_power" )] + public decimal? activePower { get; set; } + /// + /// 无功功率 + /// + [SugarColumn(ColumnName="reactive_power" )] + public decimal? reactivePower { get; set; } + + /// + /// 电耗量 + /// + [SugarColumn(ColumnName="consumption" )] + public decimal? consumption { get; set; } + /// + /// 采集方式 + /// 默认值: 0 + /// + [SugarColumn(ColumnName="collect_type" )] + public int? collectType { get; set; } + /// + /// 权限标识(部门) + /// + [SugarColumn(ColumnName="dept_id" )] + public int? deptId { get; set; } + /// + /// 权限标识(用户) + /// + [SugarColumn(ColumnName="user_id" )] + public int? userId { get; set; } + } +} diff --git a/Ems.CollectService.Entity/RecordWaterInstant.cs b/Ems.CollectService.Entity/RecordWaterInstant.cs new file mode 100644 index 0000000..2a92a57 --- /dev/null +++ b/Ems.CollectService.Entity/RecordWaterInstant.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Ems.CollectService.Entity +{ + /// + /// 水实时数据 + /// + [SugarTable("record_water_instant")] + public class RecordWaterInstant + { + /// + /// 自增标识 + /// + [SugarColumn(ColumnName="objid" ,IsPrimaryKey = true )] + public int objid { get; set; } + /// + /// 计量设备编号 + /// + [SugarColumn(ColumnName="monitor_id" )] + public string monitorId { get; set; } + /// + /// 采集时间 + /// + [SugarColumn(ColumnName="collect_time" )] + public DateTime? collectTime { get; set; } + /// + /// 瞬时流量 + /// + [SugarColumn(ColumnName="flux_flow" )] + public decimal? fluxFlow { get; set; } + /// + /// 累计流量 + /// + [SugarColumn(ColumnName="water_flow" )] + public decimal? waterFlow { get; set; } + /// + /// 记录时间 + /// + [SugarColumn(ColumnName="record_time" )] + public DateTime? recordTime { get; set; } + /// + /// 采集方式 + /// 默认值: 0 + /// + [SugarColumn(ColumnName="collect_type" )] + public int? collectType { get; set; } + /// + /// 权限标识(部门) + /// + [SugarColumn(ColumnName="dept_id" )] + public int? deptId { get; set; } + /// + /// 权限标识(用户) + /// + [SugarColumn(ColumnName="user_id" )] + public int? userId { get; set; } + } +} diff --git a/Ems.CollectService.Entity/SysConfig.cs b/Ems.CollectService.Entity/SysConfig.cs new file mode 100644 index 0000000..86b9e0f --- /dev/null +++ b/Ems.CollectService.Entity/SysConfig.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Ems.CollectService.Entity +{ + /// + /// 参数配置表 + /// + [SugarTable("sys_config")] + public class SysConfig + { + /// + /// 参数主键 + /// + [SugarColumn(ColumnName="config_id" ,IsPrimaryKey = true ,IsIdentity = true )] + public int ConfigId { get; set; } + /// + /// 参数名称 + /// 默认值: + /// + [SugarColumn(ColumnName="config_name" )] + public string ConfigName { get; set; } + /// + /// 参数键名 + /// 默认值: + /// + [SugarColumn(ColumnName="config_key" )] + public string ConfigKey { get; set; } + /// + /// 参数键值 + /// 默认值: + /// + [SugarColumn(ColumnName="config_value" )] + public string ConfigValue { get; set; } + /// + /// 系统内置(Y是 N否) + /// 默认值: N + /// + [SugarColumn(ColumnName="config_type" )] + public string ConfigType { get; set; } + /// + /// 创建者 + /// 默认值: + /// + [SugarColumn(ColumnName="create_by" )] + public string CreateBy { get; set; } + /// + /// 创建时间 + /// + [SugarColumn(ColumnName="create_time" )] + public DateTime? CreateTime { get; set; } + /// + /// 更新者 + /// 默认值: + /// + [SugarColumn(ColumnName="update_by" )] + public string UpdateBy { get; set; } + /// + /// 更新时间 + /// + [SugarColumn(ColumnName="update_time" )] + public DateTime? UpdateTime { get; set; } + /// + /// 备注 + /// + [SugarColumn(ColumnName="remark" )] + public string Remark { get; set; } + } +} diff --git a/Ems.CollectService.Entity/config/AppConfig.cs b/Ems.CollectService.Entity/config/AppConfig.cs new file mode 100644 index 0000000..57d48f4 --- /dev/null +++ b/Ems.CollectService.Entity/config/AppConfig.cs @@ -0,0 +1,49 @@ +using Ems.CollectService.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ems.CollectService.Entity.config +{ + public sealed class AppConfig + { + + private static readonly Lazy lazy = new Lazy(() => new AppConfig()); + + + private static StringChange stringChange = StringChange.Instance; + + + public static AppConfig Instance + { + get + { + return lazy.Value; + } + } + + private AppConfig() { } + + private static INIFile iNIFile = new INIFile(System.Environment.CurrentDirectory + "/config/App.InI"); + + /// + /// 监听端口 + /// + public int listenerPort + { + get { return stringChange.ParseToInt(iNIFile.IniReadValue("SystemConfig", "listenerPort")); } + set { iNIFile.IniWriteValue("SystemConfig", "listenerPort", value.ToString()); } + } + + /// + /// Mysql地址 + /// + public string mysqlStr + { + get { return iNIFile.IniReadValue("SystemConfig", "mysqlConnStr"); } + set { iNIFile.IniWriteValue("SystemConfig", "mysqlConnStr", value.ToString()); } + } + } +} diff --git a/Ems.CollectService.Entity/dto/EnergyType.cs b/Ems.CollectService.Entity/dto/EnergyType.cs new file mode 100644 index 0000000..f9e18c7 --- /dev/null +++ b/Ems.CollectService.Entity/dto/EnergyType.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ems.CollectService.Entity.dto +{ + /* + *结构名称:EMS_COMM_PARAMS + *创建人: + *创建时间: + *功能描述:保存电力对象ID + */ + public struct EMS_COMM_PARAMS + { + //电类型 + public const uint AI = 0x8E21; + public const uint BI = 0x8E22; + public const uint CI = 0x8E23; + public const uint AU = 0x8E11; + public const uint BU = 0x8E12; + public const uint CU = 0x8E13; + public const uint GLYS = 0xB650; + public const uint ZXYGZ = 0x9010; + public const uint JF = 0x9011; + public const uint F = 0x9012; + public const uint P = 0x9013; + public const uint G = 0x9014; + public const uint ZXWG = 0x9030; + public const uint CJSJ = 0x8030; + public const uint YGGL = 0xB651; //新增有功功率 Add By Wenjy 2023-03-23 + public const uint WGGL = 0xB652; //新增无功功率 Add By Wenjy 2023-03-23 + //蒸汽、压缩空气、水 + public const uint Press = 0x9B00; + public const uint STemperature = 0x9B01; + public const uint Frequency = 0x9B02; + public const uint FluxInstantValue = 0x9B03; + public const uint FluxEyeableTotalValue = 0x9B05; + public const uint HeatInstantValue = 0x9B06; + public const uint HeatToftalValue = 0x9B07; + public const uint Density = 0x9B0E; + //温湿度、照度 + public const uint TTempreture = 0x8E50; + public const uint Humidity = 0x8E52; + public const uint Illuminance = 0x8E51; + public const uint Concentration = 0x8E54; + public const uint Noise = 0x8E53; + } + + public class MessagePack + { + public byte m_BeginChar = 0x68; //帧头 + public byte m_EnergyType; //能源类型 + public byte[] m_Meteraddr = new byte[2];//地址 + public byte[] m_Msta = new byte[2]; //命令序列号 + public byte m_StartFlag; //起始符 + public byte m_MessageType; //控制码 + public byte[] m_PackLen = new byte[2]; //数据长度 + public byte m_Verify; + public byte m_EndChar = 0x16; //尾盘 + } +} diff --git a/Ems.CollectService.Redis/Ems.CollectService.Redis.csproj b/Ems.CollectService.Redis/Ems.CollectService.Redis.csproj new file mode 100644 index 0000000..b294936 --- /dev/null +++ b/Ems.CollectService.Redis/Ems.CollectService.Redis.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/Ems.CollectService.Redis/RedisHelper.cs b/Ems.CollectService.Redis/RedisHelper.cs new file mode 100644 index 0000000..1b49bd6 --- /dev/null +++ b/Ems.CollectService.Redis/RedisHelper.cs @@ -0,0 +1,36 @@ +using StackExchange.Redis; +using System; +using System.Collections.Concurrent; + +namespace Ems.CollectService.Redis +{ + public class RedisHelper + { + private static readonly ConfigurationOptions ConfigurationOptions = ConfigurationOptions.Parse("127.0.0.1:6379,password=admin123"); + private static readonly object Locker = new object(); + private static ConnectionMultiplexer _redisConn; + + /// + /// 单例获取 + /// + public static ConnectionMultiplexer RedisConn + { + get + { + if (_redisConn == null) + { + // 锁定某一代码块,让同一时间只有一个线程访问该代码块 + lock (Locker) + { + if (_redisConn == null || !_redisConn.IsConnected) + { + _redisConn = ConnectionMultiplexer.Connect(ConfigurationOptions); + } + } + } + return _redisConn; + } + } + } + +} diff --git a/Ems.CollectService.SqlSugarCore/Ems.CollectService.SqlSugarCore.csproj b/Ems.CollectService.SqlSugarCore/Ems.CollectService.SqlSugarCore.csproj new file mode 100644 index 0000000..7bb5055 --- /dev/null +++ b/Ems.CollectService.SqlSugarCore/Ems.CollectService.SqlSugarCore.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp3.1 + + + + + + + + + + + diff --git a/Ems.CollectService.SqlSugarCore/SqlGenerator.cs b/Ems.CollectService.SqlSugarCore/SqlGenerator.cs new file mode 100644 index 0000000..a378407 --- /dev/null +++ b/Ems.CollectService.SqlSugarCore/SqlGenerator.cs @@ -0,0 +1,77 @@ +using Microsoft.IdentityModel.Logging; +using SqlSugar; +using System; +using System.Threading.Tasks; + +namespace Ems.CollectService.SqlSugarCore +{ + public class SqlGenerator + { + #region 参数定义 + private static string ConnectionString = "Data Source=nyfw-m.db.sfcloud.local;Port=3306;Initial Catalog=sfemsrefactor;uid=highwayiot; pwd=Administrator@;min pool size=1;SslMode=none;Charset=utf8"; + + //private static string ConnectionString = "Data Source=43.143.98.48;Port=3306;Initial Catalog=hw_ems;uid=root; pwd=yq@123456;min pool size=1;SslMode=none;Charset=utf8"; + private static SqlSugarClient sqlSugarClient = null; + + private static readonly object lockHelper = new object(); + #endregion + + /// + /// 连接服务器数据库 + /// + /// + public static SqlSugarClient GetMySqlInstance() + { + if (sqlSugarClient == null) + { + lock (lockHelper) + { + if (sqlSugarClient == null) + { + sqlSugarClient = new SqlSugarClient(new ConnectionConfig() + { + DbType = DbType.MySql, + ConnectionString = ConnectionString, + InitKeyType = InitKeyType.Attribute, + IsAutoCloseConnection = true, + //AopEvents = new AopEvents + //{ + // //记录执行SQL和参数 + // OnLogExecuting = (sql, p) => + // { + // LogHelper.SqlLog(sql); + // } + //} + }); + + sqlSugarClient.Aop.OnLogExecuting = (sql, pars) => + { + Parallel.For(0, 1, e => + { + string SqlLog = ""; + foreach (string item in new string[] { GetParas(pars), "【SQL语句】:" + sql }) + { + SqlLog = SqlLog + item; + } + }); + }; + } + } + + } + return sqlSugarClient; + } + + + + private static string GetParas(SugarParameter[] pars) + { + string key = "【SQL参数】"; + foreach (var param in pars) + { + key += $"{param.ParameterName}:{param.Value}\n"; + } + return key; + } + } +} diff --git a/Ems.CollectService.SqlSugarCore/SqlSugarHelper.cs b/Ems.CollectService.SqlSugarCore/SqlSugarHelper.cs new file mode 100644 index 0000000..74e6254 --- /dev/null +++ b/Ems.CollectService.SqlSugarCore/SqlSugarHelper.cs @@ -0,0 +1,51 @@ +using Ems.CollectService.Common; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ems.CollectService.SqlSugarCore +{ + public class SqlSugarHelper //不能是泛型类 + { + private static INIFile iNIFile = new INIFile(System.Environment.CurrentDirectory + "/config/App.InI"); + + private static string ConnectionString = "Data Source=nyfw-m.db.sfcloud.local;Port=3306;Initial Catalog=sfemsrefactor;uid=highwayiot; pwd=Administrator@;min pool size=1;SslMode=none;Charset=utf8"; + + //private static string ConnectionString = "Data Source=43.143.98.48;Port=3306;Initial Catalog=hw_ems;uid=root; pwd=yq@123456;min pool size=1;SslMode=none;Charset=utf8"; + + //多库情况下使用说明: + //如果是固定多库可以传 new SqlSugarScope(List,db=>{}) 文档:多租户 + //如果是不固定多库 可以看文档Saas分库 + + + //用单例模式 + public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig() + { + ConnectionString = iNIFile.IniReadValue("SystemConfig", "mysqlConnStr"),//连接符字串 + DbType = DbType.MySql,//数据库类型 + IsAutoCloseConnection = true //不设成true要手动close + }, + db => { + //(A)全局生效配置点,一般AOP和程序启动的配置扔这里面 ,所有上下文生效 + //调试SQL事件,可以删掉 + db.Aop.OnLogExecuting = (sql, pars) => + { + //Console.WriteLine(sql);//输出sql,查看执行sql 性能无影响 + + //获取原生SQL推荐 5.1.4.63 性能OK + //UtilMethods.GetNativeSql(sql,pars) + + //获取无参数化SQL 对性能有影响,特别大的SQL参数多的,调试使用 + //UtilMethods.GetSqlString(DbType.SqlServer,sql,pars) + + }; + + //多个配置就写下面 + //db.Ado.IsDisableMasterSlaveSeparation=true; + + //注意多租户 有几个设置几个 + //db.GetConnection(i).Aop + }); + } +} diff --git a/Ems.CollectService.Timer/DeleteLogFile.cs b/Ems.CollectService.Timer/DeleteLogFile.cs new file mode 100644 index 0000000..aa3a1cd --- /dev/null +++ b/Ems.CollectService.Timer/DeleteLogFile.cs @@ -0,0 +1,89 @@ +using Ems.CollectService.Common; +using NLog; +using System; +using System.IO; + +namespace Ems.CollectService.Timer +{ + /// + /// 删除日志文件 + /// + public sealed class DeleteLogFile + { + private Logger logger = LogManager.GetCurrentClassLogger(); + private System.Timers.Timer timer = new System.Timers.Timer(1000*60*60); + + private static readonly Lazy lazy = new Lazy(() => new DeleteLogFile()); + + public static DeleteLogFile Instance + { + get + { + return lazy.Value; + } + } + + private DeleteLogFile() { } + + /// + /// 删除日志定时器 + /// + public void DeleteLogFileTimer() + { + try + { + if (!timer.Enabled) + { + timer.Elapsed += new System.Timers.ElapsedEventHandler(DeleteLogFileTick); + timer.AutoReset = true; + timer.Enabled = false; + timer.Start(); + logger.Info("删除日志文件夹定时器启动成功"); + } + } + catch (Exception ex) + { + logger.Error($"StartTimerDeleteLogFile定时删除日志文件异常{ex.Message}"); + } + } + + /// + /// 删除指定路径下的超时文件 + /// + /// + /// + private void DeleteLogFileTick(object sender, EventArgs e) + { + try + { + string fileDirect = "C:\\能源项目文件夹\\采集服务\\Log"; + int saveDay = 1; + logger.Info($"定时删除路径:{fileDirect};下超过:{saveDay}天的日志文件夹"); + DateTime nowTime = DateTime.Now; + DirectoryInfo root = new DirectoryInfo(fileDirect); + DirectoryInfo[] dics = root.GetDirectories(); + + FileAttributes attr = File.GetAttributes(fileDirect); + if (attr == FileAttributes.Directory) + { + foreach (DirectoryInfo file in dics) + { + TimeSpan t = nowTime - file.CreationTime; + int day = t.Days; + if (day > saveDay) + { + + Directory.Delete(file.FullName, true); + } + } + + } + } + catch (Exception ex) + { + logger.Error($"删除日志文件夹异常{ex.Message}"); + } + } + + } +} diff --git a/Ems.CollectService.Timer/Ems.CollectService.Timer.csproj b/Ems.CollectService.Timer/Ems.CollectService.Timer.csproj new file mode 100644 index 0000000..71f27a2 --- /dev/null +++ b/Ems.CollectService.Timer/Ems.CollectService.Timer.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/Ems.CollectService.TouchSocket/Ems.CollectService.TouchSocket.csproj b/Ems.CollectService.TouchSocket/Ems.CollectService.TouchSocket.csproj new file mode 100644 index 0000000..11dd628 --- /dev/null +++ b/Ems.CollectService.TouchSocket/Ems.CollectService.TouchSocket.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/Ems.CollectService.TouchSocket/MyFixedHeaderCustomDataHandlingAdapter.cs b/Ems.CollectService.TouchSocket/MyFixedHeaderCustomDataHandlingAdapter.cs new file mode 100644 index 0000000..168a82b --- /dev/null +++ b/Ems.CollectService.TouchSocket/MyFixedHeaderCustomDataHandlingAdapter.cs @@ -0,0 +1,27 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.Text; +using TouchSocket.Sockets; + +namespace Ems.CollectService.TouchSocket +{ + internal class MyFixedHeaderCustomDataHandlingAdapter : CustomFixedHeaderDataHandlingAdapter + { + private Logger logger = LogManager.GetCurrentClassLogger(); + public override int HeaderLength => 10; + + protected override MyFixedHeaderRequestInfo GetInstance() + { + try + { + return new MyFixedHeaderRequestInfo(); + } + catch (Exception ex) + { + logger.Error("TCP适配器异常",ex); + return new MyFixedHeaderRequestInfo(); + } + } + } +} diff --git a/Ems.CollectService.TouchSocket/MyFixedHeaderRequestInfo.cs b/Ems.CollectService.TouchSocket/MyFixedHeaderRequestInfo.cs new file mode 100644 index 0000000..e4afc56 --- /dev/null +++ b/Ems.CollectService.TouchSocket/MyFixedHeaderRequestInfo.cs @@ -0,0 +1,83 @@ +using Ems.CollectService.Common; +using NLog; +using System; +using System.Collections.Generic; +using System.Text; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace Ems.CollectService.TouchSocket +{ + public class MyFixedHeaderRequestInfo: IFixedHeaderRequestInfo + { + + #region 参数定义 + private byte[] m_sync; + private int m_bodyLength; + private byte[] m_length = new byte[2]; + private byte[] body; + public int BodyLength { get => m_bodyLength; } + /// + /// 报文头:5AA5 + /// + public byte[] Header { get => m_sync; set => m_sync = value; } + + + /// + /// 自定义属性,标识实际数据 + /// + public byte[] Body { get => body; set => body = value; } + + private Logger logger = LogManager.GetCurrentClassLogger(); + + private MsgUtil msgUtil = MsgUtil.Instance; + #endregion + + public bool OnParsingBody(byte[] body) + { + //logger.Info("》》》接收客户端原始消息数据区: " + msgUtil.bytesToHexStr(body, (int)body.Length) + "\r\n"); + + if (body.Length == this.m_bodyLength) + { + this.body = body; + return true; + } + return false; + } + + public bool OnParsingHeader(byte[] header) + { + //logger.Info("》》》接收客户端原始消息头: " + msgUtil.bytesToHexStr(header, header.Length) + "\r\n"); + + if (header.Length == 10) + { + using (ByteBlock byteBlock = new ByteBlock(header)) + { + string m_BarcodeGroupCount = ""; + int i_BarcodeGroupCount = 0; + byteBlock.Pos = 0; + byteBlock.Read(out m_sync, 10); + Array.Copy(header, 8, m_length, 0, 2); + if (header[7] == 0X01 || header[7] == 0X24) + { + this.m_bodyLength = 2;//先把crc校验和end都获取。 + return true; + } + else + { + m_BarcodeGroupCount = Convert.ToString(msgUtil.bytesToHexStr(m_length, m_length.Length)); + i_BarcodeGroupCount = Convert.ToInt32("0x" + m_BarcodeGroupCount, 16); + if (i_BarcodeGroupCount != 0) + { + this.m_bodyLength = i_BarcodeGroupCount + 2;//先把crc校验和end都获取。 + return true; + } + } + + } + } + return false; + + } + } +} diff --git a/Ems.CollectService.TouchSocket/TcpServer.cs b/Ems.CollectService.TouchSocket/TcpServer.cs new file mode 100644 index 0000000..949b176 --- /dev/null +++ b/Ems.CollectService.TouchSocket/TcpServer.cs @@ -0,0 +1,261 @@ +using Ems.CollectService.Analysis; +using Ems.CollectService.Common; +using Ems.CollectService.Entity; +using Ems.CollectService.Redis; +using Ems.CollectService.SqlSugarCore; +using NetTaste; +using NLog; +using SqlSugar; +using StackExchange.Redis; +using System; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace Ems.CollectService.TouchSocket +{ + public sealed class TcpServer + { + private static readonly Lazy lazy = new Lazy(() => new TcpServer()); + + private Logger logger = LogManager.GetCurrentClassLogger(); + + private TcpService service = new TcpService(); + + private StringChange stringChange = StringChange.Instance; + + private BufferAnalysis bufferAnalysis = BufferAnalysis.Instance; + + private MsgUtil msgUtil = MsgUtil.Instance; + + private JsonChange jsonChange = JsonChange.Instance; + + //private SqlSugarClient baseService = SqlGenerator.GetMySqlInstance(); + + //private ConnectionMultiplexer conn = RedisHelper.RedisConn; + public static TcpServer Instance + { + get + { + return lazy.Value; + } + } + + private TcpServer() { } + + public void Init(int serverPort) + { + try + { + service.Connecting = (client, e) => { //有客户端正在连接 + logger.Info($"客户端{client.IP}正在接入服务"); + }; + service.Connected = (client, e) => { //有客户端成功连接 + logger.Trace($"客户端{client.IP}接入服务成功,Id:{client.ID}"); + }; + service.Disconnected = (client, e) => { //有客户端断开连接 + logger.Trace($"客户端{client.IP}断开连接,Id:{client.ID}"); + if (client.ID.Length >= 4) + { + string clientId = string.Format("E{0}", client.ID.ToString().Substring(2, client.ID.ToString().Length - 2)); + bufferAnalysis.UpdateCollectDeviceOnLineState(clientId, 0); + } + }; + service.Received = (client, byteBlock, requestInfo) => + { + if (requestInfo is MyFixedHeaderRequestInfo myRequestInfo) + { + string body = Encoding.UTF8.GetString(myRequestInfo.Body, 0, myRequestInfo.Body.Length); + + bufferMemory(client, myRequestInfo); + } + }; + + service.Setup(new TouchSocketConfig()//载入配置 + .SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })//同时监听两个地址 + .SetDataHandlingAdapter(() => { return new MyFixedHeaderCustomDataHandlingAdapter(); })//配置适配器 + .ConfigureContainer(a =>//容器的配置顺序应该在最前面 + { + a.AddConsoleLogger();//添加一个控制台日志注入(注意:在maui中控制台日志不可用) + }) + .ConfigurePlugins(a => + { + //a.Add().SetDuration(new TimeSpan(0, 0, 0, 5, 0)); + + })) + .Start();//启动 + ReadMeterTask(); //点抄指令下发 + logger.Info($"采集服务启动成功,监听端口:{serverPort}"); + } + catch(Exception ex) + { + logger.Error($"采集服务启动异常:{ex}"); + throw new Exception(ex.Message); + } + + } + + /// + /// 缓存器 + /// + /// + /// + private void bufferMemory(SocketClient client, MyFixedHeaderRequestInfo requestInfo) + { + try + { + string header = stringChange.bytesToHexStr(requestInfo.Header, requestInfo.Header.Length); + string body = stringChange.bytesToHexStr(requestInfo.Body, requestInfo.BodyLength); + + byte[] buffer = new byte[requestInfo.Header.Length + requestInfo.Body.Length]; + Array.Copy(requestInfo.Header, 0, buffer, 0, requestInfo.Header.Length); + Array.Copy(requestInfo.Body, 0, buffer, requestInfo.Header.Length, requestInfo.Body.Length); + + //var db = conn.GetDatabase(); + switch (requestInfo.Header[7]) + { + case 0x21: + //登录指令 =>回复登录指令、下发校时指令 + //db.StringSet("LoginMessage:" + clientId, body, TimeSpan.FromMinutes(10)); + logger.Info($"{client.ID}登录指令,Header:{header};Body:{body}"); + bufferAnalysis.LoginMessageHandling(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length); + break; + case 0X24: + //心跳指令 + //db.StringSet("HeartMessage:" + clientId, body, TimeSpan.FromMinutes(10)); + logger.Info($"{client.ID}心跳指令,Header:{header};Body:{body}"); + bufferAnalysis.HeartMessageHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length); + break; + case 131: + //电表数据 + //db.StringSet("DnbMessage:" + clientId, body, TimeSpan.FromMinutes(10)); + logger.Info($"{client.ID}电表数据,Header:{header};Body:{body}"); + bufferAnalysis.EDataMessageHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 1); + break; + case 132: + //水、蒸汽、压缩空气表数据(流量类型) + //db.StringSet("FlowMessage:" + clientId, body, TimeSpan.FromMinutes(10)); + logger.Info($"{client.ID}水表数据,Header:{header};Body:{body}"); + bufferAnalysis.SDataMessageHandling(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 1); + break; + + case 147: + //电表点抄 + //db.StringSet("DnbMessage:" + clientId, body, TimeSpan.FromMinutes(10)); + logger.Info($"{client.ID}电表点抄,Header:{header};Body:{body}"); + bufferAnalysis.EDataMessageHandlingAsync(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 2); + break; + case 148: + //水表点抄 + //db.StringSet("FlowMessage:" + clientId, body, TimeSpan.FromMinutes(10)); + logger.Info($"{client.ID}水表点抄,Header:{header};Body:{body}"); + bufferAnalysis.SDataMessageHandling(client, buffer, requestInfo.Header.Length + requestInfo.Body.Length, 2); + break; + default: + logger.Info($"{client.ID}指令未匹配到对应类型;"); + break; + } + } + catch(Exception ex) + { + logger.Error("缓存器异常", ex); + } + } + + /// + /// 点抄指令下发 + /// + private void ReadMeterTask() + { + try + { + var t = Task.Run(async delegate + { + while (true) + { + //SysConfig sysConfig = baseService.Queryable().InSingle(14); + SysConfig sysConfig = SqlSugarHelper.Db.Queryable().InSingle(14); + if (sysConfig != null) + { + if (!string.IsNullOrEmpty(sysConfig.ConfigValue)) + { + logger.Warn($"通过参数配置获取到点抄表号:{sysConfig.ConfigValue}"); + + + string[] clientIds = sysConfig.ConfigValue.Split('+'); + + foreach (string item in clientIds) + { + string clientId = FormatCollectDeviceId(item.Substring(0, 5)); + SocketClient[] socketClients = service.GetClients(); + + foreach (SocketClient socketClient in socketClients) + { + logger.Warn($"客户端信息打印:{socketClient.ID};{socketClient.IP}"); + + byte[] buffer = new byte[14]; + byte[] collectBuffer = msgUtil.HexStrTorbytes(clientId.Substring(2, 4)); + + string monitorId = Convert.ToString(msgUtil.ParseToInt(item.Substring(6, 2)), 16).PadLeft(2, '0'); + monitorId += Convert.ToString(msgUtil.ParseToInt(item.Substring(8, 2)), 16).PadLeft(2, '0'); + + byte[] monitorBuffer = msgUtil.HexToString(monitorId); + + Array.Copy(new byte[] { 0x68, 0x45 }, 0, buffer, 0, 2); + Array.Copy(collectBuffer, 0, buffer, 2, collectBuffer.Length); + Array.Copy(new byte[] { 0x00, 0xBF, 0x68, 0x06, 0x00, 0x02 }, 0, buffer, 4, 6); + Array.Copy(monitorBuffer, 0, buffer, 10, monitorBuffer.Length); + + /*buffer[10] = Encoding.UTF8.GetBytes(Convert.ToString(msgUtil.ParseToInt(sysConfig.ConfigValue.Substring(6, 2)), 16))[0]; + buffer[11] = 0x00;*/ + + byte csCheck = msgUtil.Check_CS(buffer); + buffer[12] = csCheck; + buffer[13] = 0x16; + + socketClient.Send(buffer); + logger.Warn($"向客户端:{socketClient.ID};发送点抄指令:{msgUtil.bytesToHexStr(buffer, (int)buffer.Length)}"); + } + + await Task.Delay(100 * 2); + } + + + sysConfig.ConfigValue = string.Empty; + + int result = SqlSugarHelper.Db.Updateable().SetColumns(it => new SysConfig() { ConfigValue = string.Empty, UpdateTime = DateTime.Now }).Where(it => it.ConfigId == 14).ExecuteCommand(); + + } + } + else + { + logger.Warn("参数配置信息获取为空"); + } + + await Task.Delay(1000 * 2); + } + }); + } + catch (Exception ex) + { + logger.Error($"点抄数据异常:{ex.Message}"); + } + } + + /// + /// 集中器编号格式化=>ClientID + /// + /// + /// + private string FormatCollectDeviceId(string deviceId) + { + byte sensorid1 = Convert.ToByte(deviceId.Substring(1, 2)); + byte sensorid2 = Convert.ToByte(deviceId.Substring(3, 2)); + byte[] flag = Encoding.Default.GetBytes(deviceId.Substring(0, 1)); + string collectDeviceId = Convert.ToInt32(flag[0].ToString("x")) + deviceId.Substring(1); + return collectDeviceId; + } + } +} diff --git a/Ems.CollectService.sln b/Ems.CollectService.sln new file mode 100644 index 0000000..3094926 --- /dev/null +++ b/Ems.CollectService.sln @@ -0,0 +1,67 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService", "Ems.CollectService\Ems.CollectService.csproj", "{6A006389-CD61-4388-A2CD-DECFC6434FB1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService.Common", "Ems.CollectService.Common\Ems.CollectService.Common.csproj", "{BB8B9D9B-42FC-498B-B014-E0B267603C37}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService.SqlSugarCore", "Ems.CollectService.SqlSugarCore\Ems.CollectService.SqlSugarCore.csproj", "{61477E6E-73D0-4876-9B72-0006395D0823}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService.Entity", "Ems.CollectService.Entity\Ems.CollectService.Entity.csproj", "{33FDD319-923E-4EAD-88C6-4503893B227B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService.TouchSocket", "Ems.CollectService.TouchSocket\Ems.CollectService.TouchSocket.csproj", "{8E818AAC-81E1-49C4-9991-83C15BDA0D23}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService.Redis", "Ems.CollectService.Redis\Ems.CollectService.Redis.csproj", "{8FA3FAC4-E29D-4E84-94F5-BEDA94EE5B5F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ems.CollectService.Analysis", "Ems.CollectService.Analysis\Ems.CollectService.Analysis.csproj", "{61813461-23F9-45B7-A002-D058A2610DBB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ems.CollectService.Timer", "Ems.CollectService.Timer\Ems.CollectService.Timer.csproj", "{68E1353B-AF61-4DBA-A956-90BA2D8FE8F5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6A006389-CD61-4388-A2CD-DECFC6434FB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A006389-CD61-4388-A2CD-DECFC6434FB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A006389-CD61-4388-A2CD-DECFC6434FB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A006389-CD61-4388-A2CD-DECFC6434FB1}.Release|Any CPU.Build.0 = Release|Any CPU + {BB8B9D9B-42FC-498B-B014-E0B267603C37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB8B9D9B-42FC-498B-B014-E0B267603C37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB8B9D9B-42FC-498B-B014-E0B267603C37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB8B9D9B-42FC-498B-B014-E0B267603C37}.Release|Any CPU.Build.0 = Release|Any CPU + {61477E6E-73D0-4876-9B72-0006395D0823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61477E6E-73D0-4876-9B72-0006395D0823}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61477E6E-73D0-4876-9B72-0006395D0823}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61477E6E-73D0-4876-9B72-0006395D0823}.Release|Any CPU.Build.0 = Release|Any CPU + {33FDD319-923E-4EAD-88C6-4503893B227B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33FDD319-923E-4EAD-88C6-4503893B227B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33FDD319-923E-4EAD-88C6-4503893B227B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33FDD319-923E-4EAD-88C6-4503893B227B}.Release|Any CPU.Build.0 = Release|Any CPU + {8E818AAC-81E1-49C4-9991-83C15BDA0D23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E818AAC-81E1-49C4-9991-83C15BDA0D23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E818AAC-81E1-49C4-9991-83C15BDA0D23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E818AAC-81E1-49C4-9991-83C15BDA0D23}.Release|Any CPU.Build.0 = Release|Any CPU + {8FA3FAC4-E29D-4E84-94F5-BEDA94EE5B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FA3FAC4-E29D-4E84-94F5-BEDA94EE5B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FA3FAC4-E29D-4E84-94F5-BEDA94EE5B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FA3FAC4-E29D-4E84-94F5-BEDA94EE5B5F}.Release|Any CPU.Build.0 = Release|Any CPU + {61813461-23F9-45B7-A002-D058A2610DBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61813461-23F9-45B7-A002-D058A2610DBB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61813461-23F9-45B7-A002-D058A2610DBB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61813461-23F9-45B7-A002-D058A2610DBB}.Release|Any CPU.Build.0 = Release|Any CPU + {68E1353B-AF61-4DBA-A956-90BA2D8FE8F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68E1353B-AF61-4DBA-A956-90BA2D8FE8F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68E1353B-AF61-4DBA-A956-90BA2D8FE8F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68E1353B-AF61-4DBA-A956-90BA2D8FE8F5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2DD5BF85-2F1C-4982-A86C-CF2BE54E3E4C} + EndGlobalSection +EndGlobal diff --git a/Ems.CollectService/Ems.CollectService.csproj b/Ems.CollectService/Ems.CollectService.csproj new file mode 100644 index 0000000..c79154b --- /dev/null +++ b/Ems.CollectService/Ems.CollectService.csproj @@ -0,0 +1,20 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + diff --git a/Ems.CollectService/Program.cs b/Ems.CollectService/Program.cs new file mode 100644 index 0000000..4906abd --- /dev/null +++ b/Ems.CollectService/Program.cs @@ -0,0 +1,51 @@ +using Ems.CollectService.Entity.config; +using Ems.CollectService.Redis; +using Ems.CollectService.SqlSugarCore; +using Ems.CollectService.Timer; +using Ems.CollectService.TouchSocket; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.IdentityModel.Logging; +using Newtonsoft.Json; +using NLog; +using NLog.Web; +using SqlSugar; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection.Metadata; + +namespace Ems.CollectService +{ + internal class Program + { + private static Logger logger = LogManager.GetCurrentClassLogger(); + + private static TcpServer service = TcpServer.Instance; + + private static AppConfig appConfig = AppConfig.Instance; + + private static DeleteLogFile deleteLogFile = DeleteLogFile.Instance; + + + static void Main(string[] args) + { + try + { + service.Init(appConfig.listenerPort); + //定时删除日志文件夹 + deleteLogFile.DeleteLogFileTimer(); + } + catch (Exception ex) + { + logger.Error($"服务启动异常{ex.Message}"); + } + Console.ReadLine(); + } + + + + + } +}