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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 }
Generated on Tue Jul 12 2022 13:54:27 by
