Browse Source

Merge remote-tracking branch 'tyc/dev' into dev

# Conflicts:
#	modbus_PLC_laser_test/plc本地模拟.mbs
kingwang1995 7 years ago
parent
commit
cb0d3fb5c1

+ 1 - 1
modbus_PLC_laser_test/runtest.bat

@@ -1,2 +1,2 @@
-modbus_msvc.exe 192.168.0.10 503 1 2
+modbus_msvc.exe 127.0.0.1 502 1 2
 pause

+ 2 - 2
parkMonitor/App.config

@@ -36,7 +36,7 @@
     <add key="PLC_station" value="1" />
     <add key="PLC_start_address" value="0" />
     <add key="PLC_address_length" value="50" />
-    <add key="PLC_refresh_interval" value="100"/>
+    <add key="PLC_refresh_interval" value="200"/>
     <!--PLC停取车地址配置-->
     <add key="fetch_completed_address" value="9" />
     <add key="park_command_address" value="0" />
@@ -53,7 +53,7 @@
     <add key="fetch_store_ratio" value="3" />
     
     <!--上位机(Web线程)IP地址及配置serverScoket的端口-->
-    <add key="WebConfig" value="192.168.111.84:9000" />
+    <add key="WebConfig" value="192.168.111.8:9000" />
     <!--<add key ="WebConfig" value="127.0.0.1:9000"/>-->
     <!--PLC总控状态-->
     <add key="equipmentStatus_address" value="28" />

+ 3 - 2
parkMonitor/entity/AbstractMessage.cs

@@ -153,11 +153,12 @@ namespace parkMonitor.entity
     public class NumberMachineMessage : AbstractMessage
     {
         public List<NumberMachineNode> data;
-        public NumberMachineNode aModel;
+        public NumberMachineNode aNode;
 
         public NumberMachineMessage()
         {
             data = new List<NumberMachineNode>();
+            aNode = new NumberMachineNode();
         }
 
         public override bool Equals(System.Object obj)
@@ -241,7 +242,7 @@ namespace parkMonitor.entity
         public int garageID;
         public int parkingRecordsID;
         public string TimeRecord;
-        public string ip;
+        public string ip;//新添加,用于定位号牌机
 
         public Command()
         {

+ 1 - 0
parkMonitor/parkMonitor.csproj

@@ -122,6 +122,7 @@
     <Compile Include="server\NumMachine\NumMachine.designer.cs">
       <DependentUpon>NumMachine.cs</DependentUpon>
     </Compile>
+    <Compile Include="server\NumMachine\NumMachineSimul.cs" />
     <Compile Include="server\NumMachine\VzClientSDK.cs" />
     <Compile Include="server\PLCLinker\PLCLinker.cs" />
     <Compile Include="server\monitorServer\DevParamModel.cs" />

+ 8 - 3
parkMonitor/server/CoreThread/AbstractCmd.cs

@@ -44,8 +44,6 @@ namespace parkMonitor.server.CoreThread
             queuingThread = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.Queue);
             //数据库
             oper = new DBOperation();
-            //获取号牌句柄
-            NumMachine = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.NumMachine);
             //车位分配
             c = new CEntrance();
             aps = new AllotParkingSpace();
@@ -91,7 +89,7 @@ namespace parkMonitor.server.CoreThread
                     PLCMsg = (PLCMessage)PLC.GetMessage();
                     if (PLCMsg != null)
                     {
-                        if (PLCMsg.laser1.data != null)
+                        if (PLCMsg.laser1!=null && PLCMsg.laser1.data != null)
                         {
                             if (PLCMsg.laser1.status == 3)
                             {
@@ -157,6 +155,12 @@ namespace parkMonitor.server.CoreThread
             status = 3;
             pm.status = status;
             PLC.SetMessage(pm);
+            //停车完成,将相应车牌复位
+            NumberMachineMessage numberMachineMessage = new NumberMachineMessage();
+            numberMachineMessage.aNode = new NumberMachineNode();
+            numberMachineMessage.aNode.ip = "";
+            numberMachineMessage.aNode.LicenseNum = queueCmd.LicenseNum;
+            queuingThread.SetMessage(numberMachineMessage);
             Console.WriteLine("停车完成,状态复位");
             Log.WriteLog("停车完成,状态复位");
             UILogServer.ins.info("停车完成,状态复位");
@@ -192,6 +196,7 @@ namespace parkMonitor.server.CoreThread
                 Log.WriteLog(logFile, "车位x:" + parkingSpaceX);
                 Log.WriteLog(logFile, "车位y:" + parkingSpaceY);
                 Log.WriteLog(logFile, "车位z:" + parkingSpaceZ);
+                //异常情况处理有待讨论
             }
         }
     }

+ 3 - 3
parkMonitor/server/CoreThread/CoreThreadTest.cs

@@ -303,9 +303,9 @@ namespace parkMonitor.server.CoreThread
 
                     //车停完,号牌ip置空告知号牌机线程
                     NumberMachineMessage nmm = new NumberMachineMessage();
-                    nmm.aModel = new NumberMachineNode();
-                    nmm.aModel.ip = "";
-                    nmm.aModel.LicenseNum = queueCmd.LicenseNum;
+                    nmm.aNode = new NumberMachineNode();
+                    nmm.aNode.ip = "";
+                    nmm.aNode.LicenseNum = queueCmd.LicenseNum;
                     NumMachine.SetMessage(nmm);
 
                     Console.WriteLine("停车完成,状态复位");

+ 214 - 54
parkMonitor/server/CoreThread/QueuingThread.cs

