yinyujing 4 éve
szülő
commit
297ca332de

+ 4 - 1
NB_IOT_TCP_HP_SOCKET/App.config

@@ -4,11 +4,14 @@
     <add key="db" value="Data Source=127.0.0.1;Initial Catalog=sdww_qz;Persist Security Info=True;User ID=sa;Password=123456;Pooling=yes;MultipleActiveResultSets=True" />
 
     <!--心跳间隔时间(毫秒)-->
-    <add key="ConnectionTimeOut" value="12000000" />
+    <add key="ConnectionTimeOut" value="120000" />
 
     <!--执行断开静默链接间隔时间毫秒-->
     <add key="ConnectionTimeOutInterval" value="10000" />
 
+    <!--是否有MODBUS类设备1:有;0:无-->
+    <add key="IsHaveModBus" value="1" />
+    
     <!--MODBUS轮询获取抄表数据时间毫秒-->
     <add key="ModBusQueryInterval" value="120000" />
 

+ 14 - 7
NB_IOT_TCP_HP_SOCKET/MainForm_TCP.Designer.cs

@@ -56,6 +56,7 @@
             this.btnStart = new System.Windows.Forms.Button();
             this.splitContainer1 = new System.Windows.Forms.SplitContainer();
             this.panel1 = new System.Windows.Forms.Panel();
+            this.timer1 = new System.Windows.Forms.Timer(this.components);
             this.groupBox3.SuspendLayout();
             this.statusStrip1.SuspendLayout();
             this.groupBox2.SuspendLayout();
@@ -95,13 +96,12 @@
             this.groupBox3.TabIndex = 8;
             this.groupBox3.TabStop = false;
             this.groupBox3.Text = "错误信息";
-            this.groupBox3.Visible = false;
             // 
             // toolStripStatusLabel6
             // 
             this.toolStripStatusLabel6.Name = "toolStripStatusLabel6";
-            this.toolStripStatusLabel6.Size = new System.Drawing.Size(59, 17);
-            this.toolStripStatusLabel6.Text = "系统时间:";
+            this.toolStripStatusLabel6.Size = new System.Drawing.Size(68, 17);
+            this.toolStripStatusLabel6.Text = "系统时间";
             // 
             // toolStripStatusLabel5
             // 
@@ -112,8 +112,8 @@
             // toolStripStatusLabel4
             // 
             this.toolStripStatusLabel4.Name = "toolStripStatusLabel4";
-            this.toolStripStatusLabel4.Size = new System.Drawing.Size(83, 17);
-            this.toolStripStatusLabel4.Text = "系统持续运行:";
+            this.toolStripStatusLabel4.Size = new System.Drawing.Size(92, 17);
+            this.toolStripStatusLabel4.Text = "系统持续运行";
             // 
             // toolStripStatusLabel7
             // 
@@ -124,8 +124,8 @@
             // toolStripStatusLabel3
             // 
             this.toolStripStatusLabel3.Name = "toolStripStatusLabel3";
-            this.toolStripStatusLabel3.Size = new System.Drawing.Size(83, 17);
-            this.toolStripStatusLabel3.Text = "客户端连接数:";
+            this.toolStripStatusLabel3.Size = new System.Drawing.Size(92, 17);
+            this.toolStripStatusLabel3.Text = "客户端连接数";
             // 
             // toolStripStatusLabel2
             // 
@@ -332,6 +332,12 @@
             this.panel1.Size = new System.Drawing.Size(776, 48);
             this.panel1.TabIndex = 6;
             // 
+            // timer1
+            // 
+            this.timer1.Enabled = true;
+            this.timer1.Interval = 1000;
+            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+            // 
             // MainForm_TCP
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -388,5 +394,6 @@
         private System.Windows.Forms.Button btnStart;
         private System.Windows.Forms.SplitContainer splitContainer1;
         private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Timer timer1;
     }
 }

+ 246 - 84
NB_IOT_TCP_HP_SOCKET/MainForm_TCP.cs

@@ -18,10 +18,12 @@ namespace NB_IOT_TCP_HP_SOCKET
         private static Thread _SendThread;// 发送的线程
         private static Thread heartBeatThread;// 断开超时链接的线程
         private static Queue _SendConidQueue = Queue.Synchronized(new Queue()); // 存储历史记录数据的队列
-        private static string connectionTimeOut = ConfigurationManager.AppSettings["ConnectionTimeOut"]; 
-        private static string ConnectionTimeOutInterval = ConfigurationManager.AppSettings["ConnectionTimeOutInterval"];
-        private static string ModBusQueryInterval = ConfigurationManager.AppSettings["ModBusQueryInterval"];
-        private static bool isTimeRuning = false;
+        private static string connectionTimeOut = ConfigurationManager.AppSettings["ConnectionTimeOut"];  // 心跳间隔时间(毫秒)
+        private static string ConnectionTimeOutInterval = ConfigurationManager.AppSettings["ConnectionTimeOutInterval"]; // 执行断开静默链接间隔时间毫秒
+        private static string ModBusQueryInterval = ConfigurationManager.AppSettings["ModBusQueryInterval"]; // MODBUS轮询获取抄表数据时间毫秒
+        private static string IsHaveModBus = ConfigurationManager.AppSettings["IsHaveModBus"]; // 是否有MODBUS类设备1:有;0:无
+        private static bool isTimeRuning = false; // MODBUS定时器是否执行中
+        private static bool isHeartBeatRuning = false; // 心跳进程是否执行中
 
         private static Dictionary<string, object> deviceTypes;
 
