using Comal.Classes; using GenHTTP.Api.Content; using GenHTTP.Api.Infrastructure; using GenHTTP.Api.Protocol; using GenHTTP.Engine; using GenHTTP.Modules.Practices; using InABox.Clients; using InABox.Core; using Microsoft.Exchange.WebServices.Data; using Syncfusion.DocIO.DLS; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; using RequestMethod = GenHTTP.Api.Protocol.RequestMethod; namespace PRSServer.Engines { class SigfoxHandlerProperties { public ConcurrentDictionary Devices; public GPSUpdateQueue Queue; public SigfoxHandlerProperties(ConcurrentDictionary devices, GPSUpdateQueue queue) { Devices = devices; Queue = queue; } } public class SigfoxRequest { public string DeviceID { get; set; } public string MessageID { get; set; } public long TimeStamp { get; set; } public string Payload { get; set; } } class SigfoxHandler : Handler { private ConcurrentDictionary Devices; private GPSUpdateQueue Queue; private IResponseBuilder HandleSigfox(IRequest request) { if(request.Content == null) return request.Respond().Status(ResponseStatus.BadRequest); var sigfoxRequest = Serialization.Deserialize(request.Content); var location = new GPSTrackerLocation(); SigfoxBase sigfox; try { sigfox = SigfoxFactory.Parse(sigfoxRequest.Payload); } catch (Exception e) { Logger.Send(LogType.Information, "", CoreUtils.FormatException(e)); return request.Respond().Status(ResponseStatus.BadRequest); } if (sigfox is not SigfoxLocation sigfoxLocation) { Logger.Send(LogType.Information, "", string.Format("- Skipping {0} ({1})", sigfox.GetType().EntityName().Split('.').Last(), sigfoxRequest.Payload)); return request.Respond().Status(ResponseStatus.BadRequest); } var device = Devices[sigfoxRequest.DeviceID]; location.DeviceID = sigfoxRequest.DeviceID; location.Location.Latitude = sigfoxLocation.Latitude; location.Location.Longitude = sigfoxLocation.Longitude; // Incoming TimeStamp is in UTC - need to add local offset location.Location.Timestamp = sigfoxRequest.TimeStamp > 0 ? new DateTime(1970, 1, 1).AddSeconds(sigfoxRequest.TimeStamp).Add(TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow)) : DateTime.Now; location.Speed = sigfoxLocation.Speed; 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}"); Queue.QueueUpdate("Updated by Sigfox Platform", location); return request.Respond().Status(ResponseStatus.OK); } private IResponseBuilder HandlePOST(IRequest request) { var endpoint = request.Target.GetRemaining(); if (endpoint.Parts.Count == 0) return request.Respond().Status(ResponseStatus.NotFound); var endpointFirst = endpoint.Parts[0].Value; if (endpointFirst == "sigfox") return HandleSigfox(request); return request.Respond().Status(ResponseStatus.NotFound); } public override ValueTask HandleAsync(IRequest request) { try { switch (request.Method.KnownMethod) { case RequestMethod.POST: return new ValueTask(HandlePOST(request).Build()); default: Logger.Send(LogType.Error, ClientFactory.UserID, $"Request method {request.Method.RawMethod} unknown"); return new ValueTask(request.Respond().Status(ResponseStatus.MethodNotAllowed).Build()); } } catch (Exception eListen) { Logger.Send(LogType.Error, ClientFactory.UserID, eListen.Message); return new ValueTask(request.Respond().Status(ResponseStatus.InternalServerError).Build()); } } public override void Init(SigfoxHandlerProperties properties) { Devices = properties.Devices; Queue = properties.Queue; } } }