Can LMIC 1.6 be set up to use a single channel and SF?

:warning: Any packet forwarder that is not a full gateway is harmful to other users of The Things Network, and should not be used if there is even a small chance that other TTN users are in your wide area neighbourhood. So, the following solution is probably not what you need, and is only appropriate if you know what you’re doing.

I understand, show me the code.
Really, I understand, show me the code.
Really, even though I could not come up with the answer myself, I really do understand this is likely to harm others, but I still need the code.

For 1.5, if one does not want to change the library, here is how one can make an ABP or OTAA sketch work with a single channel gateway and Matthijs Kooijman’s LMiC:

  • Somewhere above onEvent define:

    // Define the single channel and data rate (SF) to use
    int channel = 0;
    int dr = DR_SF7;
    
    // Disables all channels, except for the one defined above, and sets the
    // data rate (SF). This only affects uplinks; for downlinks the default
    // channels or the configuration from the OTAA Join Accept are used.
    //
    // Not LoRaWAN compliant; FOR TESTING ONLY!
    //
    void forceTxSingleChannelDr() {
        for(int i=0; i<9; i++) { // For EU; for US use i<71
            if(i != channel) {
                LMIC_disableChannel(i);
            }
        }
        // Set data rate (SF) and transmit power for uplink
        LMIC_setDrTxpow(dr, 14);
    }
    
  • For ABP, in init() replace LMIC_setDrTxpow(DR_SF7,14); with:

    // Only use one channel and SF
    forceTxSingleChannelDr();
    
  • For OTAA, in init() after LMIC_reset(); add:

    // Make LMiC initialize the default channels, choose a channel, and
    // schedule the OTAA join
    LMIC_startJoining();
    
    // LMiC will already have decided to send on one of the 3 default
    // channels; ensure it uses the one we want
    LMIC.txChnl = channel;
    
    // ...and make sure we see the EV_JOINING event being logged
    os_runloop_once();
    
  • For OTAA, for EV_JOINED in onEvent use:

    case EV_JOINED:
        // Ignore the channels from the Join Accept
        forceTxSingleChannelDr();
    
        // Disable link check validation (automatically enabled during join)
        LMIC_setLinkCheckMode(0);
    
        break;
    

But note:

  • Only tested with LMiC 1.5, for EU868, channel 0.

  • For OTAA this assumes the first attempt succeeds; if the Join Request or Join Accept are somehow lost, LMiC will still try different channels and data rates due to the logic in nextJoinState

  • Only tested with an OTAA Join Accept received in RX1 (for EU868 using the same channel as the uplink/join request); when received in RX2 (for EU868 always using 869.525 on SF9), LMiC might also use other values to send? (But maybe the LMIC_setDrTxpow(dr, 14) suffices.)

Background

For Matthijs’ LMiC 1.5, the OTAA flow is:

  • In examples/ttn-otaa/ttn-otaa.ino, calling LMIC_reset clears the keys after which LMIC_setTxData2 is called to schedule some data to be sent.

  • In src/lmic.c, engineUpdate controls the flow, like if something has been scheduled for transmission. When LMIC.devaddr == 0 this will first trigger LMIC_startJoining:

    • LMIC_startJoining calls initJoinLoop, which for EU868 also calls initDefaultChannels. (For US915, that’s already done in LMIC_reset.)

    • In initJoinLoop, for EU868 one out of 3 channels is selected (LMIC.txChnl = os_getRndU1() % 3) while for US915 it’s set to the first channel (LMIC.txChnl = 0).

    • The actual join is not started yet; LMIC_startJoining basically schedules joining to be the first thing to do when time permits. So when manually calling LMIC_startJoining, one can quickly use LMIC.txChnl = channel to change the channel that LMiC selected.

  • Whenever a join attempt fails, nextJoinState will select another channel and/or data rate (SF), without checking if the channel is activated; see https://github.com/matthijskooijman/arduino-lmic/issues/88. One cannot change that behavior from one’s own sketch.

9 Likes