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 00048 #include "lorastack/mac/LoRaMac.h" 00049 #include "system/LoRaWANTimer.h" 00050 #include "system/lorawan_data_structures.h" 00051 #include "LoRaRadio.h" 00052 00053 class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> { 00054 private: 00055 /** End-device states. 00056 * 00057 */ 00058 typedef enum device_states { 00059 DEVICE_STATE_NOT_INITIALIZED, 00060 DEVICE_STATE_INIT, 00061 DEVICE_STATE_JOINING, 00062 DEVICE_STATE_ABP_CONNECTING, 00063 DEVICE_STATE_JOINED, 00064 DEVICE_STATE_SEND, 00065 DEVICE_STATE_IDLE, 00066 #if defined(LORAWAN_COMPLIANCE_TEST) 00067 DEVICE_STATE_COMPLIANCE_TEST, 00068 #endif 00069 DEVICE_STATE_SHUTDOWN 00070 } device_states_t; 00071 00072 public: 00073 static LoRaWANStack& get_lorawan_stack(); 00074 00075 /** Binds radio driver to PHY layer. 00076 * 00077 * MAC layer is totally detached from the PHY layer so the stack layer 00078 * needs to play the role of an arbitrator. This API gets a radio driver 00079 * object from the application (via LoRaWANInterface), binds it to the PHY 00080 * layer and initialises radio callback handles which the radio driver will 00081 * use in order to report events. 00082 * 00083 * @param radio LoRaRadio object, i.e., the radio driver 00084 * 00085 */ 00086 void bind_radio_driver(LoRaRadio& radio); 00087 00088 /** Connect OTAA or ABP using Mbed-OS config system 00089 * 00090 * Connect by Over The Air Activation or Activation By Personalization. 00091 * You need to configure the connection properly via the Mbed OS configuration 00092 * system. 00093 * 00094 * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative. 00095 * However, this is not a real error. It tells you that the connection is in progress and you will 00096 * be notified of the completion via an event. By default, after the Join Accept message 00097 * is received, base stations may provide the node with a CF-List that replaces 00098 * all user-configured channels except the Join/Default channels. A CF-List can 00099 * configure a maximum of five channels other than the default channels. 00100 * 00101 * In case of ABP, the CONNECTED event is posted before the call to `connect()` returns. 00102 * To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection. 00103 * By default, the PHY layers configure only the mandatory Join channels. The retransmission back-off restrictions 00104 * on these channels are severe and you may experience long delays or even failures in the confirmed traffic. 00105 * If you add more channels, the aggregated duty cycle becomes much more relaxed as compared to the Join (default) channels only. 00106 * 00107 * **NOTES ON RECONNECTION:** 00108 * Currently, the Mbed OS LoRaWAN implementation does not support non-volatile 00109 * memory storage. Therefore, the state and frame counters cannot be restored after 00110 * a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN 00111 * protocol, the state and frame counters are saved. Connecting again would try to 00112 * restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset 00113 * to zero for OTAA and a new Join request lets the network server know 00114 * that the counters need a reset. The same is said about the ABP but there 00115 * is no way to convey this information to the network server. For a network 00116 * server, an ABP device is always connected. That's why storing the frame counters 00117 * is important, at least for ABP. That's why we try to restore frame counters from 00118 * session information after a disconnection. 00119 * 00120 * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS 00121 * on success, or a negative error code on failure. 00122 */ 00123 lorawan_status_t connect(); 00124 00125 /** Connect OTAA or ABP with parameters 00126 * 00127 * All connection parameters are chosen by the user and provided in the 00128 * data structure passed down. 00129 * 00130 * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative. 00131 * However, this is not a real error. It tells you that connection is in progress and you will 00132 * be notified of completion via an event. By default, after Join Accept message 00133 * is received, base stations may provide the node with a CF-List which replaces 00134 * all user-configured channels except the Join/Default channels. A CF-List can 00135 * configure a maximum of five channels other than the default channels. 00136 * 00137 * In case of ABP, the CONNECTED event is posted before the call to `connect()` returns. 00138 * To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection. 00139 * By default, the PHY layers configure only the mandatory Join 00140 * channels. The retransmission back-off restrictions on these channels 00141 * are severe and you may experience long delays or even 00142 * failures in the confirmed traffic. If you add more channels, the aggregated duty 00143 * cycle becomes much more relaxed as compared to the Join (default) channels only. 00144 * 00145 * **NOTES ON RECONNECTION:** 00146 * Currently, the Mbed OS LoRaWAN implementation does not support non-volatile 00147 * memory storage. Therefore, the state and frame counters cannot be restored after 00148 * a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN 00149 * protocol, the state and frame counters are saved. Connecting again would try to 00150 * restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset 00151 * to zero for OTAA and a new Join request lets the network server know 00152 * that the counters need a reset. The same is said about the ABP but there 00153 * is no way to convey this information to the network server. For a network 00154 * server, an ABP device is always connected. That's why storing the frame counters 00155 * is important, at least for ABP. That's why we try to restore frame counters from 00156 * session information after a disconnection. 00157 * 00158 * @param connect Options for an end device connection to the gateway. 00159 * 00160 * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS, 00161 * a negative error code on failure. 00162 */ 00163 lorawan_status_t connect(const lorawan_connect_t &connect); 00164 00165 /** End device initialization. 00166 * @param queue A pointer to an EventQueue passed from the application. 00167 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00168 */ 00169 lorawan_status_t initialize_mac_layer(events::EventQueue *queue); 00170 00171 /** Sets all callbacks for the application. 00172 * 00173 * @param callbacks A pointer to the structure carrying callbacks. 00174 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00175 */ 00176 lorawan_status_t set_lora_callbacks(lorawan_app_callbacks_t *callbacks); 00177 00178 /** Adds channels to use. 00179 * 00180 * You can provide a list of channels with appropriate parameters filled 00181 * in. However, this list is not absolute. In some regions, a CF 00182 * list gets implemented by default, which means that the network can overwrite your channel 00183 * frequency settings right after receiving a Join Accept. You may try 00184 * to set up any channel or channels after that and if the channel requested 00185 * is already active, the request is silently ignored. A negative error 00186 * code is returned if there is any problem with parameters. 00187 * 00188 * You need to ensure that the base station nearby supports the channel or channels being added. 00189 * 00190 * If your list includes a default channel (a channel where Join Requests 00191 * are received) you cannot fully configure the channel parameters. 00192 * Either leave the channel settings to default or check your 00193 * corresponding PHY layer implementation. For example, LoRaPHYE868. 00194 * 00195 * @param channel_plan A list of channels or a single channel. 00196 * 00197 * @return LORAWAN_STATUS_OK on success, a negative error 00198 * code on failure. 00199 */ 00200 lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan); 00201 00202 /** Removes a channel from the list. 00203 * 00204 * @param channel_id Index of the channel being removed 00205 * 00206 * @return LORAWAN_STATUS_OK on success, a negative error 00207 * code on failure. 00208 */ 00209 lorawan_status_t remove_a_channel(uint8_t channel_id); 00210 00211 /** Removes a previously set channel plan. 00212 * 00213 * @return LORAWAN_STATUS_OK on success, a negative error 00214 * code on failure. 00215 */ 00216 lorawan_status_t drop_channel_list(); 00217 00218 /** Gets a list of currently enabled channels . 00219 * 00220 * @param channel_plan The channel plan structure to store final result. 00221 * 00222 * @return LORAWAN_STATUS_OK on success, a negative error 00223 * code on failure. 00224 */ 00225 lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan); 00226 00227 /** Sets up a retry counter for confirmed messages. 00228 * 00229 * Valid only for confirmed messages. This API sets the number of times the 00230 * stack will retry a CONFIRMED message before giving up and reporting an 00231 * error. 00232 * 00233 * @param count The number of retries for confirmed messages. 00234 * 00235 * @return LORAWAN_STATUS_OK or a negative error code. 00236 */ 00237 lorawan_status_t set_confirmed_msg_retry(uint8_t count); 00238 00239 /** Sets up the data rate. 00240 * 00241 * `set_datarate()` first verifies whether the data rate given is valid or not. 00242 * If it is valid, the system sets the given data rate to the channel. 00243 * 00244 * @param data_rate The intended data rate, for example DR_0 or DR_1. 00245 * Note that the macro DR_* can mean different 00246 * things in different regions. 00247 * 00248 * @return LORAWAN_STATUS_OK if everything goes well, otherwise 00249 * a negative error code. 00250 */ 00251 lorawan_status_t set_channel_data_rate(uint8_t data_rate); 00252 00253 /** Enables ADR. 00254 * 00255 * @param adr_enabled 0 ADR disabled, 1 ADR enabled. 00256 * 00257 * @return LORAWAN_STATUS_OK on success, a negative error 00258 * code on failure. 00259 */ 00260 lorawan_status_t enable_adaptive_datarate(bool adr_enabled); 00261 00262 /** Send message to gateway 00263 * 00264 * @param port The application port number. Port numbers 0 and 224 00265 * are reserved, whereas port numbers from 1 to 223 00266 * (0x01 to 0xDF) are valid port numbers. 00267 * Anything out of this range is illegal. 00268 * 00269 * @param data A pointer to the data being sent. The ownership of the 00270 * buffer is not transferred. The data is copied to the 00271 * internal buffers. 00272 * 00273 * @param length The size of data in bytes. 00274 * 00275 * @param flags A flag used to determine what type of 00276 * message is being sent, for example: 00277 * 00278 * MSG_UNCONFIRMED_FLAG = 0x01 00279 * MSG_CONFIRMED_FLAG = 0x02 00280 * MSG_MULTICAST_FLAG = 0x04 00281 * MSG_PROPRIETARY_FLAG = 0x08 00282 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00283 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00284 * MSG_CONFIRMED_FLAG depending on the intended use. 00285 * 00286 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00287 * a confirmed message flag for a proprietary message. 00288 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00289 * mutually exclusive. 00290 * 00291 * @param null_allowed Internal use only. Needed for sending empty packet 00292 * having CONFIRMED bit on. 00293 * 00294 * @return The number of bytes sent, or 00295 * LORAWAN_STATUS_WOULD_BLOCK if another TX is 00296 * ongoing, or a negative error code on failure. 00297 */ 00298 int16_t handle_tx(uint8_t port, const uint8_t* data, 00299 uint16_t length, uint8_t flags, bool null_allowed = false); 00300 00301 /** Receives a message from the Network Server. 00302 * 00303 * @param data A pointer to buffer where the received data will be 00304 * stored. 00305 * 00306 * @param length The size of data in bytes 00307 * 00308 * @param port The application port number. Port numbers 0 and 224 00309 * are reserved, whereas port numbers from 1 to 223 00310 * (0x01 to 0xDF) are valid port numbers. 00311 * Anything out of this range is illegal. 00312 * 00313 * In return will contain the number of port to which 00314 * message was received. 00315 * 00316 * @param flags A flag is used to determine what type of 00317 * message is being received, for example: 00318 * 00319 * MSG_UNCONFIRMED_FLAG = 0x01, 00320 * MSG_CONFIRMED_FLAG = 0x02 00321 * MSG_MULTICAST_FLAG = 0x04, 00322 * MSG_PROPRIETARY_FLAG = 0x08 00323 * 00324 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00325 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00326 * MSG_CONFIRMED_FLAG depending on the intended use. 00327 * 00328 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00329 * a confirmed message flag for a proprietary message. 00330 * 00331 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00332 * not mutually exclusive, i.e., the user can subscribe to 00333 * receive both CONFIRMED AND UNCONFIRMED messages at 00334 * the same time. 00335 * 00336 * In return will contain the flags to determine what kind 00337 * of message was received. 00338 * 00339 * @param validate_params If set to true, the given port and flags values will be checked 00340 * against the values received with the message. If values do not 00341 * match, LORAWAN_STATUS_WOULD_BLOCK will be returned. 00342 * 00343 * @return It could be one of these: 00344 * i) 0 if there is nothing else to read. 00345 * ii) Number of bytes written to user buffer. 00346 * iii) LORAWAN_STATUS_WOULD_BLOCK if there is 00347 * nothing available to read at the moment. 00348 * iv) A negative error code on failure. 00349 */ 00350 int16_t handle_rx(uint8_t* data, uint16_t length, uint8_t& port, int& flags, bool validate_params); 00351 00352 /** Send Link Check Request MAC command. 00353 * 00354 * 00355 * This API schedules a Link Check Request command (LinkCheckReq) for the network 00356 * server and once the response, i.e., LinkCheckAns MAC command is received 00357 * from the Network Server, an event is generated. 00358 * 00359 * A callback function for the link check response must be set prior to using 00360 * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown. 00361 * 00362 * @return LORAWAN_STATUS_OK on successfully queuing a request, or 00363 * a negative error code on failure. 00364 * 00365 */ 00366 lorawan_status_t set_link_check_request(); 00367 00368 /** Removes link check request sticky MAC command. 00369 * 00370 * Any already queued request may still get entertained. However, no new 00371 * requests will be made. 00372 */ 00373 void remove_link_check_request(); 00374 00375 /** Shuts down the LoRaWAN protocol. 00376 * 00377 * In response to the user call for disconnection, the stack shuts down itself. 00378 * 00379 * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown. 00380 */ 00381 lorawan_status_t shutdown(); 00382 00383 /** Change device class 00384 * 00385 * Change current device class. 00386 * 00387 * @param device_class The device class 00388 * 00389 * @return LORAWAN_STATUS_OK on success, 00390 * LORAWAN_STATUS_UNSUPPORTED is requested class is not supported, 00391 * or other negative error code if request failed. 00392 */ 00393 lorawan_status_t set_device_class(const device_class_t & device_class); 00394 00395 private: 00396 LoRaWANStack(); 00397 ~LoRaWANStack(); 00398 00399 /** 00400 * Checks if the user provided port is valid or not 00401 */ 00402 bool is_port_valid(uint8_t port); 00403 00404 /** 00405 * State machine for stack controller layer. 00406 */ 00407 lorawan_status_t lora_state_machine(device_states_t new_state); 00408 00409 /** 00410 * Callback function for MLME indication. Mac layer calls this function once 00411 * an MLME indication is received. This method translates Mac layer data 00412 * structure into stack layer data structure. 00413 */ 00414 void mlme_indication_handler(loramac_mlme_indication_t *mlmeIndication); 00415 00416 /** 00417 * Handles an MLME confirmation coming from the Mac layer and uses it to 00418 * update the state for example, a Join Accept triggers an MLME confirmation, 00419 * that eventually comes here and we take necessary steps accordingly. 00420 */ 00421 void mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm); 00422 00423 /** 00424 * Handles an MCPS confirmation coming from the Mac layer in response to an 00425 * MCPS request. We take appropriate actions in response to the confirmation, 00426 * e.g., letting the application know that ack was not received in case of 00427 * a CONFIRMED message or scheduling error etc. 00428 */ 00429 void mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm); 00430 00431 /** 00432 * Handles an MCPS indication coming from the Mac layer, e.g., once we 00433 * receive a packet from the Network Server, it is indicated to this handler 00434 * and consequently this handler posts an event to the application that 00435 * there is something available to read. 00436 */ 00437 void mcps_indication_handler(loramac_mcps_indication_t *mcps_indication); 00438 00439 /** 00440 * Sets up user application port 00441 */ 00442 lorawan_status_t set_application_port(uint8_t port); 00443 00444 /** 00445 * Handles connection internally 00446 */ 00447 lorawan_status_t handle_connect(bool is_otaa); 00448 00449 private: 00450 00451 LoRaMac _loramac; 00452 loramac_primitives_t LoRaMacPrimitives; 00453 00454 device_states_t _device_current_state; 00455 lorawan_app_callbacks_t _callbacks; 00456 lorawan_session_t _lw_session; 00457 loramac_tx_message_t _tx_msg; 00458 loramac_rx_message_t _rx_msg; 00459 uint8_t _num_retry; 00460 uint8_t _app_port; 00461 bool _link_check_requested; 00462 00463 events::EventQueue *_queue; 00464 00465 #if defined(LORAWAN_COMPLIANCE_TEST) 00466 00467 /** 00468 * Used only for compliance testing 00469 */ 00470 void compliance_test_handler(loramac_mcps_indication_t *mcps_indication); 00471 00472 /** 00473 * Used only for compliance testing 00474 */ 00475 lorawan_status_t send_compliance_test_frame_to_mac(); 00476 00477 compliance_test_t _compliance_test; 00478 #endif 00479 }; 00480 00481 #endif /* LORAWANSTACK_H_ */
Generated on Tue Jul 12 2022 15:17:25 by
1.7.2