Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaWANStack.cpp Source File

LoRaWANStack.cpp

00001 /**
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2013 Semtech
00008  ___ _____ _   ___ _  _____ ___  ___  ___ ___
00009 / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
00010 \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
00012 embedded.connectivity.solutions===============
00013 
00014 Description: LoRaWAN stack layer that controls both MAC and PHY underneath
00015 
00016 License: Revised BSD License, see LICENSE.TXT file include in the project
00017 
00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
00019 
00020 
00021 Copyright (c) 2017, Arm Limited and affiliates.
00022 
00023 SPDX-License-Identifier: BSD-3-Clause
00024 */
00025 
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include "platform/Callback.h"
00029 #include "events/EventQueue.h"
00030 
00031 #include "LoRaWANStack.h"
00032 
00033 #include "mbed-trace/mbed_trace.h"
00034 #define TRACE_GROUP "LSTK"
00035 
00036 #define INVALID_PORT                0xFF
00037 #define MAX_CONFIRMED_MSG_RETRIES   255
00038 #define COMPLIANCE_TESTING_PORT     224
00039 /**
00040  * Control flags for transient states
00041  */
00042 #define IDLE_FLAG                   0x00000000
00043 #define RETRY_EXHAUSTED_FLAG        0x00000001
00044 #define MSG_RECVD_FLAG              0x00000002
00045 #define CONNECTED_FLAG              0x00000004
00046 #define USING_OTAA_FLAG             0x00000008
00047 #define TX_DONE_FLAG                0x00000010
00048 #define CONN_IN_PROGRESS_FLAG       0x00000020
00049 
00050 using namespace mbed;
00051 using namespace events;
00052 
00053 /**
00054  * Bit mask for message flags
00055  */
00056 
00057 #define MSG_FLAG_MASK                         0x0F
00058 
00059 /*****************************************************************************
00060  * Constructor                                                               *
00061  ****************************************************************************/
00062 LoRaWANStack::LoRaWANStack()
00063     : _loramac(),
00064       _device_current_state(DEVICE_STATE_NOT_INITIALIZED),
00065       _lw_session(),
00066       _tx_msg(),
00067       _rx_msg(),
00068       _tx_metadata(),
00069       _rx_metadata(),
00070       _num_retry(1),
00071       _qos_cnt(1),
00072       _ctrl_flags(IDLE_FLAG),
00073       _app_port(INVALID_PORT),
00074       _link_check_requested(false),
00075       _automatic_uplink_ongoing(false),
00076       _queue(NULL)
00077 {
00078     _tx_metadata.stale = true;
00079     _rx_metadata.stale = true;
00080     core_util_atomic_flag_clear(&_rx_payload_in_use);
00081 
00082 #ifdef MBED_CONF_LORA_APP_PORT
00083     if (is_port_valid(MBED_CONF_LORA_APP_PORT)) {
00084         _app_port = MBED_CONF_LORA_APP_PORT;
00085     } else {
00086         tr_error("User defined port in .json is illegal.");
00087     }
00088 #endif
00089 }
00090 
00091 /*****************************************************************************
00092  * Public Methods                                                            *
00093  ****************************************************************************/
00094 void LoRaWANStack::bind_phy_and_radio_driver(LoRaRadio &radio, LoRaPHY &phy)
00095 {
00096     radio_events.tx_done = mbed::callback(this, &LoRaWANStack::tx_interrupt_handler);
00097     radio_events.rx_done = mbed::callback(this, &LoRaWANStack::rx_interrupt_handler);
00098     radio_events.rx_error = mbed::callback(this, &LoRaWANStack::rx_error_interrupt_handler);
00099     radio_events.tx_timeout = mbed::callback(this, &LoRaWANStack::tx_timeout_interrupt_handler);
00100     radio_events.rx_timeout = mbed::callback(this, &LoRaWANStack::rx_timeout_interrupt_handler);
00101 
00102     phy.set_radio_instance(radio);
00103     _loramac.bind_phy(phy);
00104 
00105     radio.lock();
00106     radio.init_radio(&radio_events);
00107     radio.unlock();
00108 }
00109 
00110 lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
00111 {
00112     if (!queue) {
00113         return LORAWAN_STATUS_PARAMETER_INVALID;
00114     }
00115 
00116     tr_debug("Initializing MAC layer");
00117     _queue = queue;
00118 
00119     return state_controller(DEVICE_STATE_IDLE);
00120 }
00121 
00122 lorawan_status_t LoRaWANStack::set_lora_callbacks(const lorawan_app_callbacks_t *callbacks)
00123 {
00124     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00125         return LORAWAN_STATUS_NOT_INITIALIZED;
00126     }
00127 
00128     if (!callbacks || !callbacks->events) {
00129         return LORAWAN_STATUS_PARAMETER_INVALID;
00130     }
00131 
00132     _callbacks.events = callbacks->events;
00133 
00134     if (callbacks->link_check_resp) {
00135         _callbacks.link_check_resp = callbacks->link_check_resp;
00136     }
00137 
00138     if (callbacks->battery_level) {
00139         _callbacks.battery_level = callbacks->battery_level;
00140         _loramac.set_batterylevel_callback(callbacks->battery_level);
00141     }
00142 
00143     return LORAWAN_STATUS_OK;
00144 }
00145 
00146 lorawan_status_t LoRaWANStack::connect()
00147 {
00148     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00149         return LORAWAN_STATUS_NOT_INITIALIZED;
00150     }
00151 
00152     if (_ctrl_flags & CONN_IN_PROGRESS_FLAG) {
00153         return LORAWAN_STATUS_BUSY;
00154     }
00155 
00156     if (_ctrl_flags & CONNECTED_FLAG) {
00157         return LORAWAN_STATUS_ALREADY_CONNECTED;
00158     }
00159 
00160     lorawan_status_t status = _loramac.prepare_join(NULL, MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION);
00161 
00162     if (LORAWAN_STATUS_OK != status) {
00163         return status;
00164     }
00165 
00166     return handle_connect(MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION);
00167 }
00168 
00169 lorawan_status_t LoRaWANStack::connect(const lorawan_connect_t &connect)
00170 {
00171     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00172         return LORAWAN_STATUS_NOT_INITIALIZED;
00173     }
00174 
00175     if (_ctrl_flags & CONN_IN_PROGRESS_FLAG) {
00176         return LORAWAN_STATUS_BUSY;
00177     }
00178 
00179     if (_ctrl_flags & CONNECTED_FLAG) {
00180         return LORAWAN_STATUS_ALREADY_CONNECTED;
00181     }
00182 
00183     if (!(connect.connect_type == LORAWAN_CONNECTION_OTAA)
00184             && !(connect.connect_type == LORAWAN_CONNECTION_ABP)) {
00185         return LORAWAN_STATUS_PARAMETER_INVALID;
00186     }
00187 
00188     bool is_otaa = (connect.connect_type == LORAWAN_CONNECTION_OTAA);
00189 
00190     lorawan_status_t status = _loramac.prepare_join(&connect, is_otaa);
00191 
00192     if (LORAWAN_STATUS_OK != status) {
00193         return status;
00194     }
00195 
00196     return handle_connect(is_otaa);
00197 }
00198 
00199 lorawan_status_t LoRaWANStack::add_channels(const lorawan_channelplan_t &channel_plan)
00200 {
00201     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00202         return LORAWAN_STATUS_NOT_INITIALIZED;
00203     }
00204 
00205     return _loramac.add_channel_plan(channel_plan);
00206 }
00207 
00208 lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
00209 {
00210     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00211         return LORAWAN_STATUS_NOT_INITIALIZED;
00212     }
00213 
00214     return _loramac.remove_single_channel(channel_id);
00215 }
00216 
00217 lorawan_status_t LoRaWANStack::drop_channel_list()
00218 {
00219     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00220         return LORAWAN_STATUS_NOT_INITIALIZED;
00221     }
00222 
00223     return _loramac.remove_channel_plan();
00224 }
00225 
00226 lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t &channel_plan)
00227 {
00228     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00229         return LORAWAN_STATUS_NOT_INITIALIZED;
00230     }
00231 
00232     return _loramac.get_channel_plan(channel_plan);
00233 }
00234 
00235 lorawan_status_t LoRaWANStack::set_confirmed_msg_retry(uint8_t count)
00236 {
00237     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00238         return LORAWAN_STATUS_NOT_INITIALIZED;
00239     }
00240 
00241     if (count >= MAX_CONFIRMED_MSG_RETRIES) {
00242         return LORAWAN_STATUS_PARAMETER_INVALID;
00243     }
00244 
00245     _num_retry = count;
00246 
00247     return LORAWAN_STATUS_OK;
00248 }
00249 
00250 lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
00251 {
00252     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00253         return LORAWAN_STATUS_NOT_INITIALIZED;
00254     }
00255 
00256     return _loramac.set_channel_data_rate(data_rate);
00257 }
00258 
00259 
00260 lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled)
00261 {
00262     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00263         return LORAWAN_STATUS_NOT_INITIALIZED;
00264     }
00265 
00266     _loramac.enable_adaptive_datarate(adr_enabled);
00267     return LORAWAN_STATUS_OK;
00268 }
00269 
00270 lorawan_status_t LoRaWANStack::stop_sending(void)
00271 {
00272     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00273         return LORAWAN_STATUS_NOT_INITIALIZED;
00274     }
00275 
00276     lorawan_status_t status = _loramac.clear_tx_pipe();
00277 
00278     if (status == LORAWAN_STATUS_OK) {
00279         _ctrl_flags &= ~TX_DONE_FLAG;
00280         _loramac.set_tx_ongoing(false);
00281         _device_current_state = DEVICE_STATE_IDLE;
00282         return LORAWAN_STATUS_OK;
00283     }
00284 
00285     return status;
00286 }
00287 
00288 int16_t LoRaWANStack::handle_tx(const uint8_t port, const uint8_t *data,
00289                                 uint16_t length, uint8_t flags,
00290                                 bool null_allowed, bool allow_port_0)
00291 {
00292     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00293         return LORAWAN_STATUS_NOT_INITIALIZED;
00294     }
00295 
00296     if (!null_allowed && !data) {
00297         return LORAWAN_STATUS_PARAMETER_INVALID;
00298     }
00299 
00300     if (!_lw_session.active) {
00301         return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
00302     }
00303 
00304     if (_loramac.tx_ongoing()) {
00305         return LORAWAN_STATUS_WOULD_BLOCK;
00306     }
00307 
00308     // add a link check request with normal data, until the application
00309     // explicitly removes it.
00310     if (_link_check_requested) {
00311         _loramac.setup_link_check_request();
00312     }
00313     _qos_cnt = 1;
00314 
00315     lorawan_status_t status;
00316 
00317     if (_loramac.nwk_joined() == false) {
00318         return LORAWAN_STATUS_NO_NETWORK_JOINED;
00319     }
00320 
00321     status = set_application_port(port, allow_port_0);
00322 
00323     if (status != LORAWAN_STATUS_OK) {
00324         tr_error("Illegal application port definition.");
00325         return status;
00326     }
00327 
00328     // All the flags are mutually exclusive. In addition to that MSG_MULTICAST_FLAG cannot be
00329     // used for uplink.
00330     switch (flags & MSG_FLAG_MASK) {
00331         case MSG_UNCONFIRMED_FLAG:
00332         case MSG_CONFIRMED_FLAG:
00333         case MSG_PROPRIETARY_FLAG:
00334             break;
00335 
00336         default:
00337             tr_error("Invalid send flags");
00338             return LORAWAN_STATUS_PARAMETER_INVALID;
00339     }
00340 
00341     int16_t len = _loramac.prepare_ongoing_tx(port, data, length, flags, _num_retry);
00342 
00343     status = state_controller(DEVICE_STATE_SCHEDULING);
00344 
00345     // send user the length of data which is scheduled now.
00346     // user should take care of the pending data.
00347     return (status == LORAWAN_STATUS_OK) ? len : (int16_t) status;
00348 }
00349 
00350 int16_t LoRaWANStack::handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params)
00351 {
00352     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00353         return LORAWAN_STATUS_NOT_INITIALIZED;
00354     }
00355 
00356     if (!_lw_session.active) {
00357         return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
00358     }
00359 
00360     // No messages to read.
00361     if (!_rx_msg.receive_ready) {
00362         return LORAWAN_STATUS_WOULD_BLOCK;
00363     }
00364 
00365     if (data == NULL || length == 0) {
00366         return LORAWAN_STATUS_PARAMETER_INVALID;
00367     }
00368 
00369     int received_flags = convert_to_msg_flag(_rx_msg.msg.mcps_indication.type );
00370     if (validate_params) {
00371         // Check received message port and flags match with the ones requested by user
00372         received_flags &= MSG_FLAG_MASK;
00373 
00374         if (_rx_msg.msg.mcps_indication.port  != port || !(flags & received_flags)) {
00375             return LORAWAN_STATUS_WOULD_BLOCK;
00376         }
00377     }
00378 
00379     // Report values back to user
00380     port = _rx_msg.msg.mcps_indication.port ;
00381     flags = received_flags;
00382 
00383     const uint8_t *base_ptr = _rx_msg.msg.mcps_indication.buffer ;
00384     uint16_t base_size = _rx_msg.msg.mcps_indication.buffer_size ;
00385     bool read_complete = false;
00386 
00387     if (_rx_msg.pending_size == 0) {
00388         _rx_msg.pending_size = _rx_msg.msg.mcps_indication.buffer_size ;
00389         _rx_msg.prev_read_size = 0;
00390     }
00391 
00392     // check the length of received message whether we can fit into user
00393     // buffer completely or not
00394     if (_rx_msg.prev_read_size == 0 && _rx_msg.msg.mcps_indication.buffer_size  <= length) {
00395         memcpy(data, base_ptr, base_size);
00396         read_complete = true;
00397     } else if (_rx_msg.pending_size > length) {
00398         _rx_msg.pending_size = _rx_msg.pending_size - length;
00399         base_size = length;
00400         memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size);
00401         _rx_msg.prev_read_size += base_size;
00402     } else {
00403         base_size = _rx_msg.pending_size;
00404         memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size);
00405         read_complete = true;
00406     }
00407 
00408     if (read_complete) {
00409         _rx_msg.msg.mcps_indication.buffer  = NULL;
00410         _rx_msg.msg.mcps_indication.buffer_size  = 0;
00411         _rx_msg.pending_size = 0;
00412         _rx_msg.receive_ready = false;
00413     }
00414 
00415     return base_size;
00416 }
00417 
00418 lorawan_status_t LoRaWANStack::set_link_check_request()
00419 {
00420     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00421         return LORAWAN_STATUS_NOT_INITIALIZED;
00422     }
00423 
00424     if (!_callbacks.link_check_resp) {
00425         tr_error("Must assign a callback function for link check request. ");
00426         return LORAWAN_STATUS_PARAMETER_INVALID;
00427     }
00428 
00429     _link_check_requested = true;
00430     return LORAWAN_STATUS_OK;
00431 }
00432 
00433 void LoRaWANStack::remove_link_check_request()
00434 {
00435     _link_check_requested = false;
00436 }
00437 
00438 lorawan_status_t LoRaWANStack::shutdown()
00439 {
00440     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00441         return LORAWAN_STATUS_NOT_INITIALIZED;
00442     }
00443 
00444     return state_controller(DEVICE_STATE_SHUTDOWN);
00445 }
00446 
00447 lorawan_status_t LoRaWANStack::set_device_class(const device_class_t &device_class)
00448 {
00449     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00450         return LORAWAN_STATUS_NOT_INITIALIZED;
00451     }
00452 
00453     if (device_class == CLASS_B) {
00454         return LORAWAN_STATUS_UNSUPPORTED;
00455     }
00456     _loramac.set_device_class(device_class,
00457                               mbed::callback(this, &LoRaWANStack::post_process_tx_no_reception));
00458     return LORAWAN_STATUS_OK;
00459 }
00460 
00461 lorawan_status_t  LoRaWANStack::acquire_tx_metadata(lorawan_tx_metadata &tx_metadata)
00462 {
00463     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00464         return LORAWAN_STATUS_NOT_INITIALIZED;
00465     }
00466 
00467     if (!_tx_metadata.stale) {
00468         tx_metadata = _tx_metadata;
00469         _tx_metadata.stale = true;
00470         return LORAWAN_STATUS_OK;
00471     }
00472 
00473     return LORAWAN_STATUS_METADATA_NOT_AVAILABLE;
00474 }
00475 
00476 lorawan_status_t LoRaWANStack::acquire_rx_metadata(lorawan_rx_metadata &metadata)
00477 {
00478     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00479         return LORAWAN_STATUS_NOT_INITIALIZED;
00480     }
00481 
00482     if (!_rx_metadata.stale) {
00483         metadata = _rx_metadata;
00484         _rx_metadata.stale = true;
00485         return LORAWAN_STATUS_OK;
00486     }
00487 
00488     return LORAWAN_STATUS_METADATA_NOT_AVAILABLE;
00489 }
00490 
00491 lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int &backoff)
00492 {
00493     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00494         return LORAWAN_STATUS_NOT_INITIALIZED;
00495     }
00496 
00497     int id = _loramac.get_backoff_timer_event_id();
00498 
00499     if (_loramac.get_backoff_timer_event_id() > 0) {
00500         backoff = _queue->time_left(id);
00501         return LORAWAN_STATUS_OK;
00502     }
00503 
00504     backoff = -1;
00505     return LORAWAN_STATUS_METADATA_NOT_AVAILABLE;
00506 }
00507 
00508 /*****************************************************************************
00509  * Interrupt handlers                                                        *
00510  ****************************************************************************/
00511 void LoRaWANStack::tx_interrupt_handler(void)
00512 {
00513     _tx_timestamp = _loramac.get_current_time();
00514     const int ret = _queue->call(this, &LoRaWANStack::process_transmission);
00515     MBED_ASSERT(ret != 0);
00516     (void)ret;
00517 }
00518 
00519 void LoRaWANStack::rx_interrupt_handler(const uint8_t *payload, uint16_t size,
00520                                         int16_t rssi, int8_t snr)
00521 {
00522     if (size > sizeof _rx_payload || core_util_atomic_flag_test_and_set(&_rx_payload_in_use)) {
00523         return;
00524     }
00525 
00526     memcpy(_rx_payload, payload, size);
00527 
00528     const uint8_t *ptr = _rx_payload;
00529     const int ret = _queue->call(this, &LoRaWANStack::process_reception,
00530                                  ptr, size, rssi, snr);
00531     MBED_ASSERT(ret != 0);
00532     (void)ret;
00533 }
00534 
00535 void LoRaWANStack::rx_error_interrupt_handler(void)
00536 {
00537     const int ret = _queue->call(this, &LoRaWANStack::process_reception_timeout,
00538                                  false);
00539     MBED_ASSERT(ret != 0);
00540     (void)ret;
00541 }
00542 
00543 void LoRaWANStack::tx_timeout_interrupt_handler(void)
00544 {
00545     const int ret = _queue->call(this, &LoRaWANStack::process_transmission_timeout);
00546     MBED_ASSERT(ret != 0);
00547     (void)ret;
00548 }
00549 
00550 void LoRaWANStack::rx_timeout_interrupt_handler(void)
00551 {
00552     const int ret = _queue->call(this, &LoRaWANStack::process_reception_timeout,
00553                                  true);
00554     MBED_ASSERT(ret != 0);
00555     (void)ret;
00556 }
00557 
00558 /*****************************************************************************
00559  * Processors for deferred interrupts                                        *
00560  ****************************************************************************/
00561 void LoRaWANStack::process_transmission_timeout()
00562 {
00563     // this is a fatal error and should not happen
00564     tr_debug("TX Timeout");
00565     _loramac.on_radio_tx_timeout();
00566     _ctrl_flags &= ~TX_DONE_FLAG;
00567     if (_device_current_state == DEVICE_STATE_JOINING) {
00568         mlme_confirm_handler();
00569     } else {
00570         state_controller(DEVICE_STATE_STATUS_CHECK);
00571     }
00572 
00573     state_machine_run_to_completion();
00574 }
00575 
00576 void LoRaWANStack::process_transmission(void)
00577 {
00578     tr_debug("Transmission completed");
00579 
00580     if (_device_current_state == DEVICE_STATE_JOINING) {
00581         _device_current_state = DEVICE_STATE_AWAITING_JOIN_ACCEPT;
00582     }
00583 
00584     if (_device_current_state == DEVICE_STATE_SENDING) {
00585         if (_loramac.get_mcps_confirmation()->req_type  == MCPS_CONFIRMED ) {
00586             tr_debug("Awaiting ACK");
00587             _device_current_state = DEVICE_STATE_AWAITING_ACK;
00588         }
00589     }
00590 
00591     _loramac.on_radio_tx_done(_tx_timestamp);
00592 }
00593 
00594 void LoRaWANStack::post_process_tx_with_reception()
00595 {
00596     if (_loramac.get_mcps_confirmation()->req_type  == MCPS_CONFIRMED ) {
00597         // if ack was not received, we will try retransmission after
00598         // ACK_TIMEOUT. handle_data_frame() already disables ACK_TIMEOUT timer
00599         // if ack was received. Otherwise, following method will be called in
00600         // LoRaMac.cpp, on_ack_timeout_timer_event().
00601         if (_loramac.get_mcps_indication()->is_ack_recvd ) {
00602             _ctrl_flags |= TX_DONE_FLAG;
00603             _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
00604             tr_debug("Ack=OK, NbTrials=%d",
00605                      _loramac.get_mcps_confirmation()->nb_retries );
00606             _loramac.post_process_mcps_req();
00607             make_tx_metadata_available();
00608             state_controller(DEVICE_STATE_STATUS_CHECK);
00609         } else {
00610             if (!_loramac.continue_sending_process()
00611                     && _loramac.get_current_slot() != RX_SLOT_WIN_1 ) {
00612                 tr_error("Retries exhausted for Class %s device",
00613                          _loramac.get_device_class() == CLASS_A ? "A" : "C");
00614                 _ctrl_flags &= ~TX_DONE_FLAG;
00615                 _ctrl_flags |= RETRY_EXHAUSTED_FLAG;
00616                 _loramac.post_process_mcps_req();
00617                 make_tx_metadata_available();
00618                 state_controller(DEVICE_STATE_STATUS_CHECK);
00619             }
00620         }
00621     } else {
00622         // handle UNCONFIRMED case here, RX slots were turned off due to
00623         // valid packet reception.
00624         uint8_t prev_QOS_level = _loramac.get_prev_QOS_level();
00625         uint8_t QOS_level = _loramac.get_QOS_level();
00626 
00627         // We will not apply QOS on the post-processing of the previous
00628         // outgoing message as we would have received QOS instruction in response
00629         // to that particular message
00630         if (QOS_level > LORAWAN_DEFAULT_QOS && _qos_cnt < QOS_level
00631                 && (prev_QOS_level == QOS_level)) {
00632             _ctrl_flags &= ~TX_DONE_FLAG;
00633             const int ret = _queue->call(this, &LoRaWANStack::state_controller,
00634                                          DEVICE_STATE_SCHEDULING);
00635             MBED_ASSERT(ret != 0);
00636             (void) ret;
00637             _qos_cnt++;
00638             tr_info("QOS: repeated transmission #%d queued", _qos_cnt);
00639         } else {
00640             _loramac.post_process_mcps_req();
00641             _ctrl_flags |= TX_DONE_FLAG;
00642             make_tx_metadata_available();
00643             state_controller(DEVICE_STATE_STATUS_CHECK);
00644         }
00645     }
00646 }
00647 
00648 void LoRaWANStack::post_process_tx_no_reception()
00649 {
00650     if (_loramac.get_mcps_confirmation()->req_type  == MCPS_CONFIRMED ) {
00651         if (_loramac.continue_sending_process()) {
00652             _ctrl_flags &= ~TX_DONE_FLAG;
00653             _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
00654             return;
00655         }
00656 
00657         tr_error("Retries exhausted for Class %s device",
00658                  _loramac.get_device_class() == CLASS_A ? "A" : "C");
00659         _ctrl_flags &= ~TX_DONE_FLAG;
00660         _ctrl_flags |= RETRY_EXHAUSTED_FLAG;
00661     } else {
00662         _ctrl_flags |= TX_DONE_FLAG;
00663 
00664         uint8_t prev_QOS_level = _loramac.get_prev_QOS_level();
00665         uint8_t QOS_level = _loramac.get_QOS_level();
00666 
00667         if (QOS_level > LORAWAN_DEFAULT_QOS && (prev_QOS_level == QOS_level)) {
00668             if (_qos_cnt < QOS_level) {
00669                 const int ret = _queue->call(this, &LoRaWANStack::state_controller,
00670                                              DEVICE_STATE_SCHEDULING);
00671                 MBED_ASSERT(ret != 0);
00672                 (void)ret;
00673                 _qos_cnt++;
00674                 tr_info("QOS: repeated transmission #%d queued", _qos_cnt);
00675                 state_machine_run_to_completion();
00676                 return;
00677             }
00678         }
00679     }
00680 
00681     _loramac.post_process_mcps_req();
00682     make_tx_metadata_available();
00683     state_controller(DEVICE_STATE_STATUS_CHECK);
00684     state_machine_run_to_completion();
00685 }
00686 
00687 void LoRaWANStack::handle_scheduling_failure(void)
00688 {
00689     tr_error("Failed to schedule transmission");
00690     state_controller(DEVICE_STATE_STATUS_CHECK);
00691     state_machine_run_to_completion();
00692 }
00693 
00694 
00695 void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size,
00696                                      int16_t rssi, int8_t snr)
00697 {
00698     _device_current_state = DEVICE_STATE_RECEIVING;
00699 
00700     _ctrl_flags &= ~MSG_RECVD_FLAG;
00701     _ctrl_flags &= ~TX_DONE_FLAG;
00702     _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
00703 
00704     _loramac.on_radio_rx_done(payload, size, rssi, snr);
00705 
00706     if (_loramac.get_mlme_confirmation()->pending ) {
00707         _loramac.post_process_mlme_request();
00708         mlme_confirm_handler();
00709 
00710         if (_loramac.get_mlme_confirmation()->req_type  == MLME_JOIN ) {
00711             core_util_atomic_flag_clear(&_rx_payload_in_use);
00712             return;
00713         }
00714     }
00715 
00716     if (!_loramac.nwk_joined()) {
00717         core_util_atomic_flag_clear(&_rx_payload_in_use);
00718         return;
00719     }
00720 
00721     make_rx_metadata_available();
00722 
00723     // Post process transmission in response to the reception
00724     post_process_tx_with_reception();
00725 
00726     // handle any pending MCPS indication
00727     if (_loramac.get_mcps_indication()->pending ) {
00728         _loramac.post_process_mcps_ind();
00729         _ctrl_flags |= MSG_RECVD_FLAG;
00730         state_controller(DEVICE_STATE_STATUS_CHECK);
00731     }
00732 
00733     // complete the cycle only if TX_DONE_FLAG is set
00734     if (_ctrl_flags & TX_DONE_FLAG) {
00735         state_machine_run_to_completion();
00736     }
00737 
00738     // suppress auto uplink if another auto-uplink is in AWAITING_ACK state
00739     if (_loramac.get_mlme_indication()->pending && !_automatic_uplink_ongoing) {
00740         tr_debug("MLME Indication pending");
00741         _loramac.post_process_mlme_ind();
00742         tr_debug("Immediate Uplink requested");
00743         mlme_indication_handler();
00744     }
00745 
00746     core_util_atomic_flag_clear(&_rx_payload_in_use);
00747 }
00748 
00749 void LoRaWANStack::process_reception_timeout(bool is_timeout)
00750 {
00751     rx_slot_t  slot = _loramac.get_current_slot();
00752 
00753     // when is_timeout == false, a CRC error took place in the received frame
00754     // we treat that erroneous frame as no frame received at all, hence handle
00755     // it exactly as we would handle timeout
00756     _loramac.on_radio_rx_timeout(is_timeout);
00757 
00758     if (slot == RX_SLOT_WIN_2  && !_loramac.nwk_joined()) {
00759         state_controller(DEVICE_STATE_JOINING);
00760         return;
00761     }
00762 
00763     /**
00764      * LoRaWAN Specification 1.0.2. Section 3.3.6
00765      * Main point:
00766      *     We indicate successful transmission
00767      * of UNCONFIRMED message after RX windows are done with.
00768      *     For a CONFIRMED message, it means that we have not received
00769      * ack (actually nothing was received), and we should retransmit if we can.
00770      *
00771      * NOTE: This code block doesn't get hit for Class C as in Class C, RX2 timeout
00772      * never occurs.
00773      */
00774     if (slot == RX_SLOT_WIN_2 ) {
00775         post_process_tx_no_reception();
00776     }
00777 }
00778 
00779 /*****************************************************************************
00780  * Private methods                                                           *
00781  ****************************************************************************/
00782 void LoRaWANStack::make_tx_metadata_available(void)
00783 {
00784     _tx_metadata.stale = false;
00785     _tx_metadata.channel = _loramac.get_mcps_confirmation()->channel ;
00786     _tx_metadata.data_rate = _loramac.get_mcps_confirmation()->data_rate ;
00787     _tx_metadata.tx_power = _loramac.get_mcps_confirmation()->tx_power ;
00788     _tx_metadata.tx_toa = _loramac.get_mcps_confirmation()->tx_toa ;
00789     _tx_metadata.nb_retries = _loramac.get_mcps_confirmation()->nb_retries ;
00790 }
00791 
00792 void LoRaWANStack::make_rx_metadata_available(void)
00793 {
00794     _rx_metadata.stale = false;
00795     _rx_metadata.rx_datarate = _loramac.get_mcps_indication()->rx_datarate ;
00796     _rx_metadata.rssi = _loramac.get_mcps_indication()->rssi ;
00797     _rx_metadata.snr = _loramac.get_mcps_indication()->snr ;
00798     _rx_metadata.channel = _loramac.get_mcps_indication()->channel ;
00799     _rx_metadata.rx_toa = _loramac.get_mcps_indication()->rx_toa ;
00800 }
00801 
00802 bool LoRaWANStack::is_port_valid(const uint8_t port, bool allow_port_0)
00803 {
00804     //Application should not use reserved and illegal port numbers.
00805     if (port == 0) {
00806         return allow_port_0;
00807     } else if (port == COMPLIANCE_TESTING_PORT) {
00808 #if !defined(LORAWAN_COMPLIANCE_TEST)
00809         return false;
00810 #endif
00811     } else {
00812         return true;
00813     }
00814 
00815     // fallback for compliance testing port if LORAWAN_COMPLIANCE_TEST
00816     // was defined
00817     return true;
00818 }
00819 
00820 lorawan_status_t LoRaWANStack::set_application_port(const uint8_t port, bool allow_port_0)
00821 {
00822     if (is_port_valid(port, allow_port_0)) {
00823         _app_port = port;
00824         return LORAWAN_STATUS_OK;
00825     }
00826 
00827     return LORAWAN_STATUS_PORT_INVALID;
00828 }
00829 
00830 void LoRaWANStack::state_machine_run_to_completion()
00831 {
00832     if (_loramac.get_device_class() == CLASS_C) {
00833         _device_current_state = DEVICE_STATE_RECEIVING;
00834         return;
00835     }
00836 
00837     _device_current_state = DEVICE_STATE_IDLE;
00838 }
00839 
00840 void LoRaWANStack::send_event_to_application(const lorawan_event_t event) const
00841 {
00842     if (_callbacks.events) {
00843         const int ret = _queue->call(_callbacks.events, event);
00844         MBED_ASSERT(ret != 0);
00845         (void)ret;
00846     }
00847 }
00848 
00849 void LoRaWANStack::send_automatic_uplink_message(const uint8_t port)
00850 {
00851     // we will silently ignore the automatic uplink event if the user is already
00852     // sending something
00853     const int16_t ret = handle_tx(port, NULL, 0, MSG_CONFIRMED_FLAG, true, true);
00854     if (ret == LORAWAN_STATUS_WOULD_BLOCK) {
00855         _automatic_uplink_ongoing = false;
00856     } else if (ret < 0) {
00857         tr_debug("Failed to generate AUTOMATIC UPLINK, error code = %d", ret);
00858         send_event_to_application(AUTOMATIC_UPLINK_ERROR);
00859     }
00860 }
00861 
00862 int LoRaWANStack::convert_to_msg_flag(const mcps_type_t type)
00863 {
00864     int msg_flag = MSG_UNCONFIRMED_FLAG;
00865     switch (type) {
00866         case MCPS_UNCONFIRMED :
00867             msg_flag = MSG_UNCONFIRMED_FLAG;
00868             break;
00869 
00870         case MCPS_CONFIRMED :
00871             msg_flag = MSG_CONFIRMED_FLAG;
00872             break;
00873 
00874         case MCPS_MULTICAST :
00875             msg_flag = MSG_MULTICAST_FLAG;
00876             break;
00877 
00878         case MCPS_PROPRIETARY :
00879             msg_flag = MSG_PROPRIETARY_FLAG;
00880             break;
00881 
00882         default:
00883             tr_error("Unknown message type!");
00884             MBED_ASSERT(0);
00885     }
00886 
00887     return msg_flag;
00888 }
00889 
00890 lorawan_status_t LoRaWANStack::handle_connect(bool is_otaa)
00891 {
00892     _ctrl_flags |= CONN_IN_PROGRESS_FLAG;
00893 
00894     if (is_otaa) {
00895         tr_debug("Initiating OTAA");
00896 
00897         // In 1.0.2 spec, counters are always set to zero for new connection.
00898         // This section is common for both normal and
00899         // connection restore at this moment. Will change in future with 1.1 support.
00900         _lw_session.downlink_counter = 0;
00901         _lw_session.uplink_counter = 0;
00902         _ctrl_flags |= USING_OTAA_FLAG;
00903     } else {
00904         // If current state is SHUTDOWN, device may be trying to re-establish
00905         // communication. In case of ABP specification is meddled about frame counters.
00906         // It says to reset counters to zero but there is no mechanism to tell the
00907         // network server that the device was disconnected or restarted.
00908         // At the moment, this implementation does not support a non-volatile
00909         // memory storage.
00910         //_lw_session.downlink_counter; //Get from NVM
00911         //_lw_session.uplink_counter; //Get from NVM
00912 
00913         tr_debug("Initiating ABP");
00914         tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu",
00915                  _lw_session.uplink_counter, _lw_session.downlink_counter);
00916         _ctrl_flags &= ~USING_OTAA_FLAG;
00917     }
00918 
00919     return state_controller(DEVICE_STATE_CONNECTING);
00920 }
00921 
00922 void LoRaWANStack::mlme_indication_handler()
00923 {
00924     if (_loramac.get_mlme_indication()->indication_type  == MLME_SCHEDULE_UPLINK ) {
00925         // The MAC signals that we shall provide an uplink as soon as possible
00926 #if MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE
00927         _automatic_uplink_ongoing = true;
00928         tr_debug("mlme indication: sending empty uplink to port 0 to acknowledge MAC commands...");
00929         const uint8_t port = 0;
00930         const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, port);
00931         MBED_ASSERT(ret != 0);
00932         (void)ret;
00933 #else
00934         send_event_to_application(UPLINK_REQUIRED);
00935 #endif
00936         return;
00937     }
00938 
00939     tr_error("Unknown MLME Indication type.");
00940 }
00941 
00942 void LoRaWANStack::mlme_confirm_handler()
00943 {
00944     if (_loramac.get_mlme_confirmation()->req_type  == MLME_LINK_CHECK ) {
00945         if (_loramac.get_mlme_confirmation()->status 
00946                 == LORAMAC_EVENT_INFO_STATUS_OK ) {
00947 
00948             if (_callbacks.link_check_resp) {
00949                 const int ret = _queue->call(
00950                                     _callbacks.link_check_resp,
00951                                     _loramac.get_mlme_confirmation()->demod_margin ,
00952                                     _loramac.get_mlme_confirmation()->nb_gateways );
00953                 MBED_ASSERT(ret != 0);
00954                 (void) ret;
00955             }
00956         }
00957     }
00958 
00959     if (_loramac.get_mlme_confirmation()->req_type  == MLME_JOIN ) {
00960 
00961         switch (_loramac.get_mlme_confirmation()->status ) {
00962             case LORAMAC_EVENT_INFO_STATUS_OK :
00963                 state_controller(DEVICE_STATE_CONNECTED);
00964                 break;
00965 
00966             case LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL :
00967                 // fatal error
00968                 _device_current_state = DEVICE_STATE_IDLE;
00969                 tr_error("Joining abandoned: CRYPTO_ERROR");
00970                 send_event_to_application(CRYPTO_ERROR);
00971                 break;
00972 
00973             case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT :
00974                 // fatal error
00975                 _device_current_state = DEVICE_STATE_IDLE;
00976                 tr_error("Joining abandoned: Radio failed to transmit");
00977                 send_event_to_application(TX_TIMEOUT);
00978                 break;
00979 
00980             default:
00981                 // non-fatal, retry if possible
00982                 _device_current_state = DEVICE_STATE_AWAITING_JOIN_ACCEPT;
00983                 state_controller(DEVICE_STATE_JOINING);
00984         }
00985     }
00986 }
00987 
00988 void LoRaWANStack::mcps_confirm_handler()
00989 {
00990     switch (_loramac.get_mcps_confirmation()->status ) {
00991 
00992         case LORAMAC_EVENT_INFO_STATUS_OK :
00993             _lw_session.uplink_counter = _loramac.get_mcps_confirmation()->ul_frame_counter ;
00994             send_event_to_application(TX_DONE);
00995             break;
00996 
00997         case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT :
00998             tr_error("Fatal Error, Radio failed to transmit");
00999             send_event_to_application(TX_TIMEOUT);
01000             break;
01001 
01002         case LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR :
01003             send_event_to_application(TX_SCHEDULING_ERROR);
01004             break;
01005 
01006         default:
01007             // if no ack was received after enough retries, send TX_ERROR
01008             send_event_to_application(TX_ERROR);
01009     }
01010 }
01011 
01012 void LoRaWANStack::mcps_indication_handler()
01013 {
01014     const loramac_mcps_indication_t  *mcps_indication = _loramac.get_mcps_indication();
01015     if (mcps_indication->status  != LORAMAC_EVENT_INFO_STATUS_OK ) {
01016         tr_error("RX_ERROR: mcps_indication status = %d", mcps_indication->status );
01017         send_event_to_application(RX_ERROR);
01018         return;
01019     }
01020 
01021     _lw_session.downlink_counter = mcps_indication->dl_frame_counter ;
01022 
01023     /**
01024      * Check port, if it's compliance testing port and the compliance testing is
01025      * not enabled, give up silently
01026      */
01027     if (mcps_indication->port  == COMPLIANCE_TESTING_PORT) {
01028 #if !defined(LORAWAN_COMPLIANCE_TEST)
01029         return;
01030 #endif
01031     }
01032 
01033     if (mcps_indication->is_data_recvd ) {
01034         // Valid message arrived.
01035         _rx_msg.type = LORAMAC_RX_MCPS_INDICATION;
01036         _rx_msg.msg.mcps_indication.buffer_size  = mcps_indication->buffer_size ;
01037         _rx_msg.msg.mcps_indication.port  = mcps_indication->port ;
01038         _rx_msg.msg.mcps_indication.buffer  = mcps_indication->buffer ;
01039         _rx_msg.msg.mcps_indication.type  = mcps_indication->type ;
01040 
01041         // Notify application about received frame..
01042         tr_debug("Packet Received %d bytes, Port=%d",
01043                  _rx_msg.msg.mcps_indication.buffer_size ,
01044                  mcps_indication->port );
01045         _rx_msg.receive_ready = true;
01046         send_event_to_application(RX_DONE);
01047     }
01048 
01049     /*
01050      * If fPending bit is set we try to generate an empty packet
01051      * with CONFIRMED flag set. We always set a CONFIRMED flag so
01052      * that we could retry a certain number of times if the uplink
01053      * failed for some reason
01054      * or
01055      * Class C and node received a confirmed message so we need to
01056      * send an empty packet to acknowledge the message.
01057      * This scenario is unspecified by LoRaWAN 1.0.2 specification,
01058      * but version 1.1.0 says that network SHALL not send any new
01059      * confirmed messages until ack has been sent
01060      */
01061     if ((_loramac.get_device_class() != CLASS_C
01062             && mcps_indication->fpending_status )
01063             || (_loramac.get_device_class() == CLASS_C
01064                 && mcps_indication->type  == MCPS_CONFIRMED )) {
01065 #if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
01066         // Do not queue an automatic uplink of there is one already outgoing
01067         // This means we have not received an ack for the previous automatic uplink
01068         if (!_automatic_uplink_ongoing) {
01069             tr_debug("Sending empty uplink message...");
01070             _automatic_uplink_ongoing = true;
01071             const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port );
01072             MBED_ASSERT(ret != 0);
01073             (void)ret;
01074         }
01075 #else
01076         send_event_to_application(UPLINK_REQUIRED);
01077 #endif
01078     }
01079 }
01080 
01081 
01082 lorawan_status_t LoRaWANStack::state_controller(device_states_t new_state)
01083 {
01084     lorawan_status_t status = LORAWAN_STATUS_OK;
01085 
01086     switch (new_state) {
01087         case DEVICE_STATE_IDLE:
01088             process_idle_state(status);
01089             break;
01090         case DEVICE_STATE_CONNECTING:
01091             process_connecting_state(status);
01092             break;
01093         case DEVICE_STATE_JOINING:
01094             process_joining_state(status);
01095             break;
01096         case DEVICE_STATE_CONNECTED:
01097             process_connected_state();
01098             break;
01099         case DEVICE_STATE_SCHEDULING:
01100             process_scheduling_state(status);
01101             break;
01102         case DEVICE_STATE_STATUS_CHECK:
01103             process_status_check_state();
01104             break;
01105         case DEVICE_STATE_SHUTDOWN:
01106             process_shutdown_state(status);
01107             break;
01108         default:
01109             //Because this is internal function only coding error causes this
01110             tr_error("Unknown state: %d:", new_state);
01111             MBED_ASSERT(false);
01112     }
01113 
01114     return status;
01115 }
01116 
01117 void LoRaWANStack::process_shutdown_state(lorawan_status_t &op_status)
01118 {
01119     /**
01120      * Remove channels
01121      * Radio will be put to sleep by the APIs underneath
01122      */
01123     drop_channel_list();
01124     _loramac.disconnect();
01125     _lw_session.active = false;
01126     _device_current_state = DEVICE_STATE_SHUTDOWN;
01127     op_status = LORAWAN_STATUS_DEVICE_OFF;
01128     _ctrl_flags = 0;
01129     send_event_to_application(DISCONNECTED);
01130 }
01131 
01132 void LoRaWANStack::process_status_check_state()
01133 {
01134     if (_device_current_state == DEVICE_STATE_SENDING ||
01135             _device_current_state == DEVICE_STATE_AWAITING_ACK) {
01136         // If there was a successful transmission, this block gets a kick after
01137         // RX2 slot is exhausted. We may or may not have a successful UNCONFIRMED transmission
01138         // here. In CONFIRMED case this block is invoked only
01139         // when the MAX number of retries are exhausted, i.e., only error
01140         // case will fall here. Moreover, it will happen for Class A only.
01141         // Another possibility is the case when the stack fails to schedule a
01142         // deferred transmission and a scheduling failure handler is invoked.
01143         _ctrl_flags &= ~TX_DONE_FLAG;
01144         _loramac.set_tx_ongoing(false);
01145         _loramac.reset_ongoing_tx();
01146         mcps_confirm_handler();
01147 
01148     } else if (_device_current_state == DEVICE_STATE_RECEIVING) {
01149 
01150         if ((_ctrl_flags & TX_DONE_FLAG) || (_ctrl_flags & RETRY_EXHAUSTED_FLAG)) {
01151             _ctrl_flags &= ~TX_DONE_FLAG;
01152             _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
01153             _loramac.set_tx_ongoing(false);
01154             _loramac.reset_ongoing_tx();
01155             // if an automatic uplink is ongoing, we should not send a TX_DONE
01156             // event to application
01157             if (_automatic_uplink_ongoing) {
01158                 _automatic_uplink_ongoing = false;
01159             } else {
01160                 mcps_confirm_handler();
01161             }
01162         }
01163 
01164         // handle any received data and send event accordingly
01165         if (_ctrl_flags & MSG_RECVD_FLAG) {
01166             _ctrl_flags &= ~MSG_RECVD_FLAG;
01167             mcps_indication_handler();
01168         }
01169     }
01170 }
01171 
01172 void LoRaWANStack::process_scheduling_state(lorawan_status_t &op_status)
01173 {
01174     if (_device_current_state != DEVICE_STATE_IDLE) {
01175         if (_device_current_state != DEVICE_STATE_RECEIVING
01176                 && _loramac.get_device_class() != CLASS_C) {
01177             op_status = LORAWAN_STATUS_BUSY;
01178             return;
01179         }
01180     }
01181 
01182     op_status = _loramac.send_ongoing_tx();
01183     if (op_status == LORAWAN_STATUS_OK) {
01184         _ctrl_flags &= ~TX_DONE_FLAG;
01185         _loramac.set_tx_ongoing(true);
01186         _device_current_state = DEVICE_STATE_SENDING;
01187     }
01188 }
01189 
01190 void LoRaWANStack::process_joining_state(lorawan_status_t &op_status)
01191 {
01192     if (_device_current_state == DEVICE_STATE_CONNECTING) {
01193         _device_current_state = DEVICE_STATE_JOINING;
01194         tr_debug("Sending Join Request ...");
01195         op_status = _loramac.join(true);
01196         return;
01197     }
01198 
01199     if (_device_current_state == DEVICE_STATE_AWAITING_JOIN_ACCEPT &&
01200             _loramac.get_current_slot() != RX_SLOT_WIN_1 ) {
01201         _device_current_state = DEVICE_STATE_JOINING;
01202         // retry join
01203         bool can_continue = _loramac.continue_joining_process();
01204 
01205         if (!can_continue) {
01206             _ctrl_flags &= ~CONN_IN_PROGRESS_FLAG;
01207             send_event_to_application(JOIN_FAILURE);
01208             _device_current_state = DEVICE_STATE_IDLE;
01209             return;
01210         }
01211     }
01212 }
01213 
01214 void LoRaWANStack::process_connected_state()
01215 {
01216     _ctrl_flags |= CONNECTED_FLAG;
01217     _ctrl_flags &= ~CONN_IN_PROGRESS_FLAG;
01218 
01219     if (_ctrl_flags & USING_OTAA_FLAG) {
01220         tr_debug("OTAA Connection OK!");
01221     }
01222 
01223     _lw_session.active = true;
01224     send_event_to_application(CONNECTED);
01225 
01226     _device_current_state = DEVICE_STATE_IDLE;
01227 }
01228 
01229 void LoRaWANStack::process_connecting_state(lorawan_status_t &op_status)
01230 {
01231     MBED_ASSERT(_device_current_state == DEVICE_STATE_IDLE ||
01232                 _device_current_state == DEVICE_STATE_SHUTDOWN);
01233 
01234     _device_current_state = DEVICE_STATE_CONNECTING;
01235 
01236     if (_ctrl_flags & USING_OTAA_FLAG) {
01237         process_joining_state(op_status);
01238         return;
01239     }
01240 
01241     op_status = _loramac.join(false);
01242     tr_debug("ABP connection OK.");
01243     process_connected_state();
01244 }
01245 
01246 void LoRaWANStack::process_idle_state(lorawan_status_t &op_status)
01247 {
01248     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
01249         _device_current_state = DEVICE_STATE_IDLE;
01250         process_uninitialized_state(op_status);
01251         return;
01252     }
01253 
01254     _device_current_state = DEVICE_STATE_IDLE;
01255     op_status = LORAWAN_STATUS_OK;
01256 }
01257 
01258 void LoRaWANStack::process_uninitialized_state(lorawan_status_t &op_status)
01259 {
01260     op_status = _loramac.initialize(_queue, mbed::callback(this,
01261                                                            &LoRaWANStack::handle_scheduling_failure));
01262 
01263     if (op_status == LORAWAN_STATUS_OK) {
01264         _device_current_state = DEVICE_STATE_IDLE;
01265     }
01266 }