@@ -34,6 +36,7 @@ namespace NB_IOT_TCP_HP_SOCKET
 
         private delegate void ShowMsg(string msg, ListBox lb);
         private ShowMsg AddMsgDelegate;
+        private DateTime dtStartTime = DateTime.Now;
         #endregion 
 
         public MainForm_TCP()
@@ -46,12 +49,6 @@ namespace NB_IOT_TCP_HP_SOCKET
             try
             {
                 server.MarkSilence = true;
-                server.DisconnectSilenceConnections(5000);//测试将事假调长
-
-                // 本机测试没必要改地址,有需求请注释或删除
-                ///this.txtIpAddress.ReadOnly = true;
-                this.groupBox3.Height = 0;
-                this.splitContainer1.Height = this.groupBox1.Height + 75;
 
                 // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作
                 AddMsgDelegate = new ShowMsg(AddMsg);
@@ -68,7 +65,7 @@ namespace NB_IOT_TCP_HP_SOCKET
                 // 其他设置
                 // server.NoDelay = true;
 
-                SetAppState(AppState.Stoped);
+                SetAppState(AppState.UnStart);
             }
             catch (Exception ex)
             {
@@ -97,13 +94,16 @@ namespace NB_IOT_TCP_HP_SOCKET
                 if (server.Start())
                 {
                     SetAppState(AppState.Started);
-                    AddMsg($"$Server Start OK -> ({ip}:{port})", lbReceiveData);
+                    AddMsg($" > Server Start OK -> ({ip}:{port}) 服务启动成功", lbReceiveData);
 
                     deviceTypes = ProtocolAnalysisTools.GetDeviceTypes();
 
-                    StartModBusSendTimer();// 启动ModBus定时发送读取数据任务
+                    if ("1".Equals(IsHaveModBus))
+                    {
+                        StartModBusSendTimer(); // 启动ModBus定时发送读取数据任务
+                    }
 
-                    StartOrResumeHeartBeatThread();// 启动心跳超市检测
+                    StartOrResumeHeartBeatThread(); // 启动心跳超时检测
                 }
                 else
                 {
@@ -125,16 +125,17 @@ namespace NB_IOT_TCP_HP_SOCKET
         private void btnStop_Click(object sender, EventArgs e)
         {
             SetAppState(AppState.Stoping);
+
             // 停止服务
-            AddMsg("$Server Stop", lbReceiveData);
             if (server.Stop())
             {
+                AddMsg($" > Server Stop 服务停止成功", lbReceiveData);
                 heartBeatThread.Suspend();
                 SetAppState(AppState.Stoped);
             }
             else
             {
-                AddMsg($"$Stop Error -> {server.ErrorMessage}({server.ErrorCode})", lbErrorData);
+                AddMsg($" > Stop Error -> {server.ErrorMessage}({server.ErrorCode})", lbErrorData);
             }
         }
 
@@ -165,10 +166,36 @@ namespace NB_IOT_TCP_HP_SOCKET
         void SetAppState(AppState state)
         {
             appState = state;
-            this.btnStart.Enabled = (appState == AppState.Stoped);
+            string status = "";
+            switch (state)
+            {
+                case AppState.UnStart:
+                    status = "未启动";
+                    break;
+                case AppState.Starting:
+                    status = "启动中";
+                    break;
+                case AppState.Started:
+                    status = "已启动";
+                    break;
+                case AppState.Stoping:
+                    status = "停止中";
+                    break;
+                case AppState.Stoped:
+                    status = "已停止";
+                    break;
+                case AppState.Error:
+                    status = "错误";
+                    break;
+                default:
+                    status = "";
+                    break;
+            }
+            this.toolStripStatusLabel1.Text = "状态:" + status;
+            this.btnStart.Enabled = (appState == AppState.Stoped || appState == AppState.UnStart);
             this.btnStop.Enabled = (appState == AppState.Started);
-            this.txtIpAddress.Enabled = (appState == AppState.Stoped);
-            this.txtPort.Enabled = (appState == AppState.Stoped);
+            this.txtIpAddress.Enabled = (appState == AppState.Stoped || appState == AppState.UnStart);
+            this.txtPort.Enabled = (appState == AppState.Stoped || appState == AppState.UnStart);
             this.txtDisConn.Enabled = (appState == AppState.Started);
             this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0);
         }
@@ -190,7 +217,7 @@ namespace NB_IOT_TCP_HP_SOCKET
                 {
                     lb.Items.RemoveAt(0);
                 }
-                lb.Items.Add(DateTime.Now.ToString() + msg);
+                lb.Items.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + msg);
                 lb.TopIndex = lb.Items.Count - (int)(lb.Height / lb.ItemHeight);
                 LogUtil.WriteLog(msg);
             }
