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.
Dependencies: nRF51_Vdd TextLCD BME280
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 }
Generated on Tue Jul 12 2022 15:15:48 by
