|
|
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|
|
using System.Configuration;
|
|
|
using System.Data;
|
|
|
using System.Drawing;
|
|
|
+using System.IO;
|
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Threading;
|
|
|
using System.Windows.Forms;
|
|
|
@@ -16,9 +17,12 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
{
|
|
|
#region 定义变量
|
|
|
private AppState appState = AppState.Stoped;
|
|
|
- private static Thread _SendThread;// 发送的线程
|
|
|
+ private static Thread _SendThread;// 处理上报抄表数据的线程
|
|
|
private static Thread heartBeatThread;// 断开超时链接的线程
|
|
|
+ private static Thread setParamThread;// 处理电池供电设备设参的线程
|
|
|
private static Queue _SendConidQueue = Queue.Synchronized(new Queue()); // 存储历史记录数据的队列
|
|
|
+ // 实例化Timer类,设置间隔时间(毫秒) 市电供电MODBUS主动获取数据定时器
|
|
|
+ private static System.Timers.Timer timer;
|
|
|
private static bool isTimeRuning = false; // MODBUS定时器是否执行中
|
|
|
private static bool isHeartBeatRuning = false; // 心跳进程是否执行中
|
|
|
|
|
|
@@ -28,6 +32,9 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
|
|
|
// 设备对应的最新链接ID
|
|
|
private static Dictionary<string, IntPtr> deveiceConnId = new Dictionary<string, IntPtr>();
|
|
|
+ private byte[] _paramData = new byte[0];
|
|
|
+ private string paramPath = AppDomain.CurrentDomain.BaseDirectory + @"远程设参\";
|
|
|
+
|
|
|
|
|
|
TcpServer server = new TcpServer();
|
|
|
|
|
|
@@ -92,8 +99,22 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
|
|
|
deviceTypes = ProtocolAnalysisTools.GetDeviceTypes();
|
|
|
|
|
|
- if ("1".Equals(ConfigurationManager.AppSettings["IsHaveModBus"]))
|
|
|
+ // 设备类型 1:电池供电;2:市电供电MODBUS;3:电池供电和市电供电MODBUS
|
|
|
+ string deviceType = ConfigurationManager.AppSettings["IsHaveModBus"];
|
|
|
+
|
|
|
+ if ("1".Equals(deviceType))
|
|
|
+ {
|
|
|
+ StartOrResumeSetParamThread(); // 启动电池供电设备设参线程
|
|
|
+ }
|
|
|
+ else if ("2".Equals(deviceType))
|
|
|
+ {
|
|
|
+ timer = new System.Timers.Timer(Convert.ToInt32(ConfigurationManager.AppSettings["ModBusQueryInterval"]));
|
|
|
+ StartModBusSendTimer(); // 启动ModBus定时发送读取数据任务
|
|
|
+ }
|
|
|
+ else if ("3".Equals(deviceType))
|
|
|
{
|
|
|
+ StartOrResumeSetParamThread(); // 启动电池供电设备设参线程
|
|
|
+ timer = new System.Timers.Timer(Convert.ToInt32(ConfigurationManager.AppSettings["ModBusQueryInterval"]));
|
|
|
StartModBusSendTimer(); // 启动ModBus定时发送读取数据任务
|
|
|
}
|
|
|
|
|
|
@@ -124,12 +145,32 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
if (server.Stop())
|
|
|
{
|
|
|
AddMsg($" > Server Stop 服务停止成功", lbReceiveData);
|
|
|
- heartBeatThread.Suspend();
|
|
|
+ // 设备类型 1:电池供电;2:市电供电MODBUS;3:电池供电和市电供电MODBUS
|
|
|
+ string deviceType = ConfigurationManager.AppSettings["IsHaveModBus"];
|
|
|
+
|
|
|
+ if ("1".Equals(deviceType))
|
|
|
+ {
|
|
|
+ setParamThread.Suspend(); // 挂起电池供电设参线程
|
|
|
+ }
|
|
|
+ else if ("2".Equals(deviceType))
|
|
|
+ {
|
|
|
+ isTimeRuning = false;
|
|
|
+ timer.Enabled = false; // 停止市电供电MODBUS主动获取数据定时器
|
|
|
+ }
|
|
|
+ else if ("3".Equals(deviceType))
|
|
|
+ {
|
|
|
+ setParamThread.Suspend(); // 挂起电池供电设参线程
|
|
|
+ isTimeRuning = false;
|
|
|
+ timer.Enabled = false; // 停止市电供电MODBUS主动获取数据定时器
|
|
|
+ }
|
|
|
+
|
|
|
+ isHeartBeatRuning = false;
|
|
|
+ heartBeatThread.Suspend(); // 挂起监控心跳线程
|
|
|
SetAppState(AppState.Stoped);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- AddMsg($" > Stop Error -> {server.ErrorMessage}({server.ErrorCode})", lbErrorData);
|
|
|
+ AddMsg($" > Stop Error 服务停止失败 -> {server.ErrorMessage}({server.ErrorCode})", lbErrorData);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -205,7 +246,7 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (lb.Items.Count > 100)
|
|
|
+ if (lb.Items.Count > 300)
|
|
|
{
|
|
|
lb.Items.RemoveAt(0);
|
|
|
}
|
|
|
@@ -244,6 +285,7 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
clientInfo.ConnId = connId;
|
|
|
clientInfo.IpAddress = ip;
|
|
|
clientInfo.Port = port;
|
|
|
+ clientInfo.IsEnd = false;
|
|
|
if (server.SetExtra(connId, clientInfo) == false)
|
|
|
{
|
|
|
AddMsg($" > [{connId},OnAccept] -> SetConnectionExtra fail", lbErrorData);
|
|
|
@@ -291,17 +333,15 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
if (clientInfo != null)
|
|
|
{
|
|
|
// clientInfo 就是accept里传入的附加数据了
|
|
|
-
|
|
|
AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} 接收数据 ({bytes.Length} bytes) \n {BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", " ")}", lbReceiveData);
|
|
|
|
|
|
-
|
|
|
PSProtocol psp = new PSProtocol();
|
|
|
// 接外包操作
|
|
|
ResMsg msg = ProtocolAnalysisTools.UnOuterPack(bytes, psp);
|
|
|
|
|
|
if (!msg.Result)
|
|
|
{
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 外包解包失败 \n {msg.Message}", lbReceiveData);
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 外包解包失败 \n {msg.Message}", lbErrorData);
|
|
|
|
|
|
}
|
|
|
else
|
|
|
@@ -321,7 +361,7 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
if (!ProtocolAnalysisTools.OuterPack(protocol2, out byte[] buffer2).Result)
|
|
|
{
|
|
|
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 心跳回应打包失败 ", lbReceiveData);
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 心跳回应打包失败 ", lbErrorData);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -331,10 +371,10 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (psp.Type == FrameType.Battery_GPRS_Report || psp.Type == FrameType.GPRS_Data)
|
|
|
+ if (psp.Type == FrameType.Battery_GPRS_Report || psp.Type == FrameType.GPRS_Data || psp.Type == FrameType.Battery_Param)
|
|
|
{
|
|
|
clientInfo.pSProtocol = psp;
|
|
|
- clientInfo.receiveTime = DateTime.Now; // 收到数据时间,MODBUS设备使用
|
|
|
+ clientInfo.ReceiveTime = DateTime.Now; // 收到数据时间,MODBUS设备使用
|
|
|
_SendConidQueue.Enqueue(clientInfo); // 将解包数据压入队列
|
|
|
|
|
|
byte[] buffer3;
|
|
|
@@ -346,7 +386,7 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
if (!ProtocolAnalysisTools.OuterPack(protocol2, out buffer3).Result)
|
|
|
{
|
|
|
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 历史记录回应打包失败 ", lbReceiveData);
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 历史记录回应打包失败 ", lbErrorData);
|
|
|
|
|
|
}
|
|
|
else
|
|
|
@@ -364,7 +404,7 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
else
|
|
|
{
|
|
|
|
|
|
- AddMsg($" > [{connId},OnReceive] -> 获取链接附加数据失败 ({bytes.Length} bytes)", lbReceiveData);
|
|
|
+ AddMsg($" > [{connId},OnReceive] -> 获取链接附加数据失败 ({bytes.Length} bytes)", lbErrorData);
|
|
|
}
|
|
|
|
|
|
return HandleResult.Ok;
|
|
|
@@ -415,28 +455,38 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
- #region 启动 发送线程
|
|
|
- private void StarSendThread()
|
|
|
- {
|
|
|
- _SendThread = new Thread(new ThreadStart(DealWithSendThread));
|
|
|
- var a = _SendThread.ThreadState;
|
|
|
- _SendThread.Start();
|
|
|
- }
|
|
|
- #endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 启动MODBUS轮询获取数据记录
|
|
|
/// </summary>
|
|
|
private void StartModBusSendTimer()
|
|
|
{
|
|
|
- int intervalTime = Convert.ToInt32(ConfigurationManager.AppSettings["ModBusQueryInterval"]);
|
|
|
- // 实例化Timer类,设置间隔时间(毫秒)
|
|
|
- System.Timers.Timer timer = new System.Timers.Timer(intervalTime);
|
|
|
timer.Elapsed += GetDeviceData; // 到达时间的时候执行事件;
|
|
|
timer.AutoReset = true; // 设置是执行一次(false)还是一直执行(true);
|
|
|
timer.Enabled = true; // 启动计时器
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 启动电池供电设备设参线程
|
|
|
+ /// </summary>
|
|
|
+ private void StartOrResumeSetParamThread()
|
|
|
+ {
|
|
|
+ if (setParamThread == null)
|
|
|
+ {
|
|
|
+ setParamThread = new Thread(new ThreadStart(SetParamThread));
|
|
|
+ }
|
|
|
+ switch (setParamThread.ThreadState)
|
|
|
+ {
|
|
|
+ case ThreadState.Stopped:
|
|
|
+ case ThreadState.Unstarted://未启动
|
|
|
+ setParamThread.Start();
|
|
|
+ break;
|
|
|
+ case ThreadState.Suspended://挂起
|
|
|
+ setParamThread.Resume();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 启动监控心跳是否超时进程
|
|
|
/// </summary>
|
|
|
@@ -455,6 +505,27 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
case ThreadState.Suspended: // 挂起
|
|
|
heartBeatThread.Resume();
|
|
|
break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 启动处理上报抄表数据的队列
|
|
|
+ /// </summary>
|
|
|
+ private void StartOrResumeSendThread()
|
|
|
+ {
|
|
|
+ if (_SendThread == null)
|
|
|
+ {
|
|
|
+ _SendThread = new Thread(new ThreadStart(DealWithSendThread));
|
|
|
+ }
|
|
|
+ switch (_SendThread.ThreadState)
|
|
|
+ {
|
|
|
+ case ThreadState.Stopped:
|
|
|
+ case ThreadState.Unstarted://未启动
|
|
|
+ _SendThread.Start();
|
|
|
+ break;
|
|
|
+ case ThreadState.Suspended://挂起
|
|
|
+ _SendThread.Resume();
|
|
|
+ break;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
@@ -516,30 +587,6 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- #region 启动或者恢复发送线程
|
|
|
- /// <summary>
|
|
|
- /// 启动处理上报抄表数据的队列
|
|
|
- /// </summary>
|
|
|
- private void StartOrResumeSendThread()
|
|
|
- {
|
|
|
- if (_SendThread == null)
|
|
|
- {
|
|
|
- _SendThread = new Thread(new ThreadStart(DealWithSendThread));
|
|
|
- }
|
|
|
- switch (_SendThread.ThreadState)
|
|
|
- {
|
|
|
- case ThreadState.Stopped:
|
|
|
- case ThreadState.Unstarted://未启动
|
|
|
- _SendThread.Start();
|
|
|
- break;
|
|
|
- case ThreadState.Suspended://挂起
|
|
|
- _SendThread.Resume();
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- #endregion
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// 循环处理发送读取抄表数据的指令
|
|
|
/// </summary>
|
|
|
@@ -659,13 +706,13 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
|
|
|
string agreement = ""; // 设备协议
|
|
|
string agreementParam = ""; // 设备协议参数
|
|
|
- string trandId = ""; // 通讯设备ID
|
|
|
+ Dictionary<string, string> trandevice = new Dictionary<string, string>(); // 通讯设备信息
|
|
|
for (int i = 0; i < dt.Rows.Count; i++)
|
|
|
{
|
|
|
|
|
|
string agreementTmp = dt.Rows[i]["设备协议"].ToString();
|
|
|
string agreementParamTmp = dt.Rows[i]["设备协议参数"].ToString();
|
|
|
- trandId = dt.Rows[i]["trandId"].ToString();
|
|
|
+ trandevice[dt.Rows[i]["transId"].ToString()] = dt.Rows[i]["名称"].ToString();
|
|
|
// 如果一个通讯设备下挂载多个设备,判断多个设备的传输协议是否一致,如果不一致则配置错误,无法进行数据转换
|
|
|
if ("".Equals(agreement) && "".Equals(agreementParam))
|
|
|
{
|
|
|
@@ -689,16 +736,55 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
{
|
|
|
if (msg.Message == "参数包")
|
|
|
{
|
|
|
- //this._paramData = new byte[data.Length];
|
|
|
- //data.CopyTo(this._paramData, 0);
|
|
|
- //if (this.DeviceDebug != null)
|
|
|
- //{
|
|
|
- // this.DeviceDebug(this, new CommDeviceDebugArgs(msg.Message, CommDeviceDebugArgs.DebugType.ReceiveData, data));
|
|
|
- //}
|
|
|
+ // 如果是参数包,记录回包内容,后面发送设参时判断回包内容用
|
|
|
+ if (!Directory.Exists(this.paramPath))
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 获取所有的设参文件夹
|
|
|
+ string[] directories = Directory.GetDirectories(this.paramPath);
|
|
|
+
|
|
|
+ if (directories.Length == 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ string destNumber = clientInfo.DestNumber;
|
|
|
+ // 一个传输设备可能对应多个设备信息及通讯设备
|
|
|
+ foreach (KeyValuePair<string, string> keyValuePair in trandevice)
|
|
|
+ {
|
|
|
+
|
|
|
+ RemoteTask remoteTask = new RemoteTask();
|
|
|
+ string filePath = "";
|
|
|
+ // 如果存在读取所有的设参文件内容
|
|
|
+ foreach (string str in directories)
|
|
|
+ {
|
|
|
+ if (str.Contains(keyValuePair.Key + "_" + keyValuePair.Value + "_"))
|
|
|
+ {
|
|
|
+ filePath = str;
|
|
|
+ remoteTask.GetRemoteTaskList(str, true);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (Task task in remoteTask.Tasklist)
|
|
|
+ {
|
|
|
+ if (psp.Data.Length >= 6)
|
|
|
+ {
|
|
|
+ task.TaskState = "完成";
|
|
|
+ task.ReceiveCode = new byte[psp.Data.Length];
|
|
|
+ psp.Data.CopyTo(task.ReceiveCode, 0);
|
|
|
+ task.OutPutFile(filePath, true);
|
|
|
+ task.DeleteFile(filePath);
|
|
|
+
|
|
|
+ clientInfo.ParamRetrunStatus = 1;
|
|
|
+ server.SetExtra(clientInfo.ConnId, clientInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_CellMonitor内包解包失败 \n {msg.Message}", lbReceiveData);
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_CellMonitor内包解包失败 \n {msg.Message}", lbErrorData);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
@@ -708,20 +794,11 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
// 如果是最后一包则发送校时指令
|
|
|
if (cm.IsEnd)
|
|
|
{
|
|
|
- PSProtocol protocol2 = new PSProtocol(psp.DestNumber, psp.SourceNumber, RandomTime());
|
|
|
- protocol2.Type = FrameType.Battery_EndComm;
|
|
|
-
|
|
|
- if (!ProtocolAnalysisTools.OuterPack(protocol2, out byte[] buffer3).Result)
|
|
|
- {
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_CellMonitor最后一包校时打包失败 \n", lbReceiveData);
|
|
|
-
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
-
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_CellMonitor最后一包校时 \n {BitConverter.ToString(buffer3, 0, buffer3.Length).Replace("-", " ")} ", lbReceiveData);
|
|
|
- server.Send(clientInfo.ConnId, buffer3, buffer3.Length);// 发送数据
|
|
|
- }
|
|
|
+ clientInfo.IsEnd = true;
|
|
|
+ clientInfo.TranDevice = trandevice;
|
|
|
+ clientInfo.DestNumber = psp.DestNumber;
|
|
|
+ clientInfo.SourceNumber = psp.SourceNumber;
|
|
|
+ server.SetExtra(clientInfo.ConnId, clientInfo);
|
|
|
}
|
|
|
|
|
|
List<HistoryRecord> list = new List<HistoryRecord>();
|
|
|
@@ -754,7 +831,7 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
- // 将数据进行封装,一条数据可能对于多个设备的数据,通过[设备信息表]中设备的[用户站参数]与CONF\US_Common.xml进行匹配拆分
|
|
|
+ // 将数据进行封装,一条数据可能对于多个设备的数据,通过[设备信息表]中设备的[用户站参数]与CONF\UserStation_Config.xml进行匹配拆分
|
|
|
List<HistoryRecord> item = this.UpdateHistoryData(cm.Record[i].PickTime, cm, dt, _analogData, _switchData);
|
|
|
if (item != null && item.Count > 0)
|
|
|
{
|
|
|
@@ -772,27 +849,42 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
{
|
|
|
#region 根据上报数据的功能码区分获取对应的下发指令的MODBUS对象
|
|
|
Modbus.FunctionCode code = (Modbus.FunctionCode)psp.Data[1];
|
|
|
+ bool unPackFlag = false;
|
|
|
+ string unPackRs = "";
|
|
|
Modbus modbus = new Modbus();
|
|
|
- if (code == Modbus.FunctionCode.F04)
|
|
|
- {
|
|
|
- modbus = sendComm[trandId][0];
|
|
|
- }
|
|
|
- else if (code == Modbus.FunctionCode.F02)
|
|
|
+ // 一个传输设备可能对应多个设备信息及通讯设备
|
|
|
+ foreach (KeyValuePair<string, string> keyValuePair in trandevice)
|
|
|
{
|
|
|
- modbus = sendComm[trandId][1];
|
|
|
+ if (code == Modbus.FunctionCode.F04)
|
|
|
+ {
|
|
|
+ modbus = sendComm[keyValuePair.Key][0];
|
|
|
+ }
|
|
|
+ else if (code == Modbus.FunctionCode.F02)
|
|
|
+ {
|
|
|
+ modbus = sendComm[keyValuePair.Key][1];
|
|
|
+ }
|
|
|
+ // 内包进行解包,解包后的数据存入modbus.UpDataArea
|
|
|
+ ResMsg msg = Modbus.UnPack(psp.Data, modbus);
|
|
|
+ if (msg.Result)
|
|
|
+ {
|
|
|
+ unPackFlag = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ unPackRs = msg.Message; ;
|
|
|
+ }
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
- // 内包进行解包,解包后的数据存入modbus.UpDataArea
|
|
|
- ResMsg msg = Modbus.UnPack(psp.Data, modbus);
|
|
|
|
|
|
- if (!msg.Result)
|
|
|
+ if (!unPackFlag)
|
|
|
{
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({modbus.UpDataArea.Length} bytes) CD_PSController内包解包失败,数据类型{code} \n {msg.Message}", lbReceiveData);
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_PSController内包解包失败,数据类型{code} \n {unPackRs}", lbErrorData);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({modbus.UpDataArea.Length} bytes) CD_PSController内包解包成功,数据类型{code} \n {BitConverter.ToString(modbus.UpDataArea, 0, modbus.UpDataArea.Length).Replace("-", " ")}", lbReceiveData);
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_PSController内包解包成功,数据类型{code} \n {BitConverter.ToString(modbus.UpDataArea, 0, modbus.UpDataArea.Length).Replace("-", " ")}", lbReceiveData);
|
|
|
|
|
|
// 获取配置的上报抄表数据的数据信息CONF/DataCellConfig.xml中CD_PSController节点,根据传输设备中的设备协议参数关联取那些字段
|
|
|
ModBusDeviceType modBusDeviceType = new ModBusDeviceType(agreementParam);
|
|
|
@@ -812,8 +904,8 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
- // 将数据进行封装,一条数据可能对于多个设备的数据,通过[设备信息表]中设备的[用户站参数]与CONF\US_Common.xml进行匹配拆分
|
|
|
- List<HistoryRecord> item = this.UpdateHistoryData(clientInfo.receiveTime, null, dt, _analogData, _switchData);
|
|
|
+ // 将数据进行封装,一条数据可能对于多个设备的数据,通过[设备信息表]中设备的[用户站参数]与CONF\UserStation_Config.xml进行匹配拆分
|
|
|
+ List<HistoryRecord> item = this.UpdateHistoryData(clientInfo.ReceiveTime, null, dt, _analogData, _switchData);
|
|
|
|
|
|
// 保存抄表数据
|
|
|
ProtocolAnalysisTools.SaveRecord(item);
|
|
|
@@ -828,6 +920,57 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 电池供电设备发送设参及校时指令进程
|
|
|
+ /// </summary>
|
|
|
+ private void SetParamThread()
|
|
|
+ {
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ // 获取所有链接ID
|
|
|
+ IntPtr[] allConnIds = server.GetAllConnectionIDs();
|
|
|
+ if (allConnIds == null || allConnIds.Length == 0)
|
|
|
+ {
|
|
|
+ Thread.Sleep(1000);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (IntPtr connId in allConnIds)
|
|
|
+ {
|
|
|
+ ClientInfo clientInfo = (ClientInfo)server.GetExtra(connId);
|
|
|
+ if (clientInfo == null)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 如果链接中数据包是最后一包进行下发设参和校时指令
|
|
|
+ if (!clientInfo.IsEnd)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (clientInfo.TranDevice == null)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Dictionary<string, string> trandevice = clientInfo.TranDevice;
|
|
|
+ string destNumber = clientInfo.DestNumber;
|
|
|
+ string sourceNumber = clientInfo.SourceNumber;
|
|
|
+ // 一个传输设备可能对应多个设备信息及通讯设备
|
|
|
+ foreach (KeyValuePair<string, string> keyValuePair in trandevice)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 发送设参指令
|
|
|
+ SendSetParam(clientInfo, keyValuePair.Key, keyValuePair.Value);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} CD_CellMonitor最后发送设参指令失败 \n {ex.Message}", lbErrorData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
///
|
|
|
/// </summary>
|
|
|
@@ -891,24 +1034,11 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
return hislist;
|
|
|
}
|
|
|
|
|
|
- private byte[] RandomTime()
|
|
|
- {
|
|
|
- int num = new Random().Next(5);
|
|
|
- TimeSpan span = (TimeSpan)(DateTime.Now.AddSeconds((double)num) - Convert.ToDateTime("2000-01-01 00:00:00"));
|
|
|
- int totalSeconds = (int)span.TotalSeconds;
|
|
|
- byte[] buffer = new byte[4];
|
|
|
- for (int i = 0; i < 4; i++)
|
|
|
- {
|
|
|
- buffer[4 - (i + 1)] = (byte)(totalSeconds >> (i * 8));
|
|
|
- }
|
|
|
- return buffer;
|
|
|
- }
|
|
|
-
|
|
|
private void timer1_Tick(object sender, EventArgs e)
|
|
|
{
|
|
|
this.toolStripStatusLabel6.Text = "系统时间:" + DateTime.Now.ToString();
|
|
|
TimeSpan span = (TimeSpan)(DateTime.Now - this.dtStartTime);
|
|
|
- this.toolStripStatusLabel4.Text = this.RunTime((int)span.TotalSeconds);
|
|
|
+ this.toolStripStatusLabel4.Text = ProtocolAnalysisTools.RunTime((int)span.TotalSeconds);
|
|
|
string coonNum = "0";
|
|
|
if (server.IsStarted && server.GetAllConnectionIDs() != null)
|
|
|
{
|
|
|
@@ -917,61 +1047,155 @@ namespace NB_IOT_TCP_HP_SOCKET
|
|
|
this.toolStripStatusLabel3.Text = "客户端连接数:" + coonNum;
|
|
|
}
|
|
|
|
|
|
- private string RunTime(int s)
|
|
|
+ private void button3_Click(object sender, EventArgs e)
|
|
|
{
|
|
|
- int num = 0;
|
|
|
- int num2 = 0;
|
|
|
- int num3 = 0;
|
|
|
- int num4 = 0;
|
|
|
- if (s < 60)
|
|
|
+ ParamSetForm paramSetForm = new ParamSetForm();
|
|
|
+ paramSetForm.ShowDialog();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 下发设参指令
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="clientInfo"></param>
|
|
|
+ /// <param name="id"></param>
|
|
|
+ /// <param name="name"></param>
|
|
|
+ private void SendSetParam(ClientInfo clientInfo, string id, string name)
|
|
|
+ {
|
|
|
+ if (!Directory.Exists(this.paramPath))
|
|
|
{
|
|
|
- num4 = s;
|
|
|
+ // 没有设参指令则校时关机
|
|
|
+ TimingShutDown(clientInfo);
|
|
|
+ return;
|
|
|
}
|
|
|
- else if ((60 <= s) && (s <= 0xe10))
|
|
|
+ // 获取所有的设参文件夹
|
|
|
+ string[] directories = Directory.GetDirectories(this.paramPath);
|
|
|
+
|
|
|
+ if (directories.Length == 0)
|
|
|
{
|
|
|
- num3 = s / 60;
|
|
|
- num4 = s % 60;
|
|
|
+ // 没有设参指令则校时关机
|
|
|
+ TimingShutDown(clientInfo);
|
|
|
+ return;
|
|
|
}
|
|
|
- else if ((0xe10 <= s) && (s <= 0x15180))
|
|
|
+
|
|
|
+ RemoteTask remoteTask = new RemoteTask();
|
|
|
+ string filePath = "";
|
|
|
+ // 如果存在读取所有的设参文件内容
|
|
|
+ foreach (string str in directories)
|
|
|
{
|
|
|
- num2 = s / 0xe10;
|
|
|
- num3 = (s % 0xe10) / 60;
|
|
|
- num4 = (s % 0xe10) % 60;
|
|
|
+ if (str.Contains(id + "_" + name + "_"))
|
|
|
+ {
|
|
|
+ filePath = str;
|
|
|
+ // 获取所有待发送的参数文件内容
|
|
|
+ remoteTask.GetRemoteTaskList(str, true);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if (remoteTask.Tasklist == null || remoteTask.Tasklist.Count == 0)
|
|
|
{
|
|
|
- num = s / 0x15180;
|
|
|
- num2 = (s % 0x15180) / 0xe10;
|
|
|
- num3 = ((s % 0x15180) % 0xe10) / 60;
|
|
|
- num4 = ((s % 0x15180) % 0xe10) % 60;
|
|
|
+ // 没有设参指令则校时关机
|
|
|
+ TimingShutDown(clientInfo);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int paramSendNum = clientInfo.ParamSendNum; // 已发送次数
|
|
|
+ int paramSendStatus = clientInfo.ParamSendStatus; // 发送状态
|
|
|
+ DateTime paramSendTime = clientInfo.ParamSendTime; // 上次发送时间
|
|
|
+
|
|
|
+ int paramSendNumTmp = Convert.ToInt32(ConfigurationManager.AppSettings["ParamSendNum"]); // 电池供电最大下发指令次数
|
|
|
+ int paramSendInterval = Convert.ToInt32(ConfigurationManager.AppSettings["ParamSendInterval"]); // 电池供电同一设备下发指令每次间隔时间(秒)
|
|
|
+
|
|
|
+ // 循环下发设参指令
|
|
|
+ foreach (Task task in remoteTask.Tasklist)
|
|
|
+ {
|
|
|
+ TimeSpan span = (TimeSpan)(DateTime.Now - paramSendTime);
|
|
|
+ // 未发送;已发送&&发送次数小于配置的最大发送次数&&两次间隔时间大于配置的间隔时间
|
|
|
+ if (paramSendStatus == 0 || paramSendStatus == 1 && paramSendNum < paramSendNumTmp && span.TotalSeconds >= paramSendInterval)
|
|
|
+ {
|
|
|
+ PSProtocol protocol2 = new PSProtocol(clientInfo.DestNumber, clientInfo.SourceNumber, task.SendCode);
|
|
|
+ protocol2.Type = FrameType.Battery_Param;
|
|
|
+
|
|
|
+ if (!ProtocolAnalysisTools.OuterPack(protocol2, out byte[] buffer3).Result)
|
|
|
+ {
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {clientInfo.SourceNumber} ({buffer3.Length} bytes) CD_CellMonitor下发设参打包失败 \n", lbErrorData);
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 下发设参数
|
|
|
+ bool sendFlag = server.Send(clientInfo.ConnId, buffer3, buffer3.Length);
|
|
|
+ // 发送成功更新发送次数和发送时间
|
|
|
+ if (sendFlag)
|
|
|
+ {
|
|
|
+ clientInfo.ParamSendStatus = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ clientInfo.ParamSendStatus = 0;
|
|
|
+ }
|
|
|
+ clientInfo.ParamSendTime = DateTime.Now;
|
|
|
+ clientInfo.ParamSendNum = paramSendNum + 1;
|
|
|
+ server.SetExtra(clientInfo.ConnId, clientInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (paramSendNum >= paramSendNumTmp)
|
|
|
+ {
|
|
|
+ task.TaskState = "超时";
|
|
|
+ task.OutPutFile(filePath, false);
|
|
|
+ // 校时关机
|
|
|
+ TimingShutDown(clientInfo);
|
|
|
+ }
|
|
|
}
|
|
|
- return ("系统持续运行:" + num.ToString() + "天" + num2.ToString() + "小时" + num3.ToString() + "分" + num4.ToString() + "秒");
|
|
|
}
|
|
|
|
|
|
- private void button3_Click(object sender, EventArgs e)
|
|
|
+ /// <summary>
|
|
|
+ /// 发送校时关机指令
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="clientInfo"></param>
|
|
|
+ private void TimingShutDown(ClientInfo clientInfo)
|
|
|
{
|
|
|
- ParamSetForm paramSetForm = new ParamSetForm();
|
|
|
- paramSetForm.ShowDialog();
|
|
|
+ PSProtocol protocol2 = new PSProtocol(clientInfo.DestNumber, clientInfo.SourceNumber, ProtocolAnalysisTools.RandomTime());
|
|
|
+ protocol2.Type = FrameType.Battery_EndComm;
|
|
|
+
|
|
|
+ if (!ProtocolAnalysisTools.OuterPack(protocol2, out byte[] buffer3).Result)
|
|
|
+ {
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {clientInfo.SourceNumber} ({buffer3.Length} bytes) CD_CellMonitor最后一包校时打包失败 \n", lbErrorData);
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {clientInfo.SourceNumber} ({buffer3.Length} bytes) CD_CellMonitor最后一包校时 \n {BitConverter.ToString(buffer3, 0, buffer3.Length).Replace("-", " ")} ", lbReceiveData);
|
|
|
+ if(server.Send(clientInfo.ConnId, buffer3, buffer3.Length)) // 发送数据
|
|
|
+ {
|
|
|
+ clientInfo.IsEnd = false;
|
|
|
+ clientInfo.ParamSendNum = 0;
|
|
|
+ clientInfo.ParamSendStatus = 0;
|
|
|
+ clientInfo.ParamRetrunStatus = 0;
|
|
|
+ server.SetExtra(clientInfo.ConnId, clientInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
public class ClientInfo
|
|
|
{
|
|
|
- public IntPtr ConnId { get; set; }
|
|
|
+ public IntPtr ConnId { get; set; } // 链接ID
|
|
|
public IntPtr NewConnId { get; set; }
|
|
|
- public string IpAddress { get; set; }
|
|
|
- public ushort Port { get; set; }
|
|
|
+ public string IpAddress { get; set; } // 客户端IP
|
|
|
+ public ushort Port { get; set; }// 客户端端口号
|
|
|
public PSProtocol pSProtocol { get; set; }
|
|
|
- public byte[] BArr { get; set; }// 存储最新数据
|
|
|
- public byte[] BSendArr { get; set; }// 存储发送的数据域的数据
|
|
|
- public string Address { get; set; }// 水表地址
|
|
|
- public CmdType CmdType { get; set; }// 指令类型
|
|
|
- public bool flag { get; set; } // 指令是否正确
|
|
|
- public string msg { get; set; } // 返回信息
|
|
|
- public int meterId { get; set; }
|
|
|
- public DateTime receiveTime { get; set; }
|
|
|
- public int SendCmdRecordId { get; set; }// 发送的缓存命令的id
|
|
|
- public int SendCmdParentId { get; set; }// 发送缓存命令的母id
|
|
|
+ public string DestNumber { get; set; } // 目标地址
|
|
|
+ public string SourceNumber { get; set; } // 源地址
|
|
|
+ public bool IsEnd { get; set; } // 是否是最后一包数据
|
|
|
+ public Dictionary<string, string> TranDevice { get; set; }
|
|
|
+ public DateTime ReceiveTime { get; set; }
|
|
|
+ #region 设参指令发送时使用属性
|
|
|
+ public DateTime ParamSendTime { get; set; } // 设参发送时间
|
|
|
+ public int ParamSendStatus { get; set; } // 设参发送状态 0:未发送;1:已发送
|
|
|
+ public int ParamRetrunStatus { get; set; } // 设参回包状态 0:未回包;1:已回包
|
|
|
+ public int ParamSendNum { get; set; } // 设参发送次数
|
|
|
+ #endregion
|
|
|
}
|
|
|
}
|