@@ -213,7 +240,7 @@ namespace NB_IOT_TCP_HP_SOCKET
             ushort port = 0;
             if (server.GetRemoteAddress(connId, ref ip, ref port))
             {
-                AddMsg($" > [{connId},OnAccept] -> PASS({ip.ToString()}:{port})", lbReceiveData);
+                AddMsg($" > [{connId},OnAccept] -> PASS({ip.ToString()}:{port}) 建立链接成功", lbReceiveData);
             }
             else
             {
@@ -237,7 +264,12 @@ namespace NB_IOT_TCP_HP_SOCKET
         #region OnHandShake(IServer sender, IntPtr connId)
         private HandleResult OnHandShake(IServer sender, IntPtr connId)
         {
-            AddMsg($" > [{connId},OnHandShake]", lbReceiveData);
+            string ip = string.Empty;
+            ushort port = 0;
+            if (server.GetRemoteAddress(connId, ref ip, ref port))
+            {
+                AddMsg($" > [{connId},OnHandShake] -> PASS({ip.ToString()}:{port}) 链接握手成功", lbReceiveData);
+            }
             return HandleResult.Ok;
         }
         #endregion
@@ -245,8 +277,13 @@ namespace NB_IOT_TCP_HP_SOCKET
         #region OnSend(IServer sender, IntPtr connId, byte[] bytes)
         HandleResult OnSend(IServer sender, IntPtr connId, byte[] bytes)
         {
-            // 服务器发数据了
-            AddMsg($" > [{connId},OnSend] -> ({bytes.Length} bytes) -> {BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", " ")}", lbSendData);
+            string ip = string.Empty;
+            ushort port = 0;
+            if (server.GetRemoteAddress(connId, ref ip, ref port))
+            {
+                // 服务器发数据了
+                AddMsg($" > [{connId},OnSend] -> {ip.ToString()}:{port} 发送数据 ({bytes.Length} bytes) -> {BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", " ")}", lbSendData);
+            }
             return HandleResult.Ok;
         }
         #endregion
@@ -263,17 +300,17 @@ namespace NB_IOT_TCP_HP_SOCKET
                 {
                     // clientInfo 就是accept里传入的附加数据了
 
-                    AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) \n {BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", " ")}", lbReceiveData);
+                    AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} 接收数据 ({bytes.Length} bytes) \n {BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", " ")}", lbReceiveData);
+
 
-                    // 将数据压入队列后 吊起线程
                     PSProtocol psp = new PSProtocol();
-                    //ProtocolAnalysisTools.UpSimplePack(clientInfo, bytes);
+                    // 接外包操作
                     ResMsg msg = ProtocolAnalysisTools.UnOuterPack(bytes, psp);
 
                     if (!msg.Result)
                     {
-                        AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) 外包解包失败 \n {msg.Message}", lbReceiveData);
-                        
+                        AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 外包解包失败 \n {msg.Message}", lbReceiveData);
+
                     }
                     else
                     {
@@ -282,9 +319,9 @@ namespace NB_IOT_TCP_HP_SOCKET
                         PSProtocol protocol2;
                         byte[] array = new byte[psp.Data.Length];
                         psp.Data.CopyTo(array, 0);
-                        AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) 外包解包成功 \n {BitConverter.ToString(psp.Data, 0, psp.Data.Length).Replace("-", " ")}", lbReceiveData);
-
+                        AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 外包解包成功 \n {BitConverter.ToString(psp.Data, 0, psp.Data.Length).Replace("-", " ")}", lbReceiveData);
 
+                        // 判断包类型 心跳或数据包
                         if (psp.Type == FrameType.GPRS_Link)
                         {
                             byte[] buffer2;
@@ -293,11 +330,11 @@ namespace NB_IOT_TCP_HP_SOCKET
                             if (!ProtocolAnalysisTools.OuterPack(protocol2, out buffer2).Result)
                             {
 
-                                AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) 心跳回应打包失败 ", lbReceiveData);
+                                AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 心跳回应打包失败 ", lbReceiveData);
                             }
                             else
                             {
-                                AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) 心跳回应成功 \n {BitConverter.ToString(buffer2, 0, buffer2.Length).Replace("-", " ")} ", lbReceiveData);
+                                AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 心跳回应成功 \n {BitConverter.ToString(buffer2, 0, buffer2.Length).Replace("-", " ")} ", lbReceiveData);
                                 server.Send(clientInfo.ConnId, buffer2, buffer2.Length);// 发送数据
                             }
                         }
@@ -306,34 +343,37 @@ namespace NB_IOT_TCP_HP_SOCKET
                             if (psp.Type == FrameType.Battery_GPRS_Report || psp.Type == FrameType.GPRS_Data)
                             {
                                 clientInfo.pSProtocol = psp;
-                                _SendConidQueue.Enqueue(clientInfo);// 将连接id 压入队列
+                                clientInfo.receiveTime = DateTime.Now; // 收到数据时间,MODBUS设备使用
+                                _SendConidQueue.Enqueue(clientInfo); // 将解包数据压入队列
 
                                 byte[] buffer3;
                                 protocol2 = new PSProtocol(psp.DestNumber, psp.SourceNumber, new byte[0]);
                                 protocol2.Type = psp.Type;
                                 protocol2.PackNum = psp.PackNum;
+
+                                // 封装回包信息,并发送
                                 if (!ProtocolAnalysisTools.OuterPack(protocol2, out buffer3).Result)
                                 {
 
-                                    AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) 历史记录回应打包失败 ", lbReceiveData);
+                                    AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 历史记录回应打包失败 ", lbReceiveData);
 
                                 }
                                 else
                                 {
 
-                                    AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} ({bytes.Length} bytes) 历史记录回应成功 \n {BitConverter.ToString(buffer3, 0, buffer3.Length).Replace("-", " ")} ", lbReceiveData);
+                                    AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {psp.SourceNumber} ({bytes.Length} bytes) 历史记录回应成功 \n {BitConverter.ToString(buffer3, 0, buffer3.Length).Replace("-", " ")} ", lbReceiveData);
                                     server.Send(clientInfo.ConnId, buffer3, buffer3.Length);// 发送数据
                                 }
                             }
                         }
                     }
 
