diff --git a/examples/lorawan/main.c b/examples/lorawan/main.c index 97770294d03f8634513a28ced684c47166305f46..da2e43212d392a359e92517bf7ad3a46fa4cb587 100644 --- a/examples/lorawan/main.c +++ b/examples/lorawan/main.c @@ -67,9 +67,15 @@ static void _prepare_next_alarm(void) static void _send_message(void) { printf("Sending: %s\n", message); - /* The send call blocks until done */ - semtech_loramac_send(&loramac, (uint8_t *)message, strlen(message)); - /* Wait until the send cycle has completed */ + /* Try to send the message */ + uint8_t ret = semtech_loramac_send(&loramac, + (uint8_t *)message, strlen(message)); + if (ret != SEMTECH_LORAMAC_TX_OK) { + printf("Cannot send message '%s', ret code: %d\n", message, ret); + return; + } + /* The send was successfully scheduled, now wait until the send cycle has + completed and a reply is received from the MAC */ semtech_loramac_recv(&loramac); } diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c index 2329708efaf1f630c67ee5f3a09dac32f4938630..7e14f352426df4b1c39e8917cbe7ad567d9ddf36 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac.c @@ -239,6 +239,7 @@ static void mcps_indication(McpsIndication_t *indication) msg.content.ptr = indication; } else { + DEBUG("[semtech-loramac] MCPS indication: TX done\n"); msg.type = MSG_TYPE_LORAMAC_TX_STATUS; msg.content.value = SEMTECH_LORAMAC_TX_DONE; } @@ -552,18 +553,16 @@ static void _send(semtech_loramac_t *mac, void *arg) { loramac_send_params_t params = *(loramac_send_params_t *)arg; uint8_t status = _semtech_loramac_send(mac, params.payload, params.len); - if (status != SEMTECH_LORAMAC_TX_OK) { - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = (uint8_t)status; - msg_send(&msg, semtech_loramac_pid); - } #ifdef MODULE_PERIPH_EEPROM - else { + if (status == SEMTECH_LORAMAC_TX_OK) { /* save the uplink counter */ _save_uplink_counter(mac); } #endif + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_TX_STATUS; + msg.content.value = (uint8_t)status; + msg_send(&msg, semtech_loramac_pid); } static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg) @@ -708,7 +707,7 @@ void *_semtech_loramac_event_loop(void *arg) } case MSG_TYPE_LORAMAC_TX_STATUS: { - DEBUG("[semtech-loramac] loramac TX status msg\n"); + DEBUG("[semtech-loramac] received TX status\n"); if (msg.content.value == SEMTECH_LORAMAC_TX_SCHEDULE) { DEBUG("[semtech-loramac] schedule immediate TX\n"); uint8_t prev_port = mac->port; @@ -717,6 +716,7 @@ void *_semtech_loramac_event_loop(void *arg) mac->port = prev_port; } else { + DEBUG("[semtech-loramac] forward TX status to caller thread\n"); msg_t msg_ret; msg_ret.type = msg.type; msg_ret.content.value = msg.content.value; @@ -828,13 +828,23 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) return SEMTECH_LORAMAC_NOT_JOINED; } + /* Correctly set the caller pid */ + mac->caller_pid = thread_getpid(); + loramac_send_params_t params; params.payload = data; params.len = len; _semtech_loramac_call(_send, ¶ms); - return SEMTECH_LORAMAC_TX_SCHEDULE; + /* Wait for TX status information from the MAC */ + msg_t msg; + msg_receive(&msg); + if (msg.type != MSG_TYPE_LORAMAC_TX_STATUS) { + return SEMTECH_LORAMAC_TX_ERROR; + } + + return (uint8_t)msg.content.value; } uint8_t semtech_loramac_recv(semtech_loramac_t *mac) diff --git a/pkg/semtech-loramac/include/semtech_loramac.h b/pkg/semtech-loramac/include/semtech_loramac.h index 2e58021d1bc3838aede88f59ef96dbb99fc2c2cc..69c7ad398d1356064f8088fc6979ab64d793264d 100644 --- a/pkg/semtech-loramac/include/semtech_loramac.h +++ b/pkg/semtech-loramac/include/semtech_loramac.h @@ -149,17 +149,22 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type); /** * @brief Sends data to the LoRaWAN network * - * This function returns immediately and leave the mac in busy state until a - * message is received from the network (with RX1 and RX2 receive windows). + * This function returns after TX status is replied from the MAC. To receive + * potential messages sent from the network an explicit call to + * @ref semtech_loramac_recv must be done after this function if it returned + * @ref SEMTECH_LORAMAC_TX_OK and within the RX windows delays. + * * @see semtech_loramac_recv * * @param[in] mac Pointer to the mac * @param[in] data The TX data * @param[in] len The length of the TX data * + * @return SEMTECH_LORAMAC_TX_OK when the message can be transmitted * @return SEMTECH_LORAMAC_NOT_JOINED when the network is not joined * @return SEMTECH_LORAMAC_BUSY when the mac is already active (join or tx in progress) - * @return SEMTECH_LORAMAC_TX_SCHEDULED when the TX is scheduled in the mac + * @return SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED when the send is rejected because of dutycycle restriction + * @return SEMTECH_LORAMAC_TX_ERROR when an invalid parameter is given */ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len); @@ -172,6 +177,9 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) * class C device, a message can be received at any time. In this case, this * function can be used in a dedicated listener thread. * + * Be sure to call this function before the end of the RX windows otherwise it + * may block the calling thread. + * * @see semtech_loramac_send * * @param[in] mac Pointer to the mac diff --git a/tests/pkg_semtech-loramac/main.c b/tests/pkg_semtech-loramac/main.c index 56d97d6a76d47dfe36b8442f3498a98580c641a2..52547aabc2d667edfa5d06facb71a7c21e744555 100644 --- a/tests/pkg_semtech-loramac/main.c +++ b/tests/pkg_semtech-loramac/main.c @@ -414,15 +414,23 @@ static int _cmd_loramac(int argc, char **argv) switch (semtech_loramac_send(&loramac, (uint8_t *)argv[2], strlen(argv[2]))) { case SEMTECH_LORAMAC_NOT_JOINED: - puts("Failed: not joined"); + puts("Cannot send: not joined"); + return 1; + + case SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED: + puts("Cannot send: dutycycle restriction"); return 1; case SEMTECH_LORAMAC_BUSY: - puts("Failed: mac is busy"); + puts("Cannot send: MAC is busy"); + return 1; + + case SEMTECH_LORAMAC_TX_ERROR: + puts("Cannot send: error"); return 1; } - /* clear the rx buffer of the mac */ + /* wait for receive windows */ switch (semtech_loramac_recv(&loramac)) { case SEMTECH_LORAMAC_DATA_RECEIVED: loramac.rx_data.payload[loramac.rx_data.payload_len] = 0;