Beispiel #1
0
        private volatile int sleepTimes = 0;//对休眠次数计数
        /// <summary>
        /// 处理PLC打包指令,每SENDTOPLC_INTERVAL毫秒发一次,
        /// 同一PLC上次与本次间隔为PLC个数*SENDTOPLC_INTERVAL,此值过大,会造成灯指令覆盖
        /// </summary>
        void HandlePackPLCComm()
        {
            while (true)
            {
                try
                {
                    int[] strKey = null;
                    lock (dicSendWindow)
                    {
                        int dicCount = dicSendWindow.Keys.Count;
                        strKey = new int[dicCount];
                        dicSendWindow.Keys.CopyTo(strKey, 0);
                    }

                    int PLCCount = strKey.Length;
                    for (int i = 0; i < PLCCount; i++)
                    {
                        int        key     = strKey[i];
                        PLCCommand command = null;
                        lock (dicSendWindow)
                        {
                            command = dicSendWindow[strKey[i]];
                        }

                        if (!command.Send)
                        {
                            Interlocked.Add(ref sleepTimes, 1);//加1

                            WinApi_PLC.SendDataAllOut((byte)key, command.ThirdFrame, command.FourthFrame);
                            //bl_plc.SendDataAllOut((byte)key, command.ThirdFrame, command.FourthFrame);
                            command.Send = true;//更新为已发送
                            lock (dicSendWindow)
                            {
                                dicSendWindow[key] = command;
                            }
                            //每个包之间都要间隔200毫秒,不然plc接收会粘包,而且plc同地址会中断
                            Thread.Sleep(SENDTOPLC_INTERVAL);
                        }
                    }
                    //循环结束后,sleepTimes=0;休眠中断间隔,=1休眠剩余时间间隔
                    if (sleepTimes <= 1)
                    {
                        int sleepInterval = PLC_INTERRUPT_INTERVAL - sleepTimes * SENDTOPLC_INTERVAL;
                        Thread.Sleep(sleepInterval < 0 ? 0 : sleepInterval);
                    }
                    Interlocked.Add(ref sleepTimes, -sleepTimes);//0
                }
                catch (Exception ex)
                {
                    Thread.Sleep(PLC_INTERRUPT_INTERVAL);
                    InternalLogger.Log.Error("处理PLC打包指令出错:" + ex.Message);
                }
            }
        }
Beispiel #2
0
 /// <summary>
 ///打包帧
 /// </summary>
 /// <param name="command"></param>
 /// <param name="lightAddress">从0开始到15</param>
 /// <param name="lightStatus"></param>
 void SetFrame(PLCCommand command, int lightAddress, byte lightStatus)
 {
     if (lightAddress >= 0 && lightAddress <= 7)
     {
         command.ThirdFrame = SetBit(command.ThirdFrame, 8 - lightAddress, lightStatus == 1);//设置第三帧
     }
     else
     {
         command.FourthFrame = SetBit(command.FourthFrame, 16 - lightAddress, lightStatus == 1);//设置第四帧
     }
 }
Beispiel #3
0
 /// <summary>
 /// 打包PLC指令
 /// PLC首次,将plc地址保存,将<led地址,发送时刻>保存;指令打包并保存
 /// PLC非首次,但LED首次,将指令打包保存
 /// PLC非首次且LED非首次,判断间隔是否满足设定;(若满足,将指令打包保存;若不满足,则新线程等待设定时间后,打包保存)
 /// </summary>
 /// <param name="plcAddress">PLC地址号</param>
 /// <param name="lightAddress">PLC控制输出端口号(一般16个)</param>
 /// <param name="lightStatus">1开灯,0关灯</param>
 /// <param name="lightTime">灯开闭间隔</param>
 private void ControlPLCInterval(int plcAddress, int lightAddress, byte lightStatus, int lightTime)
 {
     try
     {
         double curTime = (DateTime.Now.ToUniversalTime() - baseDatatime).TotalMilliseconds;
         lock (dicSendWindow)
         {
             PLCCommand command = null;
             if (dicSendWindow.ContainsKey(plcAddress))
             {
                 dicSendWindow.TryGetValue(plcAddress, out command);
                 if (command.DicLightSendTime.ContainsKey(lightAddress))//此灯已发送过
                 {
                     double preTime = 0;
                     command.DicLightSendTime.TryGetValue(lightAddress, out preTime);
                     double totalTime = curTime - preTime;
                     if (totalTime < lightTime)//时间间隔小于设定值
                     {
                         int sleepReply = (int)Math.Ceiling(lightTime - totalTime);
                         #region 在sleep前,需把本次的时间戳保存,防止后面还有指令进来
                         command.DicLightSendTime[lightAddress] = curTime + sleepReply; //更新发送时刻
                         dicSendWindow[plcAddress] = command;                           //更新
                         #endregion
                         smartThreadPool.QueueWorkItem(() =>
                         {
                             //新线程,先sleep(lightTime-totalTime)后,再lock放入dicSendWindow
                             Thread.Sleep(sleepReply);
                             lock (dicSendWindow)
                             {
                                 SetFrame(command, lightAddress, lightStatus);
                                 command.DicLightSendTime[lightAddress] = curTime + sleepReply; //更新发送时刻
                                 command.Send = false;
                                 dicSendWindow[plcAddress] = command;                           //更新
                             }
                         });
                         return;//直接退出,不要删除
                     }
                     else//大于设定间隔
                     {
                         command.DicLightSendTime[lightAddress] = curTime;//更新发送时刻
                     }
                 }
                 else//此灯第一次发送
                 {
                     command.DicLightSendTime.Add(lightAddress, curTime);//将plc下灯地址发送时刻保存
                 }
                 SetFrame(command, lightAddress, lightStatus);
                 command.Send = false;
                 dicSendWindow[plcAddress] = command;//更新
             }
             else
             {
                 command = new PLCCommand();                          //command.Send = false;默认
                 SetFrame(command, lightAddress, lightStatus);
                 command.DicLightSendTime.Add(lightAddress, curTime); //将plc下灯地址发送时刻保存
                 dicSendWindow.Add(plcAddress, command);              //新增
             }
         }
     }
     catch (Exception ex)
     {
         InternalLogger.Log.Error("打包PLC指令出错:" + ex.Message);
     }
 }