فهرست منبع

GPS Improvements

Kenric Nugteren 2 سال پیش
والد
کامیت
580d712b9d

+ 9 - 3
prs.server/Engines/GPS OLD/SigfoxListener.cs

@@ -24,9 +24,12 @@ namespace PRSServer.Engines
     {
         public ConcurrentDictionary<string, Device> Devices;
 
-        public SigfoxHandlerProperties(ConcurrentDictionary<string, Device> devices)
+        public GPSUpdateQueue Queue;
+
+        public SigfoxHandlerProperties(ConcurrentDictionary<string, Device> devices, GPSUpdateQueue queue)
         {
             Devices = devices;
+            Queue = queue;
         }
     }
 
@@ -46,6 +49,8 @@ namespace PRSServer.Engines
     {
         private ConcurrentDictionary<string, Device> Devices;
 
+        private GPSUpdateQueue Queue;
+
         private IResponseBuilder HandleSigfox(IRequest request)
         {
             if(request.Content == null) return request.Respond().Status(ResponseStatus.BadRequest);
@@ -83,14 +88,14 @@ namespace PRSServer.Engines
                 : DateTime.Now;
 
             location.Speed = sigfoxLocation.Speed;
-            // For some reaon the 
+
             location.BatteryLevel = device.CalculateBatteryLevel(sigfoxLocation.BatteryLevel); // sigfoxLocation.BatteryLevel / 5.25F * 100.0F
             location.InTrip = sigfoxLocation.InTrip;
             location.LastFixFailed = sigfoxLocation.LastFixFailed;
 
             Logger.Send(LogType.Information, "", $"Sigfox ({location.DeviceID}) Lat: {sigfoxLocation.Latitude}, Long: {sigfoxLocation.Longitude}");
 
-            new Client<GPSTrackerLocation>().Save(location, "Updated by Sigfox Platform");
+            Queue.QueueUpdate("Updated by Sigfox Platform", location);
 
             return request.Respond().Status(ResponseStatus.OK);
         }
@@ -128,6 +133,7 @@ namespace PRSServer.Engines
         public override void Init(SigfoxHandlerProperties properties)
         {
             Devices = properties.Devices;
+            Queue = properties.Queue;
         }
     }
 

+ 39 - 14
prs.server/Engines/GPS/GPSEngine.cs

@@ -60,28 +60,43 @@ namespace PRSServer
 
         public int GetNumberOfItems()
         {
+            using var profiler = new Profiler(true);
             return Directory.EnumerateFiles(QueuePath).Count();
         }
 
-        public IEnumerable<GPSDeviceUpdate> GetFirstItems()
+        /// <summary>
+        /// Get the first (earliest) items of the directory.
+        /// </summary>
+        /// <returns>A list of (filename, update) tuples.</returns>
+        public IEnumerable<Tuple<string, GPSDeviceUpdate>> GetFirstItems()
         {
+            using var profiler = new Profiler(true);
             var files = Directory.EnumerateFiles(QueuePath).OrderBy(x => x);
 
             foreach (var filename in files)
             {
-                GPSDeviceUpdate deviceUpdate;
-                using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
+                GPSDeviceUpdate? deviceUpdate = null;
+                try
                 {
+                    using var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
                     deviceUpdate = Serialization.ReadBinary<GPSDeviceUpdate>(fileStream, BinarySerializationSettings.Latest);
                 }
-                yield return deviceUpdate;
+                catch
+                {
+                    // File is probably in use.
+                }
+                if(deviceUpdate is not null)
+                {
+                    yield return new Tuple<string, GPSDeviceUpdate>(filename, deviceUpdate);
+                }
             }
         }
 
         public void QueueUpdate(GPSDeviceUpdate deviceUpdate)
         {
-            var filename = $"{DateTime.UtcNow.Ticks} - {deviceUpdate.AuditTrail}: {deviceUpdate.Location.ID}";
-            using var fileStream = new FileStream(filename, FileMode.CreateNew, FileAccess.Write);
+            var filename = Path.Combine(QueuePath, $"{DateTime.UtcNow.Ticks} - {deviceUpdate.Location.Tracker.ID}");
+
+            using var fileStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write);
             Serialization.WriteBinary(deviceUpdate, fileStream, BinarySerializationSettings.Latest);
         }
 
@@ -154,7 +169,7 @@ namespace PRSServer
                 return;
             }
 
