@@ -58,19 +58,19 @@ using namespace events;
5858/* ****************************************************************************
5959 * Private Member Functions *
6060 ****************************************************************************/
61- bool LoRaWANStack::is_port_valid (uint8_t port)
61+ bool LoRaWANStack::is_port_valid (uint8_t port, bool allow_port_0 )
6262{
6363 // Application should not use reserved and illegal port numbers.
64- if (port >= 224 || port == 0 ) {
65- return false ;
64+ if (port == 0 ) {
65+ return allow_port_0 ;
6666 } else {
6767 return true ;
6868 }
6969}
7070
71- lorawan_status_t LoRaWANStack::set_application_port (uint8_t port)
71+ lorawan_status_t LoRaWANStack::set_application_port (uint8_t port, bool allow_port_0 )
7272{
73- if (is_port_valid (port)) {
73+ if (is_port_valid (port, allow_port_0 )) {
7474 _app_port = port;
7575 return LORAWAN_STATUS_OK;
7676 }
@@ -236,10 +236,14 @@ void LoRaWANStack::mlme_indication_handler(loramac_mlme_indication_t *mlmeIndica
236236 switch ( mlmeIndication->indication_type )
237237 {
238238 case MLME_SCHEDULE_UPLINK:
239- {// The MAC signals that we shall provide an uplink as soon as possible
240- // TODO: Sending implementation missing and will be implemented using
241- // another task.
242- // OnTxNextPacketTimerEvent( );
239+ {
240+ // The MAC signals that we shall provide an uplink as soon as possible
241+ #if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
242+ tr_debug (" mlme indication: sending empty uplink to port 0 to acknowledge MAC commands..." );
243+ send_automatic_uplink_message (0 );
244+ #else
245+ send_event_to_application (UPLINK_REQUIRED);
246+ #endif
243247 break ;
244248 }
245249 default :
@@ -332,8 +336,26 @@ lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
332336 return _loramac.set_channel_data_rate (data_rate);
333337}
334338
339+ void LoRaWANStack::send_event_to_application (const lorawan_event_t event) const
340+ {
341+ if (_callbacks.events ) {
342+ const int ret = _queue->call (_callbacks.events , event);
343+ MBED_ASSERT (ret != 0 );
344+ (void )ret;
345+ }
346+ }
347+
348+ void LoRaWANStack::send_automatic_uplink_message (const uint8_t port)
349+ {
350+ const int16_t ret = handle_tx (port, NULL , 0 , MSG_CONFIRMED_FLAG, true , true );
351+ if (ret < 0 ) {
352+ send_event_to_application (AUTOMATIC_UPLINK_ERROR);
353+ }
354+ }
355+
335356int16_t LoRaWANStack::handle_tx (uint8_t port, const uint8_t * data,
336- uint16_t length, uint8_t flags, bool null_allowed)
357+ uint16_t length, uint8_t flags,
358+ bool null_allowed, bool allow_port_0)
337359{
338360 if (!null_allowed && !data) {
339361 return LORAWAN_STATUS_PARAMETER_INVALID;
@@ -364,7 +386,7 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
364386 return LORAWAN_STATUS_NO_NETWORK_JOINED;
365387 }
366388
367- status = set_application_port (port);
389+ status = set_application_port (port, allow_port_0 );
368390
369391 if (status != LORAWAN_STATUS_OK) {
370392 tr_error (" Illegal application port definition." );
@@ -379,7 +401,6 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
379401
380402 int16_t len = _loramac.prepare_ongoing_tx (port, data, length, flags, _num_retry);
381403
382-
383404 status = lora_state_machine (DEVICE_STATE_SEND);
384405
385406 // send user the length of data which is scheduled now.
@@ -501,11 +522,7 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
501522 tr_error (" Lora state machine did not return DEVICE_STATE_IDLE !" );
502523 }
503524
504- if (_callbacks.events ) {
505- const int ret = _queue->call (_callbacks.events , JOIN_FAILURE);
506- MBED_ASSERT (ret != 0 );
507- (void )ret;
508- }
525+ send_event_to_application (JOIN_FAILURE);
509526 }
510527 break ;
511528 case MLME_LINK_CHECK:
@@ -541,21 +558,13 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
541558 tr_error (" mcps_confirm_handler: Error code = %d" , mcps_confirm->status );
542559
543560 if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT) {
544- if (_callbacks.events ) {
545- const int ret = _queue->call (_callbacks.events , TX_TIMEOUT);
546- MBED_ASSERT (ret != 0 );
547- (void )ret;
548- }
561+ send_event_to_application (TX_TIMEOUT);
549562 return ;
550563 } else if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT) {
551564 tr_debug (" Did not receive Ack" );
552565 }
553566
554- if (_callbacks.events ) {
555- const int ret = _queue->call (_callbacks.events , TX_ERROR);
556- MBED_ASSERT (ret != 0 );
557- (void )ret;
558- }
567+ send_event_to_application (TX_ERROR);
559568 return ;
560569 }
561570
@@ -566,22 +575,14 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
566575
567576 _lw_session.uplink_counter = mcps_confirm->ul_frame_counter ;
568577 _loramac.set_tx_ongoing (false );
569- if (_callbacks.events ) {
570- const int ret = _queue->call (_callbacks.events , TX_DONE);
571- MBED_ASSERT (ret != 0 );
572- (void )ret;
573- }
578+ send_event_to_application (TX_DONE);
574579}
575580
576581void LoRaWANStack::mcps_indication_handler (loramac_mcps_indication_t *mcps_indication)
577582{
578583 if (mcps_indication->status != LORAMAC_EVENT_INFO_STATUS_OK) {
579- if (_callbacks.events ) {
580- tr_error (" RX_ERROR: mcps_indication status = %d" , mcps_indication->status );
581- const int ret = _queue->call (_callbacks.events , RX_ERROR);
582- MBED_ASSERT (ret != 0 );
583- (void )ret;
584- }
584+ tr_error (" RX_ERROR: mcps_indication status = %d" , mcps_indication->status );
585+ send_event_to_application (RX_ERROR);
585586 return ;
586587 }
587588
@@ -645,32 +646,28 @@ void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indic
645646 tr_debug (" Received %d bytes" , _rx_msg.msg .mcps_indication .buffer_size );
646647 _rx_msg.receive_ready = true ;
647648
648- if (_callbacks.events ) {
649- const int ret = _queue->call (_callbacks.events , RX_DONE);
650- MBED_ASSERT (ret != 0 );
651- (void )ret;
652- }
653-
654- // TODO: below if clauses can be combined,
655- // because those are calling same function with same parameters
656-
657- // If fPending bit is set we try to generate an empty packet
658- // with CONFIRMED flag set. We always set a CONFIRMED flag so
659- // that we could retry a certain number of times if the uplink
660- // failed for some reason
661- if (_loramac.get_device_class () != CLASS_C && mcps_indication->fpending_status ) {
662- tr_debug (" Pending bit set. Sending empty message to receive pending data..." );
663- handle_tx (mcps_indication->port , NULL , 0 , MSG_CONFIRMED_FLAG, true );
664- }
665-
666- // Class C and node received a confirmed message so we need to
667- // send an empty packet to acknowledge the message.
668- // This scenario is unspecified by LoRaWAN 1.0.2 specification,
669- // but version 1.1.0 says that network SHALL not send any new
670- // confirmed messages until ack has been sent
671- if (_loramac.get_device_class () == CLASS_C && mcps_indication->type == MCPS_CONFIRMED) {
672- tr_debug (" Acknowledging confirmed message (class C)..." );
673- handle_tx (mcps_indication->port , NULL , 0 , MSG_CONFIRMED_FLAG, true );
649+ send_event_to_application (RX_DONE);
650+
651+ /*
652+ * If fPending bit is set we try to generate an empty packet
653+ * with CONFIRMED flag set. We always set a CONFIRMED flag so
654+ * that we could retry a certain number of times if the uplink
655+ * failed for some reason
656+ * or
657+ * Class C and node received a confirmed message so we need to
658+ * send an empty packet to acknowledge the message.
659+ * This scenario is unspecified by LoRaWAN 1.0.2 specification,
660+ * but version 1.1.0 says that network SHALL not send any new
661+ * confirmed messages until ack has been sent
662+ */
663+ if ((_loramac.get_device_class () != CLASS_C && mcps_indication->fpending_status ) ||
664+ (_loramac.get_device_class () == CLASS_C && mcps_indication->type == MCPS_CONFIRMED)) {
665+ #if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
666+ tr_debug (" Sending empty uplink message..." );
667+ send_automatic_uplink_message (mcps_indication->port );
668+ #else
669+ send_event_to_application (UPLINK_REQUIRED);
670+ #endif
674671 }
675672 } else {
676673 // Invalid port, ports 0, 224 and 225-255 are reserved.
@@ -741,11 +738,7 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
741738 _lw_session.active = false ;
742739
743740 tr_debug (" LoRaWAN protocol has been shut down." );
744- if (_callbacks.events ) {
745- const int ret = _queue->call (_callbacks.events , DISCONNECTED);
746- MBED_ASSERT (ret != 0 );
747- (void )ret;
748- }
741+ send_event_to_application (DISCONNECTED);
749742 status = LORAWAN_STATUS_DEVICE_OFF;
750743 break ;
751744 case DEVICE_STATE_NOT_INITIALIZED:
@@ -773,11 +766,7 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
773766
774767 _lw_session.active = true ;
775768
776- if (_callbacks.events ) {
777- const int ret = _queue->call (_callbacks.events , CONNECTED);
778- MBED_ASSERT (ret != 0 );
779- (void )ret;
780- }
769+ send_event_to_application (CONNECTED);
781770 status = LORAWAN_STATUS_OK;
782771 break ;
783772 case DEVICE_STATE_ABP_CONNECTING:
@@ -789,11 +778,7 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
789778 status = LORAWAN_STATUS_OK;
790779
791780 _lw_session.active = true ;
792- if (_callbacks.events ) {
793- const int ret = _queue->call (_callbacks.events , CONNECTED);
794- MBED_ASSERT (ret != 0 );
795- (void )ret;
796- }
781+ send_event_to_application (CONNECTED);
797782 break ;
798783 case DEVICE_STATE_SEND:
799784 if (_loramac.tx_ongoing ()) {
@@ -808,19 +793,11 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
808793 break ;
809794 case LORAWAN_STATUS_CRYPTO_FAIL:
810795 tr_error (" Crypto failed. Clearing TX buffers" );
811- if (_callbacks.events ) {
812- const int ret = _queue->call (_callbacks.events , TX_CRYPTO_ERROR);
813- MBED_ASSERT (ret != 0 );
814- (void )ret;
815- }
796+ send_event_to_application (TX_CRYPTO_ERROR);
816797 break ;
817798 default :
818799 tr_error (" Failure to schedule TX!" );
819- if (_callbacks.events ) {
820- const int ret = _queue->call (_callbacks.events , TX_SCHEDULING_ERROR);
821- MBED_ASSERT (ret != 0 );
822- (void )ret;
823- }
800+ send_event_to_application (TX_SCHEDULING_ERROR);
824801 break ;
825802 }
826803 }
0 commit comments