Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaWANStack.h Source File

LoRaWANStack.h

00001 /**
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2013 Semtech
00008  ___ _____ _   ___ _  _____ ___  ___  ___ ___
00009 / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
00010 \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
00012 embedded.connectivity.solutions===============
00013 
00014 Description: LoRaWAN stack layer that controls both MAC and PHY underneath
00015 
00016 License: Revised BSD License, see LICENSE.TXT file include in the project
00017 
00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
00019 
00020 
00021 Copyright (c) 2017, Arm Limited and affiliates.
00022 
00023 SPDX-License-Identifier: BSD-3-Clause
00024 */
00025 
00026 #ifndef LORAWANSTACK_H_
00027 #define LORAWANSTACK_H_
00028 
00029 #include <stdint.h>
00030 #include "events/EventQueue.h"
00031 #include "platform/Callback.h"
00032 #include "platform/NonCopyable.h"
00033 #include "lorawan/system/LoRaWANTimer.h"
00034 #include "lorastack/mac/LoRaMac.h"
00035 #include "lorawan/system/lorawan_data_structures.h"
00036 #include "LoRaRadio.h"
00037 
00038 #ifdef MBED_CONF_LORA_PHY
00039  #if MBED_CONF_LORA_PHY      == 0
00040   #include "lorawan/lorastack/phy/LoRaPHYEU868.h"
00041   #define LoRaPHY_region LoRaPHYEU868
00042  #elif MBED_CONF_LORA_PHY    == 1
00043   #include "lorawan/lorastack/phy/LoRaPHYAS923.h"
00044   #define LoRaPHY_region LoRaPHYAS923
00045  #elif MBED_CONF_LORA_PHY    == 2
00046   #include "lorawan/lorastack/phy/LoRaPHYAU915.h"
00047  #define LoRaPHY_region LoRaPHYAU915;
00048  #elif MBED_CONF_LORA_PHY    == 3
00049   #include "lorawan/lorastack/phy/LoRaPHYCN470.h"
00050   #define LoRaPHY_region LoRaPHYCN470
00051  #elif MBED_CONF_LORA_PHY    == 4
00052   #include "lorawan/lorastack/phy/LoRaPHYCN779.h"
00053   #define LoRaPHY_region LoRaPHYCN779
00054  #elif MBED_CONF_LORA_PHY    == 5
00055   #include "lorawan/lorastack/phy/LoRaPHYEU433.h"
00056   #define LoRaPHY_region LoRaPHYEU433
00057  #elif MBED_CONF_LORA_PHY    == 6
00058   #include "lorawan/lorastack/phy/LoRaPHYIN865.h"
00059   #define LoRaPHY_region LoRaPHYIN865
00060  #elif MBED_CONF_LORA_PHY    == 7
00061   #include "lorawan/lorastack/phy/LoRaPHYKR920.h"
00062   #define LoRaPHY_region LoRaPHYKR920
00063  #elif MBED_CONF_LORA_PHY    == 8
00064   #include "lorawan/lorastack/phy/LoRaPHYUS915.h"
00065   #define LoRaPHY_region LoRaPHYUS915
00066  #elif MBED_CONF_LORA_PHY    == 9
00067   #include "lorawan/lorastack/phy/LoRaPHYUS915Hybrid.h"
00068   #define LoRaPHY_region LoRaPHYUS915Hybrid
00069  #endif //MBED_CONF_LORA_PHY == VALUE
00070 #else
00071  #error "Must set LoRa PHY layer parameters."
00072 #endif //MBED_CONF_LORA_PHY
00073 
00074 /**
00075  * A mask for the network ID.
00076  */
00077 #define LORAWAN_NETWORK_ID_MASK                          ( uint32_t )0xFE000000
00078 
00079 class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> {
00080 private:
00081     /** End-device states.
00082      *
00083      */
00084     typedef enum device_states {
00085         DEVICE_STATE_NOT_INITIALIZED,
00086         DEVICE_STATE_INIT,
00087         DEVICE_STATE_JOINING,
00088         DEVICE_STATE_ABP_CONNECTING,
00089         DEVICE_STATE_JOINED,
00090         DEVICE_STATE_SEND,
00091         DEVICE_STATE_IDLE,
00092 #if defined(LORAWAN_COMPLIANCE_TEST)
00093         DEVICE_STATE_COMPLIANCE_TEST,
00094 #endif
00095         DEVICE_STATE_SHUTDOWN
00096     } device_states_t;
00097 
00098 public:
00099     static LoRaWANStack& get_lorawan_stack();
00100 
00101     /** Binds radio driver to PHY layer.
00102      *
00103      * MAC layer is totally detached from the PHY layer so the stack layer
00104      * needs to play the role of an arbitrator. This API gets a radio driver
00105      * object from the application (via LoRaWANInterface), binds it to the PHY
00106      * layer and returns MAC layer callback handles which the radio driver will
00107      * use in order to report events.
00108      *
00109      * @param radio            LoRaRadio object, i.e., the radio driver
00110      *
00111      * @return                 A list of callbacks from MAC layer that needs to
00112      *                         be passed to radio driver
00113      */
00114     radio_events_t *bind_radio_driver(LoRaRadio& radio);
00115 
00116     /** End device initialization.
00117      * @param queue            A pointer to an EventQueue passed from the application.
00118      * @return                 LORAWAN_STATUS_OK on success, a negative error code on failure.
00119      */
00120     lorawan_status_t initialize_mac_layer(events::EventQueue *queue);
00121 
00122     /** Sets all callbacks for the application.
00123      *
00124      * @param callbacks        A pointer to the structure carrying callbacks.
00125      */
00126     void set_lora_callbacks(lorawan_app_callbacks_t *callbacks);
00127 
00128     /** Adds channels to use.
00129      *
00130      * You can provide a list of channels with appropriate parameters filled
00131      * in. However, this list is not absolute. In some regions, a CF
00132      * list gets implemented by default, which means that the network can overwrite your channel
00133      * frequency settings right after receiving a Join Accept. You may try
00134      * to set up any channel or channels after that and if the channel requested
00135      * is already active, the request is silently ignored. A negative error
00136      * code is returned if there is any problem with parameters.
00137      *
00138      * You need to ensure that the base station nearby supports the channel or channels being added.
00139      *
00140      * If your list includes a default channel (a channel where Join Requests
00141      * are received) you cannot fully configure the channel parameters.
00142      * Either leave the channel settings to default or check your
00143      * corresponding PHY layer implementation. For example, LoRaPHYE868.
00144      *
00145      * @param  channel_plan     A list of channels or a single channel.
00146      *
00147      * @return                  LORAWAN_STATUS_OK on success, a negative error
00148      *                          code on failure.
00149      */
00150     lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan);
00151 
00152     /** Removes a channel from the list.
00153      *
00154      * @param channel_id        Index of the channel being removed
00155      *
00156      * @return                  LORAWAN_STATUS_OK on success, a negative error
00157      *                          code on failure.
00158      */
00159     lorawan_status_t remove_a_channel(uint8_t channel_id);
00160 
00161     /** Removes a previously set channel plan.
00162      *
00163      * @return                  LORAWAN_STATUS_OK on success, a negative error
00164      *                          code on failure.
00165      */
00166     lorawan_status_t drop_channel_list();
00167 
00168     /** Gets a list of currently enabled channels .
00169      *
00170      * @param channel_plan      The channel plan structure to store final result.
00171      *
00172      * @return                  LORAWAN_STATUS_OK on success, a negative error
00173      *                          code on failure.
00174      */
00175     lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan);
00176 
00177     /** Sets up a retry counter for confirmed messages.
00178      *
00179      * Valid only for confirmed messages. This API sets the number of times the
00180      * stack will retry a CONFIRMED message before giving up and reporting an
00181      * error.
00182      *
00183      * @param count             The number of retries for confirmed messages.
00184      *
00185      * @return                  LORAWAN_STATUS_OK or a negative error code.
00186      */
00187     lorawan_status_t set_confirmed_msg_retry(uint8_t count);
00188 
00189     /** Sets up the data rate.
00190      *
00191      * `set_datarate()` first verifies whether the data rate given is valid or not.
00192      * If it is valid, the system sets the given data rate to the channel.
00193      *
00194      * @param data_rate   The intended data rate, for example DR_0 or DR_1.
00195      *                    Note that the macro DR_* can mean different
00196      *                    things in different regions.
00197      *
00198      * @return            LORAWAN_STATUS_OK if everything goes well, otherwise
00199      *                    a negative error code.
00200      */
00201     lorawan_status_t set_channel_data_rate(uint8_t data_rate);
00202 
00203     /** Enables ADR.
00204      *
00205      * @param adr_enabled       0 ADR disabled, 1 ADR enabled.
00206      *
00207      * @return                  LORAWAN_STATUS_OK on success, a negative error
00208      *                          code on failure.
00209      */
00210     lorawan_status_t enable_adaptive_datarate(bool adr_enabled);
00211 
00212     /** Commissions a LoRa device.
00213      *
00214      * @param commission_data   A structure representing all the commission
00215      *                          information.
00216      */
00217     void commission_device(const lorawan_dev_commission_t &commission_data);
00218 
00219     /** End device OTAA join.
00220      *
00221      * Based on the LoRaWAN standard 1.0.2.
00222      * Join the network using the Over The Air Activation (OTAA) procedure.
00223      *
00224      * @param  params           The `lorawan_connect_t` type structure.
00225      *
00226      * @return                  LORAWAN_STATUS_OK or
00227      *                          LORAWAN_STATUS_CONNECT_IN_PROGRESS on success,
00228      *                          or a negative error code on failure.
00229      */
00230     lorawan_status_t join_request_by_otaa(const lorawan_connect_t &params);
00231 
00232     /** End device ABP join.
00233      *
00234      * Based on the LoRaWAN standard 1.0.2.
00235      * Join the network using the Activation By Personalization (ABP) procedure.
00236      *
00237      * @param  params           The `lorawan_connect_t` type structure.
00238      *
00239      * @return                  LORAWAN_STATUS_OK or
00240      *                          LORAWAN_STATUS_CONNECT_IN_PROGRESS on success,
00241      *                          or a negative error code on failure.
00242      */
00243     lorawan_status_t activation_by_personalization(const lorawan_connect_t &params);
00244 
00245     /** Send message to gateway
00246      *
00247      * @param port              The application port number. Port numbers 0 and 224
00248      *                          are reserved, whereas port numbers from 1 to 223
00249      *                          (0x01 to 0xDF) are valid port numbers.
00250      *                          Anything out of this range is illegal.
00251      *
00252      * @param data              A pointer to the data being sent. The ownership of the
00253      *                          buffer is not transferred. The data is copied to the
00254      *                          internal buffers.
00255      *
00256      * @param length            The size of data in bytes.
00257      *
00258      * @param flags             A flag used to determine what type of
00259      *                          message is being sent, for example:
00260      *
00261      *                          MSG_UNCONFIRMED_FLAG = 0x01
00262      *                          MSG_CONFIRMED_FLAG = 0x02
00263      *                          MSG_MULTICAST_FLAG = 0x04
00264      *                          MSG_PROPRIETARY_FLAG = 0x08
00265      *                          MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be
00266      *                          used in conjunction with MSG_UNCONFIRMED_FLAG and
00267      *                          MSG_CONFIRMED_FLAG depending on the intended use.
00268      *
00269      *                          MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set
00270      *                          a confirmed message flag for a proprietary message.
00271      *                          MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are
00272      *                          mutually exclusive.
00273      *
00274      *
00275      * @return                  The number of bytes sent, or
00276      *                          LORAWAN_STATUS_WOULD_BLOCK if another TX is
00277      *                          ongoing, or a negative error code on failure.
00278      */
00279     int16_t handle_tx(uint8_t port, const uint8_t* data,
00280                       uint16_t length, uint8_t flags);
00281 
00282     /** Receives a message from the Network Server.
00283      *
00284      * @param port              The application port number. Port numbers 0 and 224
00285      *                          are reserved, whereas port numbers from 1 to 223
00286      *                          (0x01 to 0xDF) are valid port numbers.
00287      *                          Anything out of this range is illegal.
00288      *
00289      * @param data              A pointer to buffer where the received data will be
00290      *                          stored.
00291      *
00292      * @param length            The size of data in bytes
00293      *
00294      * @param flags             A flag is used to determine what type of
00295      *                          message is being received, for example:
00296      *
00297      *                          MSG_UNCONFIRMED_FLAG = 0x01,
00298      *                          MSG_CONFIRMED_FLAG = 0x02
00299      *                          MSG_MULTICAST_FLAG = 0x04,
00300      *                          MSG_PROPRIETARY_FLAG = 0x08
00301      *
00302      *                          MSG_MULTICAST_FLAG and MSG_PROPRIETARY_FLAG can be
00303      *                          used in conjunction with MSG_UNCONFIRMED_FLAG and
00304      *                          MSG_CONFIRMED_FLAG depending on the intended use.
00305      *
00306      *                          MSG_PROPRIETARY_FLAG|MSG_CONFIRMED_FLAG mask will set
00307      *                          a confirmed message flag for a proprietary message.
00308      *
00309      *                          MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are
00310      *                          not mutually exclusive, i.e., the user can subscribe to
00311      *                          receive both CONFIRMED AND UNCONFIRMED messages at
00312      *                          the same time.
00313      *
00314      * @return                  It could be one of these:
00315      *                             i)   0 if there is nothing else to read.
00316      *                             ii)  Number of bytes written to user buffer.
00317      *                             iii) LORAWAN_STATUS_WOULD_BLOCK if there is
00318      *                                  nothing available to read at the moment.
00319      *                             iv)  A negative error code on failure.
00320      */
00321     int16_t handle_rx(const uint8_t port, uint8_t* data,
00322                       uint16_t length, uint8_t flags);
00323 
00324     /** Send Link Check Request MAC command.
00325      *
00326      *
00327      * This API schedules a Link Check Request command (LinkCheckReq) for the network
00328      * server and once the response, i.e., LinkCheckAns MAC command is received
00329      * from the Network Server, an event is generated.
00330      *
00331      * A callback function for the link check response must be set prior to using
00332      * this API, otherwise a LORAWAN_STATUS_PARAMETER_INVALID error is thrown.
00333      *
00334      * @return          LORAWAN_STATUS_OK on successfully queuing a request, or
00335      *                  a negative error code on failure.
00336      *
00337      */
00338     lorawan_status_t set_link_check_request();
00339 
00340     /** Shuts down the LoRaWAN protocol.
00341      *
00342      * In response to the user call for disconnection, the stack shuts down itself.
00343      *
00344      * @return          LORAWAN_STATUS_DEVICE_OFF on successfully shutdown.
00345      */
00346     lorawan_status_t shutdown();
00347 
00348 private:
00349     LoRaWANStack();
00350     ~LoRaWANStack();
00351 
00352     /**
00353      * Checks if the user provided port is valid or not
00354      */
00355     bool is_port_valid(uint8_t port);
00356 
00357     /**
00358      * State machine for stack controller layer.
00359      * Needs to be wriggled for every state change
00360      */
00361     lorawan_status_t lora_state_machine();
00362 
00363     /**
00364      * Sets the current state of the device.
00365      * Every call to set_device_state() should precede with
00366      * a call to lora_state_machine() in order to take the state change
00367      * in effect.
00368      */
00369     void set_device_state(device_states_t new_state);
00370 
00371     /**
00372      * Hands over the packet to Mac layer by posting an MCPS request.
00373      */
00374     lorawan_status_t send_frame_to_mac();
00375 
00376     /**
00377      * Callback function for MLME indication. Mac layer calls this function once
00378      * an MLME indication is received. This method translates Mac layer data
00379      * structure into stack layer data structure.
00380      */
00381     void mlme_indication_handler(loramac_mlme_indication_t  *mlmeIndication);
00382 
00383     /**
00384      * Handles an MLME request coming from the upper layers and delegates
00385      * it to the Mac layer, for example, a Join request goes as an MLME request
00386      * to the Mac layer.
00387      */
00388     lorawan_status_t mlme_request_handler(loramac_mlme_req_t  *mlme_request);
00389 
00390     /**
00391      * Handles an MLME confirmation coming from the Mac layer and uses it to
00392      * update the state for example, a Join Accept triggers an MLME confirmation,
00393      * that eventually comes here and we take necessary steps accordingly.
00394      */
00395     void mlme_confirm_handler(loramac_mlme_confirm_t  *mlme_confirm);
00396 
00397     /**
00398      * Handles an MCPS request while attempting to hand over a packet from
00399      * upper layers to Mac layer. For example in response to send_frame_to_mac(),
00400      * an MCPS request is generated.
00401      */
00402     lorawan_status_t mcps_request_handler(loramac_mcps_req_t  *mcps_request);
00403 
00404     /**
00405      * Handles an MCPS confirmation coming from the Mac layer in response to an
00406      * MCPS request. We take appropriate actions in response to the confirmation,
00407      * e.g., letting the application know that ack was not received in case of
00408      * a CONFIRMED message or scheduling error etc.
00409      */
00410     void mcps_confirm_handler(loramac_mcps_confirm_t  *mcps_confirm);
00411 
00412     /**
00413      * Handles an MCPS indication coming from the Mac layer, e.g., once we
00414      * receive a packet from the Network Server, it is indicated to this handler
00415      * and consequently this handler posts an event to the application that
00416      * there is something available to read.
00417      */
00418     void mcps_indication_handler(loramac_mcps_indication_t  *mcps_indication);
00419 
00420     /**
00421      * Sets a MIB request, i.e., update a particular parameter etc.
00422      */
00423     lorawan_status_t mib_set_request(loramac_mib_req_confirm_t  *mib_set_params);
00424 
00425     /**
00426      * Requests the MIB to inquire about a particular parameter.
00427      */
00428     lorawan_status_t mib_get_request(loramac_mib_req_confirm_t  *mib_get_params);
00429 
00430     /**
00431      * Sets up user application port
00432      */
00433     lorawan_status_t set_application_port(uint8_t port);
00434 
00435     /**
00436      * Helper function to figure out if the user defined data size is possible
00437      * to send or not. The allowed size for transmission depends on the current
00438      * data rate set for the channel. If its not possible to send user defined
00439      * packet size, this method returns the maximum possible size at the moment,
00440      * otherwise the user defined size is returned which means all of user data
00441      * can be sent.
00442      */
00443     uint16_t check_possible_tx_size(uint16_t size);
00444 
00445 private:
00446 
00447     LoRaWANTimeHandler _lora_time;
00448     LoRaMac _loramac;
00449     LoRaPHY_region _lora_phy;
00450     loramac_primitives_t  LoRaMacPrimitives;
00451 
00452     device_states_t _device_current_state;
00453     lorawan_app_callbacks_t _callbacks;
00454     radio_events_t *_mac_handlers;
00455     lorawan_session_t _lw_session;
00456     loramac_tx_message_t _tx_msg;
00457     loramac_rx_message_t _rx_msg;
00458     uint8_t _num_retry;
00459     uint8_t _app_port;
00460     bool _duty_cycle_on;
00461     events::EventQueue *_queue;
00462 
00463 #if defined(LORAWAN_COMPLIANCE_TEST)
00464     /**
00465      * This function is used only for compliance testing
00466      */
00467     void prepare_special_tx_frame(uint8_t port);
00468 
00469     /**
00470      * Used only for compliance testing
00471      */
00472     void compliance_test_handler(loramac_mcps_indication_t  *mcps_indication);
00473 
00474     /**
00475      * Used only for compliance testing
00476      */
00477     lorawan_status_t send_compliance_test_frame_to_mac();
00478 
00479     uint8_t compliance_test_buffer[MBED_CONF_LORA_TX_MAX_SIZE];
00480     compliance_test_t _compliance_test;
00481 #endif
00482 };
00483 
00484 #endif /* LORAWANSTACK_H_ */