Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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       _ready_for_rx(true),
00077       _queue(NULL)
00078 {
00079     _tx_metadata.stale = true;
00080     _rx_metadata.stale = true;
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 
00314     lorawan_status_t status;
00315 
00316     if (_loramac.nwk_joined() == false) {
00317         return LORAWAN_STATUS_NO_NETWORK_JOINED;
00318     }
00319 
00320     status = set_application_port(port, allow_port_0);
00321 
00322     if (status != LORAWAN_STATUS_OK) {
00323         tr_error("Illegal application port definition.");
00324         return status;
00325     }
00326 
00327     // All the flags are mutually exclusive. In addition to that MSG_MULTICAST_FLAG cannot be
00328     // used for uplink.
00329     switch (flags & MSG_FLAG_MASK) {
00330         case MSG_UNCONFIRMED_FLAG:
00331         case MSG_CONFIRMED_FLAG:
00332         case MSG_PROPRIETARY_FLAG:
00333             break;
00334 
00335         default:
00336             tr_error("Invalid send flags");
00337             return LORAWAN_STATUS_PARAMETER_INVALID;
00338     }
00339 
00340     int16_t len = _loramac.prepare_ongoing_tx(port, data, length, flags, _num_retry);
00341 
00342     status = state_controller(DEVICE_STATE_SCHEDULING);
00343 
00344     // send user the length of data which is scheduled now.
00345     // user should take care of the pending data.
00346     return (status == LORAWAN_STATUS_OK) ? len : (int16_t) status;
00347 }
00348 
00349 int16_t LoRaWANStack::handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params)
00350 {
00351     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
00352         return LORAWAN_STATUS_NOT_INITIALIZED;
00353     }
00354 
00355     if (!_lw_session.active) {
00356         return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
00357     }
00358 
00359     // No messages to read.
00360     if (!_rx_msg.receive_ready) {
00361         return LORAWAN_STATUS_WOULD_BLOCK;
00362     }
00363 
00364     if (data == NULL || length == 0) {
00365         return LORAWAN_STATUS_PARAMETER_INVALID;
00366     }
00367 
00368     int received_flags = convert_to_msg_flag(_rx_msg.msg.mcps_indication.type);
00369     if (validate_params) {
00370         // Check received message port and flags match with the ones requested by user
00371         received_flags &= MSG_FLAG_MASK;
00372 
00373         if (_rx_msg.msg.mcps_indication.port != port || !(flags & received_flags)) {
00374             return LORAWAN_STATUS_WOULD_BLOCK;
00375         }
00376     }
00377 
00378     // Report values back to user
00379     port = _rx_msg.msg.mcps_indication.port;
00380     flags = received_flags;
00381 
00382     const uint8_t *base_ptr = _rx_msg.msg.mcps_indication.buffer;
00383     uint16_t base_size = _rx_msg.msg.mcps_indication.buffer_size;
00384     bool read_complete = false;
00385 
00386     if (_rx_msg.pending_size == 0) {
00387         _rx_msg.pending_size = _rx_msg.msg.mcps_indication.buffer_size;
00388         _rx_msg.prev_read_size = 0;
00389     }
00390 
00391     // check the length of received message whether we can fit into user
00392     // buffer completely or not
00393     if (_rx_msg.prev_read_size == 0 && _rx_msg.msg.mcps_indication.buffer_size <= length) {
00394         memcpy(data, base_ptr, base_size);
00395         read_complete = true;
00396     } else if (_rx_msg.pending_size > length) {
00397         _rx_msg.pending_size = _rx_msg.pending_size - length;
00398         base_size = length;
00399         memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size);
00400         _rx_msg.prev_read_size += base_size;
00401     } else {
00402         base_size = _rx_msg.pending_size;
00403         memcpy(data, base_ptr + _rx_msg.prev_read_size, base_size);
00404         read_complete = true;
00405     }
00406 
00407     if (read_complete) {
00408         _rx_msg.msg.mcps_indication.buffer = NULL;
00409         _rx_msg.msg.mcps_indication.buffer_size = 0;
00410         _rx_msg.pending_size = 0;
00411         _rx_msg.receive_ready = false;
00412     }
00413 
00414     return base_size;
00415 }
00416 
00417 lorawan_status_t LoRaWANStack::set_link_check_request()
00418 {
00419     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00420         return LORAWAN_STATUS_NOT_INITIALIZED;
00421     }
00422 
00423     if (!_callbacks.link_check_resp) {
00424         tr_error("Must assign a callback function for link check request. ");
00425         return LORAWAN_STATUS_PARAMETER_INVALID;
00426     }
00427 
00428     _link_check_requested = true;
00429     return LORAWAN_STATUS_OK;
00430 }
00431 
00432 void LoRaWANStack::remove_link_check_request()
00433 {
00434     _link_check_requested = false;
00435 }
00436 
00437 lorawan_status_t LoRaWANStack::shutdown()
00438 {
00439     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00440         return LORAWAN_STATUS_NOT_INITIALIZED;
00441     }
00442 
00443     return state_controller(DEVICE_STATE_SHUTDOWN);
00444 }
00445 
00446 lorawan_status_t LoRaWANStack::set_device_class(const device_class_t &device_class)
00447 {
00448     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00449         return LORAWAN_STATUS_NOT_INITIALIZED;
00450     }
00451 
00452     if (device_class == CLASS_B) {
00453         return LORAWAN_STATUS_UNSUPPORTED;
00454     }
00455     _loramac.set_device_class(device_class,
00456                               mbed::callback(this, &LoRaWANStack::post_process_tx_no_reception));
00457     return LORAWAN_STATUS_OK;
00458 }
00459 
00460 lorawan_status_t  LoRaWANStack::acquire_tx_metadata(lorawan_tx_metadata &tx_metadata)
00461 {
00462     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00463         return LORAWAN_STATUS_NOT_INITIALIZED;
00464     }
00465 
00466     if (!_tx_metadata.stale) {
00467         tx_metadata = _tx_metadata;
00468         _tx_metadata.stale = true;
00469         return LORAWAN_STATUS_OK;
00470     }
00471 
00472     return LORAWAN_STATUS_METADATA_NOT_AVAILABLE;
00473 }
00474 
00475 lorawan_status_t LoRaWANStack::acquire_rx_metadata(lorawan_rx_metadata &metadata)
00476 {
00477     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00478         return LORAWAN_STATUS_NOT_INITIALIZED;
00479     }
00480 
00481     if (!_rx_metadata.stale) {
00482         metadata = _rx_metadata;
00483         _rx_metadata.stale = true;
00484         return LORAWAN_STATUS_OK;
00485     }
00486 
00487     return LORAWAN_STATUS_METADATA_NOT_AVAILABLE;
00488 }
00489 
00490 lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int &backoff)
00491 {
00492     if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
00493         return LORAWAN_STATUS_NOT_INITIALIZED;
00494     }
00495 
00496     int id = _loramac.get_backoff_timer_event_id();
00497 
00498     if (_loramac.get_backoff_timer_event_id() > 0) {
00499         backoff = _queue->time_left(id);
00500         return LORAWAN_STATUS_OK;
00501     }
00502 
00503     backoff = -1;
00504     return LORAWAN_STATUS_METADATA_NOT_AVAILABLE;
00505 }
00506 
00507 /*****************************************************************************
00508  * Interrupt handlers                                                        *
00509  ****************************************************************************/
00510 void LoRaWANStack::tx_interrupt_handler(void)
00511 {
00512     _tx_timestamp = _loramac.get_current_time();
00513     const int ret = _queue->call(this, &LoRaWANStack::process_transmission);
00514     MBED_ASSERT(ret != 0);
00515     (void)ret;
00516 }
00517 
00518 void LoRaWANStack::rx_interrupt_handler(const uint8_t *payload, uint16_t size,
00519                                         int16_t rssi, int8_t snr)
00520 {
00521     if (!_ready_for_rx || size > sizeof _rx_payload) {
00522         return;
00523     }
00524 
00525     _ready_for_rx = false;
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                 state_controller(DEVICE_STATE_STATUS_CHECK);
00617             }
00618         }
00619     } else {
00620         // handle UNCONFIRMED case here, RX slots were turned off due to
00621         // valid packet reception.
00622         uint8_t prev_QOS_level = _loramac.get_prev_QOS_level();
00623         uint8_t QOS_level = _loramac.get_QOS_level();
00624 
00625         // We will not apply QOS on the post-processing of the previous
00626         // outgoing message as we would have received QOS instruction in response
00627         // to that particular message
00628         if (QOS_level > LORAWAN_DEFAULT_QOS && _qos_cnt < QOS_level
00629                 && (prev_QOS_level == QOS_level)) {
00630             _ctrl_flags &= ~TX_DONE_FLAG;
00631             const int ret = _queue->call(this, &LoRaWANStack::state_controller,
00632                                          DEVICE_STATE_SCHEDULING);
00633             MBED_ASSERT(ret != 0);
00634             (void) ret;
00635             _qos_cnt++;
00636             tr_info("QOS: repeated transmission #%d queued", _qos_cnt);
00637         } else {
00638             _loramac.post_process_mcps_req();
00639             _ctrl_flags |= TX_DONE_FLAG;
00640             make_tx_metadata_available();
00641             state_controller(DEVICE_STATE_STATUS_CHECK);
00642         }
00643     }
00644 }
00645 
00646 void LoRaWANStack::post_process_tx_no_reception()
00647 {
00648     if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED ) {
00649         if (_loramac.continue_sending_process()) {
00650             _ctrl_flags &= ~TX_DONE_FLAG;
00651             _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
00652             return;
00653         }
00654 
00655         tr_error("Retries exhausted for Class %s device",
00656                  _loramac.get_device_class() == CLASS_A ? "A" : "C");
00657         _ctrl_flags &= ~TX_DONE_FLAG;
00658         _ctrl_flags |= RETRY_EXHAUSTED_FLAG;
00659     } else {
00660         _ctrl_flags |= TX_DONE_FLAG;
00661 
00662         uint8_t prev_QOS_level = _loramac.get_prev_QOS_level();
00663         uint8_t QOS_level = _loramac.get_QOS_level();
00664 
00665         if (QOS_level > LORAWAN_DEFAULT_QOS && (prev_QOS_level == QOS_level)) {
00666             if (_qos_cnt < QOS_level) {
00667                 const int ret = _queue->call(this, &LoRaWANStack::state_controller,
00668                                              DEVICE_STATE_SCHEDULING);
00669                 MBED_ASSERT(ret != 0);
00670                 (void)ret;
00671                 _qos_cnt++;
00672                 tr_info("QOS: repeated transmission #%d queued", _qos_cnt);
00673                 state_machine_run_to_completion();
00674                 return;
00675             }
00676         }
00677     }
00678 
00679     _loramac.post_process_mcps_req();
00680     make_tx_metadata_available();
00681     state_controller(DEVICE_STATE_STATUS_CHECK);
00682     state_machine_run_to_completion();
00683 }
00684 
00685 void LoRaWANStack::handle_scheduling_failure(void)
00686 {
00687     tr_error("Failed to schedule transmission");
00688     state_controller(DEVICE_STATE_STATUS_CHECK);
00689     state_machine_run_to_completion();
00690 }
00691 
00692 
00693 void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size,
00694                                      int16_t rssi, int8_t snr)
00695 {
00696     _device_current_state = DEVICE_STATE_RECEIVING;
00697 
00698     _ctrl_flags &= ~MSG_RECVD_FLAG;
00699     _ctrl_flags &= ~TX_DONE_FLAG;
00700     _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
00701 
00702     _loramac.on_radio_rx_done(payload, size, rssi, snr);
00703 
00704     if (_loramac.get_mlme_confirmation()->pending) {
00705         _loramac.post_process_mlme_request();
00706         mlme_confirm_handler();
00707 
00708         if (_loramac.get_mlme_confirmation()->req_type == MLME_JOIN ) {
00709             _ready_for_rx = true;
00710             return;
00711         }
00712     }
00713 
00714     if (!_loramac.nwk_joined()) {
00715         _ready_for_rx = true;
00716         return;
00717     }
00718 
00719     make_rx_metadata_available();
00720 
00721     // Post process transmission in response to the reception
00722     post_process_tx_with_reception();
00723 
00724     // handle any pending MCPS indication
00725     if (_loramac.get_mcps_indication()->pending) {
00726         _loramac.post_process_mcps_ind();
00727         _ctrl_flags |= MSG_RECVD_FLAG;
00728         state_controller(DEVICE_STATE_STATUS_CHECK);
00729     }
00730 
00731     // complete the cycle only if TX_DONE_FLAG is set
00732     if (_ctrl_flags & TX_DONE_FLAG) {
00733         state_machine_run_to_completion();
00734     }
00735 
00736     // suppress auto uplink if another auto-uplink is in AWAITING_ACK state
00737     if (_loramac.get_mlme_indication()->pending && !_automatic_uplink_ongoing) {
00738         tr_debug("MLME Indication pending");
00739         _loramac.post_process_mlme_ind();
00740         tr_debug("Immediate Uplink requested");
00741         mlme_indication_handler();
00742     }
00743 
00744     _ready_for_rx = true;
00745 }
00746 
00747 void LoRaWANStack::process_reception_timeout(bool is_timeout)
00748 {
00749     rx_slot_t  slot = _loramac.get_current_slot();
00750 
00751     // when is_timeout == false, a CRC error took place in the received frame
00752     // we treat that erroneous frame as no frame received at all, hence handle
00753     // it exactly as we would handle timeout
00754     _loramac.on_radio_rx_timeout(is_timeout);
00755 
00756     if (slot == RX_SLOT_WIN_2  && !_loramac.nwk_joined()) {
00757         state_controller(DEVICE_STATE_JOINING);
00758         return;
00759     }
00760 
00761     /**
00762      * LoRaWAN Specification 1.0.2. Section 3.3.6
00763      * Main point:
00764      *     We indicate successful transmission
00765      * of UNCONFIRMED message after RX windows are done with.
00766      *     For a CONFIRMED message, it means that we have not received
00767      * ack (actually nothing was received), and we should retransmit if we can.
00768      *
00769      * NOTE: This code block doesn't get hit for Class C as in Class C, RX2 timeout
00770      * never occurs.
00771      */
00772     if (slot == RX_SLOT_WIN_2 ) {
00773         post_process_tx_no_reception();
00774     }
00775 }
00776 
00777 /*****************************************************************************
00778  * Private methods                                                           *
00779  ****************************************************************************/
00780 void LoRaWANStack::make_tx_metadata_available(void)
00781 {
00782     _tx_metadata.stale = false;
00783     _tx_metadata.channel = _loramac.get_mcps_confirmation()->channel;
00784     _tx_metadata.data_rate = _loramac.get_mcps_confirmation()->data_rate;
00785     _tx_metadata.tx_power = _loramac.get_mcps_confirmation()->tx_power;
00786     _tx_metadata.tx_toa = _loramac.get_mcps_confirmation()->tx_toa;
00787     _tx_metadata.nb_retries = _loramac.get_mcps_confirmation()->nb_retries;
00788 }
00789 
00790 void LoRaWANStack::make_rx_metadata_available(void)
00791 {
00792     _rx_metadata.stale = false;
00793     _rx_metadata.rx_datarate = _loramac.get_mcps_indication()->rx_datarate;
00794     _rx_metadata.rssi = _loramac.get_mcps_indication()->rssi;
00795     _rx_metadata.snr = _loramac.get_mcps_indication()->snr;
00796 }
00797 
00798 bool LoRaWANStack::is_port_valid(const uint8_t port, bool allow_port_0)
00799 {
00800     //Application should not use reserved and illegal port numbers.
00801     if (port == 0) {
00802         return allow_port_0;
00803     } else if (port == COMPLIANCE_TESTING_PORT){
00804 #if !defined(LORAWAN_COMPLIANCE_TEST)
00805         return false;
00806 #endif
00807     } else {
00808         return true;
00809     }
00810 
00811     // fallback for compliance testing port if LORAWAN_COMPLIANCE_TEST
00812     // was defined
00813     return true;
00814 }
00815 
00816 lorawan_status_t LoRaWANStack::set_application_port(const uint8_t port, bool allow_port_0)
00817 {
00818     if (is_port_valid(port, allow_port_0)) {
00819         _app_port = port;
00820         return LORAWAN_STATUS_OK;
00821     }
00822 
00823     return LORAWAN_STATUS_PORT_INVALID;
00824 }
00825 
00826 void LoRaWANStack::state_machine_run_to_completion()
00827 {
00828     if (_loramac.get_device_class() == CLASS_C) {
00829         _device_current_state = DEVICE_STATE_RECEIVING;
00830         return;
00831     }
00832 
00833     _device_current_state = DEVICE_STATE_IDLE;
00834 }
00835 
00836 void LoRaWANStack::send_event_to_application(const lorawan_event_t event) const
00837 {
00838     if (_callbacks.events) {
00839         const int ret = _queue->call(_callbacks.events, event);
00840         MBED_ASSERT(ret != 0);
00841         (void)ret;
00842     }
00843 }
00844 
00845 void LoRaWANStack::send_automatic_uplink_message(const uint8_t port)
00846 {
00847     // we will silently ignore the automatic uplink event if the user is already
00848     // sending something
00849     const int16_t ret = handle_tx(port, NULL, 0, MSG_CONFIRMED_FLAG, true, true);
00850     if (ret == LORAWAN_STATUS_WOULD_BLOCK) {
00851         _automatic_uplink_ongoing = false;
00852     } else if (ret < 0) {
00853         tr_debug("Failed to generate AUTOMATIC UPLINK, error code = %d", ret);
00854         send_event_to_application(AUTOMATIC_UPLINK_ERROR);
00855     }
00856 }
00857 
00858 int LoRaWANStack::convert_to_msg_flag(const mcps_type_t type)
00859 {
00860     int msg_flag = MSG_UNCONFIRMED_FLAG;
00861     switch (type) {
00862         case MCPS_UNCONFIRMED :
00863             msg_flag = MSG_UNCONFIRMED_FLAG;
00864             break;
00865 
00866         case MCPS_CONFIRMED :
00867             msg_flag = MSG_CONFIRMED_FLAG;
00868             break;
00869 
00870         case MCPS_MULTICAST :
00871             msg_flag = MSG_MULTICAST_FLAG;
00872             break;
00873 
00874         case MCPS_PROPRIETARY :
00875             msg_flag = MSG_PROPRIETARY_FLAG;
00876             break;
00877 
00878         default:
00879             tr_error("Unknown message type!");
00880             MBED_ASSERT(0);
00881     }
00882 
00883     return msg_flag;
00884 }
00885 
00886 lorawan_status_t LoRaWANStack::handle_connect(bool is_otaa)
00887 {
00888     _ctrl_flags |= CONN_IN_PROGRESS_FLAG;
00889 
00890     if (is_otaa) {
00891         tr_debug("Initiating OTAA");
00892 
00893         // In 1.0.2 spec, counters are always set to zero for new connection.
00894         // This section is common for both normal and
00895         // connection restore at this moment. Will change in future with 1.1 support.
00896         _lw_session.downlink_counter = 0;
00897         _lw_session.uplink_counter = 0;
00898         _ctrl_flags |= USING_OTAA_FLAG;
00899     } else {
00900         // If current state is SHUTDOWN, device may be trying to re-establish
00901         // communication. In case of ABP specification is meddled about frame counters.
00902         // It says to reset counters to zero but there is no mechanism to tell the
00903         // network server that the device was disconnected or restarted.
00904         // At the moment, this implementation does not support a non-volatile
00905         // memory storage.
00906         //_lw_session.downlink_counter; //Get from NVM
00907         //_lw_session.uplink_counter; //Get from NVM
00908 
00909         tr_debug("Initiating ABP");
00910         tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu",
00911                  _lw_session.uplink_counter, _lw_session.downlink_counter);
00912         _ctrl_flags &= ~USING_OTAA_FLAG;
00913     }
00914 
00915     return state_controller(DEVICE_STATE_CONNECTING);
00916 }
00917 
00918 void LoRaWANStack::mlme_indication_handler()
00919 {
00920     if (_loramac.get_mlme_indication()->indication_type == MLME_SCHEDULE_UPLINK ) {
00921         // The MAC signals that we shall provide an uplink as soon as possible
00922 #if MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE
00923         _automatic_uplink_ongoing = true;
00924         tr_debug("mlme indication: sending empty uplink to port 0 to acknowledge MAC commands...");
00925         const uint8_t port = 0;
00926         const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, port);
00927         MBED_ASSERT(ret != 0);
00928         (void)ret;
00929 #else
00930         send_event_to_application(UPLINK_REQUIRED);
00931 #endif
00932         return;
00933     }
00934 
00935     tr_error("Unknown MLME Indication type.");
00936 }
00937 
00938 void LoRaWANStack::mlme_confirm_handler()
00939 {
00940     if (_loramac.get_mlme_confirmation()->req_type == MLME_LINK_CHECK ) {
00941         if (_loramac.get_mlme_confirmation()->status
00942                 == LORAMAC_EVENT_INFO_STATUS_OK ) {
00943 
00944             if (_callbacks.link_check_resp) {
00945                 const int ret = _queue->call(
00946                         _callbacks.link_check_resp,
00947                         _loramac.get_mlme_confirmation()->demod_margin,
00948                         _loramac.get_mlme_confirmation()->nb_gateways);
00949                 MBED_ASSERT(ret != 0);
00950                 (void) ret;
00951             }
00952         }
00953     }
00954 
00955     if (_loramac.get_mlme_confirmation()->req_type == MLME_JOIN ) {
00956 
00957         switch (_loramac.get_mlme_confirmation()->status) {
00958             case LORAMAC_EVENT_INFO_STATUS_OK :
00959                 state_controller(DEVICE_STATE_CONNECTED);
00960                 break;
00961 
00962             case LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL :
00963                 // fatal error
00964                 _device_current_state = DEVICE_STATE_IDLE;
00965                 tr_error("Joining abandoned: CRYPTO_ERROR");
00966                 send_event_to_application(CRYPTO_ERROR);
00967                 break;
00968 
00969             case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT :
00970                 // fatal error
00971                 _device_current_state = DEVICE_STATE_IDLE;
00972                 tr_error("Joining abandoned: Radio failed to transmit");
00973                 send_event_to_application(TX_TIMEOUT);
00974                 break;
00975 
00976             default:
00977                 // non-fatal, retry if possible
00978                 _device_current_state = DEVICE_STATE_AWAITING_JOIN_ACCEPT;
00979                 state_controller(DEVICE_STATE_JOINING);
00980         }
00981     }
00982 }
00983 
00984 void LoRaWANStack::mcps_confirm_handler()
00985 {
00986     switch (_loramac.get_mcps_confirmation()->status) {
00987 
00988         case LORAMAC_EVENT_INFO_STATUS_OK :
00989             _lw_session.uplink_counter = _loramac.get_mcps_confirmation()->ul_frame_counter;
00990             send_event_to_application(TX_DONE);
00991             break;
00992 
00993         case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT :
00994             tr_error("Fatal Error, Radio failed to transmit");
00995             send_event_to_application(TX_TIMEOUT);
00996             break;
00997 
00998         case LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR :
00999             send_event_to_application(TX_SCHEDULING_ERROR);
01000             break;
01001 
01002         default:
01003             // if no ack was received after enough retries, send TX_ERROR
01004             send_event_to_application(TX_ERROR);
01005     }
01006 }
01007 
01008 void LoRaWANStack::mcps_indication_handler()
01009 {
01010     const loramac_mcps_indication_t  *mcps_indication = _loramac.get_mcps_indication();
01011     if (mcps_indication->status  != LORAMAC_EVENT_INFO_STATUS_OK ) {
01012         tr_error("RX_ERROR: mcps_indication status = %d", mcps_indication->status );
01013         send_event_to_application(RX_ERROR);
01014         return;
01015     }
01016 
01017     _lw_session.downlink_counter = mcps_indication->dl_frame_counter ;
01018 
01019     /**
01020      * Check port, if it's compliance testing port and the compliance testing is
01021      * not enabled, give up silently
01022      */
01023     if (mcps_indication->port  == COMPLIANCE_TESTING_PORT) {
01024 #if !defined(LORAWAN_COMPLIANCE_TEST)
01025         return;
01026 #endif
01027     }
01028 
01029     if (mcps_indication->is_data_recvd ) {
01030         // Valid message arrived.
01031         _rx_msg.type = LORAMAC_RX_MCPS_INDICATION;
01032         _rx_msg.msg.mcps_indication.buffer_size = mcps_indication->buffer_size ;
01033         _rx_msg.msg.mcps_indication.port = mcps_indication->port ;
01034         _rx_msg.msg.mcps_indication.buffer = mcps_indication->buffer ;
01035         _rx_msg.msg.mcps_indication.type = mcps_indication->type ;
01036 
01037         // Notify application about received frame..
01038         tr_debug("Packet Received %d bytes, Port=%d",
01039                  _rx_msg.msg.mcps_indication.buffer_size,
01040                  mcps_indication->port );
01041         _rx_msg.receive_ready = true;
01042         send_event_to_application(RX_DONE);
01043     }
01044 
01045     /*
01046      * If fPending bit is set we try to generate an empty packet
01047      * with CONFIRMED flag set. We always set a CONFIRMED flag so
01048      * that we could retry a certain number of times if the uplink
01049      * failed for some reason
01050      * or
01051      * Class C and node received a confirmed message so we need to
01052      * send an empty packet to acknowledge the message.
01053      * This scenario is unspecified by LoRaWAN 1.0.2 specification,
01054      * but version 1.1.0 says that network SHALL not send any new
01055      * confirmed messages until ack has been sent
01056      */
01057     if ((_loramac.get_device_class() != CLASS_C
01058             && mcps_indication->fpending_status )
01059             || (_loramac.get_device_class() == CLASS_C
01060                     && mcps_indication->type  == MCPS_CONFIRMED )) {
01061 #if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
01062             // Do not queue an automatic uplink of there is one already outgoing
01063             // This means we have not received an ack for the previous automatic uplink
01064             if (!_automatic_uplink_ongoing) {
01065                 tr_debug("Sending empty uplink message...");
01066                 _automatic_uplink_ongoing = true;
01067                 const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port );
01068                 MBED_ASSERT(ret != 0);
01069                 (void)ret;
01070             }
01071 #else
01072         send_event_to_application(UPLINK_REQUIRED);
01073 #endif
01074     }
01075 }
01076 
01077 
01078 lorawan_status_t LoRaWANStack::state_controller(device_states_t new_state)
01079 {
01080     lorawan_status_t status = LORAWAN_STATUS_OK;
01081 
01082     switch (new_state) {
01083         case DEVICE_STATE_IDLE:
01084             process_idle_state(status);
01085             break;
01086         case DEVICE_STATE_CONNECTING:
01087             process_connecting_state(status);
01088             break;
01089         case DEVICE_STATE_JOINING:
01090             process_joining_state(status);
01091             break;
01092         case DEVICE_STATE_CONNECTED:
01093             process_connected_state();
01094             break;
01095         case DEVICE_STATE_SCHEDULING:
01096             process_scheduling_state(status);
01097             break;
01098         case DEVICE_STATE_STATUS_CHECK:
01099             process_status_check_state();
01100             break;
01101         case DEVICE_STATE_SHUTDOWN:
01102             process_shutdown_state(status);
01103             break;
01104         default:
01105             //Because this is internal function only coding error causes this
01106             tr_error("Unknown state: %d:", new_state);
01107             MBED_ASSERT(false);
01108     }
01109 
01110     return status;
01111 }
01112 
01113 void LoRaWANStack::process_shutdown_state(lorawan_status_t &op_status)
01114 {
01115     /**
01116      * Remove channels
01117      * Radio will be put to sleep by the APIs underneath
01118      */
01119     drop_channel_list();
01120     _loramac.disconnect();
01121     _lw_session.active = false;
01122     _device_current_state = DEVICE_STATE_SHUTDOWN;
01123     op_status = LORAWAN_STATUS_DEVICE_OFF;
01124     _ctrl_flags = 0;
01125     send_event_to_application(DISCONNECTED);
01126 }
01127 
01128 void LoRaWANStack::process_status_check_state()
01129 {
01130     if (_device_current_state == DEVICE_STATE_SENDING ||
01131             _device_current_state == DEVICE_STATE_AWAITING_ACK) {
01132         // If there was a successful transmission, this block gets a kick after
01133         // RX2 slot is exhausted. We may or may not have a successful UNCONFIRMED transmission
01134         // here. In CONFIRMED case this block is invoked only
01135         // when the MAX number of retries are exhausted, i.e., only error
01136         // case will fall here. Moreover, it will happen for Class A only.
01137         // Another possibility is the case when the stack fails to schedule a
01138         // deferred transmission and a scheduling failure handler is invoked.
01139         _ctrl_flags &= ~TX_DONE_FLAG;
01140         _loramac.set_tx_ongoing(false);
01141         _loramac.reset_ongoing_tx();
01142         mcps_confirm_handler();
01143 
01144     } else if (_device_current_state == DEVICE_STATE_RECEIVING) {
01145 
01146         if ((_ctrl_flags & TX_DONE_FLAG) || (_ctrl_flags & RETRY_EXHAUSTED_FLAG)) {
01147             _ctrl_flags &= ~TX_DONE_FLAG;
01148             _ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
01149             _loramac.set_tx_ongoing(false);
01150             _loramac.reset_ongoing_tx();
01151             // if an automatic uplink is ongoing, we should not send a TX_DONE
01152             // event to application
01153             if (_automatic_uplink_ongoing) {
01154                 _automatic_uplink_ongoing = false;
01155             } else {
01156                 mcps_confirm_handler();
01157             }
01158         }
01159 
01160         // handle any received data and send event accordingly
01161         if (_ctrl_flags & MSG_RECVD_FLAG) {
01162             _ctrl_flags &= ~MSG_RECVD_FLAG;
01163             mcps_indication_handler();
01164         }
01165     }
01166 }
01167 
01168 void LoRaWANStack::process_scheduling_state(lorawan_status_t &op_status)
01169 {
01170     if (_device_current_state != DEVICE_STATE_IDLE) {
01171         if (_device_current_state != DEVICE_STATE_RECEIVING
01172                 && _loramac.get_device_class() != CLASS_C) {
01173             op_status = LORAWAN_STATUS_BUSY;
01174             return;
01175         }
01176     }
01177 
01178     op_status = _loramac.send_ongoing_tx();
01179     if (op_status == LORAWAN_STATUS_OK) {
01180         _ctrl_flags &= ~TX_DONE_FLAG;
01181         _loramac.set_tx_ongoing(true);
01182         _device_current_state = DEVICE_STATE_SENDING;
01183     }
01184 }
01185 
01186 void LoRaWANStack::process_joining_state(lorawan_status_t &op_status)
01187 {
01188     if (_device_current_state == DEVICE_STATE_CONNECTING) {
01189         _device_current_state = DEVICE_STATE_JOINING;
01190         tr_debug("Sending Join Request ...");
01191         op_status = _loramac.join(true);
01192         return;
01193     }
01194 
01195     if (_device_current_state == DEVICE_STATE_AWAITING_JOIN_ACCEPT &&
01196         _loramac.get_current_slot() != RX_SLOT_WIN_1 ) {
01197         _device_current_state = DEVICE_STATE_JOINING;
01198         // retry join
01199         bool can_continue = _loramac.continue_joining_process();
01200 
01201         if (!can_continue) {
01202             _ctrl_flags &= ~CONN_IN_PROGRESS_FLAG;
01203             send_event_to_application(JOIN_FAILURE);
01204             _device_current_state = DEVICE_STATE_IDLE;
01205             return;
01206         }
01207     }
01208 }
01209 
01210 void LoRaWANStack::process_connected_state()
01211 {
01212     _ctrl_flags |= CONNECTED_FLAG;
01213     _ctrl_flags &= ~CONN_IN_PROGRESS_FLAG;
01214 
01215     if (_ctrl_flags & USING_OTAA_FLAG) {
01216         tr_debug("OTAA Connection OK!");
01217     }
01218 
01219     _lw_session.active = true;
01220     send_event_to_application(CONNECTED);
01221 
01222     _device_current_state = DEVICE_STATE_IDLE;
01223 }
01224 
01225 void LoRaWANStack::process_connecting_state(lorawan_status_t &op_status)
01226 {
01227     MBED_ASSERT(_device_current_state == DEVICE_STATE_IDLE ||
01228                 _device_current_state == DEVICE_STATE_SHUTDOWN);
01229 
01230     _device_current_state = DEVICE_STATE_CONNECTING;
01231 
01232     if (_ctrl_flags & USING_OTAA_FLAG) {
01233         process_joining_state(op_status);
01234         return;
01235     }
01236 
01237     op_status = _loramac.join(false);
01238     tr_debug("ABP connection OK.");
01239     process_connected_state();
01240 }
01241 
01242 void LoRaWANStack::process_idle_state(lorawan_status_t &op_status)
01243 {
01244     if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
01245         _device_current_state = DEVICE_STATE_IDLE;
01246         process_uninitialized_state(op_status);
01247         return;
01248     }
01249 
01250     _device_current_state = DEVICE_STATE_IDLE;
01251     op_status = LORAWAN_STATUS_OK;
01252 }
01253 
01254 void LoRaWANStack::process_uninitialized_state(lorawan_status_t &op_status)
01255 {
01256     op_status = _loramac.initialize(_queue, mbed::callback(this,
01257                                                            &LoRaWANStack::handle_scheduling_failure));
01258 
01259     if (op_status == LORAWAN_STATUS_OK) {
01260         _device_current_state = DEVICE_STATE_IDLE;
01261     }
01262 }