BA / Mbed OS BaBoRo_test2
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 
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_ */