Beispiel #1
0
        public LoRaADRResult ComputeResult(LoRaADRTable table, float requiredSnr, DataRateIndex upstreamDataRate, int minTxPower, DataRateIndex maxDr)
        {
            // We do not have enough frame to calculate ADR. We can assume that a crash was the cause.
            if (table == null || table.Entries.Count < 20)
            {
                this.logger.LogDebug("ADR: not enough frames captured. Sending default power values");
                return(null);
            }

            // This is the first contact case to harmonize the txpower state between device and server or the crash case.
            if (!table.CurrentNbRep.HasValue || !table.CurrentTxPower.HasValue)
            {
                this.logger.LogDebug("ADR: Sending the device default power values");
                return(null);
            }

            // This is a case of standard ADR calculus.
            var newNbRep = ComputeNbRepetion(table.Entries[0].FCnt, table.Entries[LoRaADRTable.FrameCountCaptureCount - 1].FCnt, table.CurrentNbRep.GetValueOrDefault());

            (var newTxPowerIndex, var newDatarate) = GetPowerAndDRConfiguration(requiredSnr, upstreamDataRate, table.Entries.Max(x => x.Snr), table.CurrentTxPower.GetValueOrDefault(), minTxPower, maxDr);

            if (newNbRep != table.CurrentNbRep || newTxPowerIndex != table.CurrentTxPower || newDatarate != upstreamDataRate)
            {
                return(new LoRaADRResult()
                {
                    DataRate = newDatarate,
                    NbRepetition = newNbRep,
                    TxPower = newTxPowerIndex
                });
            }

            return(null);
        }
        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);
            }
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 public Task UpdateADRTable(string devEUI, LoRaADRTable table)
 {
     // void: the reference is up to date already
     return(Task.CompletedTask);
 }