Nicolas Borla
/
BBR_1Ebene
BBR 1 Ebene
Diff: mbed-os/features/lorawan/LoRaWANStack.h
- Revision:
- 0:fbdae7e6d805
diff -r 000000000000 -r fbdae7e6d805 mbed-os/features/lorawan/LoRaWANStack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os/features/lorawan/LoRaWANStack.h Mon May 14 11:29:06 2018 +0000 @@ -0,0 +1,509 @@ +/** + * \file LoRaWANStack.h + * + * \brief LoRaWAN stack layer implementation + * + * \copyright Revised BSD License, see LICENSE.TXT file include in the project + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013 Semtech + * + * ___ _____ _ ___ _ _____ ___ ___ ___ ___ + * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| + * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| + * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| + * embedded.connectivity.solutions=============== + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + * + * \author Daniel Jaeckle ( STACKFORCE ) + * + * \defgroup LoRaWAN stack layer that controls MAC layer underneath + * + * License: Revised BSD License, see LICENSE.TXT file include in the project + * + * Copyright (c) 2017, Arm Limited and affiliates. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef LORAWANSTACK_H_ +#define LORAWANSTACK_H_ + +#include <stdint.h> +#include "events/EventQueue.h" +#include "platform/Callback.h" +#include "platform/NonCopyable.h" +#include "platform/ScopedLock.h" + +#include "lorastack/mac/LoRaMac.h" +#include "system/LoRaWANTimer.h" +#include "system/lorawan_data_structures.h" +#include "LoRaRadio.h" + +class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> { + +public: + LoRaWANStack(); + + /** Binds radio driver to PHY layer. + * + * MAC layer is totally detached from the PHY layer so the stack layer + * needs to play the role of an arbitrator. This API gets a radio driver + * object from the application (via LoRaWANInterface), binds it to the PHY + * layer and initialises radio callback handles which the radio driver will + * use in order to report events. + * + * @param radio LoRaRadio object, i.e., the radio driver + * + */ + void bind_radio_driver(LoRaRadio& radio); + + /** End device initialization. + * @param queue A pointer to an EventQueue passed from the application. + * @return LORAWAN_STATUS_OK on success, a negative error code on failure. + */ + lorawan_status_t initialize_mac_layer(events::EventQueue *queue); + + /** Sets all callbacks for the application. + * + * @param callbacks A pointer to the structure carrying callbacks. + * @return LORAWAN_STATUS_OK on success, a negative error code on failure. + */ + lorawan_status_t set_lora_callbacks(const lorawan_app_callbacks_t *callbacks); + + /** Connect OTAA or ABP using Mbed-OS config system + * + * Connect by Over The Air Activation or Activation By Personalization. + * You need to configure the connection properly via the Mbed OS configuration + * system. + * + * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative. + * However, this is not a real error. It tells you that the connection is in progress and you will + * be notified of the completion via an event. By default, after the Join Accept message + * is received, base stations may provide the node with a CF-List that replaces + * all user-configured channels except the Join/Default channels. A CF-List can + * configure a maximum of five channels other than the default channels. + * + * In case of ABP, the CONNECTED event is posted before the call to `connect()` returns. + * To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection. + * By default, the PHY layers configure only the mandatory Join channels. The retransmission back-off restrictions + * on these channels are severe and you may experience long delays or even failures in the confirmed traffic. + * If you add more channels, the aggregated duty cycle becomes much more relaxed as compared to the Join (default) channels only. + * + * **NOTES ON RECONNECTION:** + * Currently, the Mbed OS LoRaWAN implementation does not support non-volatile + * memory storage. Therefore, the state and frame counters cannot be restored after + * a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN + * protocol, the state and frame counters are saved. Connecting again would try to + * restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset + * to zero for OTAA and a new Join request lets the network server know + * that the counters need a reset. The same is said about the ABP but there + * is no way to convey this information to the network server. For a network + * server, an ABP device is always connected. That's why storing the frame counters + * is important, at least for ABP. That's why we try to restore frame counters from + * session information after a disconnection. + * + * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS + * on success, or a negative error code on failure. + */ + lorawan_status_t connect(); + + /** Connect OTAA or ABP with parameters + * + * All connection parameters are chosen by the user and provided in the + * data structure passed down. + * + * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative. + * However, this is not a real error. It tells you that connection is in progress and you will + * be notified of completion via an event. By default, after Join Accept message + * is received, base stations may provide the node with a CF-List which replaces + * all user-configured channels except the Join/Default channels. A CF-List can + * configure a maximum of five channels other than the default channels. + * + * In case of ABP, the CONNECTED event is posted before the call to `connect()` returns. + * To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection. + * By default, the PHY layers configure only the mandatory Join + * channels. The retransmission back-off restrictions on these channels + * are severe and you may experience long delays or even + * failures in the confirmed traffic. If you add more channels, the aggregated duty + * cycle becomes much more relaxed as compared to the Join (default) channels only. + * + * **NOTES ON RECONNECTION:** + * Currently, the Mbed OS LoRaWAN implementation does not support non-volatile + * memory storage. Therefore, the state and frame counters cannot be restored after + * a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN + * protocol, the state and frame counters are saved. Connecting again would try to + * restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset + * to zero for OTAA and a new Join request lets the network server know + * that the counters need a reset. The same is said about the ABP but there + * is no way to convey this information to the network server. For a network + * server, an ABP device is always connected. That's why storing the frame counters + * is important, at least for ABP. That's why we try to restore frame counters from + * session information after a disconnection. + * + * @param connect Options for an end device connection to the gateway. + * + * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS, + * a negative error code on failure. + */ + lorawan_status_t connect(const lorawan_connect_t &connect); + + /** Adds channels to use. + * + * You can provide a list of channels with appropriate parameters filled + * in. However, this list is not absolute. In some regions, a CF + * list gets implemented by default, which means that the network can overwrite your channel + * frequency settings right after receiving a Join Accept. You may try + * to set up any channel or channels after that and if the channel requested + * is already active, the request is silently ignored. A negative error + * code is returned if there is any problem with parameters. + * + * You need to ensure that the base station nearby supports the channel or channels being added. + * + * If your list includes a default channel (a channel where Join Requests + * are received) you cannot fully configure the channel parameters. + * Either leave the channel settings to default or check your + * corresponding PHY layer implementation. For example, LoRaPHYE868. + * + * @param channel_plan A list of channels or a single channel. + * + * @return LORAWAN_STATUS_OK on success, a negative error + * code on failure. + */ + lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan); + + /** Removes a channel from the list. + * + * @param channel_id Index of the channel being removed + * + * @return LORAWAN_STATUS_OK on success, a negative error + * code on failure. + */ + lorawan_status_t remove_a_channel(uint8_t channel_id); + + /** Removes a previously set channel plan. + * + * @return LORAWAN_STATUS_OK on success, a negative error + * code on failure. + */ + lorawan_status_t drop_channel_list(); + + /** Gets a list of currently enabled channels . + * + * @param channel_plan The channel plan structure to store final result. + * + * @return LORAWAN_STATUS_OK on success, a negative error + * code on failure. + */ + lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan); + + /** Sets up a retry counter for confirmed messages. + * + * Valid only for confirmed messages. This API sets the number of times the + * stack will retry a CONFIRMED message before giving up and reporting an + * error. + * + * @param count The number of retries for confirmed messages. + * + * @return LORAWAN_STATUS_OK or a negative error code. + */ + lorawan_status_t set_confirmed_msg_retry(uint8_t count); + + /** Sets up the data rate. + * + * `set_datarate()` first verifies whether the data rate given is valid or not. + * If it is valid, the system sets the given data rate to the channel. + * + * @param data_rate The intended data rate, for example DR_0 or DR_1. + * Note that the macro DR_* can mean different + * things in different regions. + * + * @return LORAWAN_STATUS_OK if everything goes well, otherwise + * a negative error code. + */ + lorawan_status_t set_channel_data_rate(uint8_t data_rate); + + /** Enables ADR. + * + * @param adr_enabled 0 ADR disabled, 1 ADR enabled. + * + * @return LORAWAN_STATUS_OK on success, a negative error + * code on failure. + */ + lorawan_status_t enable_adaptive_datarate(bool adr_enabled); + + /** Send message to gateway + * + * @param port The application port number. Port numbers 0 and 224 + * are reserved, whereas port numbers from 1 to 223 + * (0x01 to 0xDF) are valid port numbers. + * Anything out of this range is illegal. + * + * @param data A pointer to the data being sent. The ownership of the + * buffer is not transferred. The data is copied to the + * internal buffers. + * + * @param length The size of data in bytes. + * + * @param flags A flag used to determine what type of + * message is being sent, for example: + * + * MSG_UNCONFIRMED_FLAG = 0x01 + * MSG_CONFIRMED_FLAG = 0x02 + * MSG_MULTICAST_FLAG = 0x04 + * MSG_PROPRIETARY_FLAG = 0x08 + * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be + * used in conjunction with MSG_UNCONFIRMED_FLAG and + * MSG_CONFIRMED_FLAG depending on the intended use. + * + * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set + * a confirmed message flag for a proprietary message. + * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are + * mutually exclusive. + * + * @param null_allowed Internal use only. Needed for sending empty packet + * having CONFIRMED bit on. + * + * @param allow_port_0 Internal use only. Needed for flushing MAC commands. + * + * @return The number of bytes sent, or + * LORAWAN_STATUS_WOULD_BLOCK if another TX is + * ongoing, or a negative error code on failure. + */ + 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); + + /** Receives a message from the Network Server. + * + * @param data A pointer to buffer where the received data will be + * stored. + * + * @param length The size of data in bytes + * + * @param port The application port number. Port numbers 0 and 224 + * are reserved, whereas port numbers from 1 to 223 + * (0x01 to 0xDF) are valid port numbers. + * Anything out of this range is illegal. + * + * In return will contain the number of port to which + * message was received. + * + * @param flags A flag is used to determine what type of + * message is being received, for example: + * + * MSG_UNCONFIRMED_FLAG = 0x01, + * MSG_CONFIRMED_FLAG = 0x02 + * MSG_MULTICAST_FLAG = 0x04, + * MSG_PROPRIETARY_FLAG = 0x08 + * + * MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be + * used in conjunction with MSG_UNCONFIRMED_FLAG and + * MSG_CONFIRMED_FLAG depending on the intended use. + * + * MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set + * a confirmed message flag for a proprietary message. + * + * MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are + * not mutually exclusive, i.e., the user can subscribe to + * receive both CONFIRMED AND UNCONFIRMED messages at + * the same time. + * + * In return will contain the flags to determine what kind + * of message was received. + * + * @param validate_params If set to true, the given port and flags values will be checked + * against the values received with the message. If values do not + * match, LORAWAN_STATUS_WOULD_BLOCK will be returned. + * + * @return It could be one of these: + * i) 0 if there is nothing else to read. + * ii) Number of bytes written to user buffer. + * iii) LORAWAN_STATUS_WOULD_BLOCK if there is + * nothing available to read at the moment. + * iv) A negative error code on failure. + */ + int16_t handle_rx(uint8_t* data, uint16_t length, uint8_t& port, int& flags, bool validate_params); + + /** Send Link Check Request MAC command. + * + * + * This API schedules a Link Check Request command (LinkCheckReq) for the network + * server and once the response, i.e., LinkCheckAns MAC command is received + * from the Network Server, an event is generated. + * + * A callback function for the link check response must be set prior to using + * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown. + * + * @return LORAWAN_STATUS_OK on successfully queuing a request, or + * a negative error code on failure. + * + */ + lorawan_status_t set_link_check_request(); + + /** Removes link check request sticky MAC command. + * + * Any already queued request may still get entertained. However, no new + * requests will be made. + */ + void remove_link_check_request(); + + /** Shuts down the LoRaWAN protocol. + * + * In response to the user call for disconnection, the stack shuts down itself. + * + * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown. + */ + lorawan_status_t shutdown(); + + /** Change device class + * + * Change current device class. + * + * @param device_class The device class + * + * @return LORAWAN_STATUS_OK on success, + * LORAWAN_STATUS_UNSUPPORTED is requested class is not supported, + * or other negative error code if request failed. + */ + lorawan_status_t set_device_class(const device_class_t& device_class); + + void lock(void) { _loramac.lock(); } + void unlock(void) { _loramac.unlock(); } + +private: + typedef mbed::ScopedLock<LoRaWANStack> Lock; + /** + * Checks if the user provided port is valid or not + */ + bool is_port_valid(uint8_t port, bool allow_port_0 = false); + + /** + * State machine for stack controller layer. + */ + lorawan_status_t state_controller(device_states_t new_state); + + /** + * Helpers for state controller + */ + void process_uninitialized_state(lorawan_status_t& op_status); + void process_idle_state(lorawan_status_t& op_status); + void process_connected_state(); + void process_connecting_state(lorawan_status_t& op_status); + void process_joining_state(lorawan_status_t& op_status); + void process_scheduling_state(lorawan_status_t& op_status); + void process_status_check_state(); + void process_shutdown_state(lorawan_status_t& op_status); + void state_machine_run_to_completion(void); + + /** + * Handles MLME indications + */ + void mlme_indication_handler(void); + + /** + * Handles an MLME confirmation + */ + void mlme_confirm_handler(void); + + /** + * Handles an MCPS confirmation + */ + void mcps_confirm_handler(void); + + /** + * Handles an MCPS indication + */ + void mcps_indication_handler(void); + + /** + * Sets up user application port + */ + lorawan_status_t set_application_port(uint8_t port, bool allow_port_0 = false); + + /** + * Handles connection internally + */ + lorawan_status_t handle_connect(bool is_otaa); + + + /** Send event to application. + * + * @param event The event to be sent. + */ + void send_event_to_application(const lorawan_event_t event) const; + + /** Send empty uplink message to network. + * + * Sends an empty confirmed message to gateway. + * + * @param port The event to be sent. + */ + void send_automatic_uplink_message(uint8_t port); + + /** + * TX interrupt handlers and corresponding processors + */ + void tx_interrupt_handler(void); + void tx_timeout_interrupt_handler(void); + void process_transmission(void); + void process_transmission_timeout(void); + + /** + * RX interrupt handlers and corresponding processors + */ + void rx_interrupt_handler(const uint8_t *payload, uint16_t size, int16_t rssi, + int8_t snr); + void rx_timeout_interrupt_handler(void); + void rx_error_interrupt_handler(void); + void process_reception(const uint8_t *payload, uint16_t size, int16_t rssi, + int8_t snr); + void process_reception_timeout(bool is_timeout); + + int convert_to_msg_flag(const mcps_type_t type); + +private: + LoRaMac _loramac; + radio_events_t radio_events; + device_states_t _device_current_state; + lorawan_app_callbacks_t _callbacks; + lorawan_session_t _lw_session; + loramac_tx_message_t _tx_msg; + loramac_rx_message_t _rx_msg; + uint8_t _num_retry; + uint32_t _ctrl_flags; + uint8_t _app_port; + bool _link_check_requested; + bool _automatic_uplink_ongoing; + volatile bool _ready_for_rx; + uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD]; + events::EventQueue *_queue; + +#if defined(LORAWAN_COMPLIANCE_TEST) + + /** + * Used only for compliance testing + */ + void compliance_test_handler(loramac_mcps_indication_t *mcps_indication); + + /** + * Used only for compliance testing + */ + lorawan_status_t send_compliance_test_frame_to_mac(); + + compliance_test_t _compliance_test; +#endif +}; + +#endif /* LORAWANSTACK_H_ */