Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preconditions for calling myLoRaWAN.SendBuffer()? #209

Open
matthias-bs opened this issue Jan 5, 2023 · 2 comments
Open

Preconditions for calling myLoRaWAN.SendBuffer()? #209

matthias-bs opened this issue Jan 5, 2023 · 2 comments

Comments

@matthias-bs
Copy link
Contributor

matthias-bs commented Jan 5, 2023

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

@matthias-bs matthias-bs changed the title Preconditions for calling myLoRaWAN.SendBuffer() Preconditions for calling myLoRaWAN.SendBuffer()? Jan 5, 2023
@matthias-bs
Copy link
Contributor Author

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;
    }
}

@matthias-bs
Copy link
Contributor Author

matthias-bs commented Jan 6, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant