Knight KE / Mbed OS Game_Master
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     /** Acquire TX meta-data
00383      *
00384      * Upon successful transmission, TX meta-data will be made available
00385      *
00386      * @param    metadata    A reference to the inbound structure which will be
00387      *                       filled with any TX meta-data if available.
00388      *
00389      * @return               LORAWAN_STATUS_OK if successful,
00390      *                       LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise
00391      */
00392     lorawan_status_t acquire_tx_metadata(lorawan_tx_metadata &metadata);
00393 
00394     /** Acquire RX meta-data
00395      *
00396      * Upon successful reception, RX meta-data will be made available
00397      *
00398      * @param    metadata    A reference to the inbound structure which will be
00399      *                       filled with any RX meta-data if available.
00400      *
00401      * @return               LORAWAN_STATUS_OK if successful,
00402      *                       LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise
00403      */
00404     lorawan_status_t acquire_rx_metadata(lorawan_rx_metadata &metadata);
00405 
00406     /** Acquire backoff meta-data
00407      *
00408      * Get hold of backoff time after which the transmission will take place.
00409      *
00410      * @param    backoff     A reference to the inbound integer which will be
00411      *                       filled with any backoff meta-data if available.
00412      *
00413      * @return               LORAWAN_STATUS_OK if successful,
00414      *                       LORAWAN_STATUS_METADATA_NOT_AVAILABLE otherwise
00415      */
00416     lorawan_status_t acquire_backoff_metadata(int &backoff);
00417 
00418     /** Stops sending
00419      *
00420      * Stop sending any outstanding messages if they are not yet queued for
00421      * transmission, i.e., if the backoff timer is nhot elapsed yet.
00422      *
00423      * @return               LORAWAN_STATUS_OK if the transmission is cancelled.
00424      *                       LORAWAN_STATUS_BUSY otherwise.
00425      */
00426     lorawan_status_t stop_sending(void);
00427 
00428     void lock(void)
00429     {
00430         _loramac.lock();
00431     }
00432     void unlock(void)
00433     {
00434         _loramac.unlock();
00435     }
00436 
00437 private:
00438     typedef mbed::ScopedLock<LoRaWANStack> Lock;
00439     /**
00440      * Checks if the user provided port is valid or not
00441      */
00442     bool is_port_valid(uint8_t port, bool allow_port_0 = false);
00443 
00444     /**
00445      * State machine for stack controller layer.
00446      */
00447     lorawan_status_t state_controller(device_states_t new_state);
00448 
00449     /**
00450      * Helpers for state controller
00451      */
00452     void process_uninitialized_state(lorawan_status_t &op_status);
00453     void process_idle_state(lorawan_status_t &op_status);
00454     void process_connected_state();
00455     void process_connecting_state(lorawan_status_t &op_status);
00456     void process_joining_state(lorawan_status_t &op_status);
00457     void process_scheduling_state(lorawan_status_t &op_status);
00458     void process_status_check_state();
00459     void process_shutdown_state(lorawan_status_t &op_status);
00460     void state_machine_run_to_completion(void);
00461 
00462     /**
00463      * Handles MLME indications
00464      */
00465     void mlme_indication_handler(void);
00466 
00467     /**
00468      * Handles an MLME confirmation
00469      */
00470     void mlme_confirm_handler(void);
00471 
00472     /**
00473      * Handles an MCPS confirmation
00474      */
00475     void mcps_confirm_handler(void);
00476 
00477     /**
00478      * Handles an MCPS indication
00479      */
00480     void mcps_indication_handler(void);
00481 
00482     /**
00483      * Sets up user application port
00484      */
00485     lorawan_status_t set_application_port(uint8_t port, bool allow_port_0 = false);
00486 
00487     /**
00488      * Handles connection internally
00489      */
00490     lorawan_status_t handle_connect(bool is_otaa);
00491 
00492 
00493     /** Send event to application.
00494      *
00495      * @param  event            The event to be sent.
00496      */
00497     void send_event_to_application(const lorawan_event_t event) const;
00498 
00499     /** Send empty uplink message to network.
00500      *
00501      * Sends an empty confirmed message to gateway.
00502      *
00503      * @param  port            The event to be sent.
00504      */
00505     void send_automatic_uplink_message(uint8_t port);
00506 
00507     /**
00508      * TX interrupt handlers and corresponding processors
00509      */
00510     void tx_interrupt_handler(void);
00511     void tx_timeout_interrupt_handler(void);
00512     void process_transmission(void);
00513     void process_transmission_timeout(void);
00514 
00515     /**
00516      * RX interrupt handlers and corresponding processors
00517      */
00518     void rx_interrupt_handler(const uint8_t *payload, uint16_t size, int16_t rssi,
00519                               int8_t snr);
00520     void rx_timeout_interrupt_handler(void);
00521     void rx_error_interrupt_handler(void);
00522     void process_reception(const uint8_t *payload, uint16_t size, int16_t rssi,
00523                            int8_t snr);
00524     void process_reception_timeout(bool is_timeout);
00525 
00526     int convert_to_msg_flag(const mcps_type_t type);
00527 
00528     void make_tx_metadata_available(void);
00529     void make_rx_metadata_available(void);
00530 
00531     void handle_ack_expiry_for_class_c(void);
00532 
00533 private:
00534     LoRaMac _loramac;
00535     radio_events_t radio_events;
00536     device_states_t _device_current_state;
00537     lorawan_app_callbacks_t _callbacks;
00538     lorawan_session_t _lw_session;
00539     loramac_tx_message_t _tx_msg;
00540     loramac_rx_message_t _rx_msg;
00541     lorawan_tx_metadata _tx_metadata;
00542     lorawan_rx_metadata _rx_metadata;
00543     uint8_t _num_retry;
00544     uint32_t _ctrl_flags;
00545     uint8_t _app_port;
00546     bool _link_check_requested;
00547     bool _automatic_uplink_ongoing;
00548     volatile bool _ready_for_rx;
00549     uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
00550     events::EventQueue *_queue;
00551     lorawan_time_t _tx_timestamp;
00552 
00553 #if defined(LORAWAN_COMPLIANCE_TEST)
00554 
00555     /**
00556      * Used only for compliance testing
00557      */
00558     void compliance_test_handler(loramac_mcps_indication_t  *mcps_indication);
00559 
00560     /**
00561      * Used only for compliance testing
00562      */
00563     lorawan_status_t send_compliance_test_frame_to_mac();
00564 
00565     compliance_test_t _compliance_test;
00566 #endif
00567 };
00568 
00569 #endif /* LORAWANSTACK_H_ */