init
Embed:
(wiki syntax)
Show/hide line numbers
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 #include "lorawan/LoRaWANStack.h" 00031 #if defined(FEATURE_COMMON_PAL) 00032 #include "mbed_trace.h" 00033 #define TRACE_GROUP "LSTK" 00034 #else 00035 #define tr_debug(...) (void(0)) //dummies if feature common pal is not added 00036 #define tr_info(...) (void(0)) //dummies if feature common pal is not added 00037 #define tr_error(...) (void(0)) //dummies if feature common pal is not added 00038 #define tr_warn(...) (void(0)) //dummies if feature common pal is not added 00039 #endif //defined(FEATURE_COMMON_PAL) 00040 00041 #define INVALID_PORT 0xFF 00042 #define MAX_CONFIRMED_MSG_RETRIES 255 00043 00044 using namespace mbed; 00045 using namespace events; 00046 00047 #if defined(LORAWAN_COMPLIANCE_TEST) 00048 /** 00049 * 00050 * User application data buffer size if compliance test is used 00051 */ 00052 #if (MBED_CONF_LORA_PHY == 0 || MBED_CONF_LORA_PHY == 4 || MBED_CONF_LORA_PHY == 6 || MBED_CONF_LORA_PHY == 7) 00053 #define LORAWAN_COMPLIANCE_TEST_DATA_SIZE 16 00054 #elif (MBED_CONF_LORA_PHY == 1 || MBED_CONF_LORA_PHY == 2 || MBED_CONF_LORA_PHY == 8 || MBED_CONF_LORA_PHY == 9) 00055 #define LORAWAN_COMPLIANCE_TEST_DATA_SIZE 11 00056 #else 00057 #error "Must set LoRa PHY layer parameters." 00058 #endif 00059 #endif 00060 00061 /***************************************************************************** 00062 * Private Member Functions * 00063 ****************************************************************************/ 00064 bool LoRaWANStack::is_port_valid(uint8_t port) 00065 { 00066 //Application should not use reserved and illegal port numbers. 00067 if (port >= 224 || port == 0) { 00068 return false; 00069 } else { 00070 return true; 00071 } 00072 } 00073 00074 lorawan_status_t LoRaWANStack::set_application_port(uint8_t port) 00075 { 00076 if (is_port_valid(port)) { 00077 _app_port = port; 00078 return LORAWAN_STATUS_OK; 00079 } 00080 00081 return LORAWAN_STATUS_PORT_INVALID; 00082 } 00083 00084 /***************************************************************************** 00085 * Constructor and destructor * 00086 ****************************************************************************/ 00087 LoRaWANStack::LoRaWANStack() 00088 : _loramac(_lora_time), _lora_phy(_lora_time), 00089 _device_current_state(DEVICE_STATE_NOT_INITIALIZED), _mac_handlers(NULL), 00090 _num_retry(1), _queue(NULL), _duty_cycle_on(MBED_CONF_LORA_DUTY_CYCLE_ON) 00091 { 00092 #ifdef MBED_CONF_LORA_APP_PORT 00093 // is_port_valid() is not virtual, so we can call it in constructor 00094 if (is_port_valid(MBED_CONF_LORA_APP_PORT)) { 00095 _app_port = MBED_CONF_LORA_APP_PORT; 00096 } else { 00097 tr_error("User defined port in .json is illegal."); 00098 _app_port = INVALID_PORT; 00099 } 00100 00101 #else 00102 // initialize it to INVALID_PORT (255) an illegal port number. 00103 // user should set the port 00104 _app_port = INVALID_PORT; 00105 #endif 00106 00107 memset(&_lw_session, 0, sizeof(_lw_session)); 00108 memset(&_tx_msg, 0, sizeof(_tx_msg)); 00109 memset(&_rx_msg, 0, sizeof(_rx_msg)); 00110 00111 LoRaMacPrimitives.mcps_confirm = callback(this, &LoRaWANStack::mcps_confirm_handler); 00112 LoRaMacPrimitives.mcps_indication = callback(this, &LoRaWANStack::mcps_indication_handler); 00113 LoRaMacPrimitives.mlme_confirm = callback(this, &LoRaWANStack::mlme_confirm_handler); 00114 LoRaMacPrimitives.mlme_indication = callback(this, &LoRaWANStack::mlme_indication_handler); 00115 } 00116 00117 LoRaWANStack::~LoRaWANStack() 00118 { 00119 } 00120 00121 /***************************************************************************** 00122 * Public member functions * 00123 ****************************************************************************/ 00124 LoRaWANStack& LoRaWANStack::get_lorawan_stack() 00125 { 00126 static LoRaWANStack _lw_stack; 00127 return _lw_stack; 00128 } 00129 00130 radio_events_t *LoRaWANStack::bind_radio_driver(LoRaRadio& radio) 00131 { 00132 // Store pointer to callback routines inside MAC layer (non-IRQ safe) 00133 _mac_handlers = _loramac.get_phy_event_handlers(); 00134 // passes the reference to radio driver down to PHY layer 00135 _lora_phy.set_radio_instance(radio); 00136 return _mac_handlers; 00137 } 00138 00139 lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue) 00140 { 00141 if (DEVICE_STATE_NOT_INITIALIZED != _device_current_state) 00142 { 00143 tr_debug("Initialized already"); 00144 return LORAWAN_STATUS_OK; 00145 } 00146 00147 tr_debug("Initializing MAC layer"); 00148 00149 //store a pointer to Event Queue 00150 _queue = queue; 00151 00152 #if defined(LORAWAN_COMPLIANCE_TEST) 00153 _compliance_test.app_data_buffer = compliance_test_buffer; 00154 #endif 00155 00156 _lora_time.activate_timer_subsystem(queue); 00157 _loramac.initialize(&LoRaMacPrimitives, &_lora_phy, queue); 00158 00159 loramac_mib_req_confirm_t mib_req; 00160 00161 mib_req.type = MIB_ADR ; 00162 mib_req.param .is_adr_enable = MBED_CONF_LORA_ADR_ON; 00163 mib_set_request(&mib_req); 00164 00165 mib_req.type = MIB_PUBLIC_NETWORK ; 00166 mib_req.param .enable_public_nwk = MBED_CONF_LORA_PUBLIC_NETWORK; 00167 mib_set_request(&mib_req); 00168 00169 // Reset counters to zero. Will change in future with 1.1 support. 00170 _lw_session.downlink_counter = 0; 00171 _lw_session.uplink_counter = 0; 00172 00173 // Start loRaWAN state machine. 00174 set_device_state(DEVICE_STATE_INIT); 00175 return lora_state_machine(); 00176 } 00177 00178 #if defined(LORAWAN_COMPLIANCE_TEST) 00179 /** 00180 * 00181 * Prepares the upload message to reserved ports 00182 * 00183 * \param port Application port 00184 */ 00185 void LoRaWANStack::prepare_special_tx_frame(uint8_t port) 00186 { 00187 if (port == 224) { 00188 // Clear any normal message stuff before compliance test. 00189 memset(&_tx_msg, 0, sizeof(_tx_msg)); 00190 00191 if (_compliance_test.link_check == true) { 00192 _compliance_test.link_check = false; 00193 _compliance_test.state = 1; 00194 _tx_msg.f_buffer_size = 3; 00195 _tx_msg.f_buffer[0] = 5; 00196 _tx_msg.f_buffer[1] = _compliance_test.demod_margin; 00197 _tx_msg.f_buffer[2] = _compliance_test.nb_gateways; 00198 } else { 00199 switch (_compliance_test.state) { 00200 case 4: 00201 _compliance_test.state = 1; 00202 _tx_msg.f_buffer_size = _compliance_test.app_data_size; 00203 00204 _tx_msg.f_buffer[0] = _compliance_test.app_data_buffer[0]; 00205 for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, MBED_CONF_LORA_TX_MAX_SIZE); ++i) { 00206 _tx_msg.f_buffer[i] = _compliance_test.app_data_buffer[i]; 00207 } 00208 break; 00209 case 1: 00210 _tx_msg.f_buffer_size = 2; 00211 _tx_msg.f_buffer[0] = _compliance_test.downlink_counter >> 8; 00212 _tx_msg.f_buffer[1] = _compliance_test.downlink_counter; 00213 break; 00214 } 00215 } 00216 } 00217 } 00218 00219 /** Hands over the compliance test frame to MAC layer 00220 * 00221 * \return returns the state of the LoRa MAC 00222 */ 00223 lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac() 00224 { 00225 loramac_mcps_req_t mcps_req; 00226 00227 get_phy_params_t phy_params; 00228 phy_param_t default_datarate; 00229 phy_params.attribute = PHY_DEF_TX_DR ; 00230 default_datarate = _lora_phy.get_phy_params(&phy_params); 00231 00232 prepare_special_tx_frame(_compliance_test.app_port); 00233 00234 if (!_compliance_test.is_tx_confirmed) { 00235 mcps_req.type = MCPS_UNCONFIRMED ; 00236 mcps_req.req.unconfirmed .fport = _compliance_test.app_port; 00237 mcps_req.f_buffer = _tx_msg.f_buffer; 00238 mcps_req.f_buffer_size = _tx_msg.f_buffer_size; 00239 mcps_req.req.unconfirmed .data_rate = default_datarate.value ; 00240 00241 tr_info("Transmit unconfirmed compliance test frame %d bytes.", mcps_req.f_buffer_size); 00242 00243 for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) { 00244 tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]); 00245 } 00246 } else if (_compliance_test.is_tx_confirmed) { 00247 mcps_req.type = MCPS_CONFIRMED ; 00248 mcps_req.req.confirmed .fport = _compliance_test.app_port; 00249 mcps_req.f_buffer = _tx_msg.f_buffer; 00250 mcps_req.f_buffer_size = _tx_msg.f_buffer_size; 00251 mcps_req.req.confirmed .nb_trials = _num_retry; 00252 mcps_req.req.confirmed .data_rate = default_datarate.value ; 00253 00254 tr_info("Transmit confirmed compliance test frame %d bytes.", mcps_req.f_buffer_size); 00255 00256 for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) { 00257 tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]); 00258 } 00259 } else { 00260 return LORAWAN_STATUS_SERVICE_UNKNOWN; 00261 } 00262 00263 return mcps_request_handler(&mcps_req); 00264 } 00265 #endif 00266 00267 uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size) 00268 { 00269 loramac_tx_info_t tx_info; 00270 if (_loramac.query_tx_possible(size, &tx_info) == LORAWAN_STATUS_LENGTH_ERROR) { 00271 // Cannot transmit this much. Return how much data can be sent 00272 // at the moment 00273 return tx_info.max_possible_payload_size ; 00274 } 00275 00276 return tx_info.current_payload_size ; 00277 } 00278 00279 /** Hands over the frame to MAC layer 00280 * 00281 * \return returns the state of the LoRa MAC 00282 */ 00283 lorawan_status_t LoRaWANStack::send_frame_to_mac() 00284 { 00285 loramac_mcps_req_t mcps_req; 00286 lorawan_status_t status; 00287 loramac_mib_req_confirm_t mib_get_params; 00288 00289 get_phy_params_t phy_params; 00290 phy_param_t default_datarate; 00291 phy_params.attribute = PHY_DEF_TX_DR ; 00292 default_datarate = _lora_phy.get_phy_params(&phy_params); 00293 00294 mcps_req.type = _tx_msg.type; 00295 00296 if (MCPS_UNCONFIRMED == mcps_req.type ) { 00297 mcps_req.req.unconfirmed .fport = _tx_msg.message_u.unconfirmed.fport; 00298 mcps_req.f_buffer = _tx_msg.f_buffer; 00299 00300 mcps_req.f_buffer_size = _tx_msg.f_buffer_size; 00301 00302 mib_get_params.type = MIB_CHANNELS_DATARATE ; 00303 if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) { 00304 tr_debug("Couldn't get MIB parameters: Using default data rate"); 00305 mcps_req.req.unconfirmed .data_rate = default_datarate.value ; 00306 } else { 00307 mcps_req.req.unconfirmed .data_rate = mib_get_params.param .channel_data_rate ; 00308 } 00309 00310 } else if (mcps_req.type == MCPS_CONFIRMED ) { 00311 mcps_req.req.confirmed .fport = _tx_msg.message_u.confirmed.fport; 00312 mcps_req.f_buffer = _tx_msg.f_buffer; 00313 mcps_req.f_buffer_size = _tx_msg.f_buffer_size; 00314 mcps_req.req.confirmed .nb_trials = _tx_msg.message_u.confirmed.nb_trials; 00315 00316 mib_get_params.type = MIB_CHANNELS_DATARATE ; 00317 if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) { 00318 tr_debug("Couldn't get MIB parameters: Using default data rate"); 00319 mcps_req.req.confirmed .data_rate = default_datarate.value ; 00320 } else { 00321 mcps_req.req.confirmed .data_rate = mib_get_params.param .channel_data_rate ; 00322 } 00323 00324 } else if ( mcps_req.type == MCPS_PROPRIETARY ) { 00325 mcps_req.f_buffer = _tx_msg.f_buffer; 00326 mcps_req.f_buffer_size = _tx_msg.f_buffer_size; 00327 00328 mib_get_params.type = MIB_CHANNELS_DATARATE ; 00329 if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) { 00330 tr_debug("Couldn't get MIB parameters: Using default data rate"); 00331 mcps_req.req.proprietary .data_rate = default_datarate.value ; 00332 } else { 00333 mcps_req.req.proprietary .data_rate = mib_get_params.param .channel_data_rate ; 00334 } 00335 00336 } else { 00337 return LORAWAN_STATUS_SERVICE_UNKNOWN; 00338 } 00339 00340 status = mcps_request_handler(&mcps_req); 00341 00342 return status; 00343 } 00344 00345 lorawan_status_t LoRaWANStack::set_confirmed_msg_retry(uint8_t count) 00346 { 00347 if (count >= MAX_CONFIRMED_MSG_RETRIES) { 00348 return LORAWAN_STATUS_PARAMETER_INVALID; 00349 } 00350 00351 _num_retry = count; 00352 00353 return LORAWAN_STATUS_OK; 00354 } 00355 00356 void LoRaWANStack::set_device_state(device_states_t new_state) 00357 { 00358 _device_current_state = new_state; 00359 } 00360 00361 /*! 00362 * \brief MLME-Indication event function 00363 * 00364 * \param [IN] mlmeIndication - Pointer to the indication structure. 00365 */ 00366 void LoRaWANStack::mlme_indication_handler(loramac_mlme_indication_t *mlmeIndication) 00367 { 00368 switch( mlmeIndication->indication_type ) 00369 { 00370 case MLME_SCHEDULE_UPLINK : 00371 {// The MAC signals that we shall provide an uplink as soon as possible 00372 // TODO: Sending implementation missing and will be implemented using 00373 // another task. 00374 //OnTxNextPacketTimerEvent( ); 00375 break; 00376 } 00377 default: 00378 break; 00379 } 00380 } 00381 00382 void LoRaWANStack::set_lora_callbacks(lorawan_app_callbacks_t *cbs) 00383 { 00384 if (cbs) { 00385 if (cbs->events) { 00386 _callbacks.events = cbs->events; 00387 } 00388 00389 if (cbs->link_check_resp) { 00390 _callbacks.link_check_resp = cbs->link_check_resp; 00391 } 00392 00393 if (cbs->battery_level) { 00394 _callbacks.battery_level = cbs->battery_level; 00395 } 00396 } 00397 } 00398 00399 lorawan_status_t LoRaWANStack::add_channels(const lorawan_channelplan_t &channel_plan) 00400 { 00401 // If device is not initialized, stop right away 00402 if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) { 00403 tr_error("Stack not initialized!"); 00404 return LORAWAN_STATUS_NOT_INITIALIZED; 00405 } 00406 00407 return _loramac.add_channel_plan(channel_plan); 00408 } 00409 00410 lorawan_status_t LoRaWANStack::drop_channel_list() 00411 { 00412 if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) { 00413 tr_error("Stack not initialized!"); 00414 return LORAWAN_STATUS_NOT_INITIALIZED; 00415 } 00416 00417 return _loramac.remove_channel_plan(); 00418 } 00419 00420 lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id) 00421 { 00422 if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED ) 00423 { 00424 tr_error("Stack not initialized!"); 00425 return LORAWAN_STATUS_NOT_INITIALIZED; 00426 } 00427 00428 return _loramac.remove_single_channel(channel_id); 00429 } 00430 00431 lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t& channel_plan) 00432 { 00433 if (_device_current_state == DEVICE_STATE_JOINING 00434 || _device_current_state == DEVICE_STATE_NOT_INITIALIZED 00435 || _device_current_state == DEVICE_STATE_INIT) 00436 { 00437 tr_error("Cannot get channel plan until Joined!"); 00438 return LORAWAN_STATUS_BUSY; 00439 } 00440 00441 return _loramac.get_channel_plan(channel_plan); 00442 } 00443 00444 lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled) 00445 { 00446 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) 00447 { 00448 tr_error("Stack not initialized!"); 00449 return LORAWAN_STATUS_NOT_INITIALIZED; 00450 } 00451 00452 loramac_mib_req_confirm_t adr_mib_params; 00453 00454 adr_mib_params.type = MIB_ADR ; 00455 adr_mib_params.param .is_adr_enable = adr_enabled; 00456 00457 return mib_set_request(&adr_mib_params); 00458 } 00459 00460 lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate) 00461 { 00462 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) 00463 { 00464 tr_error("Stack not initialized!"); 00465 return LORAWAN_STATUS_NOT_INITIALIZED; 00466 } 00467 00468 loramac_mib_req_confirm_t mib_params; 00469 mib_params.type = MIB_ADR ; 00470 if (mib_get_request(&mib_params) != LORAWAN_STATUS_OK) { 00471 tr_error("Cannot set data rate. Please turn off ADR first."); 00472 return LORAWAN_STATUS_PARAMETER_INVALID; 00473 } 00474 00475 mib_params.type = MIB_CHANNELS_DATARATE ; 00476 mib_params.param .channel_data_rate = data_rate; 00477 00478 return mib_set_request(&mib_params); 00479 } 00480 00481 void LoRaWANStack::commission_device(const lorawan_dev_commission_t &commission_data) 00482 { 00483 _lw_session.connection.connect_type = commission_data.connection.connect_type ; 00484 _lw_session.downlink_counter = commission_data.downlink_counter; 00485 _lw_session.uplink_counter = commission_data.uplink_counter; 00486 00487 if (commission_data.connection.connect_type == LORAWAN_CONNECTION_OTAA) { 00488 _lw_session.connection.connection_u.otaa.app_eui = 00489 commission_data.connection.connection_u.otaa .app_eui; 00490 _lw_session.connection.connection_u.otaa.app_key = 00491 commission_data.connection.connection_u.otaa .app_key; 00492 _lw_session.connection.connection_u.otaa.dev_eui = 00493 commission_data.connection.connection_u.otaa .dev_eui; 00494 _lw_session.connection.connection_u.otaa.nb_trials = 00495 commission_data.connection.connection_u.otaa .nb_trials; 00496 } else { 00497 _lw_session.connection.connection_u.abp.dev_addr = 00498 commission_data.connection.connection_u.abp .dev_addr; 00499 _lw_session.connection.connection_u.abp.nwk_skey = 00500 commission_data.connection.connection_u.abp .nwk_skey; 00501 _lw_session.connection.connection_u.abp.app_skey = 00502 commission_data.connection.connection_u.abp .app_skey; 00503 } 00504 } 00505 00506 /** 00507 * 00508 * Join OTAA 00509 */ 00510 lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t ¶ms) 00511 { 00512 lorawan_dev_commission_t commission; 00513 00514 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) 00515 { 00516 tr_error("Stack not initialized!"); 00517 return LORAWAN_STATUS_NOT_INITIALIZED; 00518 } 00519 00520 tr_debug("Initiating OTAA"); 00521 00522 commission.connection.connect_type = LORAWAN_CONNECTION_OTAA; 00523 commission.connection.connection_u.otaa .dev_eui = params.connection_u.otaa .dev_eui; 00524 commission.connection.connection_u.otaa .app_eui = params.connection_u.otaa .app_eui; 00525 commission.connection.connection_u.otaa .app_key = params.connection_u.otaa .app_key; 00526 commission.connection.connection_u.otaa .nb_trials = params.connection_u.otaa .nb_trials; 00527 00528 // As mentioned in the comment above, in 1.0.2 spec, counters are always set 00529 // to zero for new connection. This section is common for both normal and 00530 // connection restore at this moment. Will change in future with 1.1 support. 00531 commission.downlink_counter = 0; 00532 commission.uplink_counter = 0; 00533 00534 commission_device(commission); 00535 set_device_state(DEVICE_STATE_JOINING); 00536 return lora_state_machine(); 00537 } 00538 00539 /** 00540 * 00541 * Connect ABP 00542 */ 00543 lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_connect_t ¶ms) 00544 { 00545 lorawan_status_t status; 00546 lorawan_dev_commission_t commission; 00547 00548 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) { 00549 tr_error("Stack not initialized!"); 00550 return LORAWAN_STATUS_NOT_INITIALIZED; 00551 } 00552 00553 tr_debug("Initiating ABP"); 00554 00555 commission.connection.connect_type = LORAWAN_CONNECTION_ABP; 00556 commission.connection.connection_u.abp .dev_addr = params.connection_u.abp .dev_addr; 00557 commission.connection.connection_u.abp .nwk_skey = params.connection_u.abp .nwk_skey; 00558 commission.connection.connection_u.abp .app_skey = params.connection_u.abp .app_skey; 00559 00560 // If current state is SHUTDOWN, device may be trying to re-establish 00561 // communication. In case of ABP specification is meddled about frame counters. 00562 // It says to reset counters to zero but there is no mechanism to tell the 00563 // network server that the device was disconnected or restarted. 00564 // At the moment, this implementation does not support a non-volatile 00565 // memory storage, so we try a last ditch effort here to restore correct 00566 // frame counters. If that doesn't work, user must manually reset frame 00567 // counters on their network server. 00568 commission.downlink_counter = _lw_session.downlink_counter; 00569 commission.uplink_counter = _lw_session.uplink_counter; 00570 00571 tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu", 00572 commission.uplink_counter, commission.downlink_counter); 00573 00574 commission_device(commission); 00575 00576 set_device_state(DEVICE_STATE_ABP_CONNECTING); 00577 status = lora_state_machine(); 00578 00579 return status; 00580 } 00581 00582 int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data, 00583 uint16_t length, uint8_t flags) 00584 { 00585 if (!_lw_session.active) { 00586 return LORAWAN_STATUS_NO_ACTIVE_SESSIONS; 00587 } 00588 00589 if (_tx_msg.tx_ongoing) { 00590 return LORAWAN_STATUS_WOULD_BLOCK; 00591 } 00592 00593 if (!data && length > 0) { 00594 return LORAWAN_STATUS_PARAMETER_INVALID; 00595 } 00596 00597 #if defined(LORAWAN_COMPLIANCE_TEST) 00598 if (_compliance_test.running) { 00599 return LORAWAN_STATUS_COMPLIANCE_TEST_ON; 00600 } 00601 #endif 00602 00603 loramac_mib_req_confirm_t mib_req; 00604 lorawan_status_t status; 00605 mib_req.type = MIB_NETWORK_JOINED ; 00606 status = mib_get_request(&mib_req); 00607 00608 if (status == LORAWAN_STATUS_OK) { 00609 if (mib_req.param .is_nwk_joined == false) { 00610 return LORAWAN_STATUS_NO_NETWORK_JOINED; 00611 } 00612 } 00613 00614 status = set_application_port(port); 00615 00616 if (status != LORAWAN_STATUS_OK) { 00617 tr_error("Illegal application port definition."); 00618 return status; 00619 } 00620 00621 if (flags == 0 00622 || (flags & MSG_FLAG_MASK) == (MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG)) { 00623 tr_error("CONFIRMED and UNCONFIRMED are mutually exclusive for send()"); 00624 return LORAWAN_STATUS_PARAMETER_INVALID; 00625 } 00626 00627 _tx_msg.port = port; 00628 00629 uint16_t max_possible_size = check_possible_tx_size(length); 00630 00631 if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) { 00632 // LORAWAN_APP_DATA_MAX_SIZE should at least be 00633 // either equal to or bigger than maximum possible 00634 // tx size because our tx message buffer takes its 00635 // length from that macro. Force maximum possible tx unit 00636 // to be equal to the buffer size user chose. 00637 max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE; 00638 } 00639 00640 if (max_possible_size < length) { 00641 tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes", 00642 length, max_possible_size); 00643 00644 _tx_msg.pending_size = length - max_possible_size; 00645 _tx_msg.f_buffer_size = max_possible_size; 00646 // copy user buffer upto the max_possible_size 00647 memcpy(_tx_msg.f_buffer, data, _tx_msg.f_buffer_size); 00648 } else { 00649 // Whole message can be sent at one time 00650 _tx_msg.f_buffer_size = length; 00651 _tx_msg.pending_size = 0; 00652 // copy user buffer upto the max_possible_size 00653 if (length > 0) { 00654 memcpy(_tx_msg.f_buffer, data, length); 00655 } 00656 } 00657 00658 // Handles all unconfirmed messages, including proprietary and multicast 00659 if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG 00660 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST 00661 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) { 00662 00663 _tx_msg.type = MCPS_UNCONFIRMED ; 00664 _tx_msg.message_u.unconfirmed.fport = _app_port; 00665 } 00666 00667 // Handles all confirmed messages, including proprietary and multicast 00668 if ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG 00669 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST 00670 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) { 00671 00672 _tx_msg.type = MCPS_CONFIRMED ; 00673 _tx_msg.message_u.confirmed.fport = _app_port; 00674 _tx_msg.message_u.confirmed.nb_trials = _num_retry; 00675 } 00676 00677 tr_info("RTS = %u bytes, PEND = %u", _tx_msg.f_buffer_size, _tx_msg.pending_size); 00678 set_device_state(DEVICE_STATE_SEND); 00679 status = lora_state_machine(); 00680 00681 // send user the length of data which is scheduled now. 00682 // user should take care of the pending data. 00683 return (status == LORAWAN_STATUS_OK) ? _tx_msg.f_buffer_size : (int16_t) status; 00684 } 00685 00686 int16_t LoRaWANStack::handle_rx(const uint8_t port, uint8_t* data, 00687 uint16_t length, uint8_t flags) 00688 { 00689 if (!_lw_session.active) { 00690 return LORAWAN_STATUS_NO_ACTIVE_SESSIONS; 00691 } 00692 00693 // No messages to read. 00694 if (!_rx_msg.receive_ready) { 00695 return LORAWAN_STATUS_WOULD_BLOCK; 00696 } 00697 00698 #if defined(LORAWAN_COMPLIANCE_TEST) 00699 if (_compliance_test.running) { 00700 return LORAWAN_STATUS_COMPLIANCE_TEST_ON; 00701 } 00702 #endif 00703 00704 if (data == NULL) { 00705 return LORAWAN_STATUS_PARAMETER_INVALID; 00706 } 00707 00708 uint8_t *base_ptr = _rx_msg.msg.mcps_indication.buffer; 00709 uint16_t base_size = _rx_msg.msg.mcps_indication.buffer_size; 00710 bool read_complete = false; 00711 00712 if (_rx_msg.msg.mcps_indication.port != port) { 00713 // Nothing yet received for this particular port 00714 return LORAWAN_STATUS_WOULD_BLOCK; 00715 } 00716 00717 // check if message received is a Confirmed message and user subscribed to it or not 00718 if (_rx_msg.msg.mcps_indication.type == MCPS_CONFIRMED 00719 && ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG 00720 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST 00721 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY)) { 00722 00723 tr_debug("RX - Confirmed Message, flags=%d", flags); 00724 } 00725 00726 // check if message received is a Unconfirmed message and user subscribed to it or not 00727 if (_rx_msg.msg.mcps_indication.type == MCPS_UNCONFIRMED 00728 && ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG 00729 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST 00730 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY)) { 00731 tr_debug("RX - Unconfirmed Message - flags=%d", flags); 00732 } 00733 00734 // check the length of received message whether we can fit into user 00735 // buffer completely or not 00736 if (_rx_msg.msg.mcps_indication.buffer_size > length && 00737 _rx_msg.prev_read_size == 0) { 00738 // we can't fit into user buffer. Invoke counter measures 00739 _rx_msg.pending_size = _rx_msg.msg.mcps_indication.buffer_size - length; 00740 base_size = length; 00741 _rx_msg.prev_read_size = base_size; 00742 memcpy(data, base_ptr, base_size); 00743 } else if (_rx_msg.prev_read_size == 0) { 00744 _rx_msg.pending_size = 0; 00745 _rx_msg.prev_read_size = 0; 00746 memcpy(data, base_ptr, base_size); 00747 read_complete = true; 00748 } 00749 00750 // If its the pending read then we should copy only the remaining part of 00751 // the buffer. Due to checks above, in case of a pending read, this block 00752 // will be the only one to get invoked 00753 if (_rx_msg.pending_size > 0 && _rx_msg.prev_read_size > 0) { 00754 memcpy(data, base_ptr+_rx_msg.prev_read_size, base_size); 00755 } 00756 00757 // we are done handing over received buffer to user. check if there is 00758 // anything pending. If not, memset the buffer to zero and indicate 00759 // that no read is in progress 00760 if (read_complete) { 00761 memset(_rx_msg.msg.mcps_indication.buffer, 0, LORAMAC_PHY_MAXPAYLOAD); 00762 _rx_msg.receive_ready = false; 00763 } 00764 00765 return base_size; 00766 } 00767 00768 lorawan_status_t LoRaWANStack::mlme_request_handler(loramac_mlme_req_t *mlme_request) 00769 { 00770 if (mlme_request == NULL) { 00771 return LORAWAN_STATUS_PARAMETER_INVALID; 00772 } 00773 00774 return _loramac.mlme_request(mlme_request); 00775 } 00776 00777 /** MLME-Confirm event function 00778 * 00779 * \param mlme_confirm Pointer to the confirm structure, 00780 * containing confirm attributes. 00781 */ 00782 void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm) 00783 { 00784 if (NULL == mlme_confirm) { 00785 tr_error("mlme_confirm: struct [in] is null!"); 00786 MBED_ASSERT(0); 00787 return; 00788 } 00789 00790 switch (mlme_confirm->req_type ) { 00791 case MLME_JOIN : 00792 if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK ) { 00793 // Status is OK, node has joined the network 00794 set_device_state(DEVICE_STATE_JOINED); 00795 if (lora_state_machine() != LORAWAN_STATUS_OK) { 00796 tr_error("Lora state machine did not return LORAWAN_STATUS_OK"); 00797 } 00798 } else { 00799 // Join attempt failed. 00800 set_device_state(DEVICE_STATE_IDLE); 00801 if (lora_state_machine() != LORAWAN_STATUS_IDLE) { 00802 tr_error("Lora state machine did not return DEVICE_STATE_IDLE !"); 00803 } 00804 00805 if (_callbacks.events) { 00806 const int ret = _queue->call(_callbacks.events, JOIN_FAILURE); 00807 MBED_ASSERT(ret != 0); 00808 (void)ret; 00809 } 00810 } 00811 break; 00812 case MLME_LINK_CHECK : 00813 if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK ) { 00814 // Check DemodMargin 00815 // Check NbGateways 00816 #if defined(LORAWAN_COMPLIANCE_TEST) 00817 if (_compliance_test.running == true) { 00818 _compliance_test.link_check = true; 00819 _compliance_test.demod_margin = mlme_confirm->demod_margin ; 00820 _compliance_test.nb_gateways = mlme_confirm->nb_gateways ; 00821 } else 00822 #endif 00823 { 00824 // normal operation as oppose to compliance testing 00825 if (_callbacks.link_check_resp) { 00826 const int ret = _queue->call(_callbacks.link_check_resp, 00827 mlme_confirm->demod_margin , 00828 mlme_confirm->nb_gateways ); 00829 MBED_ASSERT(ret != 0); 00830 (void)ret; 00831 } 00832 } 00833 } 00834 break; 00835 default: 00836 break; 00837 } 00838 } 00839 00840 lorawan_status_t LoRaWANStack::mcps_request_handler(loramac_mcps_req_t *mcps_request) 00841 { 00842 if (mcps_request == NULL) { 00843 return LORAWAN_STATUS_PARAMETER_INVALID; 00844 } 00845 00846 return _loramac.mcps_request(mcps_request); 00847 } 00848 00849 /** MCPS-Confirm event function 00850 * 00851 * \param mcps_confirm Pointer to the confirm structure, 00852 * containing confirm attributes. 00853 */ 00854 void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm) 00855 { 00856 if (mcps_confirm == NULL) { 00857 tr_error("mcps_confirm: struct [in] is null!"); 00858 MBED_ASSERT(0); 00859 return; 00860 } 00861 00862 if (mcps_confirm->status != LORAMAC_EVENT_INFO_STATUS_OK ) { 00863 // Couldn't schedule packet, ack not recieved in CONFIRMED case 00864 // or some other error happened. Discard buffer, unset the tx-ongoing 00865 // flag and let the application know 00866 _tx_msg.tx_ongoing = false; 00867 memset(_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE); 00868 _tx_msg.f_buffer_size = MBED_CONF_LORA_TX_MAX_SIZE; 00869 00870 tr_error("mcps_confirm_handler: Error code = %d", mcps_confirm->status ); 00871 00872 // If sending timed out, we have a special event for that 00873 if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) { 00874 if (_callbacks.events) { 00875 const int ret = _queue->call(_callbacks.events, TX_TIMEOUT); 00876 MBED_ASSERT(ret != 0); 00877 (void)ret; 00878 } 00879 return; 00880 } if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ) { 00881 tr_debug("Did not receive Ack"); 00882 } 00883 00884 // Otherwise send a general TX_ERROR event 00885 if (_callbacks.events) { 00886 const int ret = _queue->call(_callbacks.events, TX_ERROR); 00887 MBED_ASSERT(ret != 0); 00888 (void)ret; 00889 } 00890 return; 00891 } 00892 00893 // If No errors encountered, let's proceed with the status. 00894 // CONFIRMED needs special handling because of acks 00895 if (mcps_confirm->req_type == MCPS_CONFIRMED ) { 00896 // In confirmed case, we need to check if we have received the Ack or not. 00897 // This is actually just being paranoid about ack because LoRaMac.cpp doesn't 00898 // call this callback until an ack is received. 00899 if (mcps_confirm->ack_received ) { 00900 tr_debug("Ack received."); 00901 } 00902 } 00903 00904 // This part is common to both CONFIRMED and UNCONFIRMED. 00905 // Tell the application about successful transmission and store 00906 // data rate plus frame counter. 00907 _lw_session.uplink_counter = mcps_confirm->ul_frame_counter ; 00908 _tx_msg.tx_ongoing = false; 00909 if (_callbacks.events) { 00910 const int ret = _queue->call(_callbacks.events, TX_DONE); 00911 MBED_ASSERT(ret != 0); 00912 (void)ret; 00913 } 00914 } 00915 00916 /** MCPS-Indication event function 00917 * 00918 * \param mcps_indication Pointer to the indication structure, 00919 * containing indication attributes. 00920 */ 00921 void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indication) 00922 { 00923 if (mcps_indication == NULL) { 00924 tr_error("mcps_indication: struct [in] is null."); 00925 return; 00926 } 00927 00928 if (mcps_indication->status != LORAMAC_EVENT_INFO_STATUS_OK ) { 00929 if (_callbacks.events) { 00930 const int ret = _queue->call(_callbacks.events, RX_ERROR); 00931 MBED_ASSERT(ret != 0); 00932 (void)ret; 00933 } 00934 return; 00935 } 00936 00937 switch (mcps_indication->type ) { 00938 case MCPS_UNCONFIRMED : 00939 break; 00940 case MCPS_CONFIRMED : 00941 break; 00942 case MCPS_PROPRIETARY : 00943 break; 00944 case MCPS_MULTICAST : 00945 break; 00946 default: 00947 break; 00948 } 00949 00950 // Check Multicast 00951 // Check Port 00952 // Check Datarate 00953 // Check FramePending 00954 // Check Buffer 00955 // Check BufferSize 00956 // Check Rssi 00957 // Check Snr 00958 // Check RxSlot 00959 00960 _lw_session.downlink_counter++; 00961 00962 #if defined(LORAWAN_COMPLIANCE_TEST) 00963 if (_compliance_test.running == true) { 00964 _compliance_test.downlink_counter++; 00965 } 00966 #endif 00967 00968 if (mcps_indication->is_data_recvd == true) { 00969 switch (mcps_indication->port ) { 00970 case 224: 00971 #if defined(LORAWAN_COMPLIANCE_TEST) 00972 tr_debug("Compliance test command received."); 00973 compliance_test_handler(mcps_indication); 00974 #else 00975 tr_debug("Compliance test disabled."); 00976 #endif 00977 break; 00978 default: 00979 if (is_port_valid(mcps_indication->port ) == true || 00980 mcps_indication->type == MCPS_PROPRIETARY ) { 00981 00982 // Valid message arrived. 00983 _rx_msg.type = LORAMAC_RX_MCPS_INDICATION; 00984 _rx_msg.msg.mcps_indication.buffer_size = mcps_indication->buffer_size ; 00985 _rx_msg.msg.mcps_indication.port = mcps_indication->port ; 00986 00987 // no copy, just set the pointer for the user 00988 _rx_msg.msg.mcps_indication.buffer = 00989 mcps_indication->buffer ; 00990 00991 // Notify application about received frame.. 00992 tr_debug("Received %d bytes", _rx_msg.msg.mcps_indication.buffer_size); 00993 _rx_msg.receive_ready = true; 00994 00995 if (_callbacks.events) { 00996 const int ret = _queue->call(_callbacks.events, RX_DONE); 00997 MBED_ASSERT(ret != 0); 00998 (void)ret; 00999 } 01000 01001 // If fPending bit is set we try to generate an empty packet 01002 // with CONFIRMED flag set. We always set a CONFIRMED flag so 01003 // that we could retry a certain number of times if the uplink 01004 // failed for some reason 01005 if (mcps_indication->fpending_status ) { 01006 handle_tx(mcps_indication->port , NULL, 0, MSG_CONFIRMED_FLAG); 01007 } 01008 } else { 01009 // Invalid port, ports 0, 224 and 225-255 are reserved. 01010 } 01011 break; 01012 } 01013 } 01014 } 01015 01016 #if defined(LORAWAN_COMPLIANCE_TEST) 01017 /** Compliance testing function 01018 * 01019 * \param mcps_indication Pointer to the indication structure, 01020 * containing indication attributes. 01021 */ 01022 void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indication) 01023 { 01024 if (_compliance_test.running == false) { 01025 // Check compliance test enable command (i) 01026 if ((mcps_indication->buffer_size == 4) && 01027 (mcps_indication->buffer [0] == 0x01) && 01028 (mcps_indication->buffer [1] == 0x01) && 01029 (mcps_indication->buffer [2] == 0x01) && 01030 (mcps_indication->buffer [3] == 0x01)) { 01031 _compliance_test.is_tx_confirmed = false; 01032 _compliance_test.app_port = 224; 01033 _compliance_test.app_data_size = 2; 01034 _compliance_test.downlink_counter = 0; 01035 _compliance_test.link_check = false; 01036 _compliance_test.demod_margin = 0; 01037 _compliance_test.nb_gateways = 0; 01038 _compliance_test.running = true; 01039 _compliance_test.state = 1; 01040 01041 loramac_mib_req_confirm_t mib_req; 01042 mib_req.type = MIB_ADR ; 01043 mib_req.param .is_adr_enable = true; 01044 mib_set_request(&mib_req); 01045 01046 #if MBED_CONF_LORA_PHY == 0 01047 _loramac.LoRaMacTestSetDutyCycleOn(false); 01048 #endif 01049 //5000ms 01050 _loramac.LoRaMacSetTxTimer(5000); 01051 set_device_state(DEVICE_STATE_COMPLIANCE_TEST); 01052 tr_debug("Compliance test activated."); 01053 } 01054 } else { 01055 _compliance_test.state = mcps_indication->buffer [0]; 01056 switch (_compliance_test.state) { 01057 case 0: // Check compliance test disable command (ii) 01058 _compliance_test.is_tx_confirmed = true; 01059 _compliance_test.app_port = MBED_CONF_LORA_APP_PORT; 01060 _compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE; 01061 _compliance_test.downlink_counter = 0; 01062 _compliance_test.running = false; 01063 01064 loramac_mib_req_confirm_t mib_req; 01065 mib_req.type = MIB_ADR ; 01066 mib_req.param .is_adr_enable = MBED_CONF_LORA_ADR_ON; 01067 mib_set_request(&mib_req); 01068 #if MBED_CONF_LORA_PHY == 0 01069 _loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON); 01070 #endif 01071 // Go to idle state after compliance test mode. 01072 tr_debug("Compliance test disabled."); 01073 _loramac.LoRaMacStopTxTimer(); 01074 01075 // Clear any compliance test message stuff before going back to normal operation. 01076 memset(&_tx_msg, 0, sizeof(_tx_msg)); 01077 set_device_state(DEVICE_STATE_IDLE); 01078 lora_state_machine(); 01079 break; 01080 case 1: // (iii, iv) 01081 _compliance_test.app_data_size = 2; 01082 break; 01083 case 2: // Enable confirmed messages (v) 01084 _compliance_test.is_tx_confirmed = true; 01085 _compliance_test.state = 1; 01086 break; 01087 case 3: // Disable confirmed messages (vi) 01088 _compliance_test.is_tx_confirmed = false; 01089 _compliance_test.state = 1; 01090 break; 01091 case 4: // (vii) 01092 _compliance_test.app_data_size = mcps_indication->buffer_size ; 01093 01094 _compliance_test.app_data_buffer[0] = 4; 01095 for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, LORAMAC_PHY_MAXPAYLOAD); ++i) { 01096 _compliance_test.app_data_buffer[i] = mcps_indication->buffer [i] + 1; 01097 } 01098 01099 send_compliance_test_frame_to_mac(); 01100 break; 01101 case 5: // (viii) 01102 loramac_mlme_req_t mlme_req; 01103 mlme_req.type = MLME_LINK_CHECK ; 01104 mlme_request_handler(&mlme_req); 01105 break; 01106 case 6: // (ix) 01107 loramac_mlme_req_t mlme_request; 01108 loramac_mib_req_confirm_t mib_request; 01109 01110 // Disable TestMode and revert back to normal operation 01111 _compliance_test.is_tx_confirmed = true; 01112 _compliance_test.app_port = MBED_CONF_LORA_APP_PORT; 01113 _compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE; 01114 _compliance_test.downlink_counter = 0; 01115 _compliance_test.running = false; 01116 01117 mib_request.type = MIB_ADR ; 01118 mib_request.param .is_adr_enable = MBED_CONF_LORA_ADR_ON; 01119 mib_set_request(&mib_request); 01120 #if MBED_CONF_LORA_PHY == 0 01121 _loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON); 01122 #endif 01123 mlme_request.type = MLME_JOIN ; 01124 mlme_request.req.join .dev_eui = _lw_session.connection.connection_u.otaa.dev_eui; 01125 mlme_request.req.join .app_eui = _lw_session.connection.connection_u.otaa.app_eui; 01126 mlme_request.req.join .app_key = _lw_session.connection.connection_u.otaa.app_key; 01127 mlme_request.req.join .nb_trials = _lw_session.connection.connection_u.otaa.nb_trials; 01128 mlme_request_handler(&mlme_request); 01129 break; 01130 case 7: // (x) 01131 if (mcps_indication->buffer_size == 3) { 01132 loramac_mlme_req_t mlme_req; 01133 mlme_req.type = MLME_TXCW ; 01134 mlme_req.req.cw_tx_mode .timeout = (uint16_t)((mcps_indication->buffer [1] << 8) | mcps_indication->buffer [2]); 01135 mlme_request_handler(&mlme_req); 01136 } else if (mcps_indication->buffer_size == 7) { 01137 loramac_mlme_req_t mlme_req; 01138 mlme_req.type = MLME_TXCW_1 ; 01139 mlme_req.req.cw_tx_mode .timeout = (uint16_t)((mcps_indication->buffer [1] << 8) | mcps_indication->buffer [2]); 01140 mlme_req.req.cw_tx_mode .frequency = (uint32_t)((mcps_indication->buffer [3] << 16) | (mcps_indication->buffer [4] << 8) 01141 | mcps_indication->buffer [5]) * 100; 01142 mlme_req.req.cw_tx_mode .power = mcps_indication->buffer [6]; 01143 mlme_request_handler(&mlme_req); 01144 } 01145 _compliance_test.state = 1; 01146 break; 01147 } 01148 } 01149 } 01150 #endif 01151 01152 lorawan_status_t LoRaWANStack::mib_set_request(loramac_mib_req_confirm_t *mib_set_params) 01153 { 01154 if (NULL == mib_set_params) { 01155 return LORAWAN_STATUS_PARAMETER_INVALID; 01156 } 01157 return _loramac.mib_set_request_confirm(mib_set_params); 01158 } 01159 01160 lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_get_params) 01161 { 01162 if(NULL == mib_get_params) { 01163 return LORAWAN_STATUS_PARAMETER_INVALID; 01164 } 01165 return _loramac.mib_get_request_confirm(mib_get_params); 01166 } 01167 01168 lorawan_status_t LoRaWANStack::set_link_check_request() 01169 { 01170 if (!_callbacks.link_check_resp) { 01171 tr_error("Must assign a callback function for link check request. "); 01172 return LORAWAN_STATUS_PARAMETER_INVALID; 01173 } 01174 01175 loramac_mlme_req_t mlme_req; 01176 01177 mlme_req.type = MLME_LINK_CHECK ; 01178 return mlme_request_handler(&mlme_req); 01179 } 01180 01181 lorawan_status_t LoRaWANStack::shutdown() 01182 { 01183 set_device_state(DEVICE_STATE_SHUTDOWN); 01184 return lora_state_machine(); 01185 } 01186 01187 lorawan_status_t LoRaWANStack::lora_state_machine() 01188 { 01189 loramac_mib_req_confirm_t mib_req; 01190 lorawan_status_t status = LORAWAN_STATUS_DEVICE_OFF; 01191 01192 switch (_device_current_state) { 01193 case DEVICE_STATE_SHUTDOWN: 01194 /* 01195 * Remove channels 01196 * Radio will be put to sleep by the APIs underneath 01197 */ 01198 drop_channel_list(); 01199 01200 // Shutdown LoRaMac 01201 _loramac.disconnect(); 01202 01203 // Stop sending messages and set joined status to false. 01204 #if defined(LORAWAN_COMPLIANCE_TEST) 01205 _loramac.LoRaMacStopTxTimer(); 01206 #endif 01207 mib_req.type = MIB_NETWORK_JOINED ; 01208 mib_req.param .is_nwk_joined = false; 01209 mib_set_request(&mib_req); 01210 01211 // reset buffers to original state 01212 memset(_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE); 01213 _tx_msg.pending_size = 0; 01214 _tx_msg.f_buffer_size = 0; 01215 _tx_msg.tx_ongoing = false; 01216 _rx_msg.msg.mcps_indication.buffer = NULL; 01217 _rx_msg.receive_ready = false; 01218 _rx_msg.prev_read_size = 0; 01219 _rx_msg.msg.mcps_indication.buffer_size = 0; 01220 01221 // disable the session 01222 _lw_session.active = false; 01223 01224 tr_debug("LoRaWAN protocol has been shut down."); 01225 if (_callbacks.events) { 01226 const int ret = _queue->call(_callbacks.events, DISCONNECTED); 01227 MBED_ASSERT(ret != 0); 01228 (void)ret; 01229 } 01230 status = LORAWAN_STATUS_DEVICE_OFF; 01231 break; 01232 case DEVICE_STATE_NOT_INITIALIZED: 01233 // Device is disconnected. 01234 status = LORAWAN_STATUS_DEVICE_OFF; 01235 break; 01236 case DEVICE_STATE_INIT: 01237 status = LORAWAN_STATUS_OK; 01238 break; 01239 case DEVICE_STATE_JOINING: 01240 if (_lw_session.connection.connect_type == LORAWAN_CONNECTION_OTAA) { 01241 /* 01242 * OTAA join 01243 */ 01244 tr_debug("Send Join-request.."); 01245 loramac_mlme_req_t mlme_req; 01246 mlme_req.type = MLME_JOIN ; 01247 01248 mlme_req.req.join .dev_eui = _lw_session.connection.connection_u.otaa.dev_eui; 01249 mlme_req.req.join .app_eui = _lw_session.connection.connection_u.otaa.app_eui; 01250 mlme_req.req.join .app_key = _lw_session.connection.connection_u.otaa.app_key; 01251 mlme_req.req.join .nb_trials = _lw_session.connection.connection_u.otaa.nb_trials; 01252 01253 // Send join request to server. 01254 status = mlme_request_handler(&mlme_req); 01255 if (status != LORAWAN_STATUS_OK) { 01256 return status; 01257 } 01258 // Otherwise request was successful and OTAA connect is in 01259 //progress 01260 return LORAWAN_STATUS_CONNECT_IN_PROGRESS; 01261 } else { 01262 status = LORAWAN_STATUS_PARAMETER_INVALID; 01263 } 01264 break; 01265 case DEVICE_STATE_JOINED: 01266 tr_debug("Join OK!"); 01267 // Session is now active 01268 _lw_session.active = true; 01269 // Tell the application that we are connected 01270 if (_callbacks.events) { 01271 const int ret = _queue->call(_callbacks.events, CONNECTED); 01272 MBED_ASSERT(ret != 0); 01273 (void)ret; 01274 } 01275 status = LORAWAN_STATUS_OK; 01276 break; 01277 case DEVICE_STATE_ABP_CONNECTING: 01278 /* 01279 * ABP connection 01280 */ 01281 mib_req.type = MIB_NET_ID ; 01282 mib_req.param .net_id = _lw_session.connection.connection_u.abp.nwk_id; 01283 mib_set_request(&mib_req); 01284 01285 mib_req.type = MIB_DEV_ADDR ; 01286 mib_req.param .dev_addr = _lw_session.connection.connection_u.abp.dev_addr; 01287 mib_set_request(&mib_req); 01288 01289 mib_req.type = MIB_NWK_SKEY ; 01290 mib_req.param .nwk_skey = _lw_session.connection.connection_u.abp.nwk_skey; 01291 mib_set_request(&mib_req); 01292 01293 mib_req.type = MIB_APP_SKEY ; 01294 mib_req.param .app_skey = _lw_session.connection.connection_u.abp.app_skey; 01295 mib_set_request(&mib_req); 01296 01297 mib_req.type = MIB_NETWORK_JOINED ; 01298 mib_req.param .is_nwk_joined = true; 01299 mib_set_request(&mib_req); 01300 tr_debug("ABP Connection OK!"); 01301 // tell the application we are okay 01302 // if users provide wrong keys, it's their responsibility 01303 // there is no way to test ABP authentication success 01304 status = LORAWAN_STATUS_OK; 01305 // Session is now active 01306 _lw_session.active = true; 01307 if (_callbacks.events) { 01308 const int ret = _queue->call(_callbacks.events, CONNECTED); 01309 MBED_ASSERT(ret != 0); 01310 (void)ret; 01311 } 01312 break; 01313 case DEVICE_STATE_SEND: 01314 // If a transmission is ongoing, don't interrupt 01315 if (_tx_msg.tx_ongoing) { 01316 status = LORAWAN_STATUS_OK; 01317 } else { 01318 _tx_msg.tx_ongoing = true; 01319 status = send_frame_to_mac(); 01320 01321 switch (status) { 01322 case LORAWAN_STATUS_OK: 01323 tr_debug("Frame scheduled to TX.."); 01324 break; 01325 case LORAWAN_STATUS_CRYPTO_FAIL: 01326 tr_error("Crypto failed. Clearing TX buffers"); 01327 if (_callbacks.events) { 01328 const int ret = _queue->call(_callbacks.events, TX_CRYPTO_ERROR); 01329 MBED_ASSERT(ret != 0); 01330 (void)ret; 01331 } 01332 break; 01333 default: 01334 tr_error("Failure to schedule TX!"); 01335 if (_callbacks.events) { 01336 const int ret = _queue->call(_callbacks.events, TX_SCHEDULING_ERROR); 01337 MBED_ASSERT(ret != 0); 01338 (void)ret; 01339 } 01340 break; 01341 } 01342 } 01343 // otherwise all done, put device in idle state 01344 set_device_state(DEVICE_STATE_IDLE); 01345 break; 01346 case DEVICE_STATE_IDLE: 01347 //Do nothing 01348 status = LORAWAN_STATUS_IDLE; 01349 break; 01350 #if defined(LORAWAN_COMPLIANCE_TEST) 01351 case DEVICE_STATE_COMPLIANCE_TEST: 01352 //Device is in compliance test mode 01353 tr_debug("Device is in compliance test mode."); 01354 01355 //5000ms 01356 _loramac.LoRaMacSetTxTimer(5000); 01357 if (_compliance_test.running == true) { 01358 send_compliance_test_frame_to_mac(); 01359 } 01360 status = LORAWAN_STATUS_COMPLIANCE_TEST_ON; 01361 break; 01362 #endif 01363 default: 01364 status = LORAWAN_STATUS_SERVICE_UNKNOWN; 01365 break; 01366 } 01367 01368 return status; 01369 }
Generated on Tue Jul 12 2022 13:24:48 by
1.7.2