Mistake on this page?
Report an issue in GitHub or email us
LoRaWANStack.h
Go to the documentation of this file.
1 /**
2  * \file LoRaWANStack.h
3  *
4  * \brief LoRaWAN stack layer implementation
5  *
6  * \copyright Revised BSD License, see LICENSE.TXT file include in the project
7  *
8  * \code
9  * ______ _
10  * / _____) _ | |
11  * ( (____ _____ ____ _| |_ _____ ____| |__
12  * \____ \| ___ | (_ _) ___ |/ ___) _ \
13  * _____) ) ____| | | || |_| ____( (___| | | |
14  * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  * (C)2013 Semtech
16  *
17  * ___ _____ _ ___ _ _____ ___ ___ ___ ___
18  * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
19  * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
20  * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
21  * embedded.connectivity.solutions===============
22  *
23  * \endcode
24  *
25  * \author Miguel Luis ( Semtech )
26  *
27  * \author Gregory Cristian ( Semtech )
28  *
29  * \author Daniel Jaeckle ( STACKFORCE )
30  *
31  * \defgroup LoRaWAN stack layer that controls MAC layer underneath
32  *
33  * License: Revised BSD License, see LICENSE.TXT file include in the project
34  *
35  * Copyright (c) 2017, Arm Limited and affiliates.
36  *
37  * SPDX-License-Identifier: BSD-3-Clause
38  */
39 
40 #ifndef LORAWANSTACK_H_
41 #define LORAWANSTACK_H_
42 
43 #include <stdint.h>
44 #include "events/EventQueue.h"
45 #include "platform/mbed_atomic.h"
46 #include "platform/Callback.h"
47 #include "platform/NonCopyable.h"
48 #include "platform/ScopedLock.h"
49 
50 #include "lorastack/mac/LoRaMac.h"
51 #include "system/LoRaWANTimer.h"
53 #include "LoRaRadio.h"
54 
55 class LoRaPHY;
56 
57 /** LoRaWANStack Class
58  * A controller layer for LoRaWAN MAC and PHY
59  */
60 class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> {
61 
62 public:
63  LoRaWANStack();
64 
65  /** Binds PHY layer and radio driver to stack.
66  *
67  * MAC layer is totally detached from the PHY layer so the stack layer
68  * needs to play the role of an arbitrator.
69  * This API sets the PHY layer object to stack and bind the radio driver
70  * object from the application to the PHY layer.
71  * Also initialises radio callback handles which the radio driver will
72  * use in order to report events.
73  *
74  * @param radio LoRaRadio object, i.e., the radio driver
75  * @param phy LoRaPHY object.
76  *
77  */
78  void bind_phy_and_radio_driver(LoRaRadio &radio, LoRaPHY &phy);
79 
80  /** End device initialization.
81  * @param queue A pointer to an EventQueue passed from the application.
82  * @return LORAWAN_STATUS_OK on success, a negative error code on failure.
83  */
85 
86  /** Sets all callbacks for the application.
87  *
88  * @param callbacks A pointer to the structure carrying callbacks.
89  * @return LORAWAN_STATUS_OK on success, a negative error code on failure.
90  */
92 
93  /** Connect OTAA or ABP using Mbed-OS config system
94  *
95  * @return For ABP: If everything goes well, LORAWAN_STATUS_OK is returned for first call followed by
96  * a 'CONNECTED' event. Otherwise a negative error code is returned.
97  * Any subsequent call will return LORAWAN_STATUS_ALREADY_CONNECTED and no event follows.
98  *
99  * For OTAA: When a JoinRequest is sent, LORAWAN_STATUS_CONNECT_IN_PROGRESS is returned for the first call.
100  * Any subsequent call will return either LORAWAN_STATUS_BUSY (if the previous request for connection
101  * is still underway) or LORAWAN_STATUS_ALREADY_CONNECTED (if a network was already joined successfully).
102  * A 'CONNECTED' event is sent to the application when the JoinAccept is received.
103  */
105 
106  /** Connect OTAA or ABP with parameters
107  *
108  * @param connect Options for an end device connection to the gateway.
109  *
110  * @return For ABP: If everything goes well, LORAWAN_STATUS_OK is returned for first call followed by
111  * a 'CONNECTED' event. Otherwise a negative error code is returned.
112  * Any subsequent call will return LORAWAN_STATUS_ALREADY_CONNECTED and no event follows.
113  *
114  * For OTAA: When a JoinRequest is sent, LORAWAN_STATUS_CONNECT_IN_PROGRESS is returned for the first call.
115  * Any subsequent call will return either LORAWAN_STATUS_BUSY (if the previous request for connection
116  * is still underway) or LORAWAN_STATUS_ALREADY_CONNECTED (if a network was already joined successfully).
117  * A 'CONNECTED' event is sent to the application when the JoinAccept is received.
118  */
120 
121  /** Adds channels to use.
122  *
123  * You can provide a list of channels with appropriate parameters filled
124  * in. However, this list is not absolute. In some regions, a CF
125  * list gets implemented by default, which means that the network can overwrite your channel
126  * frequency settings right after receiving a Join Accept. You may try
127  * to set up any channel or channels after that and if the channel requested
128  * is already active, the request is silently ignored. A negative error
129  * code is returned if there is any problem with parameters.
130  *
131  * You need to ensure that the base station nearby supports the channel or channels being added.
132  *
133  * If your list includes a default channel (a channel where Join Requests
134  * are received) you cannot fully configure the channel parameters.
135  * Either leave the channel settings to default or check your
136  * corresponding PHY layer implementation. For example, LoRaPHYE868.
137  *
138  * @param channel_plan A list of channels or a single channel.
139  *
140  * @return LORAWAN_STATUS_OK on success, a negative error
141  * code on failure.
142  */
144 
145  /** Removes a channel from the list.
146  *
147  * @param channel_id Index of the channel being removed
148  *
149  * @return LORAWAN_STATUS_OK on success, a negative error
150  * code on failure.
151  */
152  lorawan_status_t remove_a_channel(uint8_t channel_id);
153 
154  /** Removes a previously set channel plan.
155  *
156  * @return LORAWAN_STATUS_OK on success, a negative error
157  * code on failure.
158  */
160 
161  /** Gets a list of currently enabled channels .
162  *
163  * @param channel_plan The channel plan structure to store final result.
164  *
165  * @return LORAWAN_STATUS_OK on success, a negative error
166  * code on failure.
167  */
169 
170  /** Sets up a retry counter for confirmed messages.
171  *
172  * Valid only for confirmed messages. This API sets the number of times the
173  * stack will retry a CONFIRMED message before giving up and reporting an
174  * error.
175  *
176  * @param count The number of retries for confirmed messages.
177  *
178  * @return LORAWAN_STATUS_OK or a negative error code.
179  */
181 
182  /** Sets up the data rate.
183  *
184  * `set_datarate()` first verifies whether the data rate given is valid or not.
185  * If it is valid, the system sets the given data rate to the channel.
186  *
187  * @param data_rate The intended data rate, for example DR_0 or DR_1.
188  * Note that the macro DR_* can mean different
189  * things in different regions.
190  *
191  * @return LORAWAN_STATUS_OK if everything goes well, otherwise
192  * a negative error code.
193  */
194  lorawan_status_t set_channel_data_rate(uint8_t data_rate);
195 
196  /** Enables ADR.
197  *
198  * @param adr_enabled 0 ADR disabled, 1 ADR enabled.
199  *
200  * @return LORAWAN_STATUS_OK on success, a negative error
201  * code on failure.
202  */
203  lorawan_status_t enable_adaptive_datarate(bool adr_enabled);
204 
205  /** Send message to gateway
206  *
207  * @param port The application port number. Port numbers 0 and 224
208  * are reserved, whereas port numbers from 1 to 223
209  * (0x01 to 0xDF) are valid port numbers.
210  * Anything out of this range is illegal.
211  *
212  * @param data A pointer to the data being sent. The ownership of the
213  * buffer is not transferred. The data is copied to the
214  * internal buffers.
215  *
216  * @param length The size of data in bytes.
217  *
218  * @param flags A flag used to determine what type of
219  * message is being sent, for example:
220  *
221  * MSG_UNCONFIRMED_FLAG = 0x01
222  * MSG_CONFIRMED_FLAG = 0x02
223  * MSG_MULTICAST_FLAG = 0x04
224  * MSG_PROPRIETARY_FLAG = 0x08
225  * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be
226  * used in conjunction with MSG_UNCONFIRMED_FLAG and
227  * MSG_CONFIRMED_FLAG depending on the intended use.
228  *
229  * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set
230  * a confirmed message flag for a proprietary message.
231  * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are
232  * mutually exclusive.
233  *
234  * @param null_allowed Internal use only. Needed for sending empty packet
235  * having CONFIRMED bit on.
236  *
237  * @param allow_port_0 Internal use only. Needed for flushing MAC commands.
238  *
239  * @return The number of bytes sent, or
240  * LORAWAN_STATUS_WOULD_BLOCK if another TX is
241  * ongoing, or a negative error code on failure.
242  */
243  int16_t handle_tx(uint8_t port, const uint8_t *data,
244  uint16_t length, uint8_t flags,
245  bool null_allowed = false, bool allow_port_0 = false);
246 
247  /** Receives a message from the Network Server.
248  *
249  * @param data A pointer to buffer where the received data will be
250  * stored.
251  *
252  * @param length The size of data in bytes
253  *
254  * @param port The application port number. Port numbers 0 and 224
255  * are reserved, whereas port numbers from 1 to 223
256  * (0x01 to 0xDF) are valid port numbers.
257  * Anything out of this range is illegal.
258  *
259  * In return will contain the number of port to which
260  * message was received.
261  *
262  * @param flags A flag is used to determine what type of
263  * message is being received, for example:
264  *
265  * MSG_UNCONFIRMED_FLAG = 0x01,
266  * MSG_CONFIRMED_FLAG = 0x02
267  * MSG_MULTICAST_FLAG = 0x04,
268  * MSG_PROPRIETARY_FLAG = 0x08
269  *
270  * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be
271  * used in conjunction with MSG_UNCONFIRMED_FLAG and
272  * MSG_CONFIRMED_FLAG depending on the intended use.
273  *
274  * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set
275  * a confirmed message flag for a proprietary message.
276  *
277  * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are
278  * not mutually exclusive, i.e., the user can subscribe to
279  * receive both CONFIRMED AND UNCONFIRMED messages at
280  * the same time.
281  *
282  * In return will contain the flags to determine what kind
283  * of message was received.
284  *
285  * @param validate_params If set to true, the given port and flags values will be checked
286  * against the values received with the message. If values do not
287  * match, LORAWAN_STATUS_WOULD_BLOCK will be returned.
288  *
289  * @return It could be one of these:
290  * i) 0 if there is nothing else to read.
291  * ii) Number of bytes written to user buffer.
292  * iii) LORAWAN_STATUS_WOULD_BLOCK if there is
293  * nothing available to read at the moment.
294  * iv) A negative error code on failure.
295  */
296  int16_t handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params);
297 
298  /** Send Link Check Request MAC command.
299  *
300  *
301  * This API schedules a Link Check Request command (LinkCheckReq) for the network
302  * server and once the response, i.e., LinkCheckAns MAC command is received
303  * from the Network Server, an event is generated.
304  *
305  * A callback function for the link check response must be set prior to using
306  * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown.
307  *
308  * @return LORAWAN_STATUS_OK on successfully queuing a request, or
309  * a negative error code on failure.
310  *
311  */
313 
314  /** Removes link check request sticky MAC command.
315  *
316  * Any already queued request may still get entertained. However, no new
317  * requests will be made.
318  */
320 
321  /** Shuts down the LoRaWAN protocol.
322  *
323  * In response to the user call for disconnection, the stack shuts down itself.
324  *
325  * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown.
326  */
328 
329  /** Change device class
330  *
331  * Change current device class.
332  *
333  * @param device_class The device class
334  *
335  * @return LORAWAN_STATUS_OK on success,
336  * LORAWAN_STATUS_UNSUPPORTED is requested class is not supported,
337  * or other negative error code if request failed.
338  */
339  lorawan_status_t set_device_class(const device_class_t &device_class);
340 
341  /** Acquire TX meta-data
342  *
343  * Upon successful transmission, TX meta-data will be made available
344  *
345  * @param metadata A reference to the inbound structure which will be
346  * filled with any TX meta-data if available.
347  *
348  * @return LORAWAN_STATUS_OK if successful,
349  * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise
350  */
352 
353  /** Acquire RX meta-data
354  *
355  * Upon successful reception, RX meta-data will be made available
356  *
357  * @param metadata A reference to the inbound structure which will be
358  * filled with any RX meta-data if available.
359  *
360  * @return LORAWAN_STATUS_OK if successful,
361  * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise
362  */
364 
365  /** Acquire backoff meta-data
366  *
367  * Get hold of backoff time after which the transmission will take place.
368  *
369  * @param backoff A reference to the inbound integer which will be
370  * filled with any backoff meta-data if available.
371  *
372  * @return LORAWAN_STATUS_OK if successful,
373  * LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise
374  */
376 
377  /** Stops sending
378  *
379  * Stop sending any outstanding messages if they are not yet queued for
380  * transmission, i.e., if the backoff timer is nhot elapsed yet.
381  *
382  * @return LORAWAN_STATUS_OK if the transmission is cancelled.
383  * LORAWAN_STATUS_BUSY otherwise.
384  */
386 
387  void lock(void)
388  {
389  _loramac.lock();
390  }
391  void unlock(void)
392  {
393  _loramac.unlock();
394  }
395 
396 private:
398  /**
399  * Checks if the user provided port is valid or not
400  */
401  bool is_port_valid(uint8_t port, bool allow_port_0 = false);
402 
403  /**
404  * State machine for stack controller layer.
405  */
406  lorawan_status_t state_controller(device_states_t new_state);
407 
408  /**
409  * Helpers for state controller
410  */
411  void process_uninitialized_state(lorawan_status_t &op_status);
412  void process_idle_state(lorawan_status_t &op_status);
413  void process_connected_state();
414  void process_connecting_state(lorawan_status_t &op_status);
415  void process_joining_state(lorawan_status_t &op_status);
416  void process_scheduling_state(lorawan_status_t &op_status);
417  void process_status_check_state();
418  void process_shutdown_state(lorawan_status_t &op_status);
419  void state_machine_run_to_completion(void);
420 
421  /**
422  * Handles MLME indications
423  */
424  void mlme_indication_handler(void);
425 
426  /**
427  * Handles an MLME confirmation
428  */
429  void mlme_confirm_handler(void);
430 
431  /**
432  * Handles an MCPS confirmation
433  */
434  void mcps_confirm_handler(void);
435 
436  /**
437  * Handles an MCPS indication
438  */
439  void mcps_indication_handler(void);
440 
441  /**
442  * Sets up user application port
443  */
444  lorawan_status_t set_application_port(uint8_t port, bool allow_port_0 = false);
445 
446  /**
447  * Handles connection internally
448  */
449  lorawan_status_t handle_connect(bool is_otaa);
450 
451 
452  /** Send event to application.
453  *
454  * @param event The event to be sent.
455  */
456  void send_event_to_application(const lorawan_event_t event) const;
457 
458  /** Send empty uplink message to network.
459  *
460  * Sends an empty confirmed message to gateway.
461  *
462  * @param port The event to be sent.
463  */
464  void send_automatic_uplink_message(uint8_t port);
465 
466  /**
467  * TX interrupt handlers and corresponding processors
468  */
469  void tx_interrupt_handler(void);
470  void tx_timeout_interrupt_handler(void);
471  void process_transmission(void);
472  void process_transmission_timeout(void);
473 
474  /**
475  * RX interrupt handlers and corresponding processors
476  */
477  void rx_interrupt_handler(const uint8_t *payload, uint16_t size, int16_t rssi,
478  int8_t snr);
479  void rx_timeout_interrupt_handler(void);
480  void rx_error_interrupt_handler(void);
481  void process_reception(const uint8_t *payload, uint16_t size, int16_t rssi,
482  int8_t snr);
483  void process_reception_timeout(bool is_timeout);
484 
485  int convert_to_msg_flag(const mcps_type_t type);
486 
487  void make_tx_metadata_available(void);
488  void make_rx_metadata_available(void);
489 
490  void handle_scheduling_failure(void);
491 
492  void post_process_tx_with_reception(void);
493  void post_process_tx_no_reception(void);
494 
495 private:
496  LoRaMac _loramac;
498  device_states_t _device_current_state;
499  lorawan_app_callbacks_t _callbacks;
500  lorawan_session_t _lw_session;
501  loramac_tx_message_t _tx_msg;
502  loramac_rx_message_t _rx_msg;
503  lorawan_tx_metadata _tx_metadata;
504  lorawan_rx_metadata _rx_metadata;
505  uint8_t _num_retry;
506  uint8_t _qos_cnt;
507  uint32_t _ctrl_flags;
508  uint8_t _app_port;
509  bool _link_check_requested;
510  bool _automatic_uplink_ongoing;
511  core_util_atomic_flag _rx_payload_in_use;
512  uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
513  events::EventQueue *_queue;
514  lorawan_time_t _tx_timestamp;
515 };
516 
517 #endif /* LORAWANSTACK_H_ */
lorawan_status_t stop_sending(void)
Stops sending.
Meta-data collection for the received packet.
LoRaWANStack Class A controller layer for LoRaWAN MAC and PHY.
Definition: LoRaWANStack.h:60
enum lora_events lorawan_event_t
Events needed to announce stack operation results.
int16_t handle_tx(uint8_t port, const uint8_t *data, uint16_t length, uint8_t flags, bool null_allowed=false, bool allow_port_0=false)
Send message to gateway.
lorawan_status_t acquire_rx_metadata(lorawan_rx_metadata &metadata)
Acquire RX meta-data.
lorawan_status_t set_channel_data_rate(uint8_t data_rate)
Sets up the data rate.
Meta-data collection for a transmission.
void remove_link_check_request()
Removes link check request sticky MAC command.
RAII-style mechanism for owning a lock of Lockable object for the duration of a scoped block...
Definition: ScopedLock.h:63
lorawan_status_t remove_a_channel(uint8_t channel_id)
Removes a channel from the list.
LoRaMac Class Implementation of LoRaWAN MAC layer.
Definition: LoRaMac.h:62
EventQueue.
Definition: EventQueue.h:62
loramac_rx_message_t
lorawan_status_t enable_adaptive_datarate(bool adr_enabled)
Enables ADR.
device_class_t
LoRaWAN device classes definition.
Definition: lorawan_types.h:59
Stack level TX message structure.
LoRa MAC layer implementation.
A lock-free, primitive atomic flag.
Definition: mbed_atomic.h:115
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
uint32_t lorawan_time_t
Timer time variable definition.
lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan)
Adds channels to use.
lorawan_status_t acquire_tx_metadata(lorawan_tx_metadata &metadata)
Acquire TX meta-data.
LoRaPHY Class Parent class for LoRa regional PHY implementations.
Definition: LoRaPHY.h:46
lorawan_status_t shutdown()
Shuts down the LoRaWAN protocol.
#define LORAMAC_PHY_MAXPAYLOAD
Maximum PHY layer payload size for reception.
enum device_states device_states_t
End-device states.
lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan)
Gets a list of currently enabled channels .
Stack level callback functions.
enum lorawan_status lorawan_status_t
lorawan_status_t contains status codes in response to stack operations
lorawan_connect_t structure
lorawan_status_t set_lora_callbacks(const lorawan_app_callbacks_t *callbacks)
Sets all callbacks for the application.
int16_t handle_rx(uint8_t *data, uint16_t length, uint8_t &port, int &flags, bool validate_params)
Receives a message from the Network Server.
Reporting functions for upper layers.
Definition: LoRaRadio.h:389
void lock(void)
These locks trample through to the upper layers and make the stack thread safe.
Definition: LoRaMac.h:436
DO NOT MODIFY, WILL BREAK THE API!
lorawan_status_t connect()
Connect OTAA or ABP using Mbed-OS config system.
void bind_phy_and_radio_driver(LoRaRadio &radio, LoRaPHY &phy)
Binds PHY layer and radio driver to stack.
lorawan_status_t set_confirmed_msg_retry(uint8_t count)
Sets up a retry counter for confirmed messages.
mcps_type_t
LoRaMAC data services.
Contains common data structures used by Mbed-OS LoRaWAN mplementation.
lorawan_status_t set_link_check_request()
Send Link Check Request MAC command.
lorawan_status_t initialize_mac_layer(events::EventQueue *queue)
End device initialization.
lorawan_status_t drop_channel_list()
Removes a previously set channel plan.
Interface for the radios, containing the main functions that a radio needs, and five callback functio...
Definition: LoRaRadio.h:440
lorawan_status_t set_device_class(const device_class_t &device_class)
Change device class.
lorawan_status_t acquire_backoff_metadata(int &backoff)
Acquire backoff meta-data.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.