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 / _____) _ | | 00003 ( (____ _____ ____ _| |_ _____ ____| |__ 00004 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00005 _____) ) ____| | | || |_| ____( (___| | | | 00006 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00007 (C)2013 Semtech 00008 ___ _____ _ ___ _ _____ ___ ___ ___ ___ 00009 / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 00010 \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 00012 embedded.connectivity.solutions=============== 00013 00014 Description: LoRaWAN stack layer that controls both MAC and PHY underneath 00015 00016 License: Revised BSD License, see LICENSE.TXT file include in the project 00017 00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 00019 00020 00021 Copyright (c) 2017, Arm Limited and affiliates. 00022 00023 SPDX-License-Identifier: BSD-3-Clause 00024 */ 00025 00026 #ifndef LORAWANSTACK_H_ 00027 #define LORAWANSTACK_H_ 00028 00029 #include <stdint.h> 00030 #include "events/EventQueue.h" 00031 #include "platform/Callback.h" 00032 #include "platform/NonCopyable.h" 00033 #include "lorawan/system/LoRaWANTimer.h" 00034 #include "lorastack/mac/LoRaMac.h" 00035 #include "lorawan/system/lorawan_data_structures.h" 00036 #include "LoRaRadio.h" 00037 00038 #ifdef MBED_CONF_LORA_PHY 00039 #if MBED_CONF_LORA_PHY == 0 00040 #include "lorawan/lorastack/phy/LoRaPHYEU868.h" 00041 #define LoRaPHY_region LoRaPHYEU868 00042 #elif MBED_CONF_LORA_PHY == 1 00043 #include "lorawan/lorastack/phy/LoRaPHYAS923.h" 00044 #define LoRaPHY_region LoRaPHYAS923 00045 #elif MBED_CONF_LORA_PHY == 2 00046 #include "lorawan/lorastack/phy/LoRaPHYAU915.h" 00047 #define LoRaPHY_region LoRaPHYAU915; 00048 #elif MBED_CONF_LORA_PHY == 3 00049 #include "lorawan/lorastack/phy/LoRaPHYCN470.h" 00050 #define LoRaPHY_region LoRaPHYCN470 00051 #elif MBED_CONF_LORA_PHY == 4 00052 #include "lorawan/lorastack/phy/LoRaPHYCN779.h" 00053 #define LoRaPHY_region LoRaPHYCN779 00054 #elif MBED_CONF_LORA_PHY == 5 00055 #include "lorawan/lorastack/phy/LoRaPHYEU433.h" 00056 #define LoRaPHY_region LoRaPHYEU433 00057 #elif MBED_CONF_LORA_PHY == 6 00058 #include "lorawan/lorastack/phy/LoRaPHYIN865.h" 00059 #define LoRaPHY_region LoRaPHYIN865 00060 #elif MBED_CONF_LORA_PHY == 7 00061 #include "lorawan/lorastack/phy/LoRaPHYKR920.h" 00062 #define LoRaPHY_region LoRaPHYKR920 00063 #elif MBED_CONF_LORA_PHY == 8 00064 #include "lorawan/lorastack/phy/LoRaPHYUS915.h" 00065 #define LoRaPHY_region LoRaPHYUS915 00066 #elif MBED_CONF_LORA_PHY == 9 00067 #include "lorawan/lorastack/phy/LoRaPHYUS915Hybrid.h" 00068 #define LoRaPHY_region LoRaPHYUS915Hybrid 00069 #endif //MBED_CONF_LORA_PHY == VALUE 00070 #else 00071 #error "Must set LoRa PHY layer parameters." 00072 #endif //MBED_CONF_LORA_PHY 00073 00074 /** 00075 * A mask for the network ID. 00076 */ 00077 #define LORAWAN_NETWORK_ID_MASK ( uint32_t )0xFE000000 00078 00079 class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> { 00080 public: 00081 static LoRaWANStack& get_lorawan_stack(); 00082 00083 /** Binds radio driver to PHY layer. 00084 * 00085 * MAC layer is totally detached from the PHY layer so the stack layer 00086 * needs to play the role of an arbitrator. This API gets a radio driver 00087 * object from the application (via LoRaWANInterface), binds it to the PHY 00088 * layer and returns MAC layer callback handles which the radio driver will 00089 * use in order to report events. 00090 * 00091 * @param radio LoRaRadio object, i.e., the radio driver 00092 * 00093 * @return A list of callbacks from MAC layer that needs to 00094 * be passed to radio driver 00095 */ 00096 radio_events_t *bind_radio_driver(LoRaRadio& radio); 00097 00098 /** End device initialization. 00099 * @param queue A pointer to an EventQueue passed from the application. 00100 * @return LORAWAN_STATUS_OK on success, a negative error code on failure. 00101 */ 00102 lorawan_status_t initialize_mac_layer(events::EventQueue *queue); 00103 00104 /** Sets all callbacks for the application. 00105 * 00106 * @param callbacks A pointer to the structure carrying callbacks. 00107 */ 00108 void set_lora_callbacks(lorawan_app_callbacks_t *callbacks); 00109 00110 /** Adds channels to use. 00111 * 00112 * You can provide a list of channels with appropriate parameters filled 00113 * in. However, this list is not absolute. In some regions, a CF 00114 * list gets implemented by default, which means that the network can overwrite your channel 00115 * frequency settings right after receiving a Join Accept. You may try 00116 * to set up any channel or channels after that and if the channel requested 00117 * is already active, the request is silently ignored. A negative error 00118 * code is returned if there is any problem with parameters. 00119 * 00120 * You need to ensure that the base station nearby supports the channel or channels being added. 00121 * 00122 * If your list includes a default channel (a channel where Join Requests 00123 * are received) you cannot fully configure the channel parameters. 00124 * Either leave the channel settings to default or check your 00125 * corresponding PHY layer implementation. For example, LoRaPHYE868. 00126 * 00127 * @param channel_plan A list of channels or a single channel. 00128 * 00129 * @return LORAWAN_STATUS_OK on success, a negative error 00130 * code on failure. 00131 */ 00132 lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan); 00133 00134 /** Removes a channel from the list. 00135 * 00136 * @param channel_id Index of the channel being removed 00137 * 00138 * @return LORAWAN_STATUS_OK on success, a negative error 00139 * code on failure. 00140 */ 00141 lorawan_status_t remove_a_channel(uint8_t channel_id); 00142 00143 /** Removes a previously set channel plan. 00144 * 00145 * @return LORAWAN_STATUS_OK on success, a negative error 00146 * code on failure. 00147 */ 00148 lorawan_status_t drop_channel_list(); 00149 00150 /** Gets a list of currently enabled channels . 00151 * 00152 * @param channel_plan The channel plan structure to store final result. 00153 * 00154 * @return LORAWAN_STATUS_OK on success, a negative error 00155 * code on failure. 00156 */ 00157 lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan); 00158 00159 /** Sets up a retry counter for confirmed messages. 00160 * 00161 * Valid only for confirmed messages. This API sets the number of times the 00162 * stack will retry a CONFIRMED message before giving up and reporting an 00163 * error. 00164 * 00165 * @param count The number of retries for confirmed messages. 00166 * 00167 * @return LORAWAN_STATUS_OK or a negative error code. 00168 */ 00169 lorawan_status_t set_confirmed_msg_retry(uint8_t count); 00170 00171 /** Sets up the data rate. 00172 * 00173 * `set_datarate()` first verifies whether the data rate given is valid or not. 00174 * If it is valid, the system sets the given data rate to the channel. 00175 * 00176 * @param data_rate The intended data rate, for example DR_0 or DR_1. 00177 * Note that the macro DR_* can mean different 00178 * things in different regions. 00179 * 00180 * @return LORAWAN_STATUS_OK if everything goes well, otherwise 00181 * a negative error code. 00182 */ 00183 lorawan_status_t set_channel_data_rate(uint8_t data_rate); 00184 00185 /** Enables ADR. 00186 * 00187 * @param adr_enabled 0 ADR disabled, 1 ADR enabled. 00188 * 00189 * @return LORAWAN_STATUS_OK on success, a negative error 00190 * code on failure. 00191 */ 00192 lorawan_status_t enable_adaptive_datarate(bool adr_enabled); 00193 00194 /** Commissions a LoRa device. 00195 * 00196 * @param commission_data A structure representing all the commission 00197 * information. 00198 */ 00199 void commission_device(const lorawan_dev_commission_t &commission_data); 00200 00201 /** End device OTAA join. 00202 * 00203 * Based on the LoRaWAN standard 1.0.2. 00204 * Join the network using the Over The Air Activation (OTAA) procedure. 00205 * 00206 * @param params The `lorawan_connect_t` type structure. 00207 * 00208 * @return LORAWAN_STATUS_OK or 00209 * LORAWAN_STATUS_CONNECT_IN_PROGRESS on success, 00210 * or a negative error code on failure. 00211 */ 00212 lorawan_status_t join_request_by_otaa(const lorawan_connect_t ¶ms); 00213 00214 /** End device ABP join. 00215 * 00216 * Based on the LoRaWAN standard 1.0.2. 00217 * Join the network using the Activation By Personalization (ABP) procedure. 00218 * 00219 * @param params The `lorawan_connect_t` type structure. 00220 * 00221 * @return LORAWAN_STATUS_OK or 00222 * LORAWAN_STATUS_CONNECT_IN_PROGRESS on success, 00223 * or a negative error code on failure. 00224 */ 00225 lorawan_status_t activation_by_personalization(const lorawan_connect_t ¶ms); 00226 00227 /** Send message to gateway 00228 * 00229 * @param port The application port number. Port numbers 0 and 224 00230 * are reserved, whereas port numbers from 1 to 223 00231 * (0x01 to 0xDF) are valid port numbers. 00232 * Anything out of this range is illegal. 00233 * 00234 * @param data A pointer to the data being sent. The ownership of the 00235 * buffer is not transferred. The data is copied to the 00236 * internal buffers. 00237 * 00238 * @param length The size of data in bytes. 00239 * 00240 * @param flags A flag used to determine what type of 00241 * message is being sent, for example: 00242 * 00243 * MSG_UNCONFIRMED_FLAG = 0x01 00244 * MSG_CONFIRMED_FLAG = 0x02 00245 * MSG_MULTICAST_FLAG = 0x04 00246 * MSG_PROPRIETARY_FLAG = 0x08 00247 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00248 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00249 * MSG_CONFIRMED_FLAG depending on the intended use. 00250 * 00251 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00252 * a confirmed message flag for a proprietary message. 00253 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00254 * mutually exclusive. 00255 * 00256 * 00257 * @return The number of bytes sent, or 00258 * LORAWAN_STATUS_WOULD_BLOCK if another TX is 00259 * ongoing, or a negative error code on failure. 00260 */ 00261 int16_t handle_tx(uint8_t port, const uint8_t* data, 00262 uint16_t length, uint8_t flags); 00263 00264 /** Receives a message from the Network Server. 00265 * 00266 * @param port The application port number. Port numbers 0 and 224 00267 * are reserved, whereas port numbers from 1 to 223 00268 * (0x01 to 0xDF) are valid port numbers. 00269 * Anything out of this range is illegal. 00270 * 00271 * @param data A pointer to buffer where the received data will be 00272 * stored. 00273 * 00274 * @param length The size of data in bytes 00275 * 00276 * @param flags A flag is used to determine what type of 00277 * message is being received, for example: 00278 * 00279 * MSG_UNCONFIRMED_FLAG = 0x01, 00280 * MSG_CONFIRMED_FLAG = 0x02 00281 * MSG_MULTICAST_FLAG = 0x04, 00282 * MSG_PROPRIETARY_FLAG = 0x08 00283 * 00284 * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be 00285 * used in conjunction with MSG_UNCONFIRMED_FLAG and 00286 * MSG_CONFIRMED_FLAG depending on the intended use. 00287 * 00288 * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set 00289 * a confirmed message flag for a proprietary message. 00290 * 00291 * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are 00292 * not mutually exclusive, i.e., the user can subscribe to 00293 * receive both CONFIRMED AND UNCONFIRMED messages at 00294 * the same time. 00295 * 00296 * @return It could be one of these: 00297 * i) 0 if there is nothing else to read. 00298 * ii) Number of bytes written to user buffer. 00299 * iii) LORAWAN_STATUS_WOULD_BLOCK if there is 00300 * nothing available to read at the moment. 00301 * iv) A negative error code on failure. 00302 */ 00303 int16_t handle_rx(const uint8_t port, uint8_t* data, 00304 uint16_t length, uint8_t flags); 00305 00306 /** Send Link Check Request MAC command. 00307 * 00308 * 00309 * This API schedules a Link Check Request command (LinkCheckReq) for the network 00310 * server and once the response, i.e., LinkCheckAns MAC command is received 00311 * from the Network Server, an event is generated. 00312 * 00313 * A callback function for the link check response must be set prior to using 00314 * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown. 00315 * 00316 * @return LORAWAN_STATUS_OK on successfully queuing a request, or 00317 * a negative error code on failure. 00318 * 00319 */ 00320 lorawan_status_t set_link_check_request(); 00321 00322 /** Shuts down the LoRaWAN protocol. 00323 * 00324 * In response to the user call for disconnection, the stack shuts down itself. 00325 * 00326 * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown. 00327 */ 00328 lorawan_status_t shutdown(); 00329 00330 private: 00331 LoRaWANStack(); 00332 ~LoRaWANStack(); 00333 00334 /** 00335 * Checks if the user provided port is valid or not 00336 */ 00337 bool is_port_valid(uint8_t port); 00338 00339 /** 00340 * State machine for stack controller layer. 00341 * Needs to be wriggled for every state change 00342 */ 00343 lorawan_status_t lora_state_machine(); 00344 00345 /** 00346 * Sets the current state of the device. 00347 * Every call to set_device_state() should precede with 00348 * a call to lora_state_machine() in order to take the state change 00349 * in effect. 00350 */ 00351 void set_device_state(device_states_t new_state); 00352 00353 /** 00354 * Hands over the packet to Mac layer by posting an MCPS request. 00355 */ 00356 lorawan_status_t send_frame_to_mac(); 00357 00358 /** 00359 * Callback function for MLME indication. Mac layer calls this function once 00360 * an MLME indication is received. This method translates Mac layer data 00361 * structure into stack layer data structure. 00362 */ 00363 void mlme_indication_handler(loramac_mlme_indication_t *mlmeIndication); 00364 00365 /** 00366 * Handles an MLME request coming from the upper layers and delegates 00367 * it to the Mac layer, for example, a Join request goes as an MLME request 00368 * to the Mac layer. 00369 */ 00370 lorawan_status_t mlme_request_handler(loramac_mlme_req_t *mlme_request); 00371 00372 /** 00373 * Handles an MLME confirmation coming from the Mac layer and uses it to 00374 * update the state for example, a Join Accept triggers an MLME confirmation, 00375 * that eventually comes here and we take necessary steps accordingly. 00376 */ 00377 void mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm); 00378 00379 /** 00380 * Handles an MCPS request while attempting to hand over a packet from 00381 * upper layers to Mac layer. For example in response to send_frame_to_mac(), 00382 * an MCPS request is generated. 00383 */ 00384 lorawan_status_t mcps_request_handler(loramac_mcps_req_t *mcps_request); 00385 00386 /** 00387 * Handles an MCPS confirmation coming from the Mac layer in response to an 00388 * MCPS request. We take appropriate actions in response to the confirmation, 00389 * e.g., letting the application know that ack was not received in case of 00390 * a CONFIRMED message or scheduling error etc. 00391 */ 00392 void mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm); 00393 00394 /** 00395 * Handles an MCPS indication coming from the Mac layer, e.g., once we 00396 * receive a packet from the Network Server, it is indicated to this handler 00397 * and consequently this handler posts an event to the application that 00398 * there is something available to read. 00399 */ 00400 void mcps_indication_handler(loramac_mcps_indication_t *mcps_indication); 00401 00402 /** 00403 * Sets a MIB request, i.e., update a particular parameter etc. 00404 */ 00405 lorawan_status_t mib_set_request(loramac_mib_req_confirm_t *mib_set_params); 00406 00407 /** 00408 * Requests the MIB to inquire about a particular parameter. 00409 */ 00410 lorawan_status_t mib_get_request(loramac_mib_req_confirm_t *mib_get_params); 00411 00412 /** 00413 * Sets up user application port 00414 */ 00415 lorawan_status_t set_application_port(uint8_t port); 00416 00417 /** 00418 * Helper function to figure out if the user defined data size is possible 00419 * to send or not. The allowed size for transmission depends on the current 00420 * data rate set for the channel. If its not possible to send user defined 00421 * packet size, this method returns the maximum possible size at the moment, 00422 * otherwise the user defined size is returned which means all of user data 00423 * can be sent. 00424 */ 00425 uint16_t check_possible_tx_size(uint16_t size); 00426 00427 #if defined(LORAWAN_COMPLIANCE_TEST) 00428 /** 00429 * This function is used only for compliance testing 00430 */ 00431 void prepare_special_tx_frame(uint8_t port); 00432 00433 /** 00434 * Used only for compliance testing 00435 */ 00436 void compliance_test_handler(loramac_mcps_indication_t *mcps_indication); 00437 00438 /** 00439 * Used only for compliance testing 00440 */ 00441 lorawan_status_t send_compliance_test_frame_to_mac(); 00442 #endif 00443 00444 LoRaWANTimeHandler _lora_time; 00445 LoRaMac _loramac; 00446 LoRaPHY_region _lora_phy; 00447 loramac_primitives_t LoRaMacPrimitives; 00448 00449 #if defined(LORAWAN_COMPLIANCE_TEST) 00450 uint8_t compliance_test_buffer[MBED_CONF_LORA_TX_MAX_SIZE]; 00451 compliance_test_t _compliance_test; 00452 #endif 00453 00454 device_states_t _device_current_state; 00455 lorawan_app_callbacks_t _callbacks; 00456 radio_events_t *_mac_handlers; 00457 lorawan_session_t _lw_session; 00458 loramac_tx_message_t _tx_msg; 00459 loramac_rx_message_t _rx_msg; 00460 uint8_t _app_port; 00461 uint8_t _num_retry; 00462 events::EventQueue *_queue; 00463 bool _duty_cycle_on; 00464 }; 00465 00466 #endif /* LORAWANSTACK_H_ */
Generated on Tue Jul 12 2022 13:30:24 by
