添加项目文件。

master
wenjy 1 year ago
parent ceb1f5456b
commit 98b54eab7f

@ -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<BufferAnalysis> lazy = new Lazy<BufferAnalysis>(() => new BufferAnalysis());
public static BufferAnalysis Instance
{
get
{
return lazy.Value;
}
}
private BufferAnalysis() { }
/// <summary>
/// 登录指令
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
/// <param name="count"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 心跳指令
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
/// <param name="count"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 电力仪表
/// </summary>
/// <param name="socketClient"></param>
/// <param name="buffer"></param>
/// <param name="count"></param>
/// <param name="collectType"></param>
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>(recordDnbInstant).ExecuteCommandAsync();
var info = SqlSugarHelper.Db.Insertable<RecordDnbInstant>(recordDnbInstant).ExecuteCommand();
if (info > 0)
{
logger.Info($"仪表:{recordDnbInstant.monitorId}数据保存成功");
}
}
iFirstMeterID += 70;
}//end for
}
catch (Exception ex)
{
logger.Error($"EDataMessageHandlingAsync电力仪表数据解析异常{ex.Message}");
}
}
/// <summary>
/// 水表数据
/// </summary>
/// <param name="socketClient"></param>
/// <param name="buffer"></param>
/// <param name="length"></param>
/// <param name="collectType"></param>
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>(recordWaterInstant).ExecuteCommandAsync();
var info = SqlSugarHelper.Db.Insertable<RecordWaterInstant>(recordWaterInstant).ExecuteCommand();
if (info > 0)
{
logger.Info($"仪表:{recordWaterInstant.monitorId}数据保存成功");
}
}
iFirstMeterID += 58;
}//end for
}
catch (Exception ex)
{
logger.Info($"SDataMessageHandling水表数据解析异常{ex}");
}
}
/// <summary>
/// 修改终端连接状态
/// </summary>
/// <param name="collectId">终端编号</param>
/// <param name="onLineFlag">终端状态0-离线1-在线</param>
public void UpdateCollectDeviceOnLineState(string collectId, int onLineFlag)
{
try
{
int result = SqlSugarHelper.Db.Updateable<BaseCollectDeviceInfo>()
.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;
}
}
}
}

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.1.3" />
<PackageReference Include="TouchSocket" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ems.CollectService.Common\Ems.CollectService.Common.csproj" />
<ProjectReference Include="..\Ems.CollectService.Entity\Ems.CollectService.Entity.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nancy" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.2.3" />
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
</ItemGroup>
<ItemGroup>
<None Update="C:\Users\Lenovo\.nuget\packages\nlog.config\4.7.15\contentFiles\any\any\NLog.config">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Update="NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -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
{
/// <summary>
/// 配置操作类
/// </summary>
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);
/// <summary>
/// 写INI文件
/// </summary>
/// <param name="Section"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void IniWriteValue(string Section, string Key, string Value)
{
WritePrivateProfileString(Section, Key, Value, this.path);
}
/// <summary>
/// 读取INI文件
/// </summary>
/// <param name="Section"></param>
/// <param name="Key"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 删除ini文件下所有段落
/// </summary>
public void ClearAllSection()
{
IniWriteValue(null, null, null);
}
/// <summary>
/// 删除ini文件下personal段落下的所有键
/// </summary>
/// <param name="Section"></param>
public void ClearSection(string Section)
{
IniWriteValue(Section, null, null);
}
}
}

@ -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<JsonChange> lazy = new Lazy<JsonChange>(() => new JsonChange());
public static JsonChange Instance
{
get
{
return lazy.Value;
}
}
private JsonChange() { }
/// <summary>
/// Model 实体转json
/// </summary>
/// <param name="Model">可以是单个实体也可是实体集ToList()</param>
/// <returns></returns>
public string ModeToJson(object Model)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
try
{
string str = serializer.Serialize(Model);
return str;
}
catch (Exception)
{
return "";
}
}
/// <summary>
/// json实体转Model
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonStr"></param>
/// <returns></returns>
public T JsonToMode<T>(string jsonStr)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
try
{
var info = serializer.Deserialize<T>(jsonStr);
return info;
}
catch (Exception)
{
return default(T);
}
}
/// <summary>
/// object转dictionary
/// </summary>
/// <param name="jsonData"></param>
/// <returns></returns>
public Dictionary<string, object> objectToDictionary(string jsonData)
{
Dictionary<string, object> result = new Dictionary<string, object>();
var inf = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonData);
foreach (KeyValuePair<string, object> 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<string, object> 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<string, object> ite in info)
{
result.Add(item.Key + ite.Key, ite.Value);
}
continue;
}
}
result.Add(item.Key, item.Value);
}
return result;
}
}
}