-                    StartOrResumeSendThread();// 调起发送线
+                    StartOrResumeSendThread(); // 启动处理数据进
                 }
                 else
                 {
 
-                    AddMsg($" > [{connId},OnReceive] -> ({bytes.Length} bytes)", lbReceiveData);
+                    AddMsg($" > [{connId},OnReceive] -> 获取链接附加数据失败 ({bytes.Length} bytes)", lbReceiveData);
                 }
 
                 return HandleResult.Ok;
@@ -349,20 +389,24 @@ namespace NB_IOT_TCP_HP_SOCKET
         HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode)
         {
             if (errorCode == 0)
-                //AddMsg(string.Format(" > [{0},OnClose]", connId));
                 AddMsg($" > [{connId},OnClose]", lbReceiveData);
             else
-                //AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", connId, enOperation, errorCode));
                 AddMsg($" > [{connId},OnError] -> OP:{enOperation},CODE:{errorCode}", lbReceiveData);
-            // return HPSocketSdk.HandleResult.Ok;
-            ClientInfo info = server.GetExtra<ClientInfo>(connId);
-            if (info.SendCmdRecordId > 0)
+
+            // 移除设备的链接关联关系
+            foreach (KeyValuePair<string, IntPtr> conn in deveiceConnId)
             {
-                //DealWithCacheCommand.UpdataCacheCommandType(info.SendCmdRecordId, info.SendCmdParentId, 3); // 这里有点问题 特殊情况下 会有不更新的
+                IntPtr deviceConnId = conn.Value;
+                if (connId == deviceConnId)
+                {
+                    deveiceConnId.Remove(conn.Key);
+                    break;
+                }
             }
+
+            // 移除附加数据
             if (server.RemoveExtra(connId) == false)
             {
-                //AddMsg(string.Format(" > [{0},OnClose] -> SetConnectionExtra({0}, null) fail", connId));
                 AddMsg($" > [{connId},OnClose] -> SetConnectionExtra({connId}, null) fail", lbErrorData);
             }
 
@@ -394,13 +438,16 @@ namespace NB_IOT_TCP_HP_SOCKET
         private void StartModBusSendTimer()
         {
             int intervalTime = Convert.ToInt32(ModBusQueryInterval);
-            //实例化Timer类,设置间隔时间(毫秒)
+            // 实例化Timer类,设置间隔时间(毫秒)
             System.Timers.Timer timer = new System.Timers.Timer(intervalTime);
-            timer.Elapsed += GetDeviceData;//到达时间的时候执行事件;
-            timer.AutoReset = true;//设置是执行一次(false)还是一直执行(true);
-            timer.Enabled = true;//启动计时器
+            timer.Elapsed += GetDeviceData; // 到达时间的时候执行事件;
+            timer.AutoReset = true; // 设置是执行一次(false)还是一直执行(true);
+            timer.Enabled = true; // 启动计时器
         }
 
+        /// <summary>
+        /// 启动监控心跳是否超时进程
+        /// </summary>
         private void StartOrResumeHeartBeatThread()
         {
             if (heartBeatThread == null)
@@ -410,38 +457,66 @@ namespace NB_IOT_TCP_HP_SOCKET
             switch (heartBeatThread.ThreadState)
             {
                 case ThreadState.Stopped:
-                case ThreadState.Unstarted://未启动
+                case ThreadState.Unstarted: // 未启动
                     heartBeatThread.Start();
                     break;
-                case ThreadState.Suspended://挂起
+                case ThreadState.Suspended: // 挂起
                     heartBeatThread.Resume();
                     break;
 
             }
         }
+
+        /// <summary>
+        /// 处理心跳超时的链接
+        /// </summary>
         private void DisconnectConnections()
         {
             while (true)
             {
-                // 获取所有连接
-                IntPtr[] allConnIds = server.GetAllConnectionIDs();
-                
-                foreach (KeyValuePair<string, IntPtr> conn in deveiceConnId)
+                if (!isHeartBeatRuning)
                 {
-                    IntPtr connId = conn.Value;
-                    if (allConnIds == null || Array.IndexOf(allConnIds, connId) == -1)
-                    {
-                        deveiceConnId.Remove(conn.Key);
-                        continue;
-                    }
-                    uint SilenceTime = 0;
-                    if (server.GetSilencePeriod(connId, ref SilenceTime))
+                    isHeartBeatRuning = true;
+                    try
                     {
-                        if (SilenceTime > Convert.ToInt32(connectionTimeOut))
+
+                        // 获取所有连接
+                        IntPtr[] allConnIds = server.GetAllConnectionIDs();
+
+                        List<string> disconnectId = new List<string>();
+
+                        // 处理设备对应的链接,如果超时则断开链接并移除设备-链接对应关系
+                        foreach (KeyValuePair<string, IntPtr> conn in deveiceConnId)
                         {
-                            server.Disconnect(connId);
-                            deveiceConnId.Remove(conn.Key);
+                            IntPtr connId = conn.Value;
+                            if (allConnIds == null || Array.IndexOf(allConnIds, connId) == -1)
+                            {
+                                disconnectId.Add(conn.Key);
+                                continue;
+                            }
+                            uint SilenceTime = 0;
+                            if (server.GetSilencePeriod(connId, ref SilenceTime))
+                            {
+                                if (SilenceTime > Convert.ToInt32(connectionTimeOut))
+                                {
+                                    server.Disconnect(connId);
+                                    disconnectId.Add(conn.Key);
+                                }
+                            }
+                        }
+
+                        foreach (string key in disconnectId)
+                        {
+                            deveiceConnId.Remove(key);
                         }
+                        // 关闭所有静默链接(主要是只建立链接没有上报过数据的链接)
+                        server.DisconnectSilenceConnections(Convert.ToUInt32(connectionTimeOut));
+
+                        isHeartBeatRuning = false;
+                    }
+                    catch (Exception)
+                    {
+                        isHeartBeatRuning = false;
                     }
                 }
                 Thread.Sleep(Convert.ToInt32(ConnectionTimeOutInterval));
@@ -449,6 +524,9 @@ namespace NB_IOT_TCP_HP_SOCKET
         }
 
         #region 启动或者恢复发送线程
+        /// <summary>
+        /// 启动处理上报抄表数据的队列
+        /// </summary>
         private void StartOrResumeSendThread()
         {
             if (_SendThread == null)
@@ -514,6 +592,7 @@ namespace NB_IOT_TCP_HP_SOCKET
                             {
                                 if (server.Send(conId, buffer, buffer.Length))
                                 {
+                                    AddMsg($" > [{conId},OnSend] -> {transId} ({buffer.Length} bytes) ModBus读模拟量寄存器 \n {BitConverter.ToString(buffer, 0, buffer.Length).Replace("-", " ")}", lbReceiveData);
                                     sendFlag = true;
                                     modbusArr[0] = modbus;
                                 }
@@ -527,6 +606,7 @@ namespace NB_IOT_TCP_HP_SOCKET
                             {
                                 if (server.Send(conId, buffer, buffer.Length))
                                 {
+                                    AddMsg($" > [{conId},OnSend] -> {transId} ({buffer.Length} bytes) ModBus读开关量输入状态 \n {BitConverter.ToString(buffer, 0, buffer.Length).Replace("-", " ")}", lbReceiveData);
                                     sendFlag = true;
                                     modbusArr[1] = modbus;
                                 }
@@ -544,10 +624,13 @@ namespace NB_IOT_TCP_HP_SOCKET
                 {
                     isTimeRuning = false;
                 }
-                
+
             }
         }
 
+        /// <summary>
+        /// 处理上报抄表数据(上报抄表数据已经存入队列)
+        /// </summary>
         private void DealWithSendThread()
         {
             //定义变量
@@ -563,15 +646,16 @@ namespace NB_IOT_TCP_HP_SOCKET
                     }
                     else
                     {
-                        Label_1:
+                    Label_1:
                         arr = null;
                         // 处理数据
                         ClientInfo clientInfo = (ClientInfo)_SendConidQueue.Dequeue();
                         PSProtocol psp = clientInfo.pSProtocol;
-                        clientInfo.NewConnId = deveiceConnId[psp.SourceNumber];
+                        //clientInfo.NewConnId = deveiceConnId[psp.SourceNumber];
                         // 原地址
                         string sourceNumber = psp.SourceNumber;
 
+                        // 查询该传输设备对应的设备信息及通讯设备信息
                         DataTable dt = ProtocolAnalysisTools.GetDeviceList(sourceNumber);
 
                         string agreement = ""; // 设备协议
@@ -582,7 +666,7 @@ namespace NB_IOT_TCP_HP_SOCKET
 
                             string agreementTmp = dt.Rows[i]["设备协议"].ToString();
                             string agreementParamTmp = dt.Rows[i]["设备协议参数"].ToString();
-                            trandId = dt.Rows[i]["trandId"].ToString(); 
+                            trandId = dt.Rows[i]["trandId"].ToString();
                             // 如果一个通讯设备下挂载多个设备,判断多个设备的传输协议是否一致,如果不一致则配置错误,无法进行数据转换
                             if ("".Equals(agreement) && "".Equals(agreementParam))
                             {
@@ -599,6 +683,7 @@ namespace NB_IOT_TCP_HP_SOCKET
                         if (agreement.Equals("CD_CellMonitor"))
                         {
                             CellMonitor cm = new CellMonitor();
+                            // 抄表数据进行解包操作,解包后抄表数据存入cm.Record
                             ResMsg msg = ProtocolAnalysisTools.UnInnerPack(cm, psp.Data);
 
                             if (!msg.Result)
@@ -614,28 +699,35 @@ namespace NB_IOT_TCP_HP_SOCKET
                                 }
                                 else
                                 {
-                                    AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({psp.Data.Length} bytes) 内包解包失败 \n {msg.Message}", lbReceiveData);
+                                    AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_CellMonitor内包解包失败 \n {msg.Message}", lbReceiveData);
                                 }
                             }
                             else
                             {
-                                AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} ({psp.Data.Length} bytes) 内包解包成功 \n {BitConverter.ToString(psp.Data, 0, psp.Data.Length).Replace("-", " ")}", lbReceiveData);
+                                AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({psp.Data.Length} bytes) CD_CellMonitor内包解包成功 \n {BitConverter.ToString(psp.Data, 0, psp.Data.Length).Replace("-", " ")}", lbReceiveData);
 
+                                // 如果是最后一包则发送校时指令
                                 if (cm.IsEnd)
                                 {
                                     byte[] buffer = RandomTime();
-                                    AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} ({buffer.Length} bytes) 最后一包校时 \n {BitConverter.ToString(buffer, 0, buffer.Length).Replace("-", " ")} ", lbReceiveData);
+                                    AddMsg($" > [{clientInfo.ConnId},OnSend] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({buffer.Length} bytes) CD_CellMonitor最后一包校时 \n {BitConverter.ToString(buffer, 0, buffer.Length).Replace("-", " ")} ", lbReceiveData);
                                     server.Send(clientInfo.ConnId, buffer, buffer.Length);// 发送数据
                                 }
 
                                 List<HistoryRecord> list = new List<HistoryRecord>();
+
+                                // 获取配置的上报抄表数据的数据信息CONF/DataCellConfig.xml中CD_CellMonitor节点,根据传输设备中的设备协议参数关联取那些字段
                                 CellMonitorDeviceType cellMonitorDeviceType = new CellMonitorDeviceType(agreementParam);
+                                // 模拟量
                                 Dictionary<string, CommOption> _analogData = cellMonitorDeviceType.GetAnalogCommOptions();
+                                // 开关量
                                 Dictionary<string, CommOption> _switchData = cellMonitorDeviceType.GetSwitchCommOptions();
 
                                 for (int i = 0; i < cm.Record.Count; i++)
                                 {
                                     List<CommData> list2 = new List<CommData>();
+
+                                    #region 将数据与配置的字段进行关联
                                     foreach (MonitorValue value2 in cm.Record[i].Analog)
                                     {
                                         if (_analogData.ContainsKey(value2.Name))
@@ -650,7 +742,9 @@ namespace NB_IOT_TCP_HP_SOCKET
                                             _switchData[value3.Name].ExplainData(value3.Value);
                                         }
                                     }
+                                    #endregion
 
+                                    // 将数据进行封装,一条数据可能对于多个设备的数据,通过[设备信息表]中设备的[用户站参数]与CONF\US_Common.xml进行匹配拆分
                                     List<HistoryRecord> item = this.UpdateHistoryData(cm.Record[i].PickTime, cm, dt, _analogData, _switchData);
                                     if (item != null && item.Count > 0)
                                     {
@@ -659,12 +753,14 @@ namespace NB_IOT_TCP_HP_SOCKET
 
                                 }
 
+                                // 保存抄表数据
                                 ProtocolAnalysisTools.SaveRecord(list);
                             }
                         }
                         // MODBUS类设备
                         else if (agreement.Equals("CD_PSController"))
                         {
+                            #region 根据上报数据的功能码区分获取对应的下发指令的MODBUS对象
                             Modbus.FunctionCode code = (Modbus.FunctionCode)psp.Data[1];
                             Modbus modbus = new Modbus();
                             if (code == Modbus.FunctionCode.F04)
@@ -675,21 +771,43 @@ namespace NB_IOT_TCP_HP_SOCKET
                             {
                                 modbus = sendComm[trandId][1];
                             }
+                            #endregion
 
-                            Modbus.UnPack(psp.Data, modbus);
-                            ModBusDeviceType modBusDeviceType = new ModBusDeviceType(agreementParam);
-                            Dictionary<string, CommOption> _analogData = modBusDeviceType.GetAnalogCommOptions();
-                            Dictionary<string, CommOption> _switchData = modBusDeviceType.GetSwitchCommOptions();
-                            if (code == Modbus.FunctionCode.F04)
+                            // 内包进行解包,解包后的数据存入modbus.UpDataArea
+                            ResMsg msg = Modbus.UnPack(psp.Data, modbus);
+
+                            if (!msg.Result)
                             {
-                                ProtocolAnalysisTools.OrganizeAnalogData(modbus.UpDataArea, _analogData, Convert.ToInt32(modBusDeviceType.AnalogStartAddress));
+                                AddMsg($" > [{clientInfo.ConnId},OnReceive] -> {clientInfo.IpAddress}:{clientInfo.Port} {sourceNumber} ({modbus.UpDataArea.Length} bytes) CD_PSController内包解包失败,数据类型{code} \n {msg.Message}", lbReceiveData);
                             }
-                            else if (code == Modbus.FunctionCode.F02)
+                            else
                             {
-                                ProtocolAnalysisTools.OrganizeSwitchData(modbus.UpDataArea, _switchData, Convert.ToInt32(modBusDeviceType.SwitchStartAddress));
+                                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);
+
+                                // 获取配置的上报抄表数据的数据信息CONF/DataCellConfig.xml中CD_PSController节点,根据传输设备中的设备协议参数关联取那些字段
+                                ModBusDeviceType modBusDeviceType = new ModBusDeviceType(agreementParam);
+                                // 模拟量
+                                Dictionary<string, CommOption> _analogData = modBusDeviceType.GetAnalogCommOptions();
+                                // 开关量
+                                Dictionary<string, CommOption> _switchData = modBusDeviceType.GetSwitchCommOptions();
+
+                                #region 将数据与配置的字段进行关联
+                                if (code == Modbus.FunctionCode.F04)
+                                {
+                                    ProtocolAnalysisTools.OrganizeAnalogData(modbus.UpDataArea, _analogData, Convert.ToInt32(modBusDeviceType.AnalogStartAddress));
+                                }
+                                else if (code == Modbus.FunctionCode.F02)
+                                {
+                                    ProtocolAnalysisTools.OrganizeSwitchData(modbus.UpDataArea, _switchData, Convert.ToInt32(modBusDeviceType.SwitchStartAddress));
+                                }
+                                #endregion
+
+                                // 将数据进行封装,一条数据可能对于多个设备的数据,通过[设备信息表]中设备的[用户站参数]与CONF\US_Common.xml进行匹配拆分
+                                List<HistoryRecord> item = this.UpdateHistoryData(clientInfo.receiveTime, null, dt, _analogData, _switchData);
+
+                                // 保存抄表数据
+                                ProtocolAnalysisTools.SaveRecord(item);
                             }
-                            List<HistoryRecord> item = this.UpdateHistoryData(DateTime.Now, null, dt, _analogData, _switchData);
-                            ProtocolAnalysisTools.SaveRecord(item);
                         }
                     }
                 }
