using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using log4net; namespace bsmd.AIS2Service { /// /// Manager / Thread Klasse um die "aktuelle" Situation zu aktualisieren und die Daten /// in die (Sqlite-Zwischen-) Datenbank zu schieben /// internal class SitRep : IAISThread { private Thread _thread; private bool _stopFlag = false; private static readonly ILog _log = LogManager.GetLogger(typeof(SitRep)); private readonly ConcurrentQueue _inputQueue; private readonly ConcurrentDictionary _sitRep; private const int sleepMS = 250; public SitRep(ConcurrentQueue inputQueue, ConcurrentDictionary sitRep) { _inputQueue = inputQueue; _sitRep = sitRep; } private void ReadMessages() { try { while (!_stopFlag) { if(_inputQueue.TryDequeue(out AISClass aisMessage)) { switch(aisMessage.MessageType) { case AISClass.AISType.POSITION_REPORT: case AISClass.AISType.POSITION_REPORT_ASSIGNED: case AISClass.AISType.POSITION_REPORT_SPECIAL: { AIS_PosReport posReport = aisMessage as AIS_PosReport; if(!_sitRep.ContainsKey(posReport.MMSI)) { AIS_Target target = new AIS_Target(posReport.MMSI); _sitRep[posReport.MMSI] = target; } _sitRep[posReport.MMSI].Update(posReport); } break; case AISClass.AISType.STATIC_VOYAGE_DATA: { AIS_StaticData staticData = aisMessage as AIS_StaticData; if(!_sitRep.ContainsKey(staticData.MMSI)) { AIS_Target target = new AIS_Target(staticData.MMSI); _sitRep[staticData.MMSI] = target; } _sitRep[staticData.MMSI].Update(staticData); } break; default: _log.InfoFormat("currently discarding AIS message {0}", aisMessage.MessageType); break; } } else { Thread.Sleep(sleepMS); _log.DebugFormat("Targets: {0}", _sitRep.Count); } } } catch (Exception ex) { _log.ErrorFormat("Something bad has happened: {0}", ex.Message); this.FatalErrorOccurred?.Invoke(this, new EventArgs()); } } #region IAISThread implementation public string Name { get { return "Sit rep"; } } public event EventHandler FatalErrorOccurred; public void Start() { if (_thread != null) return; // may not run twice ThreadStart runReader = new ThreadStart(this.ReadMessages); _thread = new Thread(runReader); _thread.Start(); } public void Stop() { if (_thread == null) return; _stopFlag = true; _thread.Join(); _thread = null; } #endregion } }