/// <summary> /// 查找外围优先级最低的跟踪,判断是否替换该跟踪 /// </summary> bool tryReplaceLowPrior(GateTrackInfo[] tracks, ShipTrackConfig ship, bool isCompulsory) { var outtracks = tracks.Where(_ => _.TrackStatus == GateTrackStatus.OuterTrack && !_.Ship.IsOutstanding).ToArray(); if (outtracks.Count() == 0) { return(false); } int shipPrior = ship.Ship.Priority; ///尝试调用低优先级的船舶跟踪闸机进行跟踪 var min = outtracks.Min(_ => _.Ship.Ship.Priority);//获取优先级最低值 if (isCompulsory || min < shipPrior) { var track = outtracks.LastOrDefault(_ => _.Ship.Ship.Priority == min); track.Update(ship); onTrack(track); return(true); } else { trace($"未找到优先级较低的闸机跟踪。{RegionId} {Name}: {ship.Ship.MMSI} - {ship.Ship.Name} {min} > {shipPrior}"); } return(false); }
bool tryKeepTrack(GateTrackInfo[] tracks, ShipTrackConfig ship, string shipId) { ///优先调用前一次跟踪该船的闸机 var oldtrack = tracks.FirstOrDefault(track => track.ShipID == shipId); if (oldtrack != null)//找到之前正在跟踪的闸机,保持继续跟踪 { oldtrack.Update(ship); onTrack(oldtrack); } return(oldtrack != null); }
bool updateReplaceGateUtil(GateTrackInfo lastTrack, ShipTrackConfig shipInfo, string gateId) { if (lastTrack == null) { var gateInfo = FenceMgr.Instance.Fence.Gates.FirstOrDefault(_ => _.ID == gateId); lastTrack = new GateTrackInfo(gateInfo, shipInfo); } else { lastTrack.Update(shipInfo); } return(onTrack(lastTrack)); }
bool isTimeout(ShipTrackConfig ship) { ShipTrackConfig.ShipSignalType type = ShipTrackConfig.ShipSignalType.AISTrack; if (ship.Ship.MMSI == 0) { type = ShipTrackConfig.ShipSignalType.RadarTrack; } else if (IsInner) { type = ShipTrackConfig.ShipSignalType.Signal; } return(ship.IsTimeout(type)); }
public void Update(ShipTrackConfig ship) { if (ShipID != ship.Ship.ID && ShipID != ship.Ship.MMSI.ToString()) { Ship = ship; } else { bool isAlarm = (ship.OutstandTime == ship.Ship.UpdateTime && !ship.IsOutstanded) && Ship.OutstandTime != ship.OutstandTime; bool isOut = ship.MoveOutTime != DateTime.MinValue; bool lastIsOut = Ship.MoveOutTime != DateTime.MinValue; if (isOut != lastIsOut) { Ship.Update(ship.Ship, isAlarm, isOut); } else { Ship.Update(ship.Ship, isAlarm); } } }
/// <summary>进出港报警推送</summary> private bool updateAlarm(GateTrackInfo[] tracks, ShipTrackConfig shipInfo, string shipId) { if (shipInfo.OutstandTime != DateTime.MinValue) //进入区域报警,优先调用前一次跟踪该船的闸机 { if (tryKeepTrack(tracks, shipInfo, shipId)) //优先调用前一次跟踪该船的闸机 { return(true); } } //此时进出港报警且未找到正在跟踪的闸机,查找可用闸机并完成跟踪报警 //调用空闲或可用的闸机(优先级最高的一个) string[] freeGates = getFreeGates(tracks); if (freeGates.Length > 0)//选取第一个空闲的闸机进行跟踪 { return(tryReplaceGate(tracks, shipInfo, freeGates.First())); } else //找到所有外围在跟踪的列表,抢占优先级低的跟踪 { return(tryReplaceLowPrior(tracks, shipInfo, true)); } }
/// <summary>在港船舶心跳</summary> private bool updateInInner(GateTrackInfo[] tracks, ShipTrackConfig shipInfo) { bool result = false; if (shipInfo.MoveOutTime == DateTime.MinValue)//确保船舶数据在港内 { string[] freeGates = getFreeGates(tracks); if (freeGates.Length > 0) { trace($"_+_+{RegionId} {Name} 尝试刷新{freeGates.Length}个闸机。+_+_"); foreach (var free in freeGates)//刷新所有空闲的闸机 { result = result || tryReplaceGate(tracks, shipInfo, free); } } else { trace($"_+_+{RegionId} {Name} 尝试获取低优先级个闸机。+_+_"); result = tryReplaceLowPrior(tracks, shipInfo, true);//此时内部区域无闸机可用,选择外围区域跟踪中优先级最低的闸机进行跟踪 } } return(result); }
public GateTrackInfo(GateInfo gate, ShipTrackConfig ship) { Gate = gate; Update(ship); }
public void Update(ShipInfo ship, bool isFirstData) { if (GateIds == null || GateIds.Length == 0)//区域未绑定任何闸机,直接跳过。 { return; } string shipID = ship.MMSI == 0 ? ship.ID : ship.MMSI.ToString(); if (IsInner && ship.MMSI == 0)//不考虑雷达目标在内部区域 { return; } lock (_obj) { ShipTrackConfig lastTrack = null; if (Tracks.ContainsKey(shipID))//找到该船之前的跟踪记录 { lastTrack = Tracks[shipID]; } bool inRegion = Calculator.PtInPolygon(ship.Longitude, ship.Latitude, Regions); if (inRegion) { bool isAlarm = !isFirstData && IsInner && (lastTrack == null || lastTrack.IsMoved); //不考虑首次刷新的内部区域的船舶(此时认为该船不是刚进入区域,已离港或者首次进入的船舶进行进港报警 if (lastTrack == null) //无历史跟踪数据 { if (!IsInner && ship.SOG < 1) //外围区域速度过慢的船舶不启用跟踪 { return; } Tracks[shipID] = new ShipTrackConfig(ship, isAlarm); } else { lastTrack.Update(ship, isAlarm, false); } trace($"-----------船舶 {ship.ID}:{ship.Name} 进入区域 {RegionId} {Name} - {IsInner}.报警:{isAlarm} - 跟踪总数 {Tracks.Count}"); TrackEventMgr.Instance.Enqueue(shipID); } else if (lastTrack != null) //当前船舶不在区域内,且该船历史在区域内跟踪 { if (!ValidPoly.Contains(ship.Longitude, ship.Latitude)) //信号严重偏移且上一次在区域内,此时认为信号错误。2.4海里 { Common.Log.Logger.Default.Error($"明显异常的船舶 {ship.MMSI},{ship.Name} : {lastTrack.Ship.Longitude},{lastTrack.Ship.Latitude} -> {ship.Longitude},{ship.Latitude}"); return; } else if (!_strictValidPoly.Contains(ship.Longitude, ship.Latitude))//信号有一定的偏移且上一次在区域内,此时认为可能会信号错误。0.6海里 { Common.Log.Logger.Default.Error($"可能异常的船舶 {ship.MMSI},{ship.Name} : {lastTrack.Ship.Longitude},{lastTrack.Ship.Latitude} -> {ship.Longitude},{ship.Latitude}"); } bool isalarm = false; if (IsInner) { if (!lastTrack.IsMoved)//未离港的船舶刚离港发送离港报警 { isalarm = true; } else if (!lastTrack.IsOutstanding)//已经超时的报警信息需要先清除,否则外部检测会出问题。 { Common.Log.Logger.Default.Trace($"船舶离开内部区域报警结束,准备清除该记录...{shipID}:{ship.Name} -离开内部区域 {RegionId} {Name} "); removeShip(shipID, lastTrack.Ship.Name); return; } } else if (!lastTrack.IsMoved)//外围区域仅考虑首次离开的船舶刷新 { return; } lastTrack.Update(ship, isalarm, true); TrackEventMgr.Instance.Enqueue(shipID); trace($"+++++++++++++船舶 {shipID} :{ship.Name} 离开区域心跳 {RegionId} {Name} - {IsInner} - Alarm:{isalarm}"); } } }
bool tryReplaceGate(GateTrackInfo[] tracks, ShipTrackConfig shipInfo, string gateId) { var lastTrack = tracks.FirstOrDefault(_ => _.GateId == gateId); return(updateReplaceGateUtil(lastTrack, shipInfo, gateId)); }