mcci-catena/arduino-lorawan

Preconditions for calling myLoRaWAN.SendBuffer()?

matthias-bs opened this issue · 2 comments

Hi,

My sketch is based on the example simple_sensor_bme280.ino
I am using a modified version of doUplink(void) which works just fine.
Then I have added a receive callback function named ReceiveCb with SetReceiveBufferBufferCb(ReceiveCb) to handle downlink messages - this works as expected, too.
Finally I would like to add another function to call SendBuffer() for an uplink of status data (if requested by a command in a downlink message).

I have tried a similar approach as in doUplink() to check if SendBuffer() can be called:

// if busy uplinking, just skip
if (this->m_fBusy)
    return;
// if LMIC is busy, just skip
if (LMIC.opmode & (OP_POLL | OP_TXDATA | OP_TXRXPEND))
    return;

The first condition is clear, but I'm not sure how to handle the second one.

Why are there 3 different flags checked in LMIC.opmode?
What is the difference between this and just calling GetTxReady()?

With my current trials, I either get no uplink at all (if I compare LMIC.opmode as above) or the uplink is reported to have zero payload and an undefined port [how is that possible?] (if I ignore LMIC.opmode and just check the status flag of doUplink()).

Thanks in advance for your help!

Best regards,
Matthias

Here is my code. doCfgUplink() is called from the Arduino execution loop if the flag uplinkReq was set [by the downlink callback function].

void
cMyLoRaWAN::doCfgUplink(void) {
    // if busy uplinking, just skip
    if (this->m_fBusy || mySensor.isBusy()) {
        return;
    }
    // if LMIC is busy, just skip
    //if (LMIC.opmode & (OP_POLL | OP_TXDATA | OP_TXRXPEND)) {
    //    log_v("LMIC.opmode: 0x%02X", LMIC.opmode);
    //    return;
    //}

    log_d("--- Uplink Configuration/Status ---");
    
    uint8_t uplink_payload[5];
    uint8_t port;

    // Encode data as byte array for LoRaWAN transmission
    LoraEncoder encoder(uplink_payload);

    if (uplinkReq == CMD_GET_DATETIME) {
        log_d("Date/Time");
        port = 2;
        time_t t_now = rtc.getLocalEpoch();
        encoder.writeUint8((t_now >> 24) & 0xff);
        encoder.writeUint8((t_now >> 16) & 0xff);
        encoder.writeUint8((t_now >>  8) & 0xff);
        encoder.writeUint8( t_now        & 0xff);
        log_v("Size: %d", encoder.getLength());
    } else {
      log_v("");
        return;
    }

    this->m_fBusy = true;

    // Schedule transmission
    if (! myLoRaWAN.SendBuffer(
        uplink_payload, encoder.getLength(),
        // this is the completion function:
        [](void *pClientData, bool fSucccess) -> void {
            auto const pThis = (cMyLoRaWAN *)pClientData;
            pThis->m_fBusy = false;
            uplinkReq = 0;
        },
        (void *)this,
        /* confirmed */ true,
        /* port */ port
        )) {
        // sending failed; callback has not been called and will not
        // be called. Reset busy flag.
        this->m_fBusy = false;
        uplinkReq = 0;
    }
}

Some more insights - I added checking of GetTxReady() at the beginning and a little debug output:

    this->m_fBusy = true;
    log_v("Trying SendBuffer: port=%d, size=%d", port, encoder.getLength());
    
    // Schedule transmission
    if (! myLoRaWAN.SendBuffer(
        uplink_payload, encoder.getLength(),
        // this is the completion function:
        [](void *pClientData, bool fSucccess) -> void {
            auto const pThis = (cMyLoRaWAN *)pClientData;
            pThis->m_fBusy = false;
            uplinkReq = 0;
            log_v("Sending successful");
        },
        (void *)this,
        /* confirmed */ true,
        /* port */ port
        )) {
        // sending failed; callback has not been called and will not
        // be called. Reset busy flag.
        this->m_fBusy = false;
        uplinkReq = 0;
        log_v("Sending failed");
    }
}

Resulting in:

20:58:34.622 -> [132258][V][BresserWeatherSensorTTN.ino:1126] doCfgUplink(): Trying SendBuffer: port=2, size=5
20:58:34.622 -> [132267][V][BresserWeatherSensorTTN.ino:1136] operator()(): Sending successful
20:58:34.622 -> [132274][V][BresserWeatherSensorTTN.ino:1146] doCfgUplink(): Sending failed
  1. Port and payload size are as expected
  2. The completion function is called
  3. SendBuffer() returns false (which may be o.k. or not if I understand the comments in https://github.com/mcci-catena/arduino-lorawan/blob/master/src/lib/SendBuffer.cpp correctly)

The contents of uplink_payload are as expected.