Nicolas Borla / Mbed OS BBR_1Ebene
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaWANStack.h Source File

LoRaWANStack.h

Go to the documentation of this file.
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_ */