@ -0,0 +1,510 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Ems.CollectService.Common
{
/// <summary>
/// 工具类
/// </summary>
public sealed class MsgUtil
{
private static readonly Lazy<MsgUtil> lazy = new Lazy<MsgUtil>(() => new MsgUtil());
public static MsgUtil Instance
{
get
{
return lazy.Value;
}
}
private MsgUtil() { }
#region 数据解析公共方法
/// <summary>
/// 字节数组转换成结构体
/// </summary>
/// <param name="buf"></param>
/// <param name="len"></param>
/// <param name="type"></param>
/// <returns></returns>
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;
}
//// <summary>
/// 结构体转byte数组
/// </summary>
/// <param name="structObj">要转换的结构体</param>
/// <returns>转换后的byte数组</returns>
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 消息验证方法
/// <summary>
/// CS和校验
/// </summary>
/// <param name="Abyte"></param>
/// <returns></returns>
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;
}
/// <summary>
/// BCC异或取反校验
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 将字符串强制转换成int转换失败则返回0
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
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();
}
/// <summary>
/// 从十进制转换到十六进制
/// </summary>
/// <param name="ten"></param>
/// <returns></returns>
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 消息公用的头尾
/// <summary>
/// 能源通讯协议结构体
/// </summary>
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;
};
/// <summary>
/// 头文件
/// </summary>
[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; //数据长度
}
/// <summary>
/// 结尾
/// </summary>
[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;
}
/// <summary>
/// 写入反馈 125+5
/// </summary>
[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 长度个字节数据
}
/// <summary>
/// 自报数据 125+6
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct RecAutoData
{
public Head head;
public int num;//合并编号
public RecDataCell recDatas;//自报数据
public Tail tail;
}
/// <summary>
///心跳 101
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct Heart
{
public Head head;
public Tail tail;
}
#endregion
#region 与上层应用层 消息指令
/// <summary>
/// 收到的消息指令
/// </summary>
enum RecAppMsgType
{
_ReadEpc = 125 + 3,
_ReadData = 125 + 4,
_WirteData = 125 + 5,
_AutoSendData,
_HeartBeat = 101,
_ReadEquipState = 125 + 102,
_SendGetSoftState = 125 + 103,
}
/// <summary>
/// 发送的消息指令
/// </summary>
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
}

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<variable name="myvar" value="myvalue" />
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets async ="true">
<!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
-->
<!--
Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
<!--Type输出类型
Console 输出到控制台
Debugger 输出到VS输出窗口
File 输出到文件
Mail 输出为邮件发送
Network 输出到网络地址
Database 输出到数据库-->
<default-target-parameters xsi:type="File" createDirs="true" keepFileOpen="true" autoFlush="false" openFileFlushTimeout="10" openFileCacheTimeout="30" archiveAboveSize="52428800"
archiveNumbering="Sequence" concurrentWrites="true" encoding="UTF-8" />
<!-- 输出到文件,这个文件记录错误日志 -->
<target xsi:type="File" name="Error" fileName="Log\${shortdate}\Error.txt"
layout="
【时间】:${date} ${newline}
【级别】:${level:uppercase=true} ${newline}
【程序集信息】:${callsite:className=True:fileName=True:includeSourcePath=False:methodName=True} ${newline}
【堆栈信息】:${stacktrace}${newline}
【日志名称】:${logger}${newline}
【异常信息】:${exception:format=ToString}${newline}
【内容】:${message}${newline}" />
<!-- 输出到文件,这个文件记录警告日志 -->
<target xsi:type="File" name="Warn" fileName="Log\${shortdate}\Warn.txt"
layout="
【时间】:${date} ${newline}
【内容】:${message}${newline}" />
<!-- 输出到文件,这个文件记录消息日志 -->
<target xsi:type="File" name="Info" fileName="Log\${shortdate}\Info.txt"
layout="
【时间】:${date} ${newline}
【内容】:${message}${newline}" />
<!-- 输出到文件,这个文件记录操作日志 -->
<target xsi:type="File" name="Trace" fileName="Log\${shortdate}\Trace.txt"
layout="
【时间】:${date} ${newline}
【内容】:${message}${newline}" />
<!--输出到控制台并添加必要的输出布局layout-->
<target xsi:type="Debugger" name="Debugger" layout="● ${longdate} ${level} ${logger} ${stacktrace}${message}" />
<!--说明layout指定输出文件内容的样式 ${longdate}是日期(具体到毫秒),${level}是日志的等级;${message}是具体要输出的内容。-->
<!--输出日志到CSV文件-->
<!--<target name="csv" xsi:type="File" fileName="Log\${shortdate}\Csv.csv">
<layout xsi:type="CSVLayout">
<column name="time" layout="${longdate}" />
<column name="message" layout="${message}" />
<column name="logger" layout="${logger}" />
<column name="level" layout="${level}" />
</layout>
</target>-->
<target name="Debugger" xsi:type="Console" />
</targets>
<rules>
<!-- add your logging rules here -->
<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
<!--NLog支持如下几种记录等级
1.Trace - 最常见的记录信息,一般用于普通输出
2.Debug - 同样是记录信息不过出现的频率要比Trace少一些一般用来调试程序
3.Info - 信息类型的消息
4.Warn - 警告信息,一般用于比较重要的场合
5.Error - 错误信息
6.Fatal - 致命异常信息。一般来讲,发生致命异常之后程序将无法继续执行。-->
<logger name="*" level="Error" writeTo="Error" />
<logger name="*" level="Warn" writeTo="Warn" />
<logger name="*" level="Info" writeTo="Info" />
<logger name="*" level="Trace" writeTo="Trace" />
<!--将所有记录的信息输出至控制台-->
<logger name="*" writeTo="Debugger" />
<!--<logger name="*" minlevel="Debug" writeTo="Debugger" />
此处增加了一个minlevel="Warn"规则就变成了将所有记录等级大于等于Warn的等级信息输出至控制台-->
<!--<logger name="*" minlevel="Debug" writeTo="csv" />-->
</rules>
</nlog>

