protected static void AddEntryToTable(LoRaADRTable table, LoRaADRTableEntry entry) { var existing = table.Entries.FirstOrDefault(itm => itm.FCnt == entry.FCnt); if (existing == null) { // first for this framecount, simply add it entry.GatewayCount = 1; table.Entries.Add(entry); } else { if (existing.Snr < entry.Snr) { // better SNR. Update existing.Snr = entry.Snr; existing.GatewayId = entry.GatewayId; } existing.GatewayCount++; } if (table.Entries.Count > LoRaADRTable.FrameCountCaptureCount) { table.Entries.RemoveAt(0); } }
public Task <LoRaADRTable> AddTableEntry(LoRaADRTableEntry entry) { lock (this.cache) { var table = this.cache.GetOrCreate <LoRaADRTable>(entry.DevEUI, (cacheEntry) => new LoRaADRTable()); AddEntryToTable(table, entry); return(Task.FromResult <LoRaADRTable>(table)); } }
public virtual async Task StoreADREntryAsync(LoRaADRTableEntry newEntry) { if (newEntry == null) { return; } if (!newEntry.DevEUI.IsValid || string.IsNullOrEmpty(newEntry.GatewayId)) { throw new ArgumentException("Missing Gateway ID or invalid DevEUI"); } _ = await this.store.AddTableEntry(newEntry); }
public Task <LoRaADRTable> AddTableEntry(LoRaADRTableEntry entry) { if (entry is null) { throw new ArgumentNullException(nameof(entry)); } lock (this.cache) { var table = this.cache.GetOrCreate(entry.DevEUI, (cacheEntry) => new LoRaADRTable()); AddEntryToTable(table, entry); return(Task.FromResult(table)); } }
public virtual async Task StoreADREntryAsync(LoRaADRTableEntry newEntry) { if (newEntry == null) { return; } if (string.IsNullOrEmpty(newEntry.DevEUI) || string.IsNullOrEmpty(newEntry.GatewayId)) { throw new ArgumentException("Missing DevEUI or GatewayId"); } await this.store.AddTableEntry(newEntry); }
public virtual async Task <LoRaADRResult> CalculateADRResultAndAddEntryAsync(DevEui devEUI, string gatewayId, uint fCntUp, uint fCntDown, float requiredSnr, DataRateIndex dataRate, int minTxPower, DataRateIndex maxDr, LoRaADRTableEntry newEntry = null) { var table = newEntry != null ? await this.store.AddTableEntry(newEntry) : await this.store.GetADRTable(devEUI); var currentStrategy = this.strategyProvider.GetStrategy(); var result = currentStrategy.ComputeResult(table, requiredSnr, dataRate, minTxPower, maxDr); if (result == null) { // In this case we want to reset the device to default values as we have null values if (table == null || !table.CurrentNbRep.HasValue || !table.CurrentTxPower.HasValue || fCntUp > currentStrategy.MinimumNumberOfResult) { result = ReturnDefaultValues(dataRate, currentStrategy.DefaultNbRep, currentStrategy.DefaultTxPower); } else { result = await GetLastResultAsync(devEUI) ?? new LoRaADRResult(); result.NumberOfFrames = table.Entries.Count; return(result); } } var nextFcntDown = await NextFCntDown(devEUI, gatewayId, fCntUp, fCntDown); result.CanConfirmToDevice = nextFcntDown > 0; if (result.CanConfirmToDevice) { if (table == null) { // in a reset case, we may not have a table, but still want to store the default // values that we sent to the client table = new LoRaADRTable(); } table.CurrentNbRep = result.NbRepetition; table.CurrentTxPower = result.TxPower; await this.store.UpdateADRTable(devEUI, table); UpdateState(result); result.FCntDown = nextFcntDown; } result.NumberOfFrames = table.Entries.Count; this.logger.LogDebug($"calculated ADR: CanConfirmToDevice: {result.CanConfirmToDevice}, TxPower: {result.TxPower}, DataRate: {result.DataRate}"); return(result); }