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