@ -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<StringChange> lazy = new Lazy<StringChange>(() => new StringChange());
public static StringChange Instance
{
get
{
return lazy.Value;
}
}
private StringChange() { }
#region 数据类型转换函数
/// <summary>
/// 将字符串强制转换成int转换失败则返回0
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// char数组转Array
/// </summary>
/// <param name="cha"></param>
/// <param name="len"></param>
/// <returns></returns>
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
/// <param name="strbase64">64Base码</param>
/// <param name="path">保存路径</param>
/// <param name="filename">文件名称</param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取时间戳
/// </summary>
/// <returns></returns>
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;
}
}
}

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace Ems.CollectService.Entity
{
/// <summary>
/// 采集设备信息
///</summary>
[SugarTable("base_collect_device_info")]
public class BaseCollectDeviceInfo
{
/// <summary>
/// 自增标识
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true ,IsIdentity = true )]
public int Objid { get; set; }
/// <summary>
/// 设备编号
///</summary>
[SugarColumn(ColumnName="collect_device_id" ,IsPrimaryKey = true )]
public string CollectDeviceId { get; set; }
/// <summary>
/// 设备名称
///</summary>
[SugarColumn(ColumnName="collect_device_name" )]
public string CollectDeviceName { get; set; }
/// <summary>
/// 生产厂家
///</summary>
[SugarColumn(ColumnName="manufacturer" )]
public string Manufacturer { get; set; }
/// <summary>
/// 生产编号
///</summary>
[SugarColumn(ColumnName="factory_number" )]
public string FactoryNumber { get; set; }
/// <summary>
/// 生产日期
///</summary>
[SugarColumn(ColumnName="produce_date" )]
public DateTime? ProduceDate { get; set; }
/// <summary>
/// 安装位置
///</summary>
[SugarColumn(ColumnName="address" )]
public string Address { get; set; }
/// <summary>
/// 能源类型
///</summary>
[SugarColumn(ColumnName="energy_type" )]
public int? EnergyType { get; set; }
/// <summary>
/// 型号
///</summary>
[SugarColumn(ColumnName="model" )]
public string Model { get; set; }
/// <summary>
/// 地址
///</summary>
[SugarColumn(ColumnName="ip" )]
public string Ip { get; set; }
/// <summary>
/// 备注
///</summary>
[SugarColumn(ColumnName="remark" )]
public string Remark { get; set; }
/// <summary>
/// 终端在线状态
///</summary>
[SugarColumn(ColumnName="online_state" )]
public int? OnlineState { get; set; }
/// <summary>
/// 权限标识(部门)
///</summary>
[SugarColumn(ColumnName="dept_id" )]
public int? DeptId { get; set; }
/// <summary>
/// 权限标识(用户)
///</summary>
[SugarColumn(ColumnName="user_id" )]
public int? UserId { get; set; }
/// <summary>
/// 创建人
///</summary>
[SugarColumn(ColumnName="create_by" )]
public string CreateBy { get; set; }
/// <summary>
/// 创建时间
///</summary>
[SugarColumn(ColumnName="create_time" )]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 更新人
///</summary>
[SugarColumn(ColumnName="update_by" )]
public string UpdateBy { get; set; }
/// <summary>
/// 更新时间
///</summary>
[SugarColumn(ColumnName="update_time" )]
public DateTime? UpdateTime { get; set; }
}
}

