Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LoRaWANStack.h
00001 /** 00002 * \file LoRaWANStack.h 00003 * 00004 * \brief LoRaWAN stack layer implementation 00005 * 00006 * \copyright Revised BSD License, see LICENSE.TXT file include in the project 00007 * 00008 * \code 00009 * ______ _ 00010 * / _____) _ | | 00011 * ( (____ _____ ____ _| |_ _____ ____| |__ 00012 * \____ \| ___ | (_ _) ___ |/ ___) _ \ 00013 * _____) ) ____| | | || |_| ____( (___| | | | 00014 * (______/|_____)_|_|_| \__)_____)\____)_| |_| 00015 * (C)2013 Semtech 00016 * 00017 * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 00018 * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 00019 * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 00020 * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 00021 * embedded.connectivity.solutions=============== 00022 * 00023 * \endcode 00024 * 00025 * \author Miguel Luis ( Semtech ) 00026 * 00027 * \author Gregory Cristian ( Semtech ) 00028 * 00029 * \author Daniel Jaeckle ( STACKFORCE ) 00030 * 00031 * \defgroup LoRaWAN stack layer that controls MAC layer underneath 00032 * 00033 * License: Revised BSD License, see LICENSE.TXT file include in the project 00034 * 00035 * Copyright (c) 2017, Arm Limited and affiliates. 00036 * 00037 * SPDX-License-Identifier: BSD-3-Clause 00038 */ 00039 00040 #ifndef LORAWANSTACK_H_ 00041 #define LORAWANSTACK_H_ 00042 00043 #include <stdint.h> 00044 #include "events/EventQueue.h" 00045 #include "platform/Callback.h" 00046 #include "platform/NonCopyable.h" 00047 #include "platform/ScopedLock.h" 00048 00049 #include "lorastack/mac/LoRaMac.h" 00050 #include "system/LoRaWANTimer.h" 00051 #include "system/lorawan_data_structures.h" 00052 #include "LoRaRadio.h" 00053 00054 class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> { 00055 00056 public: 00057 LoRaWANStack(); 00058 00059 /** Binds radio driver to PHY layer. 00060 * 00061 * MAC layer is totally detached from the PHY layer so the stack layer 00062 * needs to play the role of an arbitrator. This API gets a radio driver 00063 * object from the application (via LoRaWANInterface), binds it to the PHY 00064 * layer and initialises radio callback handles which the radio driver will 00065 * use in order to report events. 00066 * 00067 * @param radio LoRaRadio object, i.e., the radio driver 00068 * 00069 */ 00070 void bind_radio_driver(LoRaRadio &radio); 00071 00072 /** End device initialization. 00073 * @param queue A pointer to an EventQueue passed from the application. 00074 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00075 */ 00076 lorawan_status_t initialize_mac_layer(events::EventQueue *queue); 00077 00078 /** Sets all callbacks for the application. 00079 * 00080 * @param callbacks A pointer to the structure carrying callbacks. 00081 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00082 */ 00083 lorawan_status_t set_lora_callbacks(const lorawan_app_callbacks_t *callbacks); 00084 00085 /** Connect OTAA or ABP using Mbed-OS config system 00086 * 00087 * Connect by Over The Air Activation or Activation By Personalization. 00088 * You need to configure the connection properly via the Mbed OS configuration 00089 * system. 00090 * 00091 * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative. 00092 * However, this is not a real error. It tells you that the connection is in progress and you will 00093 * be notified of the completion via an event. By default, after the Join Accept message 00094 * is received, base stations may provide the node with a CF-List that replaces 00095 * all user-configured channels except the Join/Default channels. A CF-List can 00096 * configure a maximum of five channels other than the default channels. 00097 * 00098 * In case of ABP, the CONNECTED event is posted before the call to `connect()` returns. 00099 * To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection. 00100 * By default, the PHY layers configure only the mandatory Join channels. The retransmission back-off restrictions 00101 * on these channels are severe and you may experience long delays or even failures in the confirmed traffic. 00102 * If you add more channels, the aggregated duty cycle becomes much more relaxed as compared to the Join (default) channels only. 00103 * 00104 * **NOTES ON RECONNECTION:** 00105 * Currently, the Mbed OS LoRaWAN implementation does not support non-volatile 00106 * memory storage. Therefore, the state and frame counters cannot be restored after 00107 * a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN 00108 * protocol, the state and frame counters are saved. Connecting again would try to 00109 * restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset 00110 * to zero for OTAA and a new Join request lets the network server know 00111 * that the counters need a reset. The same is said about the ABP but there 00112 * is no way to convey this information to the network server. For a network 00113 * server, an ABP device is always connected. That's why storing the frame counters 00114 * is important, at least for ABP. That's why we try to restore frame counters from 00115 * session information after a disconnection. 00116 * 00117 * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS 00118 * on success, or a negative error code on failure. 00119 */ 00120 lorawan_status_t connect(); 00121 00122 /** Connect OTAA or ABP with parameters 00123 * 00124 * All connection parameters are chosen by the user and provided in the 00125 * data structure passed down. 00126 * 00127 * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative. 00128 * However, this is not a real error. It tells you that connection is in progress and you will 00129 * be notified of completion via an event. By default, after Join Accept message 00130 * is received, base stations may provide the node with a CF-List which replaces 00131 * all user-configured channels except the Join/Default channels. A CF-List can 00132 * configure a maximum of five channels other than the default channels. 00133 * 00134 * In case of ABP, the CONNECTED event is posted before the call to `connect()` returns. 00135 * To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection. 00136 * By default, the PHY layers configure only the mandatory Join 00137 * channels. The retransmission back-off restrictions on these channels 00138 * are severe and you may experience long delays or even 00139 * failures in the confirmed traffic. If you add more channels, the aggregated duty 00140 * cycle becomes much more relaxed as compared to the Join (default) channels only. 00141 * 00142 * **NOTES ON RECONNECTION:** 00143 * Currently, the Mbed OS LoRaWAN implementation does not support non-volatile 00144 * memory storage. Therefore, the state and frame counters cannot be restored after 00145 * a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN 00146 * protocol, the state and frame counters are saved. Connecting again would try to 00147 * restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset 00148 * to zero for OTAA and a new Join request lets the network server know 00149 * that the counters need a reset. The same is said about the ABP but there 00150 * is no way to convey this information to the network server. For a network 00151 * server, an ABP device is always connected. That's why storing the frame counters 00152 * is important, at least for ABP. That's why we try to restore frame counters from 00153 * session information after a disconnection. 00154 * 00155 * @param connect Options for an end device connection to the gateway. 00156 * 00157 * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS, 00158 * a negative error code on failure. 00159 */ 00160 lorawan_status_t connect(const lorawan_connect_t &connect); 00161 00162 /** Adds channels to use. 00163 * 00164 * You can provide a list of channels with appropriate parameters filled 00165 * in. However, this list is not absolute. In some regions, a CF 00166 * list gets implemented by default, which means that the network can overwrite your channel 00167 * frequency settings right after receiving a Join Accept. You may try 00168 * to set up any channel or channels after that and if the channel requested 00169 * is already active, the request is silently ignored. A negative error 00170 * code is returned if there is any problem with parameters. 00171 * 00172 * You need to ensure that the base station nearby supports the channel or channels being added. 00173 * 00174 * If your list includes a default channel (a channel where Join Requests 00175 * are received) you cannot fully configure the channel parameters. 00176 * Either leave the channel settings to default or check your 00177 * corresponding PHY layer implementation. For example, LoRaPHYE868. 00178 * 00179 * @param channel_plan A list of channels or a single channel. 00180 * 00181 * @return LORAWAN_STATUS_OK on success, a negative error 00182 * code on failure. 00183 */ 00184 lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan); 00185 00186 /** Removes a channel from the list. 00187 * 00188 * @param channel_id Index of the channel being removed 00189 * 00190 * @return LORAWAN_STATUS_OK on success, a negative error 00191 * code on failure. 00192 */ 00193 lorawan_status_t remove_a_channel(uint8_t channel_id); 00194 00195 /** Removes a previously set channel plan. 00196 * 00197 * @return LORAWAN_STATUS_OK on success, a negative error 00198 * code on failure. 00199 */ 00200 lorawan_status_t drop_channel_list(); 00201 00202 /** Gets a list of currently enabled channels . 00203 * 00204 * @param channel_plan The channel plan structure to store final result. 00205 * 00206 * @return LORAWAN_STATUS_OK on success, a negative error 00207 * code on failure. 00208 */ 00209 lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan); 00210 00211 /** Sets up a retry counter for confirmed messages. 00212 * 00213 * Valid only for confirmed messages. This API sets the number of times the 00214 * stack will retry a CONFIRMED message before giving up and reporting an 00215 * error. 00216 * 00217 * @param count The number of retries for confirmed messages. 00218 * 00219 * @return LORAWAN_STATUS_OK or a negative error code. 00220 */ 00221 lorawan_status_t set_confirmed_msg_retry(uint8_t count); 00222 00223 /** Sets up the data rate. 00224 * 00225 * `set_datarate()` first verifies whether the data rate given is valid or not. 00226 * If it is valid, the system sets the given data rate to the channel. 00227 * 00228 * @param data_rate The intended data rate, for example DR_0 or DR_1. 00229 * Note that the macro DR_* can mean different 00230 * things in different regions. 00231 * 00232 * @return LORAWAN_STATUS_OK if everything goes well, otherwise 00233 * a negative error code. 00234 */ 00235 lorawan_status_t set_channel_data_rate(uint8_t data_rate); 00236 00237 /** Enables ADR. 00238 * 00239 * @param adr_enabled 0 ADR disabled, 1 ADR enabled. 00240 * 00241 * @return LORAWAN_STATUS_OK on success, a negative error 00242 * code on failure. 00243 */ 00244 lorawan_status_t enable_adaptive_datarate(bool adr_enabled); 00245 00246 /** Send message to gateway 00247 * 00248 * @param port The application port number. Port numbers 0 and 224 00249 * are reserved, whereas port numbers from 1 to 223 00250 * (0x01 to 0xDF) are valid port numbers. 00251 * Anything out of this range is illegal. 00252 * 00253 * @param data A pointer to the data being sent. The ownership of the 00254 * buffer is not transferred. The data is copied to the 00255 * internal buffers. 00256 * 00257 * @param length The size of data in bytes. 00258 * 00259 * @param flags A flag used to determine what type of 00260 * message is being sent, for example: 00261 * 00262 * MSG_UNCONFIRMED_FLAG = 0x01 00263 * MSG_CONFIRMED_FLAG = 0x02 00264 * MSG_MULTICAST_FLAG = 0x04 00265 * MSG_PROPRIETARY_FLAG = 0x08 00266 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00267 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00268 * MSG_CONFIRMED_FLAG depending on the intended use. 00269 * 00270 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00271 * a confirmed message flag for a proprietary message. 00272 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00273 * mutually exclusive. 00274 * 00275 * @param null_allowed Internal use only. Needed for sending empty packet 00276 * having CONFIRMED bit on. 00277 * 00278 * @param allow_port_0 Internal use only. Needed for flushing MAC commands. 00279 * 00280 * @return The number of bytes sent, or 00281 * LORAWAN_STATUS_WOULD_BLOCK if another TX is 00282 * ongoing, or a negative error code on failure. 00283 */ 00284 int16_t handle_tx(uint8_t port, const uint8_t *data, 00285 uint16_t length, uint8_t flags, 00286 bool null_allowed = false, bool allow_port_0 = false); 00287 00288 /** Receives a message from the Network Server. 00289 * 00290 * @param data A pointer to buffer where the received data will be 00291 * stored. 00292 * 00293 * @param length The size of data in bytes 00294 * 00295 * @param port The application port number. Port numbers 0 and 224 00296 * are reserved, whereas port numbers from 1 to 223 00297 * (0x01 to 0xDF) are valid port numbers. 00298 * Anything out of this range is illegal. 00299 * 00300 * In return will contain the number of port to which 00301 * message was received. 00302 * 00303 * @param flags A flag is used to determine what type of 00304 * message is being received, for example: 00305 * 00306 * MSG_UNCONFIRMED_FLAG = 0x01, 00307 * MSG_CONFIRMED_FLAG = 0x02 00308 * MSG_MULTICAST_FLAG = 0x04, 00309 * MSG_PROPRIETARY_FLAG = 0x08 00310 * 00311 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00312 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00313 * MSG_CONFIRMED_FLAG depending on the intended use. 00314 * 00315 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00316 * a confirmed message flag for a proprietary message. 00317 * 00318 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00319 * not mutually exclusive, i.e., the user can subscribe to 00320 * receive both CONFIRMED AND UNCONFIRMED messages at 00321 * the same time. 00322 * 00323 * In return will contain the flags to determine what kind 00324 * of message was received. 00325 * 00326 * @param validate_params If set to true, the given port and flags values will be checked 00327 * against the values received with the message. If values do not 00328 * match, LORAWAN_STATUS_WOULD_BLOCK will be returned. 00329 * 00330 * @return It could be one of these: 00331 * i) 0 if there is nothing else to read. 00332 * ii) Number of bytes written to user buffer. 00333 * iii) LORAWAN_STATUS_WOULD_BLOCK if there is 00334 * nothing available to read at the moment. 00335 * iv) A negative error code on failure. 00336 */ 00337 int16_t handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params); 00338 00339 /** Send Link Check Request MAC command. 00340 * 00341 * 00342 * This API schedules a Link Check Request command (LinkCheckReq) for the network 00343 * server and once the response, i.e., LinkCheckAns MAC command is received 00344 * from the Network Server, an event is generated. 00345 * 00346 * A callback function for the link check response must be set prior to using 00347 * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown. 00348 * 00349 * @return LORAWAN_STATUS_OK on successfully queuing a request, or 00350 * a negative error code on failure. 00351 * 00352 */ 00353 lorawan_status_t set_link_check_request(); 00354 00355 /** Removes link check request sticky MAC command. 00356 * 00357 * Any already queued request may still get entertained. However, no new 00358 * requests will be made. 00359 */ 00360 void remove_link_check_request(); 00361 00362 /** Shuts down the LoRaWAN protocol. 00363 * 00364 * In response to the user call for disconnection, the stack shuts down itself. 00365 * 00366 * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown. 00367 */ 00368 lorawan_status_t shutdown(); 00369 00370 /** Change device class 00371 * 00372 * Change current device class. 00373 * 00374 * @param device_class The device class 00375 * 00376 * @return LORAWAN_STATUS_OK on success, 00377 * LORAWAN_STATUS_UNSUPPORTED is requested class is not supported, 00378 * or other negative error code if request failed. 00379 */ 00380 lorawan_status_t set_device_class(const device_class_t &device_class); 00381 00382 /** Acquire TX meta-data 00383 * 00384 * Upon successful transmission, TX meta-data will be made available 00385 * 00386 * @param metadata A reference to the inbound structure which will be 00387 * filled with any TX meta-data if available. 00388 * 00389 * @return LORAWAN_STATUS_OK if successful, 00390 * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise 00391 */ 00392 lorawan_status_t acquire_tx_metadata(lorawan_tx_metadata &metadata); 00393 00394 /** Acquire RX meta-data 00395 * 00396 * Upon successful reception, RX meta-data will be made available 00397 * 00398 * @param metadata A reference to the inbound structure which will be 00399 * filled with any RX meta-data if available. 00400 * 00401 * @return LORAWAN_STATUS_OK if successful, 00402 * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise 00403 */ 00404 lorawan_status_t acquire_rx_metadata(lorawan_rx_metadata &metadata); 00405 00406 /** Acquire backoff meta-data 00407 * 00408 * Get hold of backoff time after which the transmission will take place. 00409 * 00410 * @param backoff A reference to the inbound integer which will be 00411 * filled with any backoff meta-data if available. 00412 * 00413 * @return LORAWAN_STATUS_OK if successful, 00414 * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise 00415 */ 00416 lorawan_status_t acquire_backoff_metadata(int &backoff); 00417 00418 /** Stops sending 00419 * 00420 * Stop sending any outstanding messages if they are not yet queued for 00421 * transmission, i.e., if the backoff timer is nhot elapsed yet. 00422 * 00423 * @return LORAWAN_STATUS_OK if the transmission is cancelled. 00424 * LORAWAN_STATUS_BUSY otherwise. 00425 */ 00426 lorawan_status_t stop_sending(void); 00427 00428 void lock(void) 00429 { 00430 _loramac.lock(); 00431 } 00432 void unlock(void) 00433 { 00434 _loramac.unlock(); 00435 } 00436 00437 private: 00438 typedef mbed::ScopedLock<LoRaWANStack> Lock; 00439 /** 00440 * Checks if the user provided port is valid or not 00441 */ 00442 bool is_port_valid(uint8_t port, bool allow_port_0 = false); 00443 00444 /** 00445 * State machine for stack controller layer. 00446 */ 00447 lorawan_status_t state_controller(device_states_t new_state); 00448 00449 /** 00450 * Helpers for state controller 00451 */ 00452 void process_uninitialized_state(lorawan_status_t &op_status); 00453 void process_idle_state(lorawan_status_t &op_status); 00454 void process_connected_state(); 00455 void process_connecting_state(lorawan_status_t &op_status); 00456 void process_joining_state(lorawan_status_t &op_status); 00457 void process_scheduling_state(lorawan_status_t &op_status); 00458 void process_status_check_state(); 00459 void process_shutdown_state(lorawan_status_t &op_status); 00460 void state_machine_run_to_completion(void); 00461 00462 /** 00463 * Handles MLME indications 00464 */ 00465 void mlme_indication_handler(void); 00466 00467 /** 00468 * Handles an MLME confirmation 00469 */ 00470 void mlme_confirm_handler(void); 00471 00472 /** 00473 * Handles an MCPS confirmation 00474 */ 00475 void mcps_confirm_handler(void); 00476 00477 /** 00478 * Handles an MCPS indication 00479 */ 00480 void mcps_indication_handler(void); 00481 00482 /** 00483 * Sets up user application port 00484 */ 00485 lorawan_status_t set_application_port(uint8_t port, bool allow_port_0 = false); 00486 00487 /** 00488 * Handles connection internally 00489 */ 00490 lorawan_status_t handle_connect(bool is_otaa); 00491 00492 00493 /** Send event to application. 00494 * 00495 * @param event The event to be sent. 00496 */ 00497 void send_event_to_application(const lorawan_event_t event) const; 00498 00499 /** Send empty uplink message to network. 00500 * 00501 * Sends an empty confirmed message to gateway. 00502 * 00503 * @param port The event to be sent. 00504 */ 00505 void send_automatic_uplink_message(uint8_t port); 00506 00507 /** 00508 * TX interrupt handlers and corresponding processors 00509 */ 00510 void tx_interrupt_handler(void); 00511 void tx_timeout_interrupt_handler(void); 00512 void process_transmission(void); 00513 void process_transmission_timeout(void); 00514 00515 /** 00516 * RX interrupt handlers and corresponding processors 00517 */ 00518 void rx_interrupt_handler(const uint8_t *payload, uint16_t size, int16_t rssi, 00519 int8_t snr); 00520 void rx_timeout_interrupt_handler(void); 00521 void rx_error_interrupt_handler(void); 00522 void process_reception(const uint8_t *payload, uint16_t size, int16_t rssi, 00523 int8_t snr); 00524 void process_reception_timeout(bool is_timeout); 00525 00526 int convert_to_msg_flag(const mcps_type_t type); 00527 00528 void make_tx_metadata_available(void); 00529 void make_rx_metadata_available(void); 00530 00531 void handle_ack_expiry_for_class_c(void); 00532 00533 private: 00534 LoRaMac _loramac; 00535 radio_events_t radio_events; 00536 device_states_t _device_current_state; 00537 lorawan_app_callbacks_t _callbacks; 00538 lorawan_session_t _lw_session; 00539 loramac_tx_message_t _tx_msg; 00540 loramac_rx_message_t _rx_msg; 00541 lorawan_tx_metadata _tx_metadata; 00542 lorawan_rx_metadata _rx_metadata; 00543 uint8_t _num_retry; 00544 uint32_t _ctrl_flags; 00545 uint8_t _app_port; 00546 bool _link_check_requested; 00547 bool _automatic_uplink_ongoing; 00548 volatile bool _ready_for_rx; 00549 uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD]; 00550 events::EventQueue *_queue; 00551 lorawan_time_t _tx_timestamp; 00552 00553 #if defined(LORAWAN_COMPLIANCE_TEST) 00554 00555 /** 00556 * Used only for compliance testing 00557 */ 00558 void compliance_test_handler(loramac_mcps_indication_t *mcps_indication); 00559 00560 /** 00561 * Used only for compliance testing 00562 */ 00563 lorawan_status_t send_compliance_test_frame_to_mac(); 00564 00565 compliance_test_t _compliance_test; 00566 #endif 00567 }; 00568 00569 #endif /* LORAWANSTACK_H_ */
Generated on Tue Jul 12 2022 12:44:32 by
1.7.2