Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
LoRaWANStack.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/mbed_atomic.h" 00046 #include "platform/Callback.h" 00047 #include "platform/NonCopyable.h" 00048 #include "platform/ScopedLock.h" 00049 00050 #include "lorastack/mac/LoRaMac.h" 00051 #include "system/LoRaWANTimer.h" 00052 #include "system/lorawan_data_structures.h" 00053 #include "LoRaRadio.h" 00054 00055 class LoRaPHY; 00056 00057 /** LoRaWANStack Class 00058 * A controller layer for LoRaWAN MAC and PHY 00059 */ 00060 class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> { 00061 00062 public: 00063 LoRaWANStack(); 00064 00065 /** Binds PHY layer and radio driver to stack. 00066 * 00067 * MAC layer is totally detached from the PHY layer so the stack layer 00068 * needs to play the role of an arbitrator. 00069 * This API sets the PHY layer object to stack and bind the radio driver 00070 * object from the application to the PHY layer. 00071 * Also initialises radio callback handles which the radio driver will 00072 * use in order to report events. 00073 * 00074 * @param radio LoRaRadio object, i.e., the radio driver 00075 * @param phy LoRaPHY object. 00076 * 00077 */ 00078 void bind_phy_and_radio_driver(LoRaRadio &radio, LoRaPHY &phy); 00079 00080 /** End device initialization. 00081 * @param queue A pointer to an EventQueue passed from the application. 00082 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00083 */ 00084 lorawan_status_t initialize_mac_layer(events::EventQueue *queue); 00085 00086 /** Sets all callbacks for the application. 00087 * 00088 * @param callbacks A pointer to the structure carrying callbacks. 00089 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00090 */ 00091 lorawan_status_t set_lora_callbacks(const lorawan_app_callbacks_t *callbacks); 00092 00093 /** Connect OTAA or ABP using Mbed-OS config system 00094 * 00095 * @return For ABP: If everything goes well, LORAWAN_STATUS_OK is returned for first call followed by 00096 * a 'CONNECTED' event. Otherwise a negative error code is returned. 00097 * Any subsequent call will return LORAWAN_STATUS_ALREADY_CONNECTED and no event follows. 00098 * 00099 * For OTAA: When a JoinRequest is sent, LORAWAN_STATUS_CONNECT_IN_PROGRESS is returned for the first call. 00100 * Any subsequent call will return either LORAWAN_STATUS_BUSY (if the previous request for connection 00101 * is still underway) or LORAWAN_STATUS_ALREADY_CONNECTED (if a network was already joined successfully). 00102 * A 'CONNECTED' event is sent to the application when the JoinAccept is received. 00103 */ 00104 lorawan_status_t connect(); 00105 00106 /** Connect OTAA or ABP with parameters 00107 * 00108 * @param connect Options for an end device connection to the gateway. 00109 * 00110 * @return For ABP: If everything goes well, LORAWAN_STATUS_OK is returned for first call followed by 00111 * a 'CONNECTED' event. Otherwise a negative error code is returned. 00112 * Any subsequent call will return LORAWAN_STATUS_ALREADY_CONNECTED and no event follows. 00113 * 00114 * For OTAA: When a JoinRequest is sent, LORAWAN_STATUS_CONNECT_IN_PROGRESS is returned for the first call. 00115 * Any subsequent call will return either LORAWAN_STATUS_BUSY (if the previous request for connection 00116 * is still underway) or LORAWAN_STATUS_ALREADY_CONNECTED (if a network was already joined successfully). 00117 * A 'CONNECTED' event is sent to the application when the JoinAccept is received. 00118 */ 00119 lorawan_status_t connect(const lorawan_connect_t &connect); 00120 00121 /** Adds channels to use. 00122 * 00123 * You can provide a list of channels with appropriate parameters filled 00124 * in. However, this list is not absolute. In some regions, a CF 00125 * list gets implemented by default, which means that the network can overwrite your channel 00126 * frequency settings right after receiving a Join Accept. You may try 00127 * to set up any channel or channels after that and if the channel requested 00128 * is already active, the request is silently ignored. A negative error 00129 * code is returned if there is any problem with parameters. 00130 * 00131 * You need to ensure that the base station nearby supports the channel or channels being added. 00132 * 00133 * If your list includes a default channel (a channel where Join Requests 00134 * are received) you cannot fully configure the channel parameters. 00135 * Either leave the channel settings to default or check your 00136 * corresponding PHY layer implementation. For example, LoRaPHYE868. 00137 * 00138 * @param channel_plan A list of channels or a single channel. 00139 * 00140 * @return LORAWAN_STATUS_OK on success, a negative error 00141 * code on failure. 00142 */ 00143 lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan); 00144 00145 /** Removes a channel from the list. 00146 * 00147 * @param channel_id Index of the channel being removed 00148 * 00149 * @return LORAWAN_STATUS_OK on success, a negative error 00150 * code on failure. 00151 */ 00152 lorawan_status_t remove_a_channel(uint8_t channel_id); 00153 00154 /** Removes a previously set channel plan. 00155 * 00156 * @return LORAWAN_STATUS_OK on success, a negative error 00157 * code on failure. 00158 */ 00159 lorawan_status_t drop_channel_list(); 00160 00161 /** Gets a list of currently enabled channels . 00162 * 00163 * @param channel_plan The channel plan structure to store final result. 00164 * 00165 * @return LORAWAN_STATUS_OK on success, a negative error 00166 * code on failure. 00167 */ 00168 lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan); 00169 00170 /** Sets up a retry counter for confirmed messages. 00171 * 00172 * Valid only for confirmed messages. This API sets the number of times the 00173 * stack will retry a CONFIRMED message before giving up and reporting an 00174 * error. 00175 * 00176 * @param count The number of retries for confirmed messages. 00177 * 00178 * @return LORAWAN_STATUS_OK or a negative error code. 00179 */ 00180 lorawan_status_t set_confirmed_msg_retry(uint8_t count); 00181 00182 /** Sets up the data rate. 00183 * 00184 * `set_datarate()` first verifies whether the data rate given is valid or not. 00185 * If it is valid, the system sets the given data rate to the channel. 00186 * 00187 * @param data_rate The intended data rate, for example DR_0 or DR_1. 00188 * Note that the macro DR_* can mean different 00189 * things in different regions. 00190 * 00191 * @return LORAWAN_STATUS_OK if everything goes well, otherwise 00192 * a negative error code. 00193 */ 00194 lorawan_status_t set_channel_data_rate(uint8_t data_rate); 00195 00196 /** Enables ADR. 00197 * 00198 * @param adr_enabled 0 ADR disabled, 1 ADR enabled. 00199 * 00200 * @return LORAWAN_STATUS_OK on success, a negative error 00201 * code on failure. 00202 */ 00203 lorawan_status_t enable_adaptive_datarate(bool adr_enabled); 00204 00205 /** Send message to gateway 00206 * 00207 * @param port The application port number. Port numbers 0 and 224 00208 * are reserved, whereas port numbers from 1 to 223 00209 * (0x01 to 0xDF) are valid port numbers. 00210 * Anything out of this range is illegal. 00211 * 00212 * @param data A pointer to the data being sent. The ownership of the 00213 * buffer is not transferred. The data is copied to the 00214 * internal buffers. 00215 * 00216 * @param length The size of data in bytes. 00217 * 00218 * @param flags A flag used to determine what type of 00219 * message is being sent, for example: 00220 * 00221 * MSG_UNCONFIRMED_FLAG = 0x01 00222 * MSG_CONFIRMED_FLAG = 0x02 00223 * MSG_MULTICAST_FLAG = 0x04 00224 * MSG_PROPRIETARY_FLAG = 0x08 00225 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00226 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00227 * MSG_CONFIRMED_FLAG depending on the intended use. 00228 * 00229 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00230 * a confirmed message flag for a proprietary message. 00231 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00232 * mutually exclusive. 00233 * 00234 * @param null_allowed Internal use only. Needed for sending empty packet 00235 * having CONFIRMED bit on. 00236 * 00237 * @param allow_port_0 Internal use only. Needed for flushing MAC commands. 00238 * 00239 * @return The number of bytes sent, or 00240 * LORAWAN_STATUS_WOULD_BLOCK if another TX is 00241 * ongoing, or a negative error code on failure. 00242 */ 00243 int16_t handle_tx(uint8_t port, const uint8_t *data, 00244 uint16_t length, uint8_t flags, 00245 bool null_allowed = false, bool allow_port_0 = false); 00246 00247 /** Receives a message from the Network Server. 00248 * 00249 * @param data A pointer to buffer where the received data will be 00250 * stored. 00251 * 00252 * @param length The size of data in bytes 00253 * 00254 * @param port The application port number. Port numbers 0 and 224 00255 * are reserved, whereas port numbers from 1 to 223 00256 * (0x01 to 0xDF) are valid port numbers. 00257 * Anything out of this range is illegal. 00258 * 00259 * In return will contain the number of port to which 00260 * message was received. 00261 * 00262 * @param flags A flag is used to determine what type of 00263 * message is being received, for example: 00264 * 00265 * MSG_UNCONFIRMED_FLAG = 0x01, 00266 * MSG_CONFIRMED_FLAG = 0x02 00267 * MSG_MULTICAST_FLAG = 0x04, 00268 * MSG_PROPRIETARY_FLAG = 0x08 00269 * 00270 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00271 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00272 * MSG_CONFIRMED_FLAG depending on the intended use. 00273 * 00274 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00275 * a confirmed message flag for a proprietary message. 00276 * 00277 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00278 * not mutually exclusive, i.e., the user can subscribe to 00279 * receive both CONFIRMED AND UNCONFIRMED messages at 00280 * the same time. 00281 * 00282 * In return will contain the flags to determine what kind 00283 * of message was received. 00284 * 00285 * @param validate_params If set to true, the given port and flags values will be checked 00286 * against the values received with the message. If values do not 00287 * match, LORAWAN_STATUS_WOULD_BLOCK will be returned. 00288 * 00289 * @return It could be one of these: 00290 * i) 0 if there is nothing else to read. 00291 * ii) Number of bytes written to user buffer. 00292 * iii) LORAWAN_STATUS_WOULD_BLOCK if there is 00293 * nothing available to read at the moment. 00294 * iv) A negative error code on failure. 00295 */ 00296 int16_t handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params); 00297 00298 /** Send Link Check Request MAC command. 00299 * 00300 * 00301 * This API schedules a Link Check Request command (LinkCheckReq) for the network 00302 * server and once the response, i.e., LinkCheckAns MAC command is received 00303 * from the Network Server, an event is generated. 00304 * 00305 * A callback function for the link check response must be set prior to using 00306 * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown. 00307 * 00308 * @return LORAWAN_STATUS_OK on successfully queuing a request, or 00309 * a negative error code on failure. 00310 * 00311 */ 00312 lorawan_status_t set_link_check_request(); 00313 00314 /** Removes link check request sticky MAC command. 00315 * 00316 * Any already queued request may still get entertained. However, no new 00317 * requests will be made. 00318 */ 00319 void remove_link_check_request(); 00320 00321 /** Shuts down the LoRaWAN protocol. 00322 * 00323 * In response to the user call for disconnection, the stack shuts down itself. 00324 * 00325 * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown. 00326 */ 00327 lorawan_status_t shutdown(); 00328 00329 /** Change device class 00330 * 00331 * Change current device class. 00332 * 00333 * @param device_class The device class 00334 * 00335 * @return LORAWAN_STATUS_OK on success, 00336 * LORAWAN_STATUS_UNSUPPORTED is requested class is not supported, 00337 * or other negative error code if request failed. 00338 */ 00339 lorawan_status_t set_device_class(const device_class_t &device_class); 00340 00341 /** Acquire TX meta-data 00342 * 00343 * Upon successful transmission, TX meta-data will be made available 00344 * 00345 * @param metadata A reference to the inbound structure which will be 00346 * filled with any TX meta-data if available. 00347 * 00348 * @return LORAWAN_STATUS_OK if successful, 00349 * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise 00350 */ 00351 lorawan_status_t acquire_tx_metadata(lorawan_tx_metadata &metadata); 00352 00353 /** Acquire RX meta-data 00354 * 00355 * Upon successful reception, RX meta-data will be made available 00356 * 00357 * @param metadata A reference to the inbound structure which will be 00358 * filled with any RX meta-data if available. 00359 * 00360 * @return LORAWAN_STATUS_OK if successful, 00361 * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise 00362 */ 00363 lorawan_status_t acquire_rx_metadata(lorawan_rx_metadata &metadata); 00364 00365 /** Acquire backoff meta-data 00366 * 00367 * Get hold of backoff time after which the transmission will take place. 00368 * 00369 * @param backoff A reference to the inbound integer which will be 00370 * filled with any backoff meta-data if available. 00371 * 00372 * @return LORAWAN_STATUS_OK if successful, 00373 * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise 00374 */ 00375 lorawan_status_t acquire_backoff_metadata(int &backoff); 00376 00377 /** Stops sending 00378 * 00379 * Stop sending any outstanding messages if they are not yet queued for 00380 * transmission, i.e., if the backoff timer is nhot elapsed yet. 00381 * 00382 * @return LORAWAN_STATUS_OK if the transmission is cancelled. 00383 * LORAWAN_STATUS_BUSY otherwise. 00384 */ 00385 lorawan_status_t stop_sending(void); 00386 00387 void lock(void) 00388 { 00389 _loramac.lock(); 00390 } 00391 void unlock(void) 00392 { 00393 _loramac.unlock(); 00394 } 00395 00396 private: 00397 typedef mbed::ScopedLock<LoRaWANStack> Lock; 00398 /** 00399 * Checks if the user provided port is valid or not 00400 */ 00401 bool is_port_valid(uint8_t port, bool allow_port_0 = false); 00402 00403 /** 00404 * State machine for stack controller layer. 00405 */ 00406 lorawan_status_t state_controller(device_states_t new_state); 00407 00408 /** 00409 * Helpers for state controller 00410 */ 00411 void process_uninitialized_state(lorawan_status_t &op_status); 00412 void process_idle_state(lorawan_status_t &op_status); 00413 void process_connected_state(); 00414 void process_connecting_state(lorawan_status_t &op_status); 00415 void process_joining_state(lorawan_status_t &op_status); 00416 void process_scheduling_state(lorawan_status_t &op_status); 00417 void process_status_check_state(); 00418 void process_shutdown_state(lorawan_status_t &op_status); 00419 void state_machine_run_to_completion(void); 00420 00421 /** 00422 * Handles MLME indications 00423 */ 00424 void mlme_indication_handler(void); 00425 00426 /** 00427 * Handles an MLME confirmation 00428 */ 00429 void mlme_confirm_handler(void); 00430 00431 /** 00432 * Handles an MCPS confirmation 00433 */ 00434 void mcps_confirm_handler(void); 00435 00436 /** 00437 * Handles an MCPS indication 00438 */ 00439 void mcps_indication_handler(void); 00440 00441 /** 00442 * Sets up user application port 00443 */ 00444 lorawan_status_t set_application_port(uint8_t port, bool allow_port_0 = false); 00445 00446 /** 00447 * Handles connection internally 00448 */ 00449 lorawan_status_t handle_connect(bool is_otaa); 00450 00451 00452 /** Send event to application. 00453 * 00454 * @param event The event to be sent. 00455 */ 00456 void send_event_to_application(const lorawan_event_t event) const; 00457 00458 /** Send empty uplink message to network. 00459 * 00460 * Sends an empty confirmed message to gateway. 00461 * 00462 * @param port The event to be sent. 00463 */ 00464 void send_automatic_uplink_message(uint8_t port); 00465 00466 /** 00467 * TX interrupt handlers and corresponding processors 00468 */ 00469 void tx_interrupt_handler(void); 00470 void tx_timeout_interrupt_handler(void); 00471 void process_transmission(void); 00472 void process_transmission_timeout(void); 00473 00474 /** 00475 * RX interrupt handlers and corresponding processors 00476 */ 00477 void rx_interrupt_handler(const uint8_t *payload, uint16_t size, int16_t rssi, 00478 int8_t snr); 00479 void rx_timeout_interrupt_handler(void); 00480 void rx_error_interrupt_handler(void); 00481 void process_reception(const uint8_t *payload, uint16_t size, int16_t rssi, 00482 int8_t snr); 00483 void process_reception_timeout(bool is_timeout); 00484 00485 int convert_to_msg_flag(const mcps_type_t type); 00486 00487 void make_tx_metadata_available(void); 00488 void make_rx_metadata_available(void); 00489 00490 void handle_scheduling_failure(void); 00491 00492 void post_process_tx_with_reception(void); 00493 void post_process_tx_no_reception(void); 00494 00495 private: 00496 LoRaMac _loramac; 00497 radio_events_t radio_events; 00498 device_states_t _device_current_state; 00499 lorawan_app_callbacks_t _callbacks; 00500 lorawan_session_t _lw_session; 00501 loramac_tx_message_t _tx_msg; 00502 loramac_rx_message_t _rx_msg; 00503 lorawan_tx_metadata _tx_metadata; 00504 lorawan_rx_metadata _rx_metadata; 00505 uint8_t _num_retry; 00506 uint8_t _qos_cnt; 00507 uint32_t _ctrl_flags; 00508 uint8_t _app_port; 00509 bool _link_check_requested; 00510 bool _automatic_uplink_ongoing; 00511 core_util_atomic_flag _rx_payload_in_use; 00512 uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD]; 00513 events::EventQueue *_queue; 00514 lorawan_time_t _tx_timestamp; 00515 }; 00516 00517 #endif /* LORAWANSTACK_H_ */
Generated on Tue Jul 12 2022 13:54:27 by