@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace Ems.CollectService.Entity
{
/// <summary>
/// 计量设备信息
///</summary>
[SugarTable("base_monitor_info")]
public class BaseMonitorInfo
{
/// <summary>
/// 自增标识
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true ,IsIdentity = true )]
public int Objid { get; set; }
/// <summary>
/// 父级编号
///</summary>
[SugarColumn(ColumnName="parent_id" )]
public string ParentId { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName="monitor_id" ,IsPrimaryKey = true )]
public string MonitorId { get; set; }
/// <summary>
/// 计量设备名称
///</summary>
[SugarColumn(ColumnName="monitor_name" )]
public string MonitorName { get; set; }
/// <summary>
/// 计量设备位置
///</summary>
[SugarColumn(ColumnName="monitor_addr" )]
public string MonitorAddr { get; set; }
/// <summary>
/// 计量设备类型
///</summary>
[SugarColumn(ColumnName="monitor_type" )]
public int? MonitorType { get; set; }
/// <summary>
/// 计量设备状态
///</summary>
[SugarColumn(ColumnName="monitor_status" )]
public int? MonitorStatus { get; set; }
/// <summary>
/// 采集设备编号
///</summary>
[SugarColumn(ColumnName="collect_device_id" )]
public string CollectDeviceId { get; set; }
/// <summary>
/// 祖级列表
///</summary>
[SugarColumn(ColumnName="ancestors" )]
public string Ancestors { get; set; }
/// <summary>
/// 等级
///</summary>
[SugarColumn(ColumnName="grade" )]
public int? Grade { get; set; }
/// <summary>
/// 建筑类型
///</summary>
[SugarColumn(ColumnName="build_id" )]
public string BuildId { get; set; }
/// <summary>
/// 分项类型
///</summary>
[SugarColumn(ColumnName="subentry_id" )]
public string SubentryId { get; set; }
/// <summary>
/// 业态类型
///</summary>
[SugarColumn(ColumnName="business_id" )]
public string BusinessId { get; set; }
/// <summary>
/// 传感器仪表
///</summary>
[SugarColumn(ColumnName="meter_type_id" )]
public string MeterTypeId { get; set; }
/// <summary>
/// 测量器具
///</summary>
[SugarColumn(ColumnName="meter_id" )]
public string MeterId { get; set; }
/// <summary>
/// 修正值
///</summary>
[SugarColumn(ColumnName="correct_value" )]
public decimal? CorrectValue { get; set; }
/// <summary>
/// PT值
///</summary>
[SugarColumn(ColumnName="pt" )]
public int? Pt { get; set; }
/// <summary>
/// CT值
///</summary>
[SugarColumn(ColumnName="ct" )]
public int? Ct { get; set; }
/// <summary>
/// 是否虚拟
/// 默认值: _utf8mb4'false'
///</summary>
[SugarColumn(ColumnName="is_ammeter" )]
public string IsAmmeter { get; set; }
/// <summary>
/// 通断复位
///</summary>
[SugarColumn(ColumnName="is_key_monitor" )]
public int? IsKeyMonitor { get; set; }
/// <summary>
/// 是否断路
///</summary>
[SugarColumn(ColumnName="is_circuit" )]
public int? IsCircuit { get; set; }
/// <summary>
/// 权限标识(部门)
///</summary>
[SugarColumn(ColumnName="dept_id" )]
public int? DeptId { get; set; }
/// <summary>
/// 权限标识(用户)
///</summary>
[SugarColumn(ColumnName="user_id" )]
public int? UserId { get; set; }
/// <summary>
/// 创建人
///</summary>
[SugarColumn(ColumnName="create_by" )]
public string CreateBy { get; set; }
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName="create_time" )]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 更新人
///</summary>
[SugarColumn(ColumnName="update_by" )]
public string UpdateBy { get; set; }
/// <summary>
/// 更新时间
///</summary>
[SugarColumn(ColumnName="update_time" )]
public DateTime? UpdateTime { get; set; }
}
}

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ems.CollectService.Common\Ems.CollectService.Common.csproj" />
<ProjectReference Include="..\Ems.CollectService.SqlSugarCore\Ems.CollectService.SqlSugarCore.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace Ems.CollectService.Entity
{
/// <summary>
/// 电实时数据
///</summary>
[SugarTable("record_dnb_instant")]
public class RecordDnbInstant
{
/// <summary>
/// 编号
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true ,IsIdentity = true )]
public long objid { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName="monitor_id" )]
public string monitorId { get; set; }
/// <summary>
/// 采集时间
///</summary>
[SugarColumn(ColumnName="collect_time" )]
public DateTime? collectTime { get; set; }
/// <summary>
/// A项电压
///</summary>
[SugarColumn(ColumnName="vA" )]
public decimal? vA { get; set; }
/// <summary>
/// B项电压
///</summary>
[SugarColumn(ColumnName="vB" )]
public decimal? vB { get; set; }
/// <summary>
/// C项电压
///</summary>
[SugarColumn(ColumnName="vC" )]
public decimal? vC { get; set; }
/// <summary>
/// A项电流
///</summary>
[SugarColumn(ColumnName="iA" )]
public decimal? iA { get; set; }
/// <summary>
/// B项电流
///</summary>
[SugarColumn(ColumnName="iB" )]
public decimal? iB { get; set; }
/// <summary>
/// C项电流
///</summary>
[SugarColumn(ColumnName="iC" )]
public decimal? iC { get; set; }
/// <summary>
/// 记录时间
///</summary>
[SugarColumn(ColumnName="record_time" )]
public DateTime? recordTime { get; set; }
/// <summary>
/// 功率因数
///</summary>
[SugarColumn(ColumnName="glys" )]
public decimal? glys { get; set; }
/// <summary>
/// 正向有功
///</summary>
[SugarColumn(ColumnName="zxyg" )]
public decimal? zxyg { get; set; }
/// <summary>
/// 有功功率
///</summary>
[SugarColumn(ColumnName="active_power" )]
public decimal? activePower { get; set; }
/// <summary>
/// 无功功率
///</summary>
[SugarColumn(ColumnName="reactive_power" )]
public decimal? reactivePower { get; set; }
/// <summary>
/// 电耗量
///</summary>
[SugarColumn(ColumnName="consumption" )]
public decimal? consumption { get; set; }
/// <summary>
/// 采集方式
/// 默认值: 0
///</summary>
[SugarColumn(ColumnName="collect_type" )]
public int? collectType { get; set; }
/// <summary>
/// 权限标识(部门)
///</summary>
[SugarColumn(ColumnName="dept_id" )]
public int? deptId { get; set; }
/// <summary>
/// 权限标识(用户)
///</summary>
[SugarColumn(ColumnName="user_id" )]
public int? userId { get; set; }
}
}

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace Ems.CollectService.Entity
{
/// <summary>
/// 水实时数据
///</summary>
[SugarTable("record_water_instant")]
public class RecordWaterInstant
{
/// <summary>
/// 自增标识
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true )]
public int objid { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName="monitor_id" )]
public string monitorId { get; set; }
/// <summary>
/// 采集时间
///</summary>
[SugarColumn(ColumnName="collect_time" )]
public DateTime? collectTime { get; set; }
/// <summary>
/// 瞬时流量
///</summary>
[SugarColumn(ColumnName="flux_flow" )]
public decimal? fluxFlow { get; set; }
/// <summary>
/// 累计流量
///</summary>
[SugarColumn(ColumnName="water_flow" )]
public decimal? waterFlow { get; set; }
/// <summary>
/// 记录时间
///</summary>
[SugarColumn(ColumnName="record_time" )]
public DateTime? recordTime { get; set; }
/// <summary>
/// 采集方式
/// 默认值: 0
///</summary>
[SugarColumn(ColumnName="collect_type" )]
public int? collectType { get; set; }
/// <summary>
/// 权限标识(部门)
///</summary>
[SugarColumn(ColumnName="dept_id" )]
public int? deptId { get; set; }
/// <summary>
/// 权限标识(用户)
///</summary>
[SugarColumn(ColumnName="user_id" )]
public int? userId { get; set; }
}
}

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace Ems.CollectService.Entity
{
/// <summary>
/// 参数配置表
///</summary>
[SugarTable("sys_config")]
public class SysConfig
{
/// <summary>
/// 参数主键
///</summary>
[SugarColumn(ColumnName="config_id" ,IsPrimaryKey = true ,IsIdentity = true )]
public int ConfigId { get; set; }
/// <summary>
/// 参数名称
/// 默认值:
///</summary>
[SugarColumn(ColumnName="config_name" )]
public string ConfigName { get; set; }
/// <summary>
/// 参数键名
/// 默认值:
///</summary>
[SugarColumn(ColumnName="config_key" )]
public string ConfigKey { get; set; }
/// <summary>
/// 参数键值
/// 默认值:
///</summary>
[SugarColumn(ColumnName="config_value" )]
public string ConfigValue { get; set; }
/// <summary>
/// 系统内置Y是 N否
/// 默认值: N
///</summary>
[SugarColumn(ColumnName="config_type" )]
public string ConfigType { get; set; }
/// <summary>
/// 创建者
/// 默认值:
///</summary>
[SugarColumn(ColumnName="create_by" )]
public string CreateBy { get; set; }
/// <summary>
/// 创建时间
///</summary>
[SugarColumn(ColumnName="create_time" )]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 更新者
/// 默认值:
///</summary>
[SugarColumn(ColumnName="update_by" )]
public string UpdateBy { get; set; }
/// <summary>
/// 更新时间
///</summary>
[SugarColumn(ColumnName="update_time" )]
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 备注
///</summary>
[SugarColumn(ColumnName="remark" )]
public string Remark { get; set; }
}
}

