diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index c6c65082..1191ad96 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -223,6 +223,8 @@ bool lastWasTxStart; uint32_t lastTxStartTime; void myEventCb(void *pUserData, ev_t ev) { + LMIC_complianceEvent(ev); + eventQueue.putEvent(ev); if (ev == EV_TXSTART) { diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 957d6222..6158ee97 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -597,6 +597,7 @@ static void stateJustJoined (void) { LMIC.rejoinCnt = 0; LMIC.dnConf = LMIC.lastDnConf = LMIC.adrChanged = 0; LMIC.upRepeatCount = LMIC.upRepeat = 0; + LMIC.globalDutyRate = 0; #if !defined(DISABLE_MCMD_RXParamSetupReq) LMIC.dn2Ans = 0; #endif @@ -1719,6 +1720,21 @@ static bit_t processJoinAccept_nojoinframe(void) { LMIC.opmode &= ~OP_TXRXPEND; reportEventNoUpdate(EV_JOIN_TXCOMPLETE); int failed = LMICbandplan_nextJoinState(); + + if(LMIC.globalDutyRate != 0 && (LMIC.txend - LMIC.globalDutyAvail) < 0) { + LMIC.txend = LMIC.globalDutyAvail; + // Add random delay 10s is arbitrary + LMIC.txend += LMICcore_rndDelay(10); + } + + // Adjust dutyrate to respect retransmissions back-off during join + // Duty rate of 2^14 is enought to respect the max 8.7s by 24h (5.7s / 24h) + // Divide the rate by 2 every 4000s respect the limit of 36s during hours 1 to 11 + if (LMIC.globalDutyRate < 14 && os_getTime() - LMIC.lastDutyRateBackOff > sec2osticks(4000)) { + LMIC.globalDutyRate++; + LMIC.lastDutyRateBackOff = os_getTime(); + } + EV(devCond, DEBUG, (e_.reason = EV::devCond_t::NO_JACC, e_.eui = MAIN::CDEV->getEui(), e_.info = LMIC.datarate|DR_PAGE, @@ -2164,8 +2180,12 @@ bit_t LMIC_startJoining (void) { // There should be no TX/RX going on // ASSERT((LMIC.opmode & (OP_POLL|OP_TXRXPEND)) == 0); LMIC.opmode &= ~OP_POLL; - // Lift any previous duty limitation - LMIC.globalDutyRate = 0; + // Reset Duty rate limitation to respect retransmission backoff + // (max 28s < 36s during first hour) + LMIC.globalDutyRate = 7; + LMIC.globalDutyAvail = os_getTime(); + LMIC.lastDutyRateBackOff = os_getTime(); + // Cancel scanning LMIC.opmode &= ~(OP_SCAN|OP_UNJOIN|OP_REJOIN|OP_LINKDEAD|OP_NEXTCHNL); // Setup state diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 9463fa29..d94712ab 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -569,6 +569,7 @@ struct lmic_t { u1_t txChnl; // channel for next TX u1_t globalDutyRate; // max rate: 1/2^k + ostime_t lastDutyRateBackOff; u1_t upRepeat; // configured up repeat s1_t adrTxPow; // ADR adjusted TX power @@ -715,6 +716,7 @@ enum lmic_compliance_rx_action_e { LMIC_COMPLIANCE_RX_ACTION_END // exit compliance mode, discard this message }; +void LMIC_complianceEvent(ev_t ev); lmic_compliance_rx_action_t LMIC_complianceRxMessage(u1_t port, const u1_t *pMessage, size_t nMessage); // Declare onEvent() function, to make sure any definition will have the diff --git a/src/lmic/lmic_compliance.c b/src/lmic/lmic_compliance.c index d1356b94..323c2dd3 100644 --- a/src/lmic/lmic_compliance.c +++ b/src/lmic/lmic_compliance.c @@ -74,6 +74,47 @@ lmic_compliance_t LMIC_Compliance; /* +Name: LMIC_complianceEvent() + +Function: + Modify join state during compliance test. + +Definition: + void LMIC_complianceEvent(ev_t ev); + +Description: + Clients who want to handle the LoRaWAN compliance protocol on + port 224 should call this routine in the event callback. + This function will update the LMIC duty rate to allow the test + to run in a raisonnable time. + +Returns: + nothing. + +*/ + + +void LMIC_complianceEvent(ev_t ev) { + lmic_compliance_state_t const complianceState = LMIC_Compliance.state; + + // only handle event during compliance test. + if(!lmic_compliance_state_IsActive(complianceState)) + return; + + switch (ev) + { + case EV_JOINING: + case EV_JOIN_TXCOMPLETE: + // Remove duty rate during join test. + LMIC.globalDutyRate = 0; + break; + default: + break; + } +} + +/* + Name: LMIC_complianceRxMessage() Function: