mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
222 lines
8.3 KiB
C
222 lines
8.3 KiB
C
/*
|
|
* Copyright (C) 2019 Freie Universität Berlin
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @defgroup pkg_nimble_autoconn Autoconn
|
|
* @ingroup pkg_nimble
|
|
* @brief Simple connection manager that automatically opens BLE
|
|
* connections to any node that fits some given filter criteria
|
|
*
|
|
* @experimental
|
|
*
|
|
* # WARNING
|
|
* This module is highly experimental! Expect bugs, instabilities and sudden API
|
|
* changes :-)
|
|
*
|
|
*
|
|
* # About
|
|
* This NimBLE submodule implements a connection manager for BLE. It takes care
|
|
* of scanning, advertising, and opening connections to neighboring nodes. For
|
|
* this autoconn periodically switches between advertising and scanning mode,
|
|
* hence from accepting incoming connection requests to scanning actively for
|
|
* new neighbors.
|
|
*
|
|
*
|
|
* # Concept
|
|
* The IETF and BT SIG standards describing IP-over-BLE only describe how to
|
|
* transfer IP data over L2CAP connection oriented channels. But they do not
|
|
* say anything about when BLE connections should be established between two
|
|
* BLE nodes in the first place. While this can be done manually (e.g. via RIOTs
|
|
* `ble` shell command), this is certainly no option in massive M2M deployments.
|
|
*
|
|
* To enable nodes to automatically connect to their neighbors, autoconn
|
|
* implements a naive strategy which makes nodes to connect to any neighbor they
|
|
* see, as long as the neighbor signals a predefined set of capabilities.
|
|
*
|
|
* In particular, neighbors are simply filtered by looking at the 16-bit service
|
|
* UUIDs included in the `Incomplete List of 16-bit Service UUIDs` field in the
|
|
* advertising data that is received from neighbors.
|
|
*
|
|
* The logical network topology (as seen by IP) is formed by the established
|
|
* BLE link layer connections. It is important to node, that the autoconn module
|
|
* will form a random topology on the link layer, as no further context
|
|
* information is used for the connection decisions. This can potentially lead
|
|
* to fragmented, non-connected sub-networks in larger deployments!
|
|
*
|
|
*
|
|
* # State Machine
|
|
* Autoconn implements a state machine, that switches a nodes role periodically
|
|
* between scanning and advertising. To make sure, that nodes always have a
|
|
* chance to see each other, especially when booted at the same point in time,
|
|
* the intervals of each role consist of a constant amount of time plus a
|
|
* random interval. This way two nodes will eventually see each other and be
|
|
* able to establish a connection.
|
|
*
|
|
* All timing values for the interval duration and the maximum amount of the
|
|
* random offset are configurable.
|
|
*
|
|
*
|
|
* # Usage
|
|
* In the current state, the filtering of neighbors is hard coded into the
|
|
* autoconn module. Two options are implemented:
|
|
*
|
|
* 1. connect to any neighbor capable of IP-over-BLE -> @ref BLE_GATT_SVC_IPSS
|
|
* UUID included in the BLE_GAP_AD_UUID16_INCOMP field of the received
|
|
* advertising data
|
|
* 2. connect to any neighbor capable of NDN-over-BLE -> @ref BLE_GATT_SVC_NDNSS
|
|
* UUID included in the BLE_GAP_AD_UUID16_INCOMP field of the received
|
|
* advertising data
|
|
*
|
|
* The active filter used in autoconn is selected using one of two submodules
|
|
* during build time:
|
|
*
|
|
* 1. `USEMDOULE += nimble_autoconn_ipsp`
|
|
* 2. `USEMODULE += nibmle_autoconn_ndnsp'
|
|
*
|
|
* @note The NDN support service (NDNSP) is defined by us and it is not at
|
|
* all standardized nor sanctioned by the BT SIG. For experimental use
|
|
* only...
|
|
*
|
|
*
|
|
* # Implementation Status
|
|
* - The filter function could be more powerful. It is probably a good idea to
|
|
* extend this module to allow for passing custom filter functions using a
|
|
* function pointer
|
|
* - Currently this module does not allow to use NimBLE as IP-over-BLE node and
|
|
* as a GATT server concurrently. This could be enabled by adding an
|
|
* additional callback function which exposes some/all GAP events to a user
|
|
* application (i.e. BLE_GAP_EVENT_SUBSCRIBE, BLE_GAP_EVENT_NOTIFY_RX,
|
|
* BLE_GAP_EVENT_NOTIFY_TX).
|
|
* - It might make sense to get rid of the periodic switching between scanning
|
|
* and advertising in favor of doing both in parallel. This would simplify the
|
|
* code (and configuration) quite a bit. But in the past, there were severe
|
|
* stability issues with NimBLE doing this, so it needs to be evaluated in the
|
|
* future if this is a feasible option.
|
|
*
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Simple automated connection manager for NimBLE netif
|
|
*
|
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
|
*/
|
|
|
|
#ifndef NIMBLE_AUTOCONN_H
|
|
#define NIMBLE_AUTOCONN_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "nimble_netif.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief Return codes used by the autoconn module
|
|
*/
|
|
enum {
|
|
NIMBLE_AUTOCONN_OK = 0, /**< like a walk in the park */
|
|
NIMBLE_AUTOCONN_PARAMERR = -1, /**< invalid parameters given */
|
|
NIMBLE_AUTOCONN_ADERR = -2, /**< error generating advertising data */
|
|
};
|
|
|
|
/**
|
|
* @brief Set of configuration parameters needed to run autoconn
|
|
*/
|
|
typedef struct {
|
|
/** amount of time spend in scanning mode [in ms] */
|
|
uint32_t period_scan_ms;
|
|
/** amount of time spend in advertising mode [in ms] */
|
|
uint32_t period_adv_ms;
|
|
/** a random value from 0 to this value is added to the duration of each
|
|
* scanning and advertising period [in ms] */
|
|
uint32_t period_jitter_ms;
|
|
/** advertising interval used when in advertising mode [in ms] */
|
|
uint32_t adv_itvl_ms;
|
|
/** scan interval applied while in scanning state [in ms] */
|
|
uint32_t scan_itvl_ms;
|
|
/** scan window applied while in scanning state [in ms] */
|
|
uint32_t scan_win_ms;
|
|
/** opening a new connection is aborted after this time [in ms] */
|
|
uint32_t conn_timeout_ms;
|
|
/** connection interval used when opening a new connection, lower bound.
|
|
* [in ms] */
|
|
uint32_t conn_itvl_min_ms;
|
|
/** connection interval, upper bound [in ms] */
|
|
uint32_t conn_itvl_max_ms;
|
|
/** slave latency used for new connections */
|
|
uint16_t conn_latency;
|
|
/** supervision timeout used for new connections [in ms] */
|
|
uint32_t conn_super_to_ms;
|
|
/** BLE PHY mode to use */
|
|
nimble_phy_t phy_mode;
|
|
/** node ID included in the advertising data, may be NULL */
|
|
const char *node_id;
|
|
} nimble_autoconn_params_t;
|
|
|
|
/**
|
|
* @brief Initialize and enable the autoconn module
|
|
*
|
|
* @warning This function **must** only be called once. Typically this is during
|
|
* system initialization or at the beginning of the user application.
|
|
* Use nimble_autoconn_update() to update parameters at runtime.
|
|
*
|
|
* @warning Autoconn expects nimble_netif to be initialized. So make sure
|
|
* nimble_netif_init() was called before calling nimble_autoconn_init().
|
|
*
|
|
* @param[in] params timing parameters to use
|
|
* @param[in] ad advertising data, if NULL it is generated
|
|
* @param[in] adlen length of @p ad in bytes
|
|
*/
|
|
int nimble_autoconn_init(const nimble_autoconn_params_t *params,
|
|
const uint8_t *ad, size_t adlen);
|
|
|
|
/**
|
|
* @brief Register a callback that is called on netif events
|
|
*
|
|
* The registered callback function is a simple pass-through of nimble_netif
|
|
* events. The callback is executed in the context of NimBLE's host thread.
|
|
*
|
|
* @param[in] cb event callback to register, may be NULL
|
|
*/
|
|
void nimble_autoconn_eventcb(nimble_netif_eventcb_t cb);
|
|
|
|
/**
|
|
* @brief Update the used parameters (timing and node ID)
|
|
*
|
|
* @param[in] params new parameters to apply
|
|
* @param[in] ad advertising data, if NULL it is generated
|
|
* @param[in] adlen length of @p ad in bytes
|
|
*
|
|
* @return NIMBLE_AUTOCONN_OK if everything went fine
|
|
* @return NIMBLE_AUTOCONN_INVALID if given parameters can not be applied
|
|
*/
|
|
int nimble_autoconn_update(const nimble_autoconn_params_t *params,
|
|
const uint8_t *ad, size_t adlen);
|
|
|
|
/**
|
|
* @brief Enable automated creation of new BLE connections
|
|
*/
|
|
void nimble_autoconn_enable(void);
|
|
|
|
/**
|
|
* @brief Disable the automated connection management
|
|
*
|
|
* @note All existing connections are kept, only the scanning and advertising
|
|
* is canceled
|
|
*/
|
|
void nimble_autoconn_disable(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* NIMBLE_AUTOCONN_H */
|
|
/** @} */
|