@ -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<AppConfig> lazy = new Lazy<AppConfig>(() => 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");
/// <summary>
/// 监听端口
/// </summary>
public int listenerPort
{
get { return stringChange.ParseToInt(iNIFile.IniReadValue("SystemConfig", "listenerPort")); }
set { iNIFile.IniWriteValue("SystemConfig", "listenerPort", value.ToString()); }
}
/// <summary>
/// Mysql地址
/// </summary>
public string mysqlStr
{
get { return iNIFile.IniReadValue("SystemConfig", "mysqlConnStr"); }
set { iNIFile.IniWriteValue("SystemConfig", "mysqlConnStr", value.ToString()); }
}
}
}

@ -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; //尾盘
}
}

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StackExchange.Redis" Version="2.6.104" />
</ItemGroup>
</Project>

@ -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;
/// <summary>
/// 单例获取
/// </summary>
public static ConnectionMultiplexer RedisConn
{
get
{
if (_redisConn == null)
{
// 锁定某一代码块,让同一时间只有一个线程访问该代码块
lock (Locker)
{
if (_redisConn == null || !_redisConn.IsConnected)
{
_redisConn = ConnectionMultiplexer.Connect(ConfigurationOptions);
}
}
}
return _redisConn;
}
}
}
}

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SqlSugarCore" Version="5.1.4.64" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ems.CollectService.Common\Ems.CollectService.Common.csproj" />
</ItemGroup>
</Project>

