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 void lock(void) { _loramac.lock(); } 00383 void unlock(void) { _loramac.unlock(); } 00384 00385 private: 00386 typedef mbed::ScopedLock<LoRaWANStack> Lock; 00387 /** 00388 * Checks if the user provided port is valid or not 00389 */ 00390 bool is_port_valid(uint8_t port, bool allow_port_0 = false); 00391 00392 /** 00393 * State machine for stack controller layer. 00394 */ 00395 lorawan_status_t state_controller(device_states_t new_state); 00396 00397 /** 00398 * Helpers for state controller 00399 */ 00400 void process_uninitialized_state(lorawan_status_t& op_status); 00401 void process_idle_state(lorawan_status_t& op_status); 00402 void process_connected_state(); 00403 void process_connecting_state(lorawan_status_t& op_status); 00404 void process_joining_state(lorawan_status_t& op_status); 00405 void process_scheduling_state(lorawan_status_t& op_status); 00406 void process_status_check_state(); 00407 void process_shutdown_state(lorawan_status_t& op_status); 00408 void state_machine_run_to_completion(void); 00409 00410 /** 00411 * Handles MLME indications 00412 */ 00413 void mlme_indication_handler(void); 00414 00415 /** 00416 * Handles an MLME confirmation 00417 */ 00418 void mlme_confirm_handler(void); 00419 00420 /** 00421 * Handles an MCPS confirmation 00422 */ 00423 void mcps_confirm_handler(void); 00424 00425 /** 00426 * Handles an MCPS indication 00427 */ 00428 void mcps_indication_handler(void); 00429 00430 /** 00431 * Sets up user application port 00432 */ 00433 lorawan_status_t set_application_port(uint8_t port, bool allow_port_0 = false); 00434 00435 /** 00436 * Handles connection internally 00437 */ 00438 lorawan_status_t handle_connect(bool is_otaa); 00439 00440 00441 /** Send event to application. 00442 * 00443 * @param event The event to be sent. 00444 */ 00445 void send_event_to_application(const lorawan_event_t event) const; 00446 00447 /** Send empty uplink message to network. 00448 * 00449 * Sends an empty confirmed message to gateway. 00450 * 00451 * @param port The event to be sent. 00452 */ 00453 void send_automatic_uplink_message(uint8_t port); 00454 00455 /** 00456 * TX interrupt handlers and corresponding processors 00457 */ 00458 void tx_interrupt_handler(void); 00459 void tx_timeout_interrupt_handler(void); 00460 void process_transmission(void); 00461 void process_transmission_timeout(void); 00462 00463 /** 00464 * RX interrupt handlers and corresponding processors 00465 */ 00466 void rx_interrupt_handler(const uint8_t *payload, uint16_t size, int16_t rssi, 00467 int8_t snr); 00468 void rx_timeout_interrupt_handler(void); 00469 void rx_error_interrupt_handler(void); 00470 void process_reception(const uint8_t *payload, uint16_t size, int16_t rssi, 00471 int8_t snr); 00472 void process_reception_timeout(bool is_timeout); 00473 00474 int convert_to_msg_flag(const mcps_type_t type); 00475 00476 private: 00477 LoRaMac _loramac; 00478 radio_events_t radio_events; 00479 device_states_t _device_current_state; 00480 lorawan_app_callbacks_t _callbacks; 00481 lorawan_session_t _lw_session; 00482 loramac_tx_message_t _tx_msg; 00483 loramac_rx_message_t _rx_msg; 00484 uint8_t _num_retry; 00485 uint32_t _ctrl_flags; 00486 uint8_t _app_port; 00487 bool _link_check_requested; 00488 bool _automatic_uplink_ongoing; 00489 volatile bool _ready_for_rx; 00490 uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD]; 00491 events::EventQueue *_queue; 00492 00493 #if defined(LORAWAN_COMPLIANCE_TEST) 00494 00495 /** 00496 * Used only for compliance testing 00497 */ 00498 void compliance_test_handler(loramac_mcps_indication_t *mcps_indication); 00499 00500 /** 00501 * Used only for compliance testing 00502 */ 00503 lorawan_status_t send_compliance_test_frame_to_mac(); 00504 00505 compliance_test_t _compliance_test; 00506 #endif 00507 }; 00508 00509 #endif /* LORAWANSTACK_H_ */
Generated on Tue Jul 12 2022 18:18:38 by