@@ -775,8 +893,51 @@ namespace NB_IOT_TCP_HP_SOCKET
             }
             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);
+            string coonNum = "0";
+            if (server.IsStarted && server.GetAllConnectionIDs() != null)
+            {
+                coonNum = server.GetAllConnectionIDs().Length.ToString();
+            }
+            this.toolStripStatusLabel3.Text = "客户端连接数:" + coonNum;
+        }
+
+        private string RunTime(int s)
+        {
+            int num = 0;
+            int num2 = 0;
+            int num3 = 0;
+            int num4 = 0;
+            if (s < 60)
+            {
+                num4 = s;
+            }
+            else if ((60 <= s) && (s <= 0xe10))
+            {
+                num3 = s / 60;
+                num4 = s % 60;
+            }
+            else if ((0xe10 <= s) && (s <= 0x15180))
+            {
+                num2 = s / 0xe10;
+                num3 = (s % 0xe10) / 60;
+                num4 = (s % 0xe10) % 60;
+            }
+            else
+            {
+                num = s / 0x15180;
+                num2 = (s % 0x15180) / 0xe10;
+                num3 = ((s % 0x15180) % 0xe10) / 60;
+                num4 = ((s % 0x15180) % 0xe10) % 60;
+            }
+            return ("系统持续运行:" + num.ToString() + "天" + num2.ToString() + "小时" + num3.ToString() + "分" + num4.ToString() + "秒");
+        }
+    }
 
     [StructLayout(LayoutKind.Sequential)]
     public class ClientInfo