@ -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
/// <summary>
/// 连接服务器数据库
/// </summary>
/// <returns></returns>
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;
}
}
}

@ -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<ConnectionConfig>,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
});
}
}

@ -0,0 +1,89 @@
using Ems.CollectService.Common;
using NLog;
using System;
using System.IO;
namespace Ems.CollectService.Timer
{
/// <summary>
/// 删除日志文件
/// </summary>
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<DeleteLogFile> lazy = new Lazy<DeleteLogFile>(() => new DeleteLogFile());
public static DeleteLogFile Instance
{
get
{
return lazy.Value;
}
}
private DeleteLogFile() { }
/// <summary>
/// 删除日志定时器
/// </summary>
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}");
}
}
/// <summary>
/// 删除指定路径下的超时文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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}");
}
}
}
}

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ems.CollectService.Common\Ems.CollectService.Common.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TouchSocket" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ems.CollectService.Analysis\Ems.CollectService.Analysis.csproj" />
<ProjectReference Include="..\Ems.CollectService.Common\Ems.CollectService.Common.csproj" />
<ProjectReference Include="..\Ems.CollectService.Redis\Ems.CollectService.Redis.csproj" />
</ItemGroup>
</Project>

@ -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<MyFixedHeaderRequestInfo>
{
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();
}
}
}
}

