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