mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-04-19 00:26:57 +00:00
146 lines
3.0 KiB
JavaScript
146 lines
3.0 KiB
JavaScript
export function name() {
|
|
return "JS example for default ADR algorithm";
|
|
}
|
|
|
|
export function id() {
|
|
return "js_example_default";
|
|
}
|
|
|
|
export function handle(req) {
|
|
let resp = {
|
|
dr: req.dr,
|
|
txPowerIndex: req.txPowerIndex,
|
|
nbTrans: req.nbTrans,
|
|
};
|
|
|
|
if (!req.adr) {
|
|
return resp;
|
|
}
|
|
|
|
if (req.dr > req.maxDr) {
|
|
resp.dr = req.maxDr;
|
|
}
|
|
|
|
// Set the new Nb Trans.
|
|
resp.nbTrans = getNbTrans(req.nbTrans, getPacketLossPercentage(req));
|
|
|
|
// Calculate the number of steps.
|
|
let snrMax = getMaxSnr(req);
|
|
let snrMargin = snrMax - req.requiredSnrForDr - req.installationMargin;
|
|
let nStep = Math.floor(snrMargin / 3);
|
|
|
|
// In case of negative steps the ADR algorithm will increase the TxPower
|
|
// if possible. To avoid up / down / up / down TxPower changes, wait until
|
|
// we have at least the required number of uplink history elements.
|
|
if (nStep < 0 && getHistoryCount(req) != requiredHistoryCount()) {
|
|
return resp;
|
|
}
|
|
|
|
let [desiredTxPowerIndex, desiredDr] = getIdealTxPowerIndexAndDr(
|
|
nStep,
|
|
resp.txPowerIndex,
|
|
resp.dr,
|
|
req.maxTxPowerIndex,
|
|
req.maxDr,
|
|
);
|
|
|
|
resp.dr = desiredDr;
|
|
resp.txPowerIndex = desiredTxPowerIndex;
|
|
|
|
return resp;
|
|
}
|
|
|
|
function getIdealTxPowerIndexAndDr(nbStep, txPowerIndex, dr, maxTxPowerIndex, maxDr) {
|
|
while (nbStep !== 0) {
|
|
if (nbStep > 0) {
|
|
if (dr < maxDr) {
|
|
// Increase the DR.
|
|
dr++;
|
|
} else if (txPowerIndex < maxTxPowerIndex) {
|
|
// Decrease the Tx Power.
|
|
txPowerIndex++;
|
|
}
|
|
nbStep--;
|
|
} else {
|
|
// Incease the TxPower.
|
|
if (txPowerIndex > 0) {
|
|
txPowerIndex--;
|
|
}
|
|
nbStep++;
|
|
}
|
|
}
|
|
|
|
return [txPowerIndex, dr];
|
|
}
|
|
|
|
function requiredHistoryCount() {
|
|
return 20;
|
|
}
|
|
|
|
function getHistoryCount(req) {
|
|
let count = 0;
|
|
for (let uh of req.uplinkHistory) {
|
|
if (uh.txPowerIndex === req.txPowerIndex) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
function getMaxSnr(req) {
|
|
let maxSnr = -999.0;
|
|
|
|
for (let uh of req.uplinkHistory) {
|
|
if (uh.maxSnr > maxSnr) {
|
|
maxSnr = uh.maxSnr;
|
|
}
|
|
}
|
|
|
|
return maxSnr;
|
|
}
|
|
|
|
function getNbTrans(currentNbTrans, pktLossRate) {
|
|
const pktLossTable = [
|
|
[1, 1, 2],
|
|
[1, 2, 3],
|
|
[2, 3, 3],
|
|
[3, 3, 3],
|
|
];
|
|
|
|
if (currentNbTrans < 1) {
|
|
currentNbTrans = 1;
|
|
}
|
|
if (currentNbTrans > 3) {
|
|
currentNbTrans = 3;
|
|
}
|
|
|
|
const nbTransIndex = currentNbTrans - 1;
|
|
|
|
if (pktLossRate < 5.0) {
|
|
return pktLossTable[0][nbTransIndex];
|
|
} else if (pktLossRate < 10.0) {
|
|
return pktLossTable[1][nbTransIndex];
|
|
} else if (pktLossRate < 30.0) {
|
|
return pktLossTable[2][nbTransIndex];
|
|
}
|
|
|
|
return pktLossTable[3][nbTransIndex];
|
|
}
|
|
|
|
function getPacketLossPercentage(req) {
|
|
if (req.uplinkHistory.length < requiredHistoryCount()) {
|
|
return 0.0;
|
|
}
|
|
|
|
let lostPackets = 0;
|
|
let previousFCnt = req.uplinkHistory[0].fCnt;
|
|
|
|
for (let uh of req.uplinkHistory.slice(1)) {
|
|
lostPackets += uh.fCnt - previousFCnt - 1;
|
|
previousFCnt = uh.fCnt;
|
|
}
|
|
|
|
return lostPackets / req.uplinkHistory.length * 100.0;
|
|
}
|