@@ -793,6 +954,7 @@ namespace NB_IOT_TCP_HP_SOCKET
         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
     }

+ 3 - 0
NB_IOT_TCP_HP_SOCKET/MainForm_TCP.resx

@@ -1256,4 +1256,7 @@
   <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>374, 17</value>
   </metadata>
+  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>495, 17</value>
+  </metadata>
 </root>

+ 1 - 1
NB_IOT_TCP_HP_SOCKET/WWKJUtil/EnumCommonClass.cs

@@ -3,7 +3,7 @@
     
     public enum AppState
     {
-        Starting, Started, Stoping, Stoped, Error
+        UnStart, Starting, Started, Stoping, Stoped, Error
     }
 
     //指令类型的枚举

+ 1 - 1
NB_IOT_TCP_HP_SOCKET/WWKJUtil/LogUtil.cs

@@ -31,7 +31,7 @@ namespace NB_IOT_TCP_HP_SOCKET.WWKJUtil
                         Directory.CreateDirectory(folder);
                     fs = new FileStream(folder + "/" + filename, System.IO.FileMode.Append, System.IO.FileAccess.Write);
                     sw = new StreamWriter(fs, Encoding.UTF8);
-                    sw.WriteLine(DateTime.Now.ToString() + "     " + debugstr + "\r\n");
+                    sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "     " + debugstr + "\r\n");
                 }
                 catch(Exception ex)
                 {

+ 14 - 8
NB_IOT_TCP_HP_SOCKET/WWKJUtil/Modbus.cs

@@ -908,6 +908,12 @@ namespace NB_IOT_TCP_HP_SOCKET.WWKJUtil
             return new ResMsg();
         }
 
