using centralController.model; using db; using nettyCommunication; using parkMonitor.LOG; 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 connecting { 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); DBOperation dbHandle = null; if (localDB) dbHandle = Monitor.Monitor.localDBOper; else dbHandle = Monitor.Monitor.remoteDBOper; if (!dbHandle.UpdateTransaction(vehicleUpdateList)) { if (!dbHandle.Insert(vehicleInsertList, out int id)) return false; else return true; } else return true; } /// /// 插入预约记录 /// /// /// /// /// /// /// /// private bool InsertOrderRecord(bool localDB, string userID, bool parking, string license, string orderTime, int orderLength, out int id) { 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, out id); else result = Monitor.Monitor.remoteDBOper.Insert(orderList, out id); return result; } /// /// 找到当前预约记录ID,暂未使用 /// /// /// /// 最近第几条记录,1表示最新一条 /// private int FindCurrentOrderRecordID(bool localDB, string license, int latestIndex = 1) { int currentID = 0; int count = 10; while (count-- > 0 && 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, out int currentID); ////查询预约记录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, count; lock (waitToReserveLock) { //可预约车位总数 allBookableSpace = Monitor.Monitor.ins.GetFreeSpaceCount(4); count = 0; DateTime start, end; try { start = DateTime.Parse(msg.bookTime); end = start.AddHours(msg.bookLength); //Console.WriteLine("--------"+msg.bookTime+","+msg.bookLength); } catch { Console.WriteLine("时间解析异常1"); return false; } Queue.Enumerator enumer = waitToReserveQueue.GetEnumerator(); while (enumer.MoveNext()) { DateTime tempStart, tempEnd; try { tempStart = DateTime.Parse(enumer.Current.bookTime); tempEnd = tempStart.AddHours(enumer.Current.bookLength); //Console.WriteLine("#########" + enumer.Current.bookTime + "," + enumer.Current.bookLength); } catch { Console.WriteLine("时间解析异常2"); return false; } //Console.WriteLine("**********" + start.ToString() + "," + end.ToString() + "," + tempStart.ToString() + "," + tempEnd.ToString()); //Console.WriteLine("**********" + ((tempStart - end).TotalMinutes > 0)+","+ ((start - tempEnd).TotalMinutes > 0)); if (!((tempStart - end).TotalMinutes > 0 || (start - tempEnd).TotalMinutes > 0)) { count += 1; } } Queue.Enumerator enumer2 = reservedQueue.GetEnumerator(); while (enumer2.MoveNext()) { DateTime tempStart, tempEnd; try { tempStart = DateTime.Parse(enumer2.Current.bookTime); tempEnd = tempStart.AddHours(enumer2.Current.bookLength); //Console.WriteLine("#########" + enumer.Current.bookTime + "," + enumer.Current.bookLength); } catch { Console.WriteLine("时间解析异常2"); return false; } //Console.WriteLine("**********" + start.ToString() + "," + end.ToString() + "," + tempStart.ToString() + "," + tempEnd.ToString()); //Console.WriteLine("**********" + ((tempStart - end).TotalMinutes > 0)+","+ ((start - tempEnd).TotalMinutes > 0)); if (!((tempStart - end).TotalMinutes > 0 || (start - tempEnd).TotalMinutes > 0)) { count += 1; } } } Console.WriteLine("----------" + msg.context + ":" + allBookableSpace + "," + count); 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"; returnMsg.garageID = Monitor.Monitor.garageID; returnMsg.context = msg.context; comm.SendMessage(returnMsg); Monitor.Monitor.SetNotification("车辆" + msg.context + "预约停车,已无可预约车位", parkMonitor.model.TextColor.Warning); } else { bool DBOperResult = true; lock (waitToReserveLock) { waitToReserveQueue.Enqueue(msg); } //预约记录与车辆状态写入数据库 DBOperResult = DBOperResult && ReserveDBOperation(true, msg.sender, true, msg.context, msg.bookTime, msg.bookLength); DBOperResult = DBOperResult && ReserveDBOperation(false, msg.sender, true, msg.context, msg.bookTime, msg.bookLength); //回复成功给web if (!DBOperResult) Log.WriteLog(LogType.process, LogFile.WARNING, msg.context+"从"+msg.bookTime+"开始预约"+msg.bookLength+"小时,预约指令数据库操作未获得记录ID"); returnMsg.cmd = "OK"; returnMsg.garageID = Monitor.Monitor.garageID; returnMsg.context = msg.context; comm.SendMessage(returnMsg); Monitor.Monitor.SetNotification("车辆" + msg.context + "预约停车,操作成功", parkMonitor.model.TextColor.Log); } } break; case "CANCELRESERVE": //IEqualityComparer comparer ; //if(waitToReserveQueue.Contains(msg, ) 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; case "RESPONSE": if (msg.context == "REGSUCCESS") { Console.WriteLine("收到web注册指令"); } else if (msg.context == "HEARTSUCCESS") { Console.WriteLine("收到web心跳指令"); } 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 && countdown>1) { Thread.Sleep(300); if (countdown == 2) { Monitor.Monitor.SetNotification("未能获取预约指令位0状态,尝试手动清除", parkMonitor.model.TextColor.Warning); MainBlockStru mbs = new MainBlockStru { centralHearbeat = -1, bookParkCmd = parking ? (short)0 : (short)-1, bookFetchCmd = !parking ? (short)0 : (short)-1, licenseReceived = -1 }; Monitor.Monitor.PLC.WriteToPLC(mbs, PLCDataType.central); Thread.Sleep(500); } continue; } 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); Log.WriteLog(LogType.process, LogFile.INFO, mb.bookParkCmd + "," + mb.bookFetchCmd + "预约停车指令写入PLC"); break; } } /// /// 根据时间段处理所有准备预约及已预约指令 /// 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) { //如果是预约停车,通知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); Log.WriteLog(LogType.process, LogFile.INFO, msg.context + " 预约已超时"); //通知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; connecting = 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); } Connect(); }); //持续接收消息 receiveMsg = new Thread(() => { while (!isClosing) { try { if (connected && comm != null) { byte[] bytes = new byte[256]; MessageUTF8 msg = ((MessageUTF8)comm.ReceiveMessage(out bytes)); //string str = ""; //str = Encoding.Default.GetString(bytes); //Console.WriteLine(str); 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; } /// /// 主动连接web服务器 /// public void Connect() { //持续判断连接状态并重连 if (!connecting) { connecting = true; int count = 12; while (!isClosing) { //if (receiveMsg != null) // Console.WriteLine(Connections.isAlive() + ", " + receiveMsg.ThreadState.ToString()); if (Connections.isAlive()) { if (!connected) { comm = new Communication(); Monitor.Monitor.SetNotification("web已连接上", parkMonitor.model.TextColor.Info); } connected = true; if (receiveMsg != null && receiveMsg.ThreadState == ThreadState.Aborted) { try { receiveMsg.Start(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } else { if (count == 12 && connected) Monitor.Monitor.SetNotification("web连接已断开", parkMonitor.model.TextColor.Warning); else if (count == 0) break; connected = false; count--; 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); } Monitor.Monitor.SetNotification("重连web服务器超时,请检查网络并手动连接web服务器", parkMonitor.model.TextColor.Error); connecting = false; } else { Monitor.Monitor.SetNotification("正在尝试连接,请勿重复点击", parkMonitor.model.TextColor.Warning); } } /// /// 获取连接状态 /// /// public bool GetConnectStatus() { return connected; } } }