/// <summary> /// Helper method to resolve FcntDown in case one was not yet acquired /// </summary> /// <returns>0 if the resolution failed or > 0 if a valid frame count was acquired</returns> async ValueTask <uint> EnsureHasFcntDownAsync( LoRaDevice loRaDevice, uint?fcntDown, uint payloadFcnt, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) { if (fcntDown > 0) { return(fcntDown.Value); } var newFcntDown = await frameCounterStrategy.NextFcntDown(loRaDevice, payloadFcnt); // Failed to update the fcnt down // In multi gateway scenarios it means the another gateway was faster than using, can stop now if (newFcntDown <= 0) { Logger.Log(loRaDevice.DevEUI, "another gateway has already sent ack or downlink msg", LogLevel.Debug); } else { Logger.Log(loRaDevice.DevEUI, $"down frame counter: {loRaDevice.FCntDown}", LogLevel.Debug); } return(newFcntDown); }
public ILoRaADRManager Create(ILoRaADRStrategyProvider strategyProvider, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy, LoRaDevice loRaDevice) { if (loRaDevice is null) { throw new ArgumentNullException(nameof(loRaDevice)); } return(!string.IsNullOrEmpty(loRaDevice.GatewayID) ? new LoRaADRDefaultManager(CurrentInMemoryStore, strategyProvider, frameCounterStrategy, loRaDevice, this.loggerFactory.CreateLogger <LoRaADRDefaultManager>()) : new LoRaADRMultiGatewayManager(loRaDevice, this.loRaDeviceAPIService, this.loggerFactory.CreateLogger <LoRaADRMultiGatewayManager>())); }
/// <summary> /// Helper method to resolve FcntDown in case one was not yet acquired /// </summary> /// <returns>0 if the resolution failed or > 0 if a valid frame count was acquired</returns> async ValueTask <uint> EnsureHasFcntDownAsync( LoRaDevice loRaDevice, uint?fcntDown, uint payloadFcnt, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) { if (fcntDown.HasValue) { return(fcntDown.Value); } var newFcntDown = await frameCounterStrategy.NextFcntDown(loRaDevice, payloadFcnt); // Failed to update the fcnt down // In multi gateway scenarios it means the another gateway was faster than using, can stop now LogFrameCounterDownState(loRaDevice, newFcntDown); return(newFcntDown); }
private async Task <bool> DetermineIfFramecounterIsFromNewlyStartedDeviceAsync(LoRaDevice loRaDevice, uint payloadFcnt, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) { var isFrameCounterFromNewlyStartedDevice = false; if (payloadFcnt <= 1) { if (loRaDevice.IsABP) { if (loRaDevice.IsABPRelaxedFrameCounter && loRaDevice.FCntUp >= 0 && payloadFcnt <= 1) { // known problem when device restarts, starts fcnt from zero // We need to await this reset to avoid races on the server with deduplication and // fcnt down calculations await frameCounterStrategy.ResetAsync(loRaDevice, payloadFcnt, this.configuration.GatewayID); isFrameCounterFromNewlyStartedDevice = true; } } else if (loRaDevice.FCntUp == payloadFcnt && payloadFcnt == 0) { // Some devices start with frame count 0 isFrameCounterFromNewlyStartedDevice = true; } } return(isFrameCounterFromNewlyStartedDevice); }
private async Task <LoRaADRResult> PerformADR(LoRaRequest request, LoRaDevice loRaDevice, LoRaPayloadData loraPayload, uint payloadFcnt, LoRaADRResult loRaADRResult, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) { var loRaADRManager = this.loRaADRManagerFactory.Create(this.loRaADRStrategyProvider, frameCounterStrategy, loRaDevice); var loRaADRTableEntry = new LoRaADRTableEntry() { DevEUI = loRaDevice.DevEUI, FCnt = payloadFcnt, GatewayId = this.configuration.GatewayID, Snr = request.Rxpk.Lsnr }; // If the ADR req bit is not set we don't perform rate adaptation. if (!loraPayload.IsAdrReq) { _ = loRaADRManager.StoreADREntryAsync(loRaADRTableEntry); } else { loRaADRResult = await loRaADRManager.CalculateADRResultAndAddEntryAsync( loRaDevice.DevEUI, this.configuration.GatewayID, payloadFcnt, loRaDevice.FCntDown, (float)request.Rxpk.RequiredSnr, request.Region.GetDRFromFreqAndChan(request.Rxpk.Datr), request.Region.TXPowertoMaxEIRP.Count - 1, request.Region.MaxADRDataRate, loRaADRTableEntry); Logger.Log(loRaDevice.DevEUI, $"device sent ADR ack request, computing an answer", LogLevel.Debug); } return(loRaADRResult); }
public ILoRaADRManager Create(ILoRaADRStrategyProvider strategyProvider, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy, LoRaDevice loRaDevice) { return(!string.IsNullOrEmpty(loRaDevice.GatewayID) ? new LoRaADRDefaultManager(CurrentInMemoryStore, strategyProvider, frameCounterStrategy, loRaDevice) : new LoRaADRMultiGatewayManager(loRaDevice, this.loRaDeviceAPIService)); }
public LoRaADRDefaultManager(ILoRaADRStore store, ILoRaADRStrategyProvider strategyProvider, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy, LoRaDevice loRaDevice, ILogger <LoRaADRDefaultManager> logger) : base(store, strategyProvider, logger) { LoRaDevice = loRaDevice; this.frameCounterStrategy = frameCounterStrategy; }
private static bool DetermineIfFramecounterIsFromNewlyStartedDevice(LoRaDevice loRaDevice, uint payloadFcnt, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) { var isFrameCounterFromNewlyStartedDevice = false; if (payloadFcnt <= 1) { if (loRaDevice.IsABP) { if (loRaDevice.IsABPRelaxedFrameCounter && loRaDevice.FCntUp >= 0 && payloadFcnt <= 1) { // known problem when device restarts, starts fcnt from zero _ = frameCounterStrategy.ResetAsync(loRaDevice); isFrameCounterFromNewlyStartedDevice = true; } } else if (loRaDevice.FCntUp == payloadFcnt && payloadFcnt == 0) { // Some devices start with frame count 0 isFrameCounterFromNewlyStartedDevice = true; } } return(isFrameCounterFromNewlyStartedDevice); }
public LoRaDeviceFrameCounterSession(LoRaDevice loRaDevice, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) { this.loRaDevice = loRaDevice; this.frameCounterStrategy = frameCounterStrategy; }
protected override Task <LoRaADRResult> PerformADR(LoRaRequest request, LoRaDevice loRaDevice, LoRaPayloadData loraPayload, uint payloadFcnt, LoRaADRResult loRaADRResult, ILoRaDeviceFrameCounterUpdateStrategy frameCounterStrategy) => Task.FromResult(PerformADRAssert());