/// <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));
 }
示例#5
0
 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);
        }
示例#8
0
 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));
        }