@@ -16,6 +16,7 @@ namespace parkMonitor.server.CoreThread
 {
     class QueuingThread : IEquipments
     {
+        Queue<NumberMachineNode> LicenseQueue = new Queue<NumberMachineNode>();
         Queue<Command> StoreCmdQueue = new Queue<Command>();
         Queue<Command> ValidStoreCmdQueue = new Queue<Command>();
         Queue<Command> FetchCmdQueue = new Queue<Command>();
@@ -41,6 +42,9 @@ namespace parkMonitor.server.CoreThread
             catch (Exception) { fetchStoreRatio = 3; UILogServer.ins.error("未找到停取车比例与计时参数"); }
         }
 
+        /// <summary>
+        /// 从web线程获得用户指令
+        /// </summary>
         private void ReceiveFromWebThread()
         {
             while (!isClosing)
@@ -62,7 +66,7 @@ namespace parkMonitor.server.CoreThread
                     cmd.parkingRecordsID = webMsg.parkingRecordsID;
                     cmd.TimeRecord = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                     webMsg = null;
-                    UILogServer.ins.info("收到web指令:"+cmd.commandType+"--"+cmd.LicenseNum);
+                    UILogServer.ins.info("收到web指令:" + cmd.commandType + "--" + cmd.LicenseNum);
                 }
                 //input user command
                 if (cmd != null)
@@ -85,102 +89,258 @@ namespace parkMonitor.server.CoreThread
             }
         }
 