@ -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; }
/// <summary>
/// 报文头:5AA5
/// </summary>
public byte[] Header { get => m_sync; set => m_sync = value; }
/// <summary>
/// 自定义属性,标识实际数据
/// </summary>
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;
}
}
}

@ -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<TcpServer> lazy = new Lazy<TcpServer>(() => 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<CheckClearPlugin>().SetDuration(new TimeSpan(0, 0, 0, 5, 0));
}))
.Start();//启动
ReadMeterTask(); //点抄指令下发
logger.Info($"采集服务启动成功,监听端口:{serverPort}");
}
catch(Exception ex)
{
logger.Error($"采集服务启动异常:{ex}");
throw new Exception(ex.Message);
}
}
/// <summary>
/// 缓存器
/// </summary>
/// <param name="clientId"></param>
/// <param name="requestInfo"></param>
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);
}
}
/// <summary>
/// 点抄指令下发
/// </summary>
private void ReadMeterTask()
{
try
{
var t = Task.Run(async delegate
{
while (true)
{
//SysConfig sysConfig = baseService.Queryable<SysConfig>().InSingle(14);
SysConfig sysConfig = SqlSugarHelper.Db.Queryable<SysConfig>().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<SysConfig>().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}");
}
}
/// <summary>
/// 集中器编号格式化=>ClientID
/// </summary>
/// <param name="monitorId"></param>
/// <returns></returns>
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;
}
}
}

@ -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

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ems.CollectService.Common\Ems.CollectService.Common.csproj" />
<ProjectReference Include="..\Ems.CollectService.Entity\Ems.CollectService.Entity.csproj" />
<ProjectReference Include="..\Ems.CollectService.Redis\Ems.CollectService.Redis.csproj" />
<ProjectReference Include="..\Ems.CollectService.Timer\Ems.CollectService.Timer.csproj" />
<ProjectReference Include="..\Ems.CollectService.TouchSocket\Ems.CollectService.TouchSocket.csproj" />
</ItemGroup>
</Project>

@ -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();
}
}
}
Loading…
Cancel
Save