-            sigfoxListener = new Listener<SigfoxHandler, SigfoxHandlerProperties>(new SigfoxHandlerProperties(DeviceCache));
+            sigfoxListener = new Listener<SigfoxHandler, SigfoxHandlerProperties>(new SigfoxHandlerProperties(DeviceCache, UpdateQueue));
             sigfoxListener.InitPort((ushort)Properties.SigfoxListenPort);
 
             Logger.Send(LogType.Information, "", "Starting Sigfox Listener on port " + Properties.SigfoxListenPort);
@@ -171,14 +186,15 @@ namespace PRSServer
             UpdateServerTimer.Start();
         }
 
-        private Queue<GPSDeviceUpdate> LocationQueueCache = new();
+        // List of (filename, update)
+        private Queue<Tuple<string, GPSDeviceUpdate>> LocationQueueCache = new();
 
         private void GetLocationQueue(int nLocations)
         {
             LocationQueueCache.EnsureCapacity(LocationQueueCache.Count + nLocations);
-            foreach(var deviceUpdate in UpdateQueue.GetFirstItems().Take(50))
+            foreach(var item in UpdateQueue.GetFirstItems().Take(nLocations))
             {
-                LocationQueueCache.Enqueue(deviceUpdate);
+                LocationQueueCache.Enqueue(item);
             }
         }
 
@@ -192,17 +208,26 @@ namespace PRSServer
 
             if (LocationQueueCache.Count > 0)
             {
-                var last = LocationQueueCache.Dequeue();
+                var (filename, update) = LocationQueueCache.Dequeue();
 
                 Logger.Send(LogType.Information, "",
-                    string.Format("Updating Server ({0}): {1} - {2}", UpdateQueue.GetNumberOfItems(), last.Location.DeviceID, last.AuditTrail));
-                new Client<GPSTrackerLocation>().Save(last.Location, last.AuditTrail, (_, exception) =>
+                    string.Format("Updating Server ({0}): {1} - {2}", UpdateQueue.GetNumberOfItems(), update.Location.DeviceID, update.AuditTrail));
+                new Client<GPSTrackerLocation>().Save(update.Location, update.AuditTrail, (_, exception) =>
                 {
                     if (exception is not null)
                     {
-                        Logger.Send(LogType.Error, "", $"Error saving GPS Tracker Location ({last.AuditTrail}): {CoreUtils.FormatException(exception)}");
+                        Logger.Send(LogType.Error, "", $"Error saving GPS Tracker Location ({update.AuditTrail}): {CoreUtils.FormatException(exception)}");
                     }
                 });
+
+                try
+                {
+                    File.Delete(filename);
+                }
+                catch
+                {
+                    // Probably got deleted.
+                }
             }
         }
 

+ 1 - 1
prs.server/Engines/GPS/OEMConnection.cs

@@ -28,7 +28,7 @@ namespace PRSServer
 
         private bool Finished = false;
         private Task? ReadTask;
-        private CancellationTokenSource TokenSource;
+        private CancellationTokenSource TokenSource = new();
 
         // References to necessary caches
         private GPSDeviceCache Devices;

+ 22 - 13
prs.server/Engines/GPS/OEMListener.cs

@@ -45,27 +45,36 @@ namespace PRSServer
 
         private void AcceptClient()
         {
+            Logger.Send(LogType.Information, "", "Waiting for client.");
             listener.AcceptTcpClientAsync().ContinueWith(t =>
             {
-                var connection = new OEMConnection(t.Result, Cache, Queue);
-                lock (connectionsLock)
+                try
                 {
-                    Connections.Add(connection);
-                }
-
-                connection.OnCompletion = () =>
-                {
-                    // When the connection finishes, we should remove it from our list.
+                    Logger.Send(LogType.Information, "", "Client Connected");
+                    var connection = new OEMConnection(t.Result, Cache, Queue);
                     lock (connectionsLock)
                     {
-                        Connections.Remove(connection);
+                        Connections.Add(connection);
                     }
-                };
 
-                connection.Run();
+                    connection.OnCompletion = () =>
+                    {
+                        // When the connection finishes, we should remove it from our list.
+                        lock (connectionsLock)
+                        {
+                            Connections.Remove(connection);
+                        }
+                    };
+
+                    connection.Run();
 
-                // Accept a new client.
-                AcceptClient();
+                    // Accept a new client.
+                    AcceptClient();
+                }
+                catch (Exception e)
+                {
+                    Logger.Send(LogType.Error, "", CoreUtils.FormatException(e));
+                }
             }, TaskContinuationOptions.OnlyOnRanToCompletion);
         }