+        /// <summary>
+        /// MODBUS解包处理
+        /// </summary>
+        /// <param name="package"></param>
+        /// <param name="modbus"></param>
+        /// <returns></returns>
         public static ResMsg UnPack(byte[] package, Modbus modbus)
         {
             int num4;
@@ -927,16 +933,16 @@ namespace NB_IOT_TCP_HP_SOCKET.WWKJUtil
             }
             int index = 0;
             int num = package[index];
-            //if (modbus.Id != num)
-            //{
-            //    return new ResMsg(false, "ID错误");
-            //}
+            if (modbus.Id != num)
+            {
+                return new ResMsg(false, "ID错误");
+            }
             index++;
             FunctionCode code = (FunctionCode)package[index];
-            //if (((byte)modbus.FunCode) != (((byte)code) & 0x7f))
-            //{
-            //    return new ResMsg(false, "功能码不匹配");
-            //}
+            if (((byte)modbus.FunCode) != (((byte)code) & 0x7f))
+            {
+                return new ResMsg(false, "功能码不匹配");
+            }
             index++;
             switch (code)
             {

+ 55 - 41
NB_IOT_TCP_HP_SOCKET/WWKJUtil/ProtocolAnalysisTools.cs

@@ -253,7 +253,7 @@ namespace NB_IOT_TCP_HP_SOCKET.WWKJUtil
         }
 
         /// <summary>
-        /// 进行内包拆包操作
+        /// 电池供电进行内包拆包操作
         /// </summary>
         /// <param name="cm"></param>
         /// <param name="data"></param>
