using centralController.model; using nettyCommunication; using PLCS7; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace centralController.WebServer { class MyWebServer : IWebServer { private Queue waitToReserveQueue = null; private Queue reservedQueue = null; private object waitToReserveLock = new object(); private object reservedLock = new object(); private Communication comm = null; private Thread receiveMsg = null; private bool isClosing { get; set; } private bool connected { get; set; } public void BookFetchRecord() { throw new NotImplementedException(); } public void BookParkRecord() { throw new NotImplementedException(); } /// /// 更新预约车车辆状态 /// /// /// /// /// /// private bool UpdateVehicleState(bool localDB, int state, int orderRecordsID, string license) { string vehicleUpdateSql = ""; string vehicleInsertSql = ""; if (orderRecordsID > 0) { if (state >= 0) { vehicleUpdateSql = "update vehicle set vehiclepParkState = " + state + " ,orderRecordsID = " + orderRecordsID + " where numberPlate = '" + license + "';"; vehicleInsertSql = "insert into vehicle (numberPlate,vehiclepParkState,orderRecordsID) values " + "('" + license + "'," + state + "," + orderRecordsID + ");"; } else { vehicleUpdateSql = "update vehicle set orderRecordsID = " + orderRecordsID + " where numberPlate = '" + license + "';"; vehicleInsertSql = "insert into vehicle (numberPlate,orderRecordsID) values " + "('" + license + "'," + orderRecordsID + ");"; } } else { if (state >= 0) { vehicleUpdateSql = "update vehicle set vehiclepParkState = " + state + " where numberPlate = '" + license + "';"; vehicleInsertSql = "insert into vehicle (numberPlate,vehiclepParkState) values " + "('" + license + "'," + state + ");"; } else { return false; } } List vehicleUpdateList = new List(); List vehicleInsertList = new List(); vehicleUpdateList.Add(vehicleUpdateSql); vehicleInsertList.Add(vehicleInsertSql); if (localDB) { if (!Monitor.Monitor.localDBOper.Insert(vehicleInsertList)) { if (!Monitor.Monitor.localDBOper.UpdateTransaction(vehicleUpdateList)) return false; else return true; } else return true; } else { if (!Monitor.Monitor.remoteDBOper.Insert(vehicleInsertList)) { if (!Monitor.Monitor.remoteDBOper.UpdateTransaction(vehicleUpdateList)) return false; else return true; } else return true; } } /// /// 插入预约记录 /// /// /// /// /// /// /// /// private bool InsertOrderRecord(bool localDB, string userID, bool parking, string license, string orderTime, int orderLength) { bool result = false; string orderRecordInsertSql; if (parking) { orderRecordInsertSql = "insert into orderrecords (userID,numberPlate,garageID, bookParkTime, bookHour, bookPrice,bookState) " + "VALUES (" + userID + ", '" + license + "', '" + Monitor.Monitor.garageID + "', '" + orderTime + "', " + orderLength + ",NULL, '0');"; } else { orderRecordInsertSql = "insert into orderrecords (userID,numberPlate,garageID, bookFetchTime, bookHour, bookPrice,bookState) " + "VALUES (" + userID + ", '" + license + "', '" + Monitor.Monitor.garageID + "', '" + orderTime + "', " + orderLength + ",NULL, '2');"; } List orderList = new List(); orderList.Add(orderRecordInsertSql); if (localDB) result = Monitor.Monitor.localDBOper.Insert(orderList); else result = Monitor.Monitor.remoteDBOper.Insert(orderList); return result; } /// /// 找到当前预约记录ID /// /// /// /// 最近第几条记录,1表示最新一条 /// private int FindCurrentOrderRecordID(bool localDB, string license, int latestIndex = 1) { int currentID = 0; List orderRecords = Monitor.Monitor.GetOrderRecords(localDB, license, DateTime.Now.ToString("yyyy-MM-dd"), DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")); if (orderRecords.Count != 0) { try { currentID = (int)(UInt32)orderRecords[latestIndex - 1][0]; } catch { } } return currentID; } /// /// 预约数据库操作 /// /// /// /// /// /// /// /// private bool ReserveDBOperation(bool localDB, string userID, bool parking, string license, string orderTime, int orderLength) { UpdateVehicleState(localDB, parking ? 4 : 5, 0, license); //预约记录插入db InsertOrderRecord(localDB, userID, parking, license, orderTime, orderLength); //查询预约记录id号 int currentID = FindCurrentOrderRecordID(localDB, license); if (currentID == 0) { /*反馈web,预约失败*/ return false; } //更新车辆状态 UpdateVehicleState(localDB, parking ? 4 : 5, currentID, license); return true; } /// /// 检查预约指令是否可行 /// /// /// private bool ReservationValidate(MessageUTF8 msg) { //可预约车位总数 int allBookableSpace = Monitor.Monitor.ins.GetFreeSpaceCount(3); int count = 0; DateTime start, end; try { start = DateTime.Parse(msg.bookTime); end = start.AddHours(msg.bookLength); } catch { return false; } lock (waitToReserveLock) { Queue.Enumerator enumer = waitToReserveQueue.GetEnumerator(); while (enumer.MoveNext()) { DateTime tempStart, tempEnd; try { tempStart = DateTime.Parse(enumer.Current.bookTime); tempEnd = start.AddHours(enumer.Current.bookLength); } catch { return false; } if (!((tempStart - end).TotalMinutes > 0 || (start - tempEnd).TotalMinutes > 0)) { count += 1; } } } if (allBookableSpace >= count) return true; else return false; } /// /// 根据消息类型分别处理 /// /// private void MsgHandling(MessageUTF8 msg) { try { switch (msg.cmd) { //预约停 case "RESERVE": if (msg.sender != "" && msg.bookTime != "" && msg.bookLength != 0) { MessageUTF8 returnMsg = new MessageUTF8(); if (!ReservationValidate(msg)) { //回复预约失败给web returnMsg.cmd = "FAILED"; comm.SendMessage(returnMsg); Monitor.Monitor.SetNotification("车辆" + msg.context + "预约停车,已无可预约车位",parkMonitor.model.TextColor.Warning); } else { lock (waitToReserveLock) { waitToReserveQueue.Enqueue(msg); } //预约记录与车辆状态写入数据库 ReserveDBOperation(true, msg.sender, true, msg.context, msg.bookTime, msg.bookLength); ReserveDBOperation(false, msg.sender, true, msg.context, msg.bookTime, msg.bookLength); //回复成功给web returnMsg.cmd = "0"; comm.SendMessage(returnMsg); Monitor.Monitor.SetNotification("车辆" + msg.context + "预约停车,操作成功",parkMonitor.model.TextColor.Log); } } break; //预约取 case "PREFETCH": break; //停车 case "PARK": //根据号牌寻找对应号牌机编号,找不到则返回失败信息 //判断号牌机编号对应PLC数据块是否空闲,空闲则判断按钮状态并发送停车指令到PLC,否则返回失败信息 break; //取车 case "FETCH": break; //连接断开消息 case "DISCONNECT": Monitor.Monitor.SetNotification("收到连接断开提示消息",parkMonitor.model.TextColor.Warning); break; //更新广告 case "ADVERT": string adAlert = ""; bool result = Monitor.Monitor.advertMgr.UpdateAdvert(out adAlert); if (!result) { Monitor.Monitor.SetNotification("广告更新失败,请尝试手动更新",parkMonitor.model.TextColor.Warning); } else { Monitor.Monitor.SetNotification("广告更新成功\n" + adAlert,parkMonitor.model.TextColor.Log); } break; default: Monitor.Monitor.SetNotification("接收到无法识别的指令",parkMonitor.model.TextColor.Warning); break; } } catch (Exception ex) { Console.WriteLine("收消息," + ex.Message + "\n" + ex.StackTrace); } } private void SendBookCmd(bool parking, int state) { int countdown = 5; while (countdown-- > 0) { if (Monitor.Monitor.mainBlockInfo.bookParkCmd != 0) Thread.Sleep(300); else { MainBlockStru mb = new MainBlockStru { centralHearbeat = -1, bookParkCmd = parking ? (short)state : (short)-1, bookFetchCmd = !parking ? (short)state : (short)-1, licenseReceived = -1 }; Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central); Monitor.Monitor.SetNotification(mb.bookParkCmd + "," + mb.bookFetchCmd + "预约停车指令写入PLC",parkMonitor.model.TextColor.Log); break; } if (countdown == 2) { Monitor.Monitor.SetNotification("未能获取预约指令位0状态,尝试手动清除",parkMonitor.model.TextColor.Warning); MainBlockStru mb = new MainBlockStru { centralHearbeat = -1, bookParkCmd = parking ? (short)0 : (short)-1, bookFetchCmd = !parking ? (short)0 : (short)-1, licenseReceived = -1 }; Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central); Thread.Sleep(500); } } } /// /// 根据时间段处理所有准备预约及已预约指令 /// private void ReserveMsgHandling() { while (!isClosing) { //处理准备预约指令队列 lock (waitToReserveLock) { for (int i = 0; i < waitToReserveQueue.Count; i++) { try { MessageUTF8 msg = waitToReserveQueue.Dequeue(); DateTime startTime = DateTime.Parse(msg.bookTime); TimeSpan ts = DateTime.Now - startTime; //达到预约启动时间,放入已预约队列 Console.WriteLine("当前时间差:" + ts.TotalMinutes + ",指令类型:" + msg.cmd); if (ts.TotalMinutes >= 0) { Console.WriteLine(); //如果是预约停车,通知PLC减少一个可预约车位数 if (msg.cmd == "RESERVE") { SendBookCmd(true, 1); Monitor.Monitor.SetNotification("通知PLC减少可预约车位",parkMonitor.model.TextColor.Log); } reservedQueue.Enqueue(msg); } //还未达到启动时间 else { waitToReserveQueue.Enqueue(msg); } } catch { } } } lock (reservedLock) { for (int i = 0; i < reservedQueue.Count; i++) { try { MessageUTF8 msg = reservedQueue.Dequeue(); DateTime startTime = DateTime.Parse(msg.bookTime); TimeSpan ts = DateTime.Now - startTime; //预约超时 if (ts.TotalMinutes > msg.bookLength * 60) { Monitor.Monitor.SetNotification(msg.context+" 预约已超时",parkMonitor.model.TextColor.Warning); //通知PLC将可预约车位数恢复一个 SendBookCmd(true, 2); //恢复车辆状态 UpdateVehicleState(true, 0, 0, msg.context); UpdateVehicleState(false, 0, 0, msg.context); } else { reservedQueue.Enqueue(msg); } } catch { } } } Thread.Sleep(5000); } } /// /// 启动消息接收,启动超时指令处理 /// /// /// public bool Start(int port) { isClosing = false; waitToReserveQueue = new Queue(); reservedQueue = new Queue(); //MessageUTF8 message = new MessageUTF8(); //message.context = "sending message test"; //message.cmd = "S"; //message.parkingRecordsID = 1; //持续进行连接尝试 Task.Factory.StartNew(() => { //初始化后与web持续连接 while (!isClosing) { try { Connections.close(); Connections.Connection(); connected = true; comm = new Communication(); break; } catch (Exception) { connected = false; Console.WriteLine("服务没有开启,请检查服务器"); } Thread.Sleep(2000); } //持续判断连接状态并重连 while (!isClosing) { if(receiveMsg!=null) Console.WriteLine(Connections.isAlive() + ", " + receiveMsg.ThreadState.ToString()); if (Connections.isAlive()) { if (!connected) { comm = new Communication(); } connected = true; if (receiveMsg!=null && receiveMsg.ThreadState == ThreadState.Aborted) { try { receiveMsg.Start(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } else { connected = false; try { if (receiveMsg!=null && receiveMsg.ThreadState == ThreadState.WaitSleepJoin) { receiveMsg.Interrupt(); } } catch (Exception ex) { Monitor.Monitor.SetNotification("连接断开,终止消息接收线程",parkMonitor.model.TextColor.Log); } Console.WriteLine(" 连接关闭,需要重新连接注册"); try { Connections.close(); Connections.Connection(); } catch (Exception) { Console.WriteLine("服务没有开启,请检查服务器"); } } Thread.Sleep(1000); } }); //持续接收消息 receiveMsg = new Thread(() => { while (!isClosing) { try { if (connected && comm != null) { MessageUTF8 msg = ((MessageUTF8)comm.ReceiveMessage()); if (msg != null) { MsgHandling(msg); } //Monitor.Monitor.SetNotification(msg.context); } } catch { Console.WriteLine("线程已中断"); } } }); receiveMsg.Start(); //根据所处时间段处理预约指令 Task.Factory.StartNew(() => { ReserveMsgHandling(); }); return true; } /// /// 停止消息接收模块 /// public void Stop() { isClosing = true; Connections.close(); //throw new NotImplementedException(); } /// /// 预约车辆入场检测 /// /// /// public bool ReservedCarCheck(string license) { //对提前入场车辆,将预约指令丢出 lock (waitToReserveLock) { for (int i = 0; i < waitToReserveQueue.Count; i++) { MessageUTF8 msg = waitToReserveQueue.Dequeue(); if (msg.context != license) { waitToReserveQueue.Enqueue(msg); } } } //已进入预约状态车辆入场,审核确认后指令丢出 lock (reservedLock) { for (int i = 0; i < reservedQueue.Count; i++) { MessageUTF8 msg = reservedQueue.Dequeue(); if (msg.context == license) { return true; } else { reservedQueue.Enqueue(msg); } } } return false; } } }