using GpsModels; using GPSBusiness; using GPSBusiness.GPSStandard; using GPSServer.Helper; using HPSocketCS; using Newtonsoft.Json; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using GPSBusiness.BBGPSStandard; using GPSBusiness.Enum; using GPSBusiness.Helper; using GPSBusiness.Redis; using GPSBusiness.Sql; using Toogps.Mongo.Repository; using GPSBusiness.Model; using GPSBuSiness.Util; namespace GPSServer { public partial class Main : Form { #region 显示消息 private delegate void ShowMsg(string msg); private ShowMsg _addMsgLabel; private ShowMsg _addMsgLabel1; private ShowMsg _addMsgLabel2; private ShowMsg _addMsgLabel3; // 显示消息:终端连接数 void AddMsg(string msg) { if (this.lbZD.InvokeRequired) { this.lbZD.Invoke(_addMsgLabel, msg); } else { this.lbZD.Text = msg; } } // 显示消息:实时队列中的数据 void AddMsg1(string msg) { if (this.lbDL.InvokeRequired) { this.lbDL.Invoke(_addMsgLabel1, msg); } else { this.lbDL.Text = msg; } } // 显示消息:持久化队列数据 void AddMsg2(string msg) { if (this.lbCJH.InvokeRequired) { this.lbCJH.Invoke(_addMsgLabel2, msg); } else { this.lbCJH.Text = msg; } } // 显示消息:完成持久化的数据 void AddMsg3(string msg) { if (this.label7.InvokeRequired) { this.label7.Invoke(_addMsgLabel3, msg); } else { this.label7.Text = msg; } } #endregion /// /// 应用状态 /// private AppState _appState = AppState.Stoped; /// /// gps设备tcp服务 /// private readonly TcpServer _gpsEquServer = new TcpServer(); public static SqlRepository CarService = new SqlRepository(); private static int _persistenceGpsNo = 0; private static int _persistenceCarGpsNo = 0; private static long _savePsNo = 0; /// /// 出发厂区半径 /// private static int _setOutRadius; /// /// 到达工地半径 /// private static int _arriveRadius; public Main() { InitializeComponent(); } private void Main_Load(object sender, EventArgs e) { this.Log().Info("程序启动"); _setOutRadius = int.Parse(ConfigurationManager.AppSettings["SetOutRadius"]); _arriveRadius = int.Parse(ConfigurationManager.AppSettings["ArriveRadius"]); _addMsgLabel += AddMsg; _addMsgLabel1 += AddMsg1; _addMsgLabel2 += AddMsg2; _addMsgLabel3 += AddMsg3; GpsStandardHelper.BBStandardToCarGPSHandler = new BbStandardToCarGpsHandler(CarService); _gpsEquServer.OnPrepareListen += new TcpServerEvent.OnPrepareListenEventHandler(OnGpsEquServerPrepareListen); _gpsEquServer.OnAccept += new TcpServerEvent.OnAcceptEventHandler(OnGpsEquServerAccept); _gpsEquServer.OnSend += new TcpServerEvent.OnSendEventHandler(OnGPSEquServerSend); _gpsEquServer.OnClose += new TcpServerEvent.OnCloseEventHandler(OnGpsEquServerClose); _gpsEquServer.OnError += new TcpServerEvent.OnErrorEventHandler(OnGpsEquServerError); _gpsEquServer.OnReceive += new TcpServerEvent.OnReceiveEventHandler(OnGpsEquServerReceive); _gpsEquServer.OnShutdown += new TcpServerEvent.OnShutdownEventHandler(OnGpsEquServerShutdown); CarService.Init(); CarService.InitCompany(); CarService.InitOrders(); SetAppState(AppState.Stoped); // var list = CarGpsRepository.MongoGetListDemo(); } #region GPSEquService Handle private HandleResult OnGpsEquServerPrepareListen(IntPtr soListen) { return HandleResult.Ok; } private HandleResult OnGpsEquServerAccept(IntPtr connId, IntPtr pClient) { AddMsg(_gpsEquServer.ConnectionCount.ToString()); return HandleResult.Ok; } private HandleResult OnGPSEquServerSend(IntPtr connId, IntPtr pData, int length) { return HandleResult.Ok; } private HandleResult OnGpsEquServerClose(IntPtr connId) { AddMsg((_gpsEquServer.ConnectionCount - 1).ToString()); return HandleResult.Ok; } private HandleResult OnGpsEquServerError(IntPtr connId, SocketOperation enOperation, int errorCode) { return OnGpsEquServerClose(connId); } /// /// 接收设备发来的数据 /// /// /// /// /// private HandleResult OnGpsEquServerReceive(IntPtr intPtr, IntPtr pData, int length) { try { byte[] bytes = new byte[length]; string mdtStr = ""; Marshal.Copy(pData, bytes, 0, length); var gpsResponseDatas = GpsStandardHelper.GetGpsStandardData(bytes, intPtr, mdtStr); foreach (var gpsResponseData in gpsResponseDatas) { if (gpsResponseData.GpsInfo != null) { var gpsModel = gpsResponseData.GpsInfo; if (gpsModel == null) continue; if (gpsModel.Acc == -1 )//沃瑞特心跳或者博实结未定位 { gpsModel.GpsState = GpsStateEnum.Motionless.ToInt(); //默认静止 gpsModel.DurationTime = ""; gpsModel.AccDurationTime = ""; #region 先处理沃瑞特心跳在线实时的时间===沃瑞特gps心跳时间间隔:2分钟一次。 var haveSpeedModel = RedisRepository.GetLastHaveSpeed(gpsModel); if (haveSpeedModel != null) { var time2 = DateTime.Now - haveSpeedModel.GpsTime; gpsModel.DurationTime = CalculationGpsHelper.TimeSpanFormat(time2); if (time2.TotalSeconds < 31) { gpsModel.GpsState = GpsStateEnum.Moving.ToInt(); gpsModel.Speed = haveSpeedModel.Speed; gpsModel.DurationTime = ""; } } FirstStatusCacheService(gpsModel, (int)StatusEnum.Acc); //分析Acc持续时长 var firstAccModel = RedisRepository.GetFirstStatus(gpsModel, (int)StatusEnum.Acc); if (firstAccModel != null) { if (firstAccModel.Acc != -1) { var time3 = DateTime.Now - firstAccModel.GpsTime; if (time3.TotalMilliseconds > 0) gpsModel.AccDurationTime = CalculationGpsHelper.TimeSpanFormat(time3); } } FirstStatusCacheService(gpsModel, (int)StatusEnum.Work); //分析作业持续时长 var firstWorkModel = RedisRepository.GetFirstStatus(gpsModel, (int)StatusEnum.Work); if (firstWorkModel != null) { if (firstWorkModel.Work != -1) { var time3 = DateTime.Now - firstWorkModel.GpsTime; if (time3.TotalMilliseconds > 0) gpsModel.WorkDurationTime = CalculationGpsHelper.TimeSpanFormat(time3); } } "bytes".Log().DebugFormat("GpsRealTimeRepository"); //MyGpsServer.UpdateGpsRealTimeGpsStateWrt(gpsModel); GpsRealTimeRepository.UpdateGpsRealTimeGpsStateWrt(gpsModel); #endregion } else//有gps数据信息,则加入到队列。 { //加入队列 ConcurrentQueue concurrentQueues; if (MApplication.ConcurrentQueues.TryGetValue(1, out concurrentQueues) == false) { //三次失败就不再尝试了 concurrentQueues = new ConcurrentQueue(); if (MApplication.ConcurrentQueues.TryAdd(1, concurrentQueues) == false) { if (MApplication.ConcurrentQueues.TryAdd(1, concurrentQueues) == false) { if (MApplication.ConcurrentQueues.TryAdd(1, concurrentQueues) == false) { this.Log().Error("TryAdd(model.SiteId, ConcurrentQueues) false"); } } } } //转成高德地图坐标点 //var tgGps = // MapHelper.Gps84ToGD((double)gpsModel.Latitude, // (double)gpsModel.Longitude); //基站定位不做多余解析 if (gpsModel.LocationStatus != 0) { var gdGps = GPSUtil.gps84_To_Gcj02((double)gpsModel.Latitude, (double)gpsModel.Longitude); if (gdGps.Length > 0) { gpsModel.Latitude = Convert.ToDecimal(gdGps[0]); gpsModel.Longitude = Convert.ToDecimal(gdGps[1]); } } gpsModel.Address = MapHelper.GetLocationByLngLat(gpsModel.Longitude, gpsModel.Latitude); // this.Log().InfoFormat("GPS数据对比,tgGps={0},gdGps={1},gdGps={2}", JsonConvert.SerializeObject(tgGps),gdGps[0], gdGps[1]); this.Log().InfoFormat(gpsModel.Address); concurrentQueues.Enqueue(gpsModel); _persistenceGpsNo++; this.Log().InfoFormat("添加一条Gps位置信息到队列,共{0}条,model={1}", _persistenceGpsNo, JsonConvert.SerializeObject(gpsModel)); } } //应答数据不为null,应答设备联接 if (gpsResponseData.ReturnData != null) { _gpsEquServer.Send(intPtr, gpsResponseData.ReturnData, gpsResponseData.ReturnData.Length); } } AddMsg1(_persistenceGpsNo.ToString()); } catch (Exception ex) { this.Log().ErrorFormat("OnGPSEquServerReceive=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace); } return HandleResult.Ok; } private HandleResult OnGpsEquServerShutdown() { AddMsg((_gpsEquServer.ConnectionCount - 1).ToString()); return HandleResult.Ok; } #endregion private void btnStart_Click(object sender, EventArgs e) { SetAppState(AppState.Starting); StartGpsEquServer(); } private void StartGpsEquServer() { try { _gpsEquServer.IpAddress = this.txtResIpAddress.Text.Trim(); _gpsEquServer.Port = ushort.Parse(this.txtResPort.Text.Trim()); // 启动接收服务 if (_gpsEquServer.Start()) { this.Text = string.Format("{2} - ({0}:{1})", this.txtResIpAddress.Text, this.txtResPort.Text, "GPS服务程序"); SetAppState(AppState.Started); } else { SetAppState(AppState.Stoped); throw new Exception(string.Format("$ receive Server Start Error -> {0}({1})", _gpsEquServer.ErrorMessage, _gpsEquServer.ErrorCode)); } } catch (Exception ex) { this.Log().ErrorFormat("StartGpsEquServer=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace); } } // 设置程序状态 private void SetAppState(AppState state) { _appState = state; this.btnStart.Enabled = (_appState == AppState.Stoped); this.btnStop.Enabled = (_appState == AppState.Started); this.txtResIpAddress.Enabled = (_appState == AppState.Stoped); this.txtResPort.Enabled = (_appState == AppState.Stoped); } private void btnStop_Click(object sender, EventArgs e) { try { SetAppState(AppState.Stoping); // 停止服务 if (_gpsEquServer.Stop()) { this.Text = "GPS服务程序"; SetAppState(AppState.Stoped); } else { this.Log().Error(string.Format("btnStop_Click Error -> {0}({1})", _gpsEquServer.ErrorMessage, _gpsEquServer.ErrorCode)); } } catch (Exception ex) { this.Log().ErrorFormat("btnStop_Click=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace); } } // 更新车辆、公司、订单信息 private void timer1_Tick(object sender, EventArgs e) { if (_appState != AppState.Started) return; CarService.Init(); CarService.InitCompany(); CarService.InitOrders(); } // 定时器:PersistenceGpsRealTime private void timer2_Tick(object sender, EventArgs e) { if (_appState != AppState.Started) return; PersistenceGpsRealTime(); } //更新车辆实时位置,更新Redis相关的Gps信息:1、车辆最后GPS时间。2、最后存在速度的GPS时间。3、Acc第一次开启的时间 private void PersistenceGpsRealTime() { try { foreach (var concurrentQueue in MApplication.ConcurrentQueues) { try { if (concurrentQueue.Value.Count == 0) continue; var models = new List(); for (var i = 0; i < Convert.ToInt32(_gpsEquServer.ConnectionCount); ) { GpsModel model; if (concurrentQueue.Value.TryDequeue(out model)) { models.Add(model); i++; _persistenceGpsNo--; } else { break; } } if (models.Count == 0) continue; foreach (var item in models) { var gpsModel = item; //=======================更新车辆实时==位置========================== //MyGpsServer.UpdateGpsRealTime(gpsModel); //当有GPS数据时再更新主表 if (gpsModel.Latitude > 0 && gpsModel.Longitude > 0) { GpsRealTimeRepository.UpdateGpsRealTime(gpsModel); } else { this.Log().ErrorFormat("gpsModel.Latitude=0:{2}", gpsModel.VehicleId); } //=======================更新车辆实时==位置========================== //有速度的最后定位时间 到Redis LastHaveSpeedCacheService(gpsModel); //更新Acc 到Redis FirstStatusCacheService(gpsModel, (int)StatusEnum.Acc); //更新Work 到Redis FirstStatusCacheService(gpsModel, (int)StatusEnum.Work); //=======================更新车辆实时==状态========================== AnalysesGpsState(gpsModel);//TODO:逻辑检查,判断上两句存储在Redis的数据,是否会符合业务逻辑。是否会影响 //=======================更新车辆实时==状态========================== //入列到待持久化队列中 ConcurrentQueue carConcurrentQueues; if (MApplication.CarConcurrentQueues.TryGetValue(gpsModel.VehicleId, out carConcurrentQueues) == false) { //三次失败就不再尝试了 carConcurrentQueues = new ConcurrentQueue(); if (MApplication.CarConcurrentQueues.TryAdd(gpsModel.VehicleId, carConcurrentQueues) == false) { if (MApplication.CarConcurrentQueues.TryAdd(gpsModel.VehicleId, carConcurrentQueues) == false) { if (MApplication.CarConcurrentQueues.TryAdd(gpsModel.VehicleId, carConcurrentQueues) == false) { this.Log().Error("TryAdd(model.VehicleId, ConcurrentQueues) false"); } } } } carConcurrentQueues.Enqueue(gpsModel); _persistenceCarGpsNo++; } } catch (Exception ex) { this.Log().ErrorFormat("PersistenceGpsRealTime=concurrentQueue.Key={3}=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace, concurrentQueue.Key); } } AddMsg1(_persistenceGpsNo.ToString()); AddMsg2(_persistenceCarGpsNo.ToString()); } catch (Exception ex) { this.Log().ErrorFormat("timer2_Tick=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace); } } // 定时器:持久化gps数据到轨迹表。 private void timer3_Tick(object sender, EventArgs e) { if (_appState != AppState.Started) return; PersistenceCarGps(); } // 定时器:分析Gps离线后关闭车辆Acc开关。 private void timer4_Tick(object sender, EventArgs e) { if (_appState != AppState.Started) return; UpdateGpsRealTimeAccState(); } /// /// 离线时关闭车辆的Acc状态 /// public void UpdateGpsRealTimeAccState() { try { var list = GpsRealTimeRepository.GetOffLineGpsRealTime(); if(!list.Any()) return; var offLineList = list.ConvertAll(x => new GpsModel { Acc = 0, Work = 0, // VehicleId =x.VehicleId, // SimNo = x.SimNo, // CompanyId = x.CompanyId , // Longitude = x.Longitude, // Latitude = x.Latitude, // Speed = x.Speed, // Direct = x.Direct, GpsState = 0, //GpsTime = x.GpsTime, // RecTime = x.RecTime, //Address = x.Address, DurationTime = "", AccDurationTime = "", WorkDurationTime = "", }); offLineList.ForEach(x => { FirstStatusCacheService(x,(int)StatusEnum.Acc); FirstStatusCacheService(x, (int)StatusEnum.Work); GpsRealTimeRepository.UpdateGpsRealTimeGpsStateWrt(x); }); this.Log().InfoFormat("更改Acc状态,更新车辆{0}辆", offLineList.Count); } catch (Exception ex) { this.Log().ErrorFormat("UpdateGpsRealTimeAccState=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace); } } // 持久化gps数据到轨迹表。 private void PersistenceCarGps() { this.Log().Debug("PersistenceCarGps"); try { foreach (var concurrentQueue in MApplication.CarConcurrentQueues) { try { if (concurrentQueue.Value.Count == 0) continue; var models = new List(); while (true) { GpsModel model; if (concurrentQueue.Value.TryDequeue(out model)) { models.Add(model); _persistenceCarGpsNo--; } else { break; } } string tableName = "Car_" + concurrentQueue.Key + "_" + DateTime.Now.ToString("yyyyMM"); //string tableName = "CarGps_" + concurrentQueue.Key + "_test2_" + DateTime.Now.ToString("yyyyMM"); //测试 //插入数据到mongodb中。 CarGpsRepository.InsertCarGpsList(models, tableName); _savePsNo += models.Count; } catch (Exception ex) { this.Log().ErrorFormat("PersistenceCarGps持久化gps数据到Car表异常=concurrentQueue.Key={3}=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace, concurrentQueue.Key); } } AddMsg2(_persistenceCarGpsNo.ToString()); AddMsg3(_savePsNo.ToString()); } catch (Exception ex) { this.Log().ErrorFormat("PersistenceCarGps=报错=,ex.Message={0},ex.InnerException={1},ex.StackTrace={2}", ex.Message, ex.InnerException, ex.StackTrace); } } //分析车辆任务状态 //分析车辆状态:0:离线,1:移动[在线],2:短停[在线],3:长停[在线] //分析车辆长停短停离线持续时间。 //分析订单状态是否【已出发】【已到达】【作业中】,有开启gps分析才会分析这个。订单状态:0未指派、1已指派、2已接单、3已出发、4已完成、5已删除、6已到达、7作业中、8已作废、9已撤销 private void AnalysesGpsState(GpsModel lastModel) { var car = SqlRepository.Cars.FirstOrDefault(s => s.Id == lastModel.VehicleId); if(car == null) return; var gpsState = GpsStateEnum.OffLine.ToInt(); //Gps时间>15min则表示离线 var durationTime = ""; //gps持续时长 //int Acc = 0; //Acc状态 var AccDurationTime = ""; //Acc持续时长 var workDurationTime = ""; //Acc持续时长 var time = DateTime.Now - lastModel.GpsTime; durationTime = CalculationGpsHelper.TimeSpanFormat(time);//持续时长,长停短停的。//默认为离线持续时长 AccDurationTime = durationTime; //默认跟gps时长一致。 if (time.TotalMinutes <= 15)//表示在线 { gpsState = GpsStateEnum.Motionless.ToInt();//静止 if (lastModel.Speed > 0) { gpsState = GpsStateEnum.Moving.ToInt();//移动 durationTime = ""; } else { var haveSpeedModel = RedisRepository.GetLastHaveSpeed(lastModel); if (haveSpeedModel != null) { var time2 = DateTime.Now - haveSpeedModel.GpsTime; durationTime = CalculationGpsHelper.TimeSpanFormat(time2); } } //分析Acc持续时长 var firstAccModel = RedisRepository.GetFirstStatus(lastModel, (int) StatusEnum.Acc); if (firstAccModel != null) { var time3 = DateTime.Now - firstAccModel.GpsTime; AccDurationTime = CalculationGpsHelper.TimeSpanFormat(time3); } //分析作业持续时长 var firstWorkModel = RedisRepository.GetFirstStatus(lastModel, (int)StatusEnum.Work); if (firstWorkModel != null) { var time3 = DateTime.Now - firstWorkModel.GpsTime; workDurationTime = CalculationGpsHelper.TimeSpanFormat(time3); } } //=======================更新车辆实时状态========================== //MyGpsServer.UpdateGpsRealTimeGpsState(car, gpsState, durationTime, AccDurationTime); GpsRealTimeRepository.UpdateGpsRealTimeGpsState(car, gpsState, durationTime, AccDurationTime, workDurationTime); //=======================更新车辆实时状态========================== //========分析订单状态(公司已开启订单分析),更改订单的State:已出发,已到达,作业中================= //找到此车辆所属公司 var company = SqlRepository.Companys.Find(s => s.Id == 99999); if (company != null) { //找到此车辆所有订单 var ods = SqlRepository.Orders.FindAll(s => s.VehicleId == car.Id); if (ods.Any()) { foreach (var odModel in ods) { //分析:已出发//已接单的才能进行此分析。 var flag1 = odModel.State == ViOrderStateEnum.Accepted.ToInt(); var flag3 = odModel.State == ViOrderStateEnum.SetOut.ToInt(); if (flag1) { var distance = CalculationGpsHelper.GetDistance((double)lastModel.Longitude, (double)lastModel.Latitude, company.Longitude, company.Latitude); if (distance > _setOutRadius && !ods.Exists(s => s.Id != odModel.Id && s.State != 1)) { if (CarService.ExistThisStateOrder(odModel.Id, ViOrderStateEnum.SetOut.ToInt())) MyGpsServer.UpdateOrderState(odModel.Id, ViOrderStateEnum.SetOut.ToInt(), DateTime.Now); } } //分析:已到达//已接单或已出发才能进行此分析。 if (flag1 || flag3) { var distance2 = CalculationGpsHelper.GetDistance((double)lastModel.Longitude, (double)lastModel.Latitude, (double)odModel.Longitude, (double)odModel.Latitude); if (distance2 < _arriveRadius) { if (CarService.ExistThisStateOrder(odModel.Id, ViOrderStateEnum.Arrive.ToInt())) MyGpsServer.UpdateOrderState(odModel.Id, ViOrderStateEnum.Arrive.ToInt(), DateTime.Now); } } var flag5 = odModel.State == ViOrderStateEnum.Arrive.ToInt(); //分析:作业中//已到达且到达时间大于5分钟,则为工作中 if (flag5 && odModel.ArriveTime.Year > 1900) { var ts = DateTime.Now - odModel.ArriveTime; if (ts.Minutes > 5) { if (CarService.ExistThisStateOrder(odModel.Id, ViOrderStateEnum.Working.ToInt())) MyGpsServer.UpdateOrderState(odModel.Id, ViOrderStateEnum.Working.ToInt(), DateTime.Now); } } } } } } /// /// 车辆最后存在速度的GPS时间 /// /// /// public void LastHaveSpeedCacheService(GpsModel model) { if (RedisRepository.IsSetLastHaveSpeed(model) && model.Speed <= 0) return; RedisRepository.SetLastHaveSpeed(model); } /// /// 车辆Acc/作业状态第一次开启的时间 /// /// /// 1Acc,2Work /// public void FirstStatusCacheService(GpsModel model,int type) { if (type == (int)StatusEnum.Acc && model.Acc == -1) return; if (type == (int)StatusEnum.Work && model.Work == -1) return; if (!RedisRepository.IsSetFirstStatus(model, type)) { RedisRepository.SetFirstStatus(model, type); } else { var redisModel = RedisRepository.GetFirstStatus(model, type); switch (type) { case (int) StatusEnum.Acc: { if (redisModel == null || redisModel.Acc == model.Acc) return; break; } case (int)StatusEnum.Work: { if (redisModel == null || redisModel.Work == model.Work) return; break; } } RedisRepository.SetFirstStatus(model, type); var entity = new GpsCarStatusDurationModel { VehicleId = model.VehicleId, CompanyId = model.CompanyId, Code = model.VehicleCode, VehicleName = model.VehiclePlate, State = type == (int) StatusEnum.Acc ? model.Acc : model.Work, DurationTime = CalculationGpsHelper.TimeSpanFormat(model.GpsTime - redisModel.GpsTime), TimeBegin = redisModel.GpsTime, TimeEnd = model.GpsTime, CreatedTime = DateTime.Now, ModifiedTime = DateTime.Now, Type = type }; //Acc变更,则保存Acc持续时长 GpsRealTimeRepository.AddGpsCarStatusDuration(entity); } } } public enum AppState { Starting, Started, Stoping, Stoped, Error } }