@@ -598,70 +598,84 @@ namespace NB_IOT_TCP_HP_SOCKET.WWKJUtil
             Dictionary<string, HistoryRecord> lastData = new Dictionary<string, HistoryRecord>();
             foreach (HistoryRecord record2 in list)
             {
-                string deviceid = record2.DeviceId;
-                string tablename = "";
                 try
                 {
-                    tablename = "历史记录_" + ("000000" + deviceid).Substring(deviceid.Length, 6) + "_" + record2.RecordTime.ToString("yyyy");
-                }
-                catch
-                {
-                    tablename = "历史记录_" + ("000000" + deviceid).Substring(deviceid.Length, 6) + "_" + DateTime.Now.Year.ToString();
-                }
-                // 判断同一抄表时间的历史记录是否存在
-                if (!CheckRecordExsit(tablename, record2.RecordTime))
-                {
-                    StringBuilder strSql = new StringBuilder();
-                    strSql.Append("DECLARE @NewId int SELECT @NewId = (isnull(MAX(ID), 0) + 1) FROM ").Append(tablename);
-                    strSql.Append(" insert into ").Append(tablename).Append(" ( ID,设备ID,记录时间,采集时间,设备状态,通讯状态,数据来源");
-                    List <CommData> dataList = record2.DataList;
-                    StringBuilder cellValue = new StringBuilder();
-                    for (int i = 0; i < dataList.Count; i++)
+                    string deviceid = record2.DeviceId;
+                    string tablename = "";
+                    try
                     {
-                        CommData commData = dataList[i];
-                        strSql.Append(",").Append(commData.Name);
-                        if ((((commData.Value == null) || (commData.Value == "")) || ((commData.Value == "未知") || (commData.Value == "--"))) || (commData.Value == "非数字"))
-                        {
-                            cellValue.Append(",0");
-                        }
-                        else
+                        tablename = "历史记录_" + ("000000" + deviceid).Substring(deviceid.Length, 6) + "_" + record2.RecordTime.ToString("yyyy");
+                    }
+                    catch
+                    {
+                        tablename = "历史记录_" + ("000000" + deviceid).Substring(deviceid.Length, 6) + "_" + DateTime.Now.Year.ToString();
+                    }
+                    // 判断同一抄表时间的历史记录是否存在
+                    if (!CheckRecordExsit(tablename, record2.RecordTime))
+                    {
+                        StringBuilder strSql = new StringBuilder();
+                        strSql.Append("DECLARE @NewId int SELECT @NewId = (isnull(MAX(ID), 0) + 1) FROM ").Append(tablename);
+                        strSql.Append(" insert into ").Append(tablename).Append(" ( ID,设备ID,记录时间,采集时间,设备状态,通讯状态,数据来源");
+                        List<CommData> dataList = record2.DataList;
+                        StringBuilder cellValue = new StringBuilder();
+                        for (int i = 0; i < dataList.Count; i++)
                         {
-                            if (commData.Tag == null || "".Equals(commData.Tag) || "BIT".Equals(commData.Tag.ToUpper()))
+                            CommData commData = dataList[i];
+                            strSql.Append(",").Append(commData.Name);
+                            if ((((commData.Value == null) || (commData.Value == "")) || ((commData.Value == "未知") || (commData.Value == "--"))) || (commData.Value == "非数字"))
                             {
-                                cellValue.Append(",'").Append(commData.Value).Append("'");
+                                cellValue.Append(",0");
                             }
                             else
                             {
-                                cellValue.Append(",").Append(commData.Value);
+                                if (commData.Tag == null || "".Equals(commData.Tag) || "BIT".Equals(commData.Tag.ToUpper()))
+                                {
+                                    cellValue.Append(",'").Append(commData.Value).Append("'");
+                                }
+                                else
+                                {
+                                    cellValue.Append(",").Append(commData.Value);
+                                }
                             }
                         }
-                    }
-                    strSql.Append(") values (@NewId,").Append(deviceid).Append(",GETDATE(),'").Append(record2.RecordTime.ToString()).Append("','全部正常','全部正常','").Append(record2.DataSource).Append("'").Append(cellValue.ToString()).Append(")");
+                        strSql.Append(") values (@NewId,").Append(deviceid).Append(",GETDATE(),'").Append(record2.RecordTime.ToString()).Append("','全部正常','全部正常','").Append(record2.DataSource).Append("'").Append(cellValue.ToString()).Append(")");
 
-                    int rs = DBHelper.Query(strSql.ToString());
+                        int rs = DBHelper.Query(strSql.ToString());
 
-                    if (rs == 1)
-                    {
-                        if (lastData.ContainsKey(deviceid))
+                        if (rs == 1)
                         {
-                            HistoryRecord historyRecord = lastData[deviceid];
-                            if (record2.RecordTime >= historyRecord.RecordTime)
+                            if (lastData.ContainsKey(deviceid))
+                            {
+                                HistoryRecord historyRecord = lastData[deviceid];
+                                if (record2.RecordTime >= historyRecord.RecordTime)
+                                {
+                                    lastData[deviceid] = record2;
+                                }
+                            }
+                            else
                             {
                                 lastData[deviceid] = record2;
                             }
                         }
-                        else
-                        {
-                            lastData[deviceid] = record2;
-                        }
                     }
                 }
+                catch (Exception)
+                {
+                    continue;
+                }
             }
 
             // 更新最后状态信息
             foreach (KeyValuePair<string, HistoryRecord> kvp in lastData)
             {
-                UpdateDeviceLastData(kvp);
+                try
+                {
+                    UpdateDeviceLastData(kvp);
+                }
+                catch (Exception)
+                {
+                    continue;
+                }
             }
         }