+        /// <summary>
+        /// 队列线程主业务逻辑
+        /// </summary>
         private void Run()
         {
+            NumberMachineNode temp = null;
             while (!isClosing)
             {
-                Command cmd = null;
-                //接收号牌消息
-                //update license when it has been used
-                if (numMachineHandle != null && (license == null || license.ip == "used" || license.ip == ""))
+                lock (LicenseQueue)
                 {
-                    license = ((NumberMachineMessage)numMachineHandle.GetMessage()).aModel;
+                    //本地号牌已使用,则接收新的号牌消息
+                    if (numMachineHandle != null && !NumMachineNodeValidation(license))
+                    {
+                        license = ((NumberMachineMessage)numMachineHandle.GetMessage()).aNode;
+                        //无重复则入号牌队列,并将号牌机线程获得的Node中ip标记为已使用
+                        if (NumMachineNodeValidation(license) && !LicenseQueue.Contains(license))
+                        {
+                            LicenseQueue.Enqueue((NumberMachineNode)license.Clone());
+                            license.ip = "used";
+                            //UILogServer.ins.log("已扫描到号牌:" + license.LicenseNum + ",开始排队");
+                            Console.WriteLine("已扫描到号牌:" + license.LicenseNum + ",开始排队");
+                        }
+                    }
+
+                    //将已被使用的号牌从号牌队列排除
+                    for (int i = 0; i < LicenseQueue.Count; i++)
+                    {
+                        temp = LicenseQueue.Dequeue();
+                        if (temp != null && temp.ip != "used")
+                        {
+                            LicenseQueue.Enqueue(temp);
+                        }
+                    }
                 }
+
                 //队列业务逻辑
-                //match license number
-                for (int i = 0; i < StoreCmdQueue.Count; i++)
+                UserCmdMatch();
+                Scheduling();
+                lock (StoreCmdQueue)
                 {
-                    cmd = StoreCmdQueue.Dequeue();
-                    //指令超时处理
-                    TimeSpan userTimeSpan = DateTime.Now - DateTime.Parse(cmd.TimeRecord);
-                    //Console.WriteLine("指令已扫描时间:" + userTimeSpan.TotalSeconds);
-                    if (userTimeSpan.TotalMinutes >= userTime)
-                    {
-                        UILogServer.ins.error("异常:用户指令已存在时间:" + userTimeSpan.TotalSeconds + "秒 ,强制出队");
-                        //Console.WriteLine("指令已扫描时间:" + userTimeSpan.TotalSeconds);
-                        //cmd.LicenseNum = "";
-                        cmd.commandType = 'e';
-                        ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
-                        if (StoreCmdQueue.Count != 0)
-                            cmd = StoreCmdQueue.Dequeue();
-                        else
-                            break;
-                    }
-                    if (license != null && cmd.LicenseNum.Equals(license.LicenseNum))
+                    UserCmdTimeOut();
+                }
+                lock (LicenseQueue)
+                {
+                    LicTimeOut();
+                }
+                Thread.Sleep(200);
+            }
+        }
+
+        private bool NumMachineNodeValidation(NumberMachineNode node)
+        {
+            return (node != null && node.ip != null && node.ip != "" && node.ip != "used") ? true : false;
+        }
+
+        /// <summary>
+        /// 停车指令超时处理
+        /// </summary>
+        private void UserCmdTimeOut()
+        {
+            Command cmd = null;
+            for (int i = 0; i < StoreCmdQueue.Count; i++)
+            {
+                cmd = StoreCmdQueue.Dequeue();
+
+                //指令超时处理
+                TimeSpan userTimeSpan = DateTime.Now - DateTime.Parse(cmd.TimeRecord);
+                //Console.WriteLine("指令已扫描时间:" + userTimeSpan.TotalSeconds);
+                if (userTimeSpan.TotalMinutes >= userTime)
+                {
+                    UILogServer.ins.error("异常:用户指令已存在时间:" + userTimeSpan.TotalSeconds + "秒 ,强制出队");
+                    //Console.WriteLine("异常:用户指令已存在时间:" + userTimeSpan.TotalSeconds + "秒 ,强制出队");
+                    //cmd.LicenseNum = "";
+                    cmd.commandType = 'e';
+                    lock (ValidStoreCmdQueue)
                     {
-                        //匹配上,时间定为号牌机获取号牌时间
-                        cmd.TimeRecord = license.TimeRecord;
                         ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
-                        license.ip = "used";
-                        break;
                     }
+                    if (StoreCmdQueue.Count != 0)
+                        cmd = StoreCmdQueue.Dequeue();
                     else
-                    {
-                        StoreCmdQueue.Enqueue((Command)cmd.Clone());
-                    }
+                        break;
                 }
-                //号牌超时处理
-                if (license != null && license.TimeRecord != "")
+            }
+        }
+
+        /// <summary>
+        /// 号牌超时处理
+        /// </summary>
+        private void LicTimeOut()
+        {
+            foreach (NumberMachineNode n in LicenseQueue)
+            {
+                if (NumMachineNodeValidation(n))
                 {
-                    TimeSpan licTimeSpan = DateTime.Now - DateTime.Parse(license.TimeRecord);
-                    //测试,超过5分钟自动出队
-                    //Console.WriteLine("号牌已扫描时间:"+ licTimeSpan.TotalSeconds);
-                    if (license.ip!="used" && license.ip != "" && licTimeSpan.TotalMinutes >= licenseTime)
+                    //计算时间差,超过5分钟自动出队(?处理方式待讨论),并将该Node标记为已使用,等待统一处理
+                    TimeSpan licTimeSpan = DateTime.Now - DateTime.Parse(n.TimeRecord);
+                    if (licTimeSpan.TotalMinutes >= licenseTime)
                     {
                         UILogServer.ins.error("异常:号牌已扫描时间:" + licTimeSpan.TotalSeconds + "秒 ,强制出队");
-                        //Console.WriteLine("号牌已扫描时间:" + licTimeSpan.TotalSeconds);
-                        cmd = new Command();
-                        cmd.ip = license.ip;
+                        //Console.WriteLine("异常:号牌已扫描时间:" + licTimeSpan.TotalSeconds + "秒 ,强制出队");
+                        Command cmd = new Command();
+                        cmd.ip = n.ip;
                         cmd.commandType = 's';
-                        cmd.LicenseNum = license.LicenseNum;
+                        cmd.LicenseNum = n.LicenseNum;
                         cmd.userID = "";
                         cmd.garageID = 0;
                         cmd.parkingRecordsID = 0;
-                        cmd.TimeRecord = license.TimeRecord;
-                        ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
+                        cmd.TimeRecord = n.TimeRecord;
+                        lock (ValidStoreCmdQueue)
+                        {
+                            ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
+                        }
                         //numMachineHandle.SetMessage((AbstractMessage)cmd.Clone());
-                        license.ip = "used";
+                        n.ip = "used";
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// 停车匹配,一轮中从停车指令队列取一个,遍历号牌队列;之后反之,以号牌遍历停车指令队列
+        /// 匹配上则入合法指令队列,并标记号牌队列相应元素为已使用
+        /// </summary>
+        private void UserCmdMatch()
+        {
+            Command cmd = null;
+            NumberMachineNode num = null;
+
+            //以单用户指令遍历号牌队列
+            lock (StoreCmdQueue)
+            {
+                if (StoreCmdQueue.Count != 0)
+                {
+                    cmd = StoreCmdQueue.Dequeue();
+                    num = new NumberMachineNode();
+                    lock (LicenseQueue)
+                    {
+                        for (int i = 0; i < LicenseQueue.Count; i++)
+                        {
+                            num = LicenseQueue.Dequeue();
+                            //匹配成功
+                            if (cmd.LicenseNum.Equals(num.LicenseNum))
+                            {
+                                cmd.TimeRecord = num.TimeRecord;
+                                ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
+                                cmd = null;
+                                break;
+                            }
+                            else
+                            {
+                                LicenseQueue.Enqueue((NumberMachineNode)num.Clone());
+                            }
+                        }
+                    }
+                    if (cmd != null)
+                    {
+                        StoreCmdQueue.Enqueue(cmd);
                     }
                 }
+            }
 
-                //scheduling algorithm
-                int fetch = fetchStoreRatio;
+            //以单号牌遍历停车指令队列
+            lock (LicenseQueue)
+            {
+                if (LicenseQueue.Count != 0)
+                {
+                    num = LicenseQueue.Dequeue();
+                    cmd = new Command();
+                    lock (StoreCmdQueue)
+                    {
+                        for (int i = 0; i < StoreCmdQueue.Count; i++)
+                        {
+                            cmd = StoreCmdQueue.Dequeue();
+                            //匹配成功
+                            if (num.LicenseNum.Equals(cmd.LicenseNum))
+                            {
+                                cmd.TimeRecord = num.TimeRecord;
+                                ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
+                                cmd = null;
+                                break;
+                            }
+                            else
+                            {
+                                StoreCmdQueue.Enqueue((Command)cmd.Clone());
+                            }
+                        }
+                    }
+                    if (cmd != null)
+                    {
+                        LicenseQueue.Enqueue(num);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// 停取车调度,控制停取车比例,可多取一停,也可一取一停
+        /// </summary>
+        private void Scheduling()
+        {
+            //scheduling algorithm
+            int fetch = fetchStoreRatio;
+            Command cmd = null;
+            lock (FetchCmdQueue)
+            {
                 while (FetchCmdQueue.Count != 0 && fetch-- > 0)
                 {
                     cmd = FetchCmdQueue.Dequeue();
                     ExecutableCmdQueue.Enqueue((Command)cmd.Clone());
-                    UILogServer.ins.info("任务:取出号牌为 "+cmd.LicenseNum+" 的车辆,开始排队"); 
+                    //UILogServer.ins.info("任务:取出号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
                 }
+            }
+            lock (ValidStoreCmdQueue)
+            {
                 if (ValidStoreCmdQueue.Count != 0)
                 {
                     cmd = ValidStoreCmdQueue.Dequeue();
                     ExecutableCmdQueue.Enqueue((Command)cmd.Clone());
-                    UILogServer.ins.info("任务:存入号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
+                    //UILogServer.ins.info("任务:存入号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
                 }
-                Thread.Sleep(1000);
             }
         }
 
-        //公有方法
-        //please reset the licenseNum to "" after using
+        /// <summary>
+        /// 获取一个停取车指令
+        /// </summary>
         public AbstractMessage GetMessage()
         {
-            return (Command)ExecutableCmdQueue.Dequeue();
+            lock (ExecutableCmdQueue)
+            {
+                return (Command)ExecutableCmdQueue.Dequeue();
+            }
         }
 
+        /// <summary>
+        /// 由核心线程调用,传入已存车完成需要标记的号牌
+        /// </summary>
+        /// <example>
+        /// NumberMachineMessage numberMachineMessage = new NumberMachineMessage();
+        /// numberMachineMessage.aNode = new NumberMachineNode();
+        /// numberMachineMessage.aNode.ip = "";
+        /// numberMachineMessage.aNode.LicenseNum = "the number plate that has been used";
+        /// QueueingHandle.SetMessage(numberMachineMessage);
+        /// </example>
+        /// <param name="message"></param>
         public void SetMessage(AbstractMessage message)
         {
-            //there's no need to do any thing
+            if (numMachineHandle != null)
+            {
+                numMachineHandle.SetMessage(message);
+            }
         }
 
         public void Start()

+ 74 - 97
parkMonitor/server/NumMachine/NumMachine.cs

@@ -176,23 +176,16 @@ namespace parkMonitor.server
             {
                 while (!closing)
                 {
-                    //根据外部信号强制输出
-                    //for (int i = 0; i < lv.devPushed.Count; i++)
-                    //{
-                    //    if (lv.devPushed[i] && ipHandleMap.TryGetValue(lv.data[i].ip, out int myHandle))
-                    //    {
-                    //        ActivateSnap(myHandle);
-                    //    }
-                    //}
+                    Thread.Sleep(REFRESHINGTIME);
                     //定时返回号牌
                     Dictionary<int, PictureBox>.Enumerator enumer = devPicMap.GetEnumerator();
                     do
                     {
-                        string ip = Get_IP(enumer.Current.Key);
+                        //string ip = Get_IP(enumer.Current.Key);
                         ActivateSnap(enumer.Current.Key);
-
                         //Debug.WriteLine(lv.data.Count.ToString()+":\n"+ lv.data[lv.data.Count-1].LicenseNum+ lv.data[lv.data.Count - 1].TimeRecord);
                     } while (enumer.MoveNext());
+
                     //更新设备状态
                     foreach (NumberMachineNode nmn in nmMsg.data)
                     {
@@ -207,6 +200,7 @@ namespace parkMonitor.server
                             LogFile logError = LogFile.ERROR;
                             Log.WriteLog(logError, "ip为 " + nmn.ip + " 的号牌机 连接中断。");
                             UILogServer.ins.info("ip为 " + nmn.ip + " 的号牌机 连接中断。");
+                            Thread.Sleep(10000);
                         }
                     }
                     //删除已停好车的号牌
@@ -218,26 +212,6 @@ namespace parkMonitor.server
                             LicBuffer.Enqueue((NumberMachineNode)n.Clone());
                         }
                     }
-                    //已入队则换号牌
-                    if (nmMsg != null && nmMsg.aModel != null && nmMsg.aModel.ip == "used")
-                    {
-                        for (int i = 0; i < LicBuffer.Count; i++)
-                        {
-                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aModel.Clone());
-                            NumberMachineNode n = LicBuffer.Dequeue();
-                            if (n.ip != "used" && n.ip != "")
-                            {
-                                nmMsg.aModel = n;
-                                break;
-                            }
-                            else
-                            {
-                                LicBuffer.Enqueue((NumberMachineNode)n.Clone());
-                            }
-                        }
-                    }
-
-                    Thread.Sleep(REFRESHINGTIME);
                 }
             }
             catch (Exception ex)
@@ -436,7 +410,7 @@ namespace parkMonitor.server
             //新设备,号牌不为空
             if (!found && !(plateInformation.plate == "_无_"))
             {
-                NumberMachineNode nmn = new NumberMachineNode(strIP, plateInformation.plate, DateTime.Now.ToLocalTime().ToString(), GetStatus(strIP));
+                NumberMachineNode nmn = new NumberMachineNode(strIP, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
                 NumberMachineNode nmnc = (NumberMachineNode)nmn.Clone();
                 nmMsg.data.Add(nmnc);
                 FilterLic(strIP, nmnc);
@@ -463,30 +437,33 @@ namespace parkMonitor.server
                 filter = new Dictionary<NumberMachineNode, int>();
                 filterMap.Add(ip, filter);
             }
+            //计数器异常
             else if (!filterMap.TryGetValue(ip, out filter))
             {
                 return;
             }
-            //filter计数。    
+
+            //filter计数
             int count = 0;
-            if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))
+            if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))//存在则数量+1
             {
                 filter.Remove(nmn);
                 filter.Add(nmn, count + 1);
             }
-            else
+            else//不存在则计数1
             {
                 filter.Add(nmn, 1);
             }
 
             filterCount += 1;
+            //达到计数限制,计算众数是否达标,达标则入队
             if (filterCount >= FILTERINGNUMBER)
             {
                 Dictionary<NumberMachineNode, int>.Enumerator enumer = filter.GetEnumerator();
                 do
                 {
                     //遍历,筛到号牌则入队
-                    if (enumer.Current.Value >= (int)(filterCount * 0.8) && !LicBuffer.Contains(enumer.Current.Key) && (nmMsg.aModel == null || nmMsg.aModel.LicenseNum != enumer.Current.Key.LicenseNum))
+                    if (enumer.Current.Value >= (int)(filterCount * 0.8) && !LicBuffer.Contains(enumer.Current.Key) && (nmMsg.aNode == null || nmMsg.aNode.LicenseNum != enumer.Current.Key.LicenseNum))
                     {
                         LicBuffer.Enqueue((NumberMachineNode)enumer.Current.Key.Clone());
                     }
@@ -579,7 +556,14 @@ namespace parkMonitor.server
 
         }
 
-        //公有方法
+        private bool NodeValidation(NumberMachineNode node)
+        {
+            return (node != null && node.ip != "" && node.ip != "used") ? true : false;
+        }
+
+        /// <summary>
+        /// 系统启动
+        /// </summary>
         public void Start()
         {
             Task.Run(() =>
@@ -607,10 +591,11 @@ namespace parkMonitor.server
 
         }
 
-        //系统关闭
+        /// <summary>
+        /// 系统关闭
+        /// </summary>
         public void Stop()
         {
-            closing = true;
             VzClientSDK.VZLPRClient_StopFindDevice();
             Dictionary<int, PictureBox>.Enumerator enumer = devPicMap.GetEnumerator();
             do
@@ -630,91 +615,83 @@ namespace parkMonitor.server
             //this.Close();
         }
 
-        //调用时,核心线程需将aModel里ip置为空字符串
+        /// <summary>
+        /// 监控线程获取号牌机信息,核心线程获取号牌信息
+        /// </summary>
         public AbstractMessage GetMessage()
         {
-            for(int i = 0; i < LicBuffer.Count; i++)
+            lock (LicBuffer)
             {
-                NumberMachineNode n = LicBuffer.Dequeue();
-                if ((nmMsg.aModel == null || nmMsg.aModel.ip == "" || nmMsg.aModel.ip == "used") &&n!=null&& n.ip!="" && n.ip!="used")
+                //准备输出的数据中存在非法Node,且LicBuffer可出队产生一个合法Node,则替换该非法Node,否则让Node=null
+                if (!NodeValidation(nmMsg.aNode))
                 {
-                    UILogServer.ins.info("号牌:" + n.LicenseNum + ",准备入队");
-                    nmMsg.aModel = n;
-                    break;
+                    for (int i = 0; i < LicBuffer.Count; i++)
+                    {
+                        NumberMachineNode n = LicBuffer.Dequeue();
+                        if (NodeValidation(n))
+                        {
+                            Console.WriteLine("号牌:" + n.LicenseNum + ",准备入队");
+                            nmMsg.aNode = n;
+                            break;
+                        }
+                        else
+                        {
+                            LicBuffer.Enqueue(n);
+                        }
+                    }
                 }
-                else
+                //输出前再判断号牌是否合法
+                if (!NodeValidation(nmMsg.aNode))
                 {
-                    LicBuffer.Enqueue(n);
+                    nmMsg.aNode = null;
                 }
             }
-            ////buffer不为空且,aModel不存在或其中ip已被置空
-            //if (LicBuffer.Count != 0 && (nmMsg.aModel == null || nmMsg.aModel.ip == "" || nmMsg.aModel.ip == "used"))
-            //{
-            //    NumberMachineNode n = LicBuffer.Dequeue();
-                
-            //    nmMsg.aModel = LicBuffer.Dequeue();
-            //    UILogServer.ins.info("号牌:" + nmMsg.aModel.LicenseNum + ",准备入队");
-            //}
             return nmMsg;
         }
 
+        /// <summary>
+        /// 一次停车流程完成时调用该方法,发送已完成车辆号牌信息
+        /// </summary>
+        /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
         public void SetMessage(AbstractMessage message)
         {
             if (message.GetType().Equals(typeof(NumberMachineMessage)))
             {
-                NumberMachineNode n = ((NumberMachineMessage)message).aModel;
-                if (n != null && n.ip == "")
+                NumberMachineNode n = ((NumberMachineMessage)message).aNode;
+                lock (LicBuffer)
                 {
-                    if (nmMsg != null && nmMsg.aModel != null && nmMsg.aModel.LicenseNum.Equals(n.LicenseNum))
-                    {
-                        nmMsg.aModel.ip = "";
-                        LicBuffer.Enqueue((NumberMachineNode)nmMsg.aModel.Clone());
-                        nmMsg.aModel = null;
-                    }
-                    else
+                    //输入号牌格式无误
+                    if (n != null && n.ip != null && n.ip == "")
                     {
-                        for (int i = 0; i < LicBuffer.Count; i++)
+                        //与类成员变量中aNode号牌相同,将其ip复位表示已使用,重新入队等待清除
+                        if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum.Equals(n.LicenseNum))
+                        {
+                            nmMsg.aNode.ip = "";
+                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
+                            nmMsg.aNode = null;
+                        }
+                        //搜索号牌队列,将相应号牌置空,准备清除
+                        else
                         {
-                            NumberMachineNode temp = LicBuffer.Dequeue();
-                            //已匹配上,ip置空
-                            if (temp.LicenseNum.Equals(n.LicenseNum))
+                            for (int i = 0; i < LicBuffer.Count; i++)
                             {
-                                temp.ip = "";
+
+                                NumberMachineNode temp = LicBuffer.Dequeue();
+                                //已匹配上,ip置空
+                                if (temp.LicenseNum.Equals(n.LicenseNum))
+                                {
+                                    temp.ip = "";
+                                    LicBuffer.Enqueue(temp);
+                                    break;
+                                }
                                 LicBuffer.Enqueue(temp);
-                                break;
                             }
-                            LicBuffer.Enqueue(temp);
                         }
                     }
-
                 }
             }
-                //传入异常号牌,根据ip找到handle,并以此获得intPtr 图像结构体,调用VzLPRClient_ImageSaveToJpeg,存下图片
-                //if (message.GetType().Equals(typeof(Command)))
-                //{
-                //    Command cmd = (Command)message;
-                //    if (cmd != null && cmd.ip != "" && ipHandleMap.TryGetValue(cmd.ip, out int handle) && handleImgMap.TryGetValue(handle, out IntPtr pImgFull))
-                //    //if (cmd != null && cmd.ip != "" && ipHandleMap.TryGetValue(cmd.ip, out int handle) && devPicMap.TryGetValue(handle, out PictureBox pic))
-                //    {
-                //        string strFilePath = ConfigurationManager.AppSettings["LogPath"] + DateTime.Now.ToString("yyyyMMddHHmmssffff");
-                //        if (!Directory.Exists(strFilePath))
-                //        {
-                //            Directory.CreateDirectory(strFilePath);
-                //        }
-                //        string path = strFilePath + "\\" + cmd.ip + ".jpg";
-                //        int temp = VzClientSDK.VzLPRClient_ImageSaveToJpeg(pImgFull, path, 100);
-                //        //VzClientSDK.VzLPRClient_GetSnapShootToJpeg2(handle,path,100);
-                //        LogFile logFile = LogFile.ERROR_NUMBERPLATE;
-                //        Log.WriteLog(logFile, "异常号牌" + cmd.ip + "已拍照保存于 " + strFilePath);
-                //        //UILogServer.ins.error(temp + "..异常号牌" + cmd.ip + "已拍照保存于 " + strFilePath);
-                //    }
-                //    else
-                //    {
-                //        UILogServer.ins.error("参数错误,异常号牌图片未保存");
-                //    }
-                //}
-
         }
+
     }
     public class Win32API
     {

+ 171 - 0
parkMonitor/server/NumMachine/NumMachineSimul.cs

@@ -0,0 +1,171 @@
+using parkMonitor.entity;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace parkMonitor.server
+{
+    class NumMachineSimul : IEquipments
+    {
+        ///<summary>号牌队列</summary>
+        private Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
+        /// <summary>
+        /// 号牌信息
+        /// </summary>
+        private NumberMachineMessage nmMsg = new NumberMachineMessage();
+        private const string header = "鄂A000";
+        /// <summary>
+        /// 号牌数组
+        /// </summary>
+        private List<string> NumExamples = new List<string>();
+        /// <summary>
+        /// 号牌对象数组
+        /// </summary>
+        private List<NumberMachineNode> NumNodes = new List<NumberMachineNode>();
+        private bool closing = false;
+
+        /// <summary>
+        /// 主逻辑
+        /// </summary>
+        private void Run()
+        {
+            while (!closing)
+            {
+                Thread.Sleep(2000);
+                foreach (NumberMachineNode n in NumNodes)
+                {
+                    if(!LicBuffer.Contains(n))
+                        LicBuffer.Enqueue((NumberMachineNode)n.Clone());
+                    Thread.Sleep(7000);
+                }
+                //除去已停车完成的号牌
+                lock (LicBuffer)
+                {
+                    NumberMachineNode temp = null;
+                    for (int i = 0; i < LicBuffer.Count; i++)
+                    {
+                        temp = LicBuffer.Dequeue();
+                        if (temp.ip != "")
+                        {
+                            LicBuffer.Enqueue(temp);
+                        }
+                    }
+                }
+            }
+        }
+
+        private bool NodeValidation(NumberMachineNode node)
+        {
+            return (node != null && node.ip != null && node.ip != "" && node.ip != "used") ? true : false;
+        }
+
+        /// <summary>
+        /// 监控线程获取号牌机信息,核心线程获取号牌信息
+        /// </summary>
+        public AbstractMessage GetMessage()
+        {
+            lock (LicBuffer)
+            {
+                //准备输出的数据中存在非法Node,且LicBuffer可出队产生一个合法Node,则替换该非法Node
+                if (!NodeValidation(nmMsg.aNode))
+                {
+                    for (int i = 0; i < LicBuffer.Count; i++)
+                    {
+                        NumberMachineNode n = LicBuffer.Dequeue();
+                        if (NodeValidation(n))
+                        {
+                            Console.WriteLine("号牌:" + n.LicenseNum + ",准备入队");
+                            nmMsg.aNode = n;
+                            break;
+                        }
+                        else
+                        {
+                            LicBuffer.Enqueue(n);
+                        }
+                    }
+                }
+                //输出前再判断号牌是否合法
+                if (!NodeValidation(nmMsg.aNode))
+                {
+                    nmMsg.aNode = null;
+                }
+            }
+            return nmMsg;
+        }
+
+        /// <summary>
+        /// 一次停车流程完成时调用该方法,发送已完成车辆号牌信息
+        /// </summary>
+        /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
+        public void SetMessage(AbstractMessage message)
+        {
+            if (message.GetType().Equals(typeof(NumberMachineMessage)))
+            {
+                NumberMachineNode n = ((NumberMachineMessage)message).aNode;
+                //输入号牌格式无误
+                lock (LicBuffer)
+                {
+                    if (n != null && n.ip == "")
+                    {
+                        //与类成员变量中aNode号牌相同,将其ip复位表示已使用,重新入队等待清除
+                        if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum.Equals(n.LicenseNum))
+                        {
+                            nmMsg.aNode.ip = "";
+                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
+                            nmMsg.aNode = null;
+                        }
+                        //搜索号牌队列,将相应号牌置空,准备清除
+                        else
+                        {
+                            for (int i = 0; i < LicBuffer.Count; i++)
+                            {
+
+                                NumberMachineNode temp = LicBuffer.Dequeue();
+                                //已匹配上,ip置空
+                                if (temp.LicenseNum.Equals(n.LicenseNum))
+                                {
+                                    temp.ip = "";
+                                    LicBuffer.Enqueue(temp);
+                                    break;
+                                }
+                                LicBuffer.Enqueue(temp);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        public void Start()
+        {
+            closing = false;
+            //创建模拟号牌
+            int temp = 0;
+            Task.Factory.StartNew(() =>
+            {
+                for (int i = 0; i < 10; i++)
+                {
+                    temp = 111 * i;
+                    NumExamples.Add(header + temp.ToString("D3"));
+                }
+                foreach (string str in NumExamples)
+                {
+                    NumberMachineNode node = new NumberMachineNode("192.168.0.20", str, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), 1);
+                    NumNodes.Add((NumberMachineNode)node.Clone());
+                }
+            });
+            Task.Factory.StartNew(() =>
+            {
+                Run();
+            });
+        }
+
+        public void Stop()
+        {
+            closing = true;
+        }
+    }
+}

+ 50 - 25
parkMonitor/server/PLCLinker/PLCLinker.cs

@@ -234,7 +234,7 @@ namespace parkMonitor.server
                             while (true)
                             {
                                 Console.WriteLine("尝试重连plc");
-                                UILogServer.ins.error("尝试重连plc");
+                                UILogServer.ins.log("尝试重连plc");
                                 LinkStart();
                                 Thread.Sleep(10000);
                                 if (isConnection)
@@ -271,6 +271,7 @@ namespace parkMonitor.server
                     {
                         AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
                         Console.WriteLine("读取失败");
+                        isConnection = false;
                         exceptionBreak = true;
                     }
                 }
@@ -330,14 +331,15 @@ namespace parkMonitor.server
                             if (laser1_rescan > 0)
                             {
                                 //laser1_frequencyDivision = laser_rescan_count * (int)(LASER_TIME_SCALE / PLC_refresh_interval);
-                                UILogServer.ins.error("激光1算异常,重新测量");
+                                UILogServer.ins.error("激光1算异常,重新测量");
                                 laser1_rescan--;
                                 //停车完成置0
                                 SendtoPLC(park_completed_addr.ToString(), "0");
                                 //开始停车归零后置1
                                 SendtoPLC(park_command_addr.ToString(), "0");
-                                Thread.Sleep(500);
+                                Thread.Sleep(1000);
                                 SendtoPLC(park_command_addr.ToString(), "1");
+                                Thread.Sleep(2000);
                             }
                             else if (laser1_rescan == 0)
                             {
@@ -346,7 +348,7 @@ namespace parkMonitor.server
                                 AsyncCmdServer.ins.send(AsyncCmdType.Laser1CalcException);
                                 //laser1_rescan = laser_rescan_count;
                                 laser1_heartbeatTest = true;
-                                UILogServer.ins.error("激光1算异常超过重测次数,请检查");
+                                UILogServer.ins.error("激光1算异常超过重测次数,请检查");
                                 //laser1_frequencyDivision = laser_rescan_count * (int)(LASER_TIME_SCALE / PLC_refresh_interval);
                             }
                         }
@@ -372,14 +374,15 @@ namespace parkMonitor.server
                             if (laser2_rescan > 0)
                             {
                                 //laser2_frequencyDivision = laser_rescan_count * (int)(LASER_TIME_SCALE / PLC_refresh_interval);
-                                UILogServer.ins.error("激光2算异常,重新测量");
+                                UILogServer.ins.error("激光2算异常,重新测量");
                                 laser2_rescan--;
                                 //停车完成置0
                                 SendtoPLC(park_completed_addr.ToString(), "0");
                                 //开始停车归零后置1
                                 SendtoPLC(park_command_addr.ToString(), "0");
-                                Thread.Sleep(500);
+                                Thread.Sleep(1000);
                                 SendtoPLC(park_command_addr.ToString(), "1");
+                                Thread.Sleep(2000);
                             }
                             else if (laser2_rescan == 0)
                             {
@@ -388,7 +391,7 @@ namespace parkMonitor.server
                                 AsyncCmdServer.ins.send(AsyncCmdType.Laser2CalcException);
                                 //laser2_rescan = laser_rescan_count;
                                 laser2_heartbeatTest = true;
-                                UILogServer.ins.error("激光2算异常超过重测次数,请检查");
+                                UILogServer.ins.error("激光2算异常超过重测次数,请检查");
                                 //laser2_frequencyDivision = laser_rescan_count * (int)(LASER_TIME_SCALE / PLC_refresh_interval);
                             }
                         }
@@ -539,7 +542,7 @@ namespace parkMonitor.server
                     LaserRecord(1, ref laser1_normal, ref laser1_record, listForLaser);
                 if (laser2_status_addr != -1)
                     LaserRecord(2, ref laser2_normal, ref laser2_record, listForLaser);
-                Thread.Sleep(1000);
+                Thread.Sleep(200);
             }
             catch (Exception)
             {
@@ -599,7 +602,6 @@ namespace parkMonitor.server
 
         private void LinkStart()
         {
-            InitTimer();//启动
             if (busTcpClient != null)
             {
                 busTcpClient.ConnectClose();
@@ -612,6 +614,7 @@ namespace parkMonitor.server
                 {
                     AsyncCmdServer.ins.send(AsyncCmdType.PLCOnline);
                     Console.WriteLine("连接成功");
+                    UILogServer.ins.info("PLC连接成功");
                     isConnection = true;
                     linkCount = 0;
                 }
@@ -619,6 +622,7 @@ namespace parkMonitor.server
                 {
                     AsyncCmdServer.ins.send(AsyncCmdType.PLCOffline);
                     Console.WriteLine("连接失败,重试");
+                    //UILogServer.ins.error("PLC连接失败,重试");
                     isConnection = false;
                 }
             }
@@ -626,6 +630,7 @@ namespace parkMonitor.server
             {
                 Console.WriteLine(ex.Message);
             }
+            InitTimer();//启动计时器
         }
 
         //private void SendtoPLC(ParkingMessage pm)
@@ -673,16 +678,21 @@ namespace parkMonitor.server
                         //停车startLaser--park_command_address
                         case 1:
                             //start laser scanning for parking
-                            SendtoPLC(park_command_addr.ToString(), "1");
-                            Thread.Sleep(100);
-                            if (plcMsg.laser1 != null)
-                            {
-                                plcMsg.laser1.status = 6;
-                            }
-                            if (plcMsg.laser2 != null)
+                            Task.Factory.StartNew(() =>
                             {
-                                plcMsg.laser2.status = 6;
-                            }
+                                SendtoPLC(park_command_addr.ToString(), "0");
+                                Thread.Sleep(500);
+                                SendtoPLC(park_command_addr.ToString(), "1");
+                                if (plcMsg.laser1 != null)
+                                {
+                                    plcMsg.laser1.status = 6;
+                                }
+                                if (plcMsg.laser2 != null)
+                                {
+                                    plcMsg.laser2.status = 6;
+                                }
+                                Thread.Sleep(100);
+                            });
                             //Console.WriteLine("扫摆激光启动");
                             break;
                         //停车激光的6个数据,停车机械手,车位信息4个
@@ -737,10 +747,29 @@ namespace parkMonitor.server
                 while (!isClosing)
                 {
                     LaserMonitor();
-                    Thread.Sleep(1000);
                 }
             });
-            // MainModel.ins.plcConfigMd.;
+
+            Task.Factory.StartNew(() =>
+            {
+                while (!isClosing)
+                {
+                    //模拟plc自动重置
+                    foreach (PLCNode p in listForLaser)
+                    {
+                        int addr = Int32.Parse(p.Address);
+                        int value = Int32.Parse(p.Value);
+                        if (addr == parking_startRobot_address && value == 1)
+                        {
+                            Thread.Sleep(5000);
+                            SendtoPLC(addr.ToString(), "0");
+                            Thread.Sleep(1000);
+                            SendtoPLC(park_completed_addr.ToString(), "1");
+                        }
+                    }
+                }
+            });
+
             exceptionBreak = false;
             plcMsg.laser1 = new LaserMessage();
             plcMsg.laser2 = new LaserMessage();
@@ -749,11 +778,7 @@ namespace parkMonitor.server
             laser1CountDown = laser_countdown;
             laser2CountDown = laser_countdown;
             linkCount = 0;
-            //ipString = MainModel.ins.xmlConfig.value("parkMonitor.config.PLC.ip", "127.0.0.1");
-            //port = MainModel.ins.xmlConfig.valueInt("parkMonitor.config.PLC.port", 502);
-            //station = (byte)MainModel.ins.xmlConfig.valueInt("parkMonitor.config.PLC.station", 1);
-            //startAddr = MainModel.ins.xmlConfig.valueInt("parkMonitor.config.PLC.startAddress", 0);
-            //addrLength = MainModel.ins.xmlConfig.valueInt("parkMonitor.config.PLC.addressLength", 50);
+
             try
             {
                 ipString = ConfigurationManager.AppSettings.Get("PLC_ip_address");

+ 20 - 16
parkMonitor/server/WebThread/CentralForWebSocketServer.cs

@@ -25,6 +25,7 @@ namespace parkMonitor.server.WebThread
         {
             return (AbstractMessage)blockingQueue.Dequeue();
         }
+
         public void SetMessage(AbstractMessage message)
         {
             //multiSocketThread.SendMessage(message);
@@ -54,6 +55,7 @@ namespace parkMonitor.server.WebThread
                 throw new Exception();
             }
         }
+
         private void Run()
         {
             bool linked = false;
@@ -82,25 +84,25 @@ namespace parkMonitor.server.WebThread
                     }
                     catch (Exception)
                     {
-                        Task.Factory.StartNew(() =>
+                        //Task.Factory.StartNew(() =>
+                        //{
+                        while (!linked)
                         {
-                            while (!linked)
+                            Thread.Sleep(10000);
+                            try
+                            {
+                                listener = LazySingleton.GetInstance(localAddr, port);
+                                listener.Start();
+                                linked = true;
+                                UILogServer.ins.info("已成功重连");
+                                break;
+                            }
+                            catch (Exception)
                             {
-                                try
-                                {
-                                    listener = LazySingleton.GetInstance(localAddr, port);
-                                    listener.Start();
-                                    linked = true;
-                                    UILogServer.ins.error("已成功重连");
-                                    break;
-                                }
-                                catch (Exception)
-                                {
-                                    UILogServer.ins.error("未能与Web服务器连接,本地ip错误或网络异常");
-                                }
-                                Thread.Sleep(5000);
+                                UILogServer.ins.error("未能与Web服务器连接,本地ip错误或网络异常");
                             }
-                        });
+                        }
+                        //});
                     }
                     Thread.Sleep(5000);
                 }
@@ -108,6 +110,7 @@ namespace parkMonitor.server.WebThread
                     multiSocketThread.Close();
             });
         }
+
         public void Start()
         {
             string strTemp = ConfigurationManager.AppSettings["WebConfig"];
@@ -130,6 +133,7 @@ namespace parkMonitor.server.WebThread
             //thread.Start();
             Run();
         }
+
         public void Stop()
         {
             isClosing = true;

+ 1 - 1
parkMonitor/server/WebThread/MultiSocketThread.cs

@@ -55,7 +55,7 @@ namespace parkMonitor.server.WebThread
 
         public void Run()
         {
-            //int i = 4;
+            //int i = 2;
             //while (i-- > 0)
             //{
                 SendMessage(message);

+ 1 - 1
parkMonitor/view/mainWin/MainWindow.xaml.cs

@@ -203,7 +203,7 @@ namespace parkMonitor
         {
             CmdServer.ins.send(CmdType.MainWinClosed);
 
-           // xmlConfig.save();
+            //xmlConfig.save();
         }
 
         /// <summary>点击复位按钮</summary>