mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' of https://github.com/arendst/Tasmota into development
This commit is contained in:
commit
ca4ccd24d5
|
@ -2,6 +2,70 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.2.0] - 2021-02-08
|
||||
|
||||
### Added
|
||||
- `NimBLECharacteristic::getDescriptorByHandle`: Return the BLE Descriptor for the given handle.
|
||||
|
||||
- `NimBLEDescriptor::getStringValue`: Get the value of this descriptor as a string.
|
||||
|
||||
- `NimBLEServer::getServiceByHandle`: Get a service by its handle.
|
||||
|
||||
- `NimBLEService::getCharacteristicByHandle`: Get a pointer to the characteristic object with the specified handle.
|
||||
|
||||
- `NimBLEService::getCharacteristics`: Get the vector containing pointers to each characteristic associated with this service.
|
||||
Overloads to get a vector containing pointers to all the characteristics in a service with the UUID. (supports multiple same UUID's in a service)
|
||||
- `NimBLEService::getCharacteristics(const char *uuid)`
|
||||
- `NimBLEService::getCharacteristics(const NimBLEUUID &uuid)`
|
||||
|
||||
- `NimBLEAdvertisementData` New methods:
|
||||
- `NimBLEAdvertisementData::addTxPower`: Adds transmission power to the advertisement.
|
||||
- `NimBLEAdvertisementData::setPreferredParams`: Adds connection parameters to the advertisement.
|
||||
- `NimBLEAdvertisementData::setURI`: Adds URI data to the advertisement.
|
||||
|
||||
- `NimBLEAdvertising` New methods:
|
||||
- `NimBLEAdvertising::setName`: Set the name advertised.
|
||||
- `NimBLEAdvertising::setManufacturerData`: Adds manufacturer data to the advertisement.
|
||||
- `NimBLEAdvertising::setURI`: Adds URI data to the advertisement.
|
||||
- `NimBLEAdvertising::setServiceData`: Adds service data to the advertisement.
|
||||
- `NimBLEAdvertising::addTxPower`: Adds transmission power to the advertisement.
|
||||
- `NimBLEAdvertising::reset`: Stops the current advertising and resets the advertising data to the default values.
|
||||
|
||||
- `NimBLEDevice::setScanFilterMode`: Set the controller duplicate filter mode for filtering scanned devices.
|
||||
|
||||
- `NimBLEDevice::setScanDuplicateCacheSize`: Sets the number of advertisements filtered before the cache is reset.
|
||||
|
||||
- `NimBLEScan::setMaxResults`: This allows for setting a maximum number of advertised devices stored in the results vector.
|
||||
|
||||
- `NimBLEAdvertisedDevice` New data retrieval methods added:
|
||||
- `haveAdvInterval/getAdvInterval`: checks if the interval is advertised / gets the advertisement interval value.
|
||||
|
||||
- `haveConnParams/getMinInterval/getMaxInterval`: checks if the parameters are advertised / get min value / get max value.
|
||||
|
||||
- `haveURI/getURI`: checks if a URI is advertised / gets the URI data.
|
||||
|
||||
- `haveTargetAddress/getTargetAddressCount/getTargetAddress(index)`: checks if a target address is present / gets a count of the addresses targeted / gets the address of the target at index.
|
||||
|
||||
### Changed
|
||||
- `nimconfig.h` (Arduino) is now easier to use.
|
||||
|
||||
- `NimBLEServer::getServiceByUUID` Now takes an extra parameter of instanceID to support multiple services with the same UUID.
|
||||
|
||||
- `NimBLEService::getCharacteristic` Now takes an extra parameter of instanceID to support multiple characteristics with the same UUID.
|
||||
|
||||
- `NimBLEAdvertising` Transmission power is no longer advertised by default and can be added to the advertisement by calling `NimBLEAdvertising::addTxPower`
|
||||
|
||||
- `NimBLEAdvertising` Custom scan response data can now be used without custom advertisment.
|
||||
|
||||
- `NimBLEScan` Now uses the controller duplicate filter.
|
||||
|
||||
- `NimBLEAdvertisedDevice` Has been refactored to store the complete advertisement payload and no longer parses the data from each advertisement.
|
||||
Instead the data will be parsed on-demand when the user application asks for specific data.
|
||||
|
||||
### Fixed
|
||||
- `NimBLEHIDDevice` Characteristics now use encryption, this resolves an issue with communicating with devices requiring encryption for HID devices.
|
||||
|
||||
|
||||
## [1.1.0] - 2021-01-20
|
||||
|
||||
### Added
|
||||
|
@ -9,7 +73,7 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
- New examples for securing and authenticating client/server connections, by mblasee.
|
||||
|
||||
- `NimBLEAdvertiseing::SetMinPreferred` and `NimBLEAdvertiseing::SetMinPreferred` re-added.
|
||||
- `NimBLEAdvertising::SetMinPreferred` and `NimBLEAdvertising::SetMinPreferred` re-added.
|
||||
|
||||
- Conditional checks added for command line config options in `nimconfig.h` to support custom configuration in platformio.
|
||||
|
||||
|
@ -71,6 +135,7 @@ advertised them as 16/32bit but resolved them to 128bits. Both are now checked.
|
|||
|
||||
- (Arduino) Ensure controller mode is set to BLE Only.
|
||||
|
||||
|
||||
## [1.0.2] - 2020-09-13
|
||||
|
||||
### Changed
|
||||
|
@ -84,6 +149,7 @@ Any changes to the controller max connection settings in `sdkconfig.h` will now
|
|||
- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
|
||||
a task running on core 0 (same as the controller) has been implemented. This improves response times and reliability for all BLE functions.
|
||||
|
||||
|
||||
## [1.0.1] - 2020-09-02
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,93 +1,117 @@
|
|||
# Arduino command line and platformio config options
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED`
|
||||
|
||||
If defined, NimBLE Client functions will not be included.
|
||||
- Reduces flash size by approx. 7kB.
|
||||
<br>
|
||||
`CONFIG_BT_NIMBLE_MAX_CONNECTIONS`
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED`
|
||||
Sets the number of simultaneous connections (esp controller max is 9)
|
||||
- Default value is 3
|
||||
<br/>
|
||||
|
||||
If defined, NimBLE Scan functions will not be included.
|
||||
- Reduces flash size by approx. 26kB.
|
||||
<br>
|
||||
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED`
|
||||
Sets the default MTU size.
|
||||
- Default value is 255
|
||||
<br/>
|
||||
|
||||
If defined NimBLE Server functions will not be included.
|
||||
- Reduces flash size by approx. 16kB.
|
||||
<br>
|
||||
`CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME`
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED`
|
||||
|
||||
If defined, NimBLE Advertising functions will not be included.
|
||||
- Reduces flash size by approx. 5kB.
|
||||
<br>
|
||||
Set the default device name
|
||||
- Default value is "nimble"
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_DEBUG`
|
||||
|
||||
If defined, enables debug log messages from the NimBLE host
|
||||
- Uses approx. 32kB of flash memory.
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
`CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT`
|
||||
|
||||
If defined, NimBLE host return codes will be printed as text in debug log messages.
|
||||
- Uses approx. 7kB of flash memory.
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
`CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT`
|
||||
|
||||
If defined, GAP event codes will be printed as text in debug log messages.
|
||||
- Uses approx. 1kB of flash memory.
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
`CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT`
|
||||
|
||||
If defined, advertisment types will be printed as text while scanning in debug log messages.
|
||||
- Uses approx. 250 bytes of flash memory.
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE`
|
||||
|
||||
Set the default appearance.
|
||||
- Default value is 0x00
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED`
|
||||
|
||||
If defined, NimBLE Client functions will not be included.
|
||||
- Reduces flash size by approx. 7kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED`
|
||||
|
||||
If defined, NimBLE Scan functions will not be included.
|
||||
- Reduces flash size by approx. 26kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED`
|
||||
|
||||
If defined NimBLE Server functions will not be included.
|
||||
- Reduces flash size by approx. 16kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED`
|
||||
|
||||
If defined, NimBLE Advertising functions will not be included.
|
||||
- Reduces flash size by approx. 5kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_BONDS`
|
||||
|
||||
Sets the number of devices allowed to store/bond with
|
||||
- Default value is 3
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_CCCDS`
|
||||
|
||||
Sets the maximum number of CCCD subscriptions to store
|
||||
- Default value is 8
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_RPA_TIMEOUT`
|
||||
|
||||
Sets the random address refresh time in seconds.
|
||||
- Default value is 900
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT`
|
||||
|
||||
Set the number of msys blocks For prepare write & prepare responses. This may need to be increased if
|
||||
you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
- Default value is 12
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL`
|
||||
|
||||
Sets the NimBLE stack to use external PSRAM will be loaded
|
||||
- Must be defined with a value of 1; Default is CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_PINNED_TO_CORE`
|
||||
|
||||
Sets the core the NimBLE host stack will run on
|
||||
- Options: 0 or 1
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_TASK_STACK_SIZE`
|
||||
|
||||
Set the task stack size for the NimBLE core.
|
||||
Set the task stack size for the NimBLE core.
|
||||
- Default is 4096
|
||||
<br>
|
||||
|
||||
|
||||
`CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL`
|
||||
|
||||
Sets the NimBLE stack to use external PSRAM will be loaded
|
||||
- Must be defined with a value of 1; Default is CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
<br>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_CONNECTIONS`
|
||||
|
||||
Sets the number of simultaneous connections (esp controller max is 9)
|
||||
- Default value is 3
|
||||
<br>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_BONDS`
|
||||
|
||||
Sets the number of devices allowed to store/bond with
|
||||
- Default value is 3
|
||||
<br>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_CCCDS`
|
||||
|
||||
Sets the maximum number of CCCD subscriptions to store
|
||||
- Default value is 8
|
||||
<br>
|
||||
|
||||
`CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME`
|
||||
|
||||
Set the default device name
|
||||
- Default value is "nimble"
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ For example `BLEServer::createService(SERVICE_UUID)` will work just as it did be
|
|||
|
||||
<a name="characteristics"></a>
|
||||
### Characteristics
|
||||
The constructor for `(Nim)BLECharacteristic` is now private, so if you currently subclass it to add logic you should switch to use `NimBLEService::createCharacteristic` instead. Any custom processing logic previously in a `BLECharacteristic` subclass should be moved to a `NimBLECharacteristicCallbacks` subclass instead, and passed into `NimBLECharacteristic::setCallbacks`.
|
||||
|
||||
`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
|
||||
|
||||
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
|
||||
|
@ -218,10 +220,11 @@ If you wish to advertise these parameters you can still do so manually via `BLEA
|
|||
<br/>
|
||||
|
||||
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
|
||||
`NimBLEAdvertising::setAppearance`. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
|
||||
Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
|
||||
When using custom scan response data you must also use custom advertisement data.
|
||||
~~Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
|
||||
When using custom scan response data you must also use custom advertisement data.~~
|
||||
No longer true as of release 1.2.0 and above, custom scan response is now supported without custom advertisement data.
|
||||
<br/>
|
||||
|
||||
> BLEAdvertising::start (NimBLEAdvertising::start)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Usage Tips
|
||||
|
||||
## Put BLE functions in a task running on the NimBLE stack core
|
||||
|
||||
When commands are sent to the stack from a differnt core they can experience delays in execution.
|
||||
This library detects this and invokes the esp32 IPC to reroute these commands through the correct core but this also increases overhead.
|
||||
Therefore it is highly recommended to create tasks for BLE to run on the same core, the macro `CONFIG_BT_NIMBLE_PINNED_TO_CORE` can be used to set the core.
|
||||
<br/>
|
||||
|
||||
## Do not delete client instances unless necessary or unused
|
||||
|
||||
When a client instance has been created and has connected to a peer device and it has retrieved service/characteristic information it will store that data for the life of the client instance.
|
||||
If you are periodically connecting to the same devices and you have deleted the client instance or the services when connecting again it will cause a retrieval of that information from the peer again.
|
||||
This results in significant energy drain on the battery of the devices, fragments heap, and reduces connection performance.
|
||||
|
||||
Client instances in this library use approximately 20% of the original bluedroid library, deleteing them will provide much less gain than it did before.
|
||||
|
||||
It is recommended to retain the client instance in cases where the time between connecting to the same device is less than 5 minutes.
|
||||
<br/>
|
||||
|
||||
## Only retrieve the services and characteriscs needed
|
||||
|
||||
As a client the use of `NimBLEClient::getServices` or `NimBLERemoteService::getCharacteristics` and using `true` for the parameter should be limited to devices that are not known.
|
||||
Instead `NimBLEClient::getService(NimBLEUUID)` or `NimBLERemoteService::getCharacteristic(NimBLEUUID)` should be used to access certain attributes that are useful to the application.
|
||||
This reduces energy consumed, heap allocated, connection time and improves overall efficiency.
|
||||
<br/>
|
||||
|
||||
## Check return values
|
||||
|
||||
Many user issues can be avoided by checking if a function returned successfully, by either testing for true/false such as when calling `NimBLEClient::connect`,
|
||||
or nullptr such as when calling `NimBLEClient::getService`. The latter being a must, as calling a method on a nullptr will surely result in a crash.
|
||||
Most of the functions in this library return something that should be checked before proceeding.
|
||||
<br/>
|
||||
|
||||
## There will be bugs - please report them
|
||||
|
||||
No code is bug free and unit testing will not find them all on it's own. If you encounter a bug, please report it along with any logs and decoded backtrace if applicable.
|
||||
Best efforts will be made to correct any errors ASAP.
|
||||
|
||||
Bug reports can be made at https://github.com/h2zero/NimBLE-Arduino/issues or https://github.com/h2zero/esp-nimble-cpp/issues.
|
||||
Questions and suggestions will be happily accepted there as well.
|
|
@ -0,0 +1,71 @@
|
|||
/** Example of continuous scanning for BLE advertisements.
|
||||
* This example will scan forever while consuming as few resources as possible
|
||||
* and report all advertisments on the serial monitor.
|
||||
*
|
||||
* Created: on January 31 2021
|
||||
* Author: H2zero
|
||||
*
|
||||
*/
|
||||
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
NimBLEScan* pBLEScan;
|
||||
|
||||
class MyAdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
||||
Serial.printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scanning...");
|
||||
|
||||
/** *Optional* Sets the filtering mode used by the scanner in the BLE controller.
|
||||
*
|
||||
* Can be one of:
|
||||
* CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE (0) (default)
|
||||
* Filter by device address only, advertisements from the same address will be reported only once.
|
||||
*
|
||||
* CONFIG_BTDM_SCAN_DUPL_TYPE_DATA (1)
|
||||
* Filter by data only, advertisements with the same data will only be reported once,
|
||||
* even from different addresses.
|
||||
*
|
||||
* CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE (2)
|
||||
* Filter by address and data, advertisements from the same address will be reported only once,
|
||||
* except if the data in the advertisement has changed, then it will be reported again.
|
||||
*
|
||||
* Can only be used BEFORE calling NimBLEDevice::init.
|
||||
*/
|
||||
NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE);
|
||||
|
||||
/** *Optional* Sets the scan filter cache size in the BLE controller.
|
||||
* When the number of duplicate advertisements seen by the controller
|
||||
* reaches this value it will clear the cache and start reporting previously
|
||||
* seen devices. The larger this number, the longer time between repeated
|
||||
* device reports. Range 10 - 1000. (default 20)
|
||||
*
|
||||
* Can only be used BEFORE calling NimBLEDevice::init.
|
||||
*/
|
||||
NimBLEDevice::setScanDuplicateCacheSize(200);
|
||||
|
||||
NimBLEDevice::init("");
|
||||
|
||||
pBLEScan = NimBLEDevice::getScan(); //create new scan
|
||||
// Set the callback for when devices are discovered, no duplicates.
|
||||
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), false);
|
||||
pBLEScan->setActiveScan(true); // Set active scanning, this will get more data from the advertiser.
|
||||
pBLEScan->setInterval(97); // How often the scan occurs / switches channels; in milliseconds,
|
||||
pBLEScan->setWindow(37); // How long to scan during the interval; in milliseconds.
|
||||
pBLEScan->setMaxResults(0); // do not store the scan results, use callback only.
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// If an error occurs that stops the scan, it will be restarted here.
|
||||
if(pBLEScan->isScanning() == false) {
|
||||
// Start scan with: duration = 0 seconds(forever), no scan end callback, not a continuation of a previous scan.
|
||||
pBLEScan->start(0, nullptr, false);
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/** NimBLE_Service_Data_Advertiser Demo:
|
||||
*
|
||||
* Simple demo of advertising service data that changes every 5 seconds
|
||||
*
|
||||
* Created: on February 7 2021
|
||||
* Author: H2zero
|
||||
*
|
||||
*/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
|
||||
|
||||
static NimBLEUUID dataUuid(SERVICE_UUID);
|
||||
static NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
static uint32_t count = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting BLE work!");
|
||||
|
||||
NimBLEDevice::init("svc data");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
pAdvertising->stop();
|
||||
pAdvertising->setServiceData(dataUuid, std::string((char*)&count, sizeof(count)));
|
||||
pAdvertising->start();
|
||||
|
||||
Serial.printf("Advertising count = %d\n", count);
|
||||
count++;
|
||||
delay(5000);
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"name": "NimBLE-Arduino",
|
||||
"keywords": "esp32, bluetooth",
|
||||
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=NimBLE-Arduino
|
||||
version=1.1.0
|
||||
version=1.2.0
|
||||
author=h2zero
|
||||
maintainer=h2zero <powellperalta@gmail.com>
|
||||
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
||||
|
|
|
@ -28,25 +28,14 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
|||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() {
|
||||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() :
|
||||
m_payload(62,0)
|
||||
{
|
||||
m_advType = 0;
|
||||
m_appearance = 0;
|
||||
m_manufacturerData = "";
|
||||
m_name = "";
|
||||
m_rssi = -9999;
|
||||
m_txPower = 0;
|
||||
m_payloadLength = 0;
|
||||
m_payload = nullptr;
|
||||
|
||||
m_haveAppearance = false;
|
||||
m_haveManufacturerData = false;
|
||||
m_haveName = false;
|
||||
m_haveRSSI = false;
|
||||
m_haveServiceData = false;
|
||||
m_haveServiceUUID = false;
|
||||
m_haveTXPower = false;
|
||||
m_callbackSent = false;
|
||||
|
||||
m_callbackSent = false;
|
||||
m_timestamp = 0;
|
||||
m_advLength = 0;
|
||||
} // NimBLEAdvertisedDevice
|
||||
|
||||
|
||||
|
@ -82,25 +71,126 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
|||
* @return The appearance of the advertised device.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
||||
return m_appearance;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_APPEARANCE_LEN + 1) {
|
||||
return *field->value | *(field->value + 1) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertisement interval.
|
||||
* @return The advertisement interval in 0.625ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_ADV_ITVL_LEN + 1) {
|
||||
return *field->value | *(field->value + 1) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getAdvInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the preferred min connection interval.
|
||||
* @return The preferred min connection interval in 1.25ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
||||
return *field->value | *(field->value + 1) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getMinInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the preferred max connection interval.
|
||||
* @return The preferred max connection interval in 1.25ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
||||
return *(field->value + 2) | *(field->value + 3) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getMaxInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the manufacturer data.
|
||||
* @return The manufacturer data of the advertised device.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
||||
return m_manufacturerData;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > 1) {
|
||||
return std::string((char*)field->value, field->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} // getManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the URI from the advertisement.
|
||||
* @return The URI data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getURI() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > 1) {
|
||||
return std::string((char*)field->value, field->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} // getURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertised name.
|
||||
* @return The name of the advertised device.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getName() {
|
||||
return m_name;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
|
||||
{
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > 1) {
|
||||
return std::string((char*)field->value, field->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} // getName
|
||||
|
||||
|
||||
|
@ -122,17 +212,70 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
|
|||
} // getScan
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the number of target addresses.
|
||||
* @return The number of addresses.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the target address at the index.
|
||||
* @param [in] index The index of the target address.
|
||||
* @return The target address.
|
||||
*/
|
||||
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0xFF;
|
||||
|
||||
index++;
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
||||
|
||||
if (count < index) {
|
||||
index -= count;
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
||||
}
|
||||
|
||||
if(count > 0 && data_loc != 0xFF) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
}
|
||||
if(field->length > index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||
return NimBLEAddress(field->value + (index - 1) * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
return NimBLEAddress("");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service data.
|
||||
* @param [in] index The vector index of the service data requested.
|
||||
* @param [in] index The index of the service data requested.
|
||||
* @return The advertised service data or empty string if no data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||
if(index > m_serviceDataVec.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: index out of range");
|
||||
return "";
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
|
||||
if(data_loc != 0xFF) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > bytes) {
|
||||
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||
}
|
||||
}
|
||||
return m_serviceDataVec[index].second;
|
||||
|
||||
return "";
|
||||
} //getServiceData
|
||||
|
||||
|
||||
|
@ -141,51 +284,148 @@ std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
|||
* @param [in] uuid The uuid of the service data requested.
|
||||
* @return The advertised service data or empty string if no data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) const {
|
||||
for(auto &it : m_serviceDataVec) {
|
||||
if(it.first == uuid) {
|
||||
return it.second;
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t index = 0;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||
uint8_t plSize = m_payload.size() - 2;
|
||||
|
||||
while(data_loc < plSize) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(bytes == uuidBytes && NimBLEUUID(field->value, bytes, false) == uuid) {
|
||||
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||
}
|
||||
|
||||
index++;
|
||||
data_loc = findServiceData(index, &bytes);
|
||||
}
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: uuid not found");
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "No service data found");
|
||||
return "";
|
||||
} //getServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertised service UUID.
|
||||
* @param [in] index The vector index of the service data UUID requested.
|
||||
* @return The advertised service UUID or an empty UUID if not found.
|
||||
* @brief Get the UUID of the serice data at the index.
|
||||
* @param [in] index The index of the service data UUID requested.
|
||||
* @return The advertised service data UUID or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||
if(!haveServiceData() || index > m_serviceDataVec.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceDataUUID: index out of range");
|
||||
return NimBLEUUID("");
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
|
||||
if(data_loc != 0xFF) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length >= bytes) {
|
||||
return NimBLEUUID(field->value, bytes, false);
|
||||
}
|
||||
}
|
||||
return m_serviceDataVec[index].first;
|
||||
|
||||
return NimBLEUUID("");
|
||||
} // getServiceDataUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find the service data at the index.
|
||||
* @param [in] index The index of the service data to find.
|
||||
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
|
||||
* @return The index in the vector where the data is located, 0xFF if not found.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
uint8_t data_loc = 0;
|
||||
uint8_t found = 0;
|
||||
|
||||
*bytes = 0;
|
||||
index++;
|
||||
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16, index, &data_loc);
|
||||
if(found == index) {
|
||||
*bytes = 2;
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
index -= found;
|
||||
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, index, &data_loc);
|
||||
if(found == index) {
|
||||
*bytes = 4;
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
index -= found;
|
||||
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, index, &data_loc);
|
||||
if(found == index) {
|
||||
*bytes = 16;
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the count of advertised service data UUIDS
|
||||
* @return The number of service data UUIDS in the vector.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
return m_serviceDataVec.size();
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);
|
||||
|
||||
return count;
|
||||
} // getServiceDataCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the Service UUID.
|
||||
* @param [in] index The vector index of the service UUID requested.
|
||||
* @param [in] index The index of the service UUID requested.
|
||||
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
if(!haveServiceUUID() || index > m_serviceUUIDs.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceUUID: index out of range");
|
||||
return NimBLEUUID("");
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0;
|
||||
uint8_t uuidBytes = 0;
|
||||
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
|
||||
index++;
|
||||
|
||||
do {
|
||||
count = findAdvField(type, index, &data_loc);
|
||||
if(count >= index) {
|
||||
if(type < BLE_HS_ADV_TYPE_INCOMP_UUIDS32) {
|
||||
uuidBytes = 2;
|
||||
} else if(type < BLE_HS_ADV_TYPE_INCOMP_UUIDS128) {
|
||||
uuidBytes = 4;
|
||||
} else {
|
||||
uuidBytes = 16;
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
type++;
|
||||
index -= count;
|
||||
}
|
||||
|
||||
} while(type <= BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
||||
|
||||
if(uuidBytes > 0) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
// In the case of more than one field of service uuid's we need to adjust
|
||||
// the index to account for the uuids of the previous fields.
|
||||
if(field->length < index * uuidBytes) {
|
||||
index -= count - field->length / uuidBytes;
|
||||
}
|
||||
|
||||
if(field->length > uuidBytes * index) {
|
||||
return NimBLEUUID(field->value + uuidBytes * (index - 1), uuidBytes, false);
|
||||
}
|
||||
}
|
||||
return m_serviceUUIDs[index];
|
||||
|
||||
return NimBLEUUID("");
|
||||
} // getServiceUUID
|
||||
|
||||
|
||||
|
@ -194,18 +434,32 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
|||
* @return The count of services in the advertising packet.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
return m_serviceUUIDs.size();
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS16);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS32);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS128);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
||||
|
||||
return count;
|
||||
} // getServiceUUIDCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check advertised services for existance of the required UUID
|
||||
* @param [in] uuid The service uuid to look for in the advertisement.
|
||||
* @return Return true if service is advertised
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const {
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
|
||||
size_t count = getServiceUUIDCount();
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
if(uuid == getServiceUUID(i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} // isAdvertisingService
|
||||
|
||||
|
@ -215,16 +469,43 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const
|
|||
* @return The TX Power of the advertised device.
|
||||
*/
|
||||
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
||||
return m_txPower;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_TX_PWR_LVL_LEN + 1) {
|
||||
return *(int8_t*)field->value;
|
||||
}
|
||||
}
|
||||
|
||||
return -99;
|
||||
} // getTXPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have preferred connection parameters?
|
||||
* @return True if connection parameters are present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveConnParams() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE) > 0;
|
||||
} // haveConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have have the advertising interval?
|
||||
* @return True if the advertisement interval is present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveAdvInterval() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL) > 0;
|
||||
} // haveAdvInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have an appearance value?
|
||||
* @return True if there is an appearance value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||
return m_haveAppearance;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_APPEARANCE) > 0;
|
||||
} // haveAppearance
|
||||
|
||||
|
||||
|
@ -233,16 +514,36 @@ bool NimBLEAdvertisedDevice::haveAppearance() {
|
|||
* @return True if there is manufacturer data present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveManufacturerData() {
|
||||
return m_haveManufacturerData;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA) > 0;
|
||||
} // haveManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have a URI?
|
||||
* @return True if there is a URI present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveURI() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
|
||||
} // haveURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does the advertisement contain a target address?
|
||||
* @return True if an address is present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveTargetAddress() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have a name value?
|
||||
* @return True if there is a name value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveName() {
|
||||
return m_haveName;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_COMP_NAME) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME) > 0;
|
||||
} // haveName
|
||||
|
||||
|
||||
|
@ -251,7 +552,7 @@ bool NimBLEAdvertisedDevice::haveName() {
|
|||
* @return True if there is a signal strength value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||
return m_haveRSSI;
|
||||
return m_rssi != -9999;
|
||||
} // haveRSSI
|
||||
|
||||
|
||||
|
@ -260,7 +561,7 @@ bool NimBLEAdvertisedDevice::haveRSSI() {
|
|||
* @return True if there is a service data value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||
return m_haveServiceData;
|
||||
return getServiceDataCount() > 0;
|
||||
} // haveServiceData
|
||||
|
||||
|
||||
|
@ -269,7 +570,7 @@ bool NimBLEAdvertisedDevice::haveServiceData() {
|
|||
* @return True if there is a service UUID value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||
return m_haveServiceUUID;
|
||||
return getServiceUUIDCount() > 0;
|
||||
} // haveServiceUUID
|
||||
|
||||
|
||||
|
@ -278,143 +579,71 @@ bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
|||
* @return True if there is a transmission power value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveTXPower() {
|
||||
return m_haveTXPower;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
|
||||
} // haveTXPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parse the advertising pay load.
|
||||
*
|
||||
* The pay load is a buffer of bytes that is either 31 bytes long or terminated by
|
||||
* a 0 length value. Each entry in the buffer has the format:
|
||||
* [length][type][data...]
|
||||
*
|
||||
* The length does not include itself but does include everything after it until the next record. A record
|
||||
* with a length value of 0 indicates a terminator.
|
||||
*
|
||||
* https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, uint8_t length) {
|
||||
struct ble_hs_adv_fields fields;
|
||||
int rc = ble_hs_adv_parse_fields(&fields, payload, length);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR.");
|
||||
return;
|
||||
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t data = 0;
|
||||
uint8_t length = m_payload.size();
|
||||
uint8_t count = 0;
|
||||
|
||||
if(length < 2) {
|
||||
return count;
|
||||
}
|
||||
|
||||
m_payload = payload;
|
||||
m_payloadLength = length;
|
||||
while (length > 1) {
|
||||
field = (ble_hs_adv_field*)&m_payload[data];
|
||||
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, m_payload, m_payloadLength);
|
||||
NIMBLE_LOGD(LOG_TAG,"payload: %s", pHex);
|
||||
free(pHex);
|
||||
#endif
|
||||
|
||||
if (fields.uuids16 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids16; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields.uuids16[i].value));
|
||||
if (field->length >= length) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.uuids32 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids32; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields.uuids32[i].value));
|
||||
}
|
||||
}
|
||||
if (field->type == type) {
|
||||
switch(type) {
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||
count += field->length / 2;
|
||||
break;
|
||||
|
||||
if (fields.uuids128 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids128; i++) {
|
||||
setServiceUUID(NimBLEUUID(&fields.uuids128[i]));
|
||||
}
|
||||
}
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS32:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS32:
|
||||
count += field->length / 4;
|
||||
break;
|
||||
|
||||
if (fields.name != NULL) {
|
||||
setName(std::string(reinterpret_cast<char*>(fields.name), fields.name_len));
|
||||
}
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS128:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS128:
|
||||
count += field->length / 16;
|
||||
break;
|
||||
|
||||
if (fields.tx_pwr_lvl_is_present) {
|
||||
setTXPower(fields.tx_pwr_lvl);
|
||||
}
|
||||
case BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR:
|
||||
case BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR:
|
||||
count += field->length / 6;
|
||||
break;
|
||||
|
||||
if (fields.svc_data_uuid16 != NULL ||
|
||||
fields.svc_data_uuid32 != NULL ||
|
||||
fields.svc_data_uuid128 != NULL)
|
||||
{
|
||||
ble_hs_adv_field *field;
|
||||
uint8_t *data = payload;
|
||||
while(length > 1) {
|
||||
field = (ble_hs_adv_field*)data;
|
||||
|
||||
if(field->length > length) {
|
||||
break;
|
||||
default:
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID16) {
|
||||
if(field->length > 2) {
|
||||
uint16_t uuid;
|
||||
memcpy(&uuid, field->value, 2);
|
||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 2), field->length - 3));
|
||||
if(data_loc != nullptr) {
|
||||
if(index == 0 || count >= index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID32) {
|
||||
if(field->length > 4) {
|
||||
uint32_t uuid;
|
||||
memcpy(&uuid, field->value, 4);
|
||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 4), field->length - 5));
|
||||
}
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID128) {
|
||||
if(field->length > 16) {
|
||||
NimBLEUUID uuid(field->value, (size_t)16, false);
|
||||
setServiceData(uuid, std::string(reinterpret_cast<char*>(field->value + 16), field->length - 17));
|
||||
}
|
||||
}
|
||||
|
||||
length -= 1 + field->length;
|
||||
data += 1 + field->length;
|
||||
}
|
||||
|
||||
length -= 1 + field->length;
|
||||
data += 1 + field->length;
|
||||
}
|
||||
|
||||
if (fields.appearance_is_present) {
|
||||
setAppearance(fields.appearance);
|
||||
if(data_loc != nullptr && field != nullptr) {
|
||||
*data_loc = data;
|
||||
}
|
||||
|
||||
if (fields.mfg_data != NULL) {
|
||||
setManufacturerData(std::string(reinterpret_cast<char*>(fields.mfg_data), fields.mfg_data_len));
|
||||
}
|
||||
|
||||
/* TODO: create storage and fucntions for these parameters
|
||||
if (fields.public_tgt_addr != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " public_tgt_addr=");
|
||||
u8p = fields.public_tgt_addr;
|
||||
for (i = 0; i < fields.num_public_tgt_addrs; i++) {
|
||||
NIMBLE_LOGD(LOG_TAG, "public_tgt_addr=%s ", addr_str(u8p));
|
||||
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
|
||||
if (fields.slave_itvl_range != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " slave_itvl_range=");
|
||||
print_bytes(fields.slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
|
||||
if (fields.adv_itvl_is_present) {
|
||||
NIMBLE_LOGD(LOG_TAG, " adv_itvl=0x%04x\n", fields.adv_itvl);
|
||||
}
|
||||
|
||||
if (fields.uri != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " uri=");
|
||||
print_bytes(fields.uri, fields.uri_len);
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
*/
|
||||
|
||||
} //parseAdvertisement
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -428,106 +657,22 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
|||
|
||||
/**
|
||||
* @brief Set the adFlag for this device.
|
||||
* @param [in] The discovered adFlag.
|
||||
* @param [in] advType The advertisement flag data from the advertisement.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
||||
m_advType = advType;
|
||||
} // setAdvType
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the appearance for this device.
|
||||
* @param [in] The discovered appearance.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setAppearance(uint16_t appearance) {
|
||||
m_appearance = appearance;
|
||||
m_haveAppearance = true;
|
||||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the manufacturer data for this device.
|
||||
* @param [in] The discovered manufacturer data.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
|
||||
m_manufacturerData = manufacturerData;
|
||||
m_haveManufacturerData = true;
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the name for this device.
|
||||
* @param [in] name The discovered name.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setName(std::string name) {
|
||||
m_name = name;
|
||||
m_haveName = true;
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the RSSI for this device.
|
||||
* @param [in] rssi The discovered RSSI.
|
||||
* @param [in] rssi The RSSI of the discovered device.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setRSSI(int rssi) {
|
||||
m_rssi = rssi;
|
||||
m_haveRSSI = true;
|
||||
m_rssi = rssi;
|
||||
} // setRSSI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Service UUID for this device.
|
||||
* @param [in] serviceUUID The discovered serviceUUID
|
||||
*/
|
||||
|
||||
void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
|
||||
return setServiceUUID(NimBLEUUID(serviceUUID));
|
||||
} // setServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Service UUID for this device.
|
||||
* @param [in] serviceUUID The discovered serviceUUID
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) {
|
||||
// Don't add duplicates
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
if (m_serviceUUIDs[i] == serviceUUID) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
m_haveServiceUUID = true;
|
||||
} // setServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the ServiceData value.
|
||||
* @param [in] uuid The UUID that the service data belongs to.
|
||||
* @param [in] data The service data.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceData(NimBLEUUID uuid, std::string data) {
|
||||
m_haveServiceData = true;
|
||||
for(auto &it : m_serviceDataVec) {
|
||||
if(it.first == uuid) {
|
||||
it.second = data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_serviceDataVec.push_back({uuid, data});
|
||||
} //setServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the power level for this device.
|
||||
* @param [in] txPower The discovered power level.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setTXPower(int8_t txPower) {
|
||||
m_txPower = txPower;
|
||||
m_haveTXPower = true;
|
||||
} // setTXPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a string representation of this device.
|
||||
* @return A string representation of this device.
|
||||
|
@ -579,10 +724,35 @@ std::string NimBLEAdvertisedDevice::toString() {
|
|||
* @return The advertisement payload.
|
||||
*/
|
||||
uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
||||
return m_payload;
|
||||
return &m_payload[0];
|
||||
} // getPayload
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stores the payload of the advertised device in a vector.
|
||||
* @param [in] payload The advertisement payload.
|
||||
* @param [in] length The length of the payload in bytes.
|
||||
* @param [in] append Indicates if the the data should be appended (scan response).
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setPayload(uint8_t *payload, uint8_t length, bool append) {
|
||||
if(!append) {
|
||||
m_advLength = length;
|
||||
m_payload.assign(payload, payload + length);
|
||||
} else {
|
||||
m_payload.insert(m_payload.end(), payload, payload + length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the length of the advertisement data in the payload.
|
||||
* @return The number of bytes in the payload that is from the advertisment.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getAdvLength() {
|
||||
return m_advLength;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertised device address type.
|
||||
* @return The device address type:
|
||||
|
@ -610,7 +780,7 @@ time_t NimBLEAdvertisedDevice::getTimestamp() {
|
|||
* @return The size of the payload in bytes.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
||||
return m_payloadLength;
|
||||
return m_payload.size();
|
||||
} // getPayloadLength
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,11 @@ public:
|
|||
NimBLEAddress getAddress();
|
||||
uint8_t getAdvType();
|
||||
uint16_t getAppearance();
|
||||
uint16_t getAdvInterval();
|
||||
uint16_t getMinInterval();
|
||||
uint16_t getMaxInterval();
|
||||
std::string getManufacturerData();
|
||||
std::string getURI();
|
||||
|
||||
/**
|
||||
* @brief A template to convert the service data to <type\>.
|
||||
|
@ -67,7 +71,7 @@ public:
|
|||
NimBLEScan* getScan();
|
||||
size_t getServiceDataCount();
|
||||
std::string getServiceData(uint8_t index = 0);
|
||||
std::string getServiceData(const NimBLEUUID &uuid) const;
|
||||
std::string getServiceData(const NimBLEUUID &uuid);
|
||||
|
||||
/**
|
||||
* @brief A template to convert the service data to <tt><type\></tt>.
|
||||
|
@ -106,12 +110,15 @@ public:
|
|||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||
size_t getServiceUUIDCount();
|
||||
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||
size_t getTargetAddressCount();
|
||||
int8_t getTXPower();
|
||||
uint8_t* getPayload();
|
||||
uint8_t getAdvLength();
|
||||
size_t getPayloadLength();
|
||||
uint8_t getAddressType();
|
||||
time_t getTimestamp();
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid) const;
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||
bool haveAppearance();
|
||||
bool haveManufacturerData();
|
||||
bool haveName();
|
||||
|
@ -119,46 +126,30 @@ public:
|
|||
bool haveServiceData();
|
||||
bool haveServiceUUID();
|
||||
bool haveTXPower();
|
||||
bool haveConnParams();
|
||||
bool haveAdvInterval();
|
||||
bool haveTargetAddress();
|
||||
bool haveURI();
|
||||
std::string toString();
|
||||
|
||||
private:
|
||||
friend class NimBLEScan;
|
||||
|
||||
void parseAdvertisement(uint8_t* payload, uint8_t length);
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setManufacturerData(std::string manufacturerData);
|
||||
void setName(std::string name);
|
||||
void setRSSI(int rssi);
|
||||
void setServiceData(NimBLEUUID serviceUUID, std::string data);
|
||||
void setServiceUUID(const char* serviceUUID);
|
||||
void setServiceUUID(NimBLEUUID serviceUUID);
|
||||
void setTXPower(int8_t txPower);
|
||||
|
||||
bool m_haveAppearance;
|
||||
bool m_haveManufacturerData;
|
||||
bool m_haveName;
|
||||
bool m_haveRSSI;
|
||||
bool m_haveServiceData;
|
||||
bool m_haveServiceUUID;
|
||||
bool m_haveTXPower;
|
||||
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setPayload(uint8_t *payload, uint8_t length, bool append);
|
||||
void setRSSI(int rssi);
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
|
||||
NimBLEAddress m_address = NimBLEAddress("");
|
||||
uint8_t m_advType;
|
||||
uint16_t m_appearance;
|
||||
std::string m_manufacturerData;
|
||||
std::string m_name;
|
||||
int m_rssi;
|
||||
int8_t m_txPower;
|
||||
uint8_t* m_payload;
|
||||
size_t m_payloadLength;
|
||||
time_t m_timestamp;
|
||||
bool m_callbackSent;
|
||||
uint8_t m_advLength;
|
||||
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
std::vector<std::pair<NimBLEUUID, std::string>>m_serviceDataVec;
|
||||
std::vector<uint8_t> m_payload;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,23 +32,29 @@ static const char* LOG_TAG = "NimBLEAdvertising";
|
|||
/**
|
||||
* @brief Construct a default advertising object.
|
||||
*/
|
||||
NimBLEAdvertising::NimBLEAdvertising() : m_slaveItvl() {
|
||||
NimBLEAdvertising::NimBLEAdvertising() {
|
||||
reset();
|
||||
} // NimBLEAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stops the current advertising and resets the advertising data to the default values.
|
||||
*/
|
||||
void NimBLEAdvertising::reset() {
|
||||
if(NimBLEDevice::getInitialized() && isAdvertising()) {
|
||||
stop();
|
||||
}
|
||||
memset(&m_advData, 0, sizeof m_advData);
|
||||
memset(&m_scanData, 0, sizeof m_scanData);
|
||||
memset(&m_advParams, 0, sizeof m_advParams);
|
||||
memset(&m_slaveItvl, 0, sizeof m_slaveItvl);
|
||||
const char *name = ble_svc_gap_device_name();
|
||||
|
||||
m_advData.name = (uint8_t *)name;
|
||||
m_advData.name_len = strlen(name);
|
||||
m_advData.name_is_complete = 1;
|
||||
m_advData.tx_pwr_lvl_is_present = 1;
|
||||
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
|
||||
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
|
||||
m_advData.appearance = 0;
|
||||
m_advData.appearance_is_present = 0;
|
||||
m_advData.mfg_data_len = 0;
|
||||
m_advData.mfg_data = nullptr;
|
||||
m_advData.slave_itvl_range = nullptr;
|
||||
|
||||
#if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON;
|
||||
|
@ -56,17 +62,13 @@ NimBLEAdvertising::NimBLEAdvertising() : m_slaveItvl() {
|
|||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
#endif
|
||||
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
m_advParams.itvl_min = 0;
|
||||
m_advParams.itvl_max = 0;
|
||||
|
||||
m_customAdvData = false;
|
||||
m_customScanResponseData = false;
|
||||
m_scanResp = true;
|
||||
m_advDataSet = false;
|
||||
// Set this to non-zero to prevent auto start if host reset before started by app.
|
||||
m_duration = BLE_HS_FOREVER;
|
||||
|
||||
} // NimBLEAdvertising
|
||||
} // reset
|
||||
|
||||
|
||||
/**
|
||||
|
@ -85,6 +87,7 @@ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
|
|||
*/
|
||||
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
||||
addServiceUUID(NimBLEUUID(serviceUUID));
|
||||
m_advDataSet = false;
|
||||
} // addServiceUUID
|
||||
|
||||
|
||||
|
@ -112,9 +115,95 @@ void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
|||
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
m_advData.appearance = appearance;
|
||||
m_advData.appearance_is_present = 1;
|
||||
m_advDataSet = false;
|
||||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add the transmission power level to the advertisement packet.
|
||||
*/
|
||||
void NimBLEAdvertising::addTxPower() {
|
||||
m_advData.tx_pwr_lvl_is_present = 1;
|
||||
m_advDataSet = false;
|
||||
} // addTxPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertised name of the device.
|
||||
* @param [in] name The name to advertise.
|
||||
*/
|
||||
void NimBLEAdvertising::setName(const std::string &name) {
|
||||
m_name.assign(name.begin(), name.end());
|
||||
m_advData.name = &m_name[0];
|
||||
m_advData.name_len = m_name.size();
|
||||
m_advDataSet = false;
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertised manufacturer data.
|
||||
* @param [in] data The data to advertise.
|
||||
*/
|
||||
void NimBLEAdvertising::setManufacturerData(const std::string &data) {
|
||||
m_mfgData.assign(data.begin(), data.end());
|
||||
m_advData.mfg_data = &m_mfgData[0];
|
||||
m_advData.mfg_data_len = m_mfgData.size();
|
||||
m_advDataSet = false;
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertised URI.
|
||||
* @param [in] uri The URI to advertise.
|
||||
*/
|
||||
void NimBLEAdvertising::setURI(const std::string &uri) {
|
||||
m_uri.assign(uri.begin(), uri.end());
|
||||
m_advData.uri = &m_uri[0];
|
||||
m_advData.uri_len = m_uri.size();
|
||||
m_advDataSet = false;
|
||||
} // setURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the service data advertised for the UUID.
|
||||
* @param [in] uuid The UUID the service data belongs to.
|
||||
* @param [in] data The data to advertise.
|
||||
* @note If data length is 0 the service data will not be advertised.
|
||||
*/
|
||||
void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
m_svcData16.assign((uint8_t*)&uuid.getNative()->u16.value, (uint8_t*)&uuid.getNative()->u16.value + 2);
|
||||
m_svcData16.insert(m_svcData16.end(), data.begin(), data.end());
|
||||
m_advData.svc_data_uuid16 = (uint8_t*)&m_svcData16[0];
|
||||
m_advData.svc_data_uuid16_len = (data.length() > 0) ? m_svcData16.size() : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
m_svcData32.assign((uint8_t*)&uuid.getNative()->u32.value, (uint8_t*)&uuid.getNative()->u32.value + 4);
|
||||
m_svcData32.insert(m_svcData32.end(), data.begin(), data.end());
|
||||
m_advData.svc_data_uuid32 = (uint8_t*)&m_svcData32[0];
|
||||
m_advData.svc_data_uuid32_len = (data.length() > 0) ? m_svcData32.size() : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
m_svcData128.assign(uuid.getNative()->u128.value, uuid.getNative()->u128.value + 16);
|
||||
m_svcData128.insert(m_svcData128.end(), data.begin(), data.end());
|
||||
m_advData.svc_data_uuid128 = (uint8_t*)&m_svcData128[0];
|
||||
m_advData.svc_data_uuid128_len = (data.length() > 0) ? m_svcData128.size() : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_advDataSet = false;
|
||||
} // setServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the type of advertisment to use.
|
||||
* @param [in] adv_type:
|
||||
|
@ -172,6 +261,8 @@ void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
|
|||
m_slaveItvl[2] = m_slaveItvl[0];
|
||||
m_slaveItvl[3] = m_slaveItvl[1];
|
||||
}
|
||||
|
||||
m_advDataSet = false;
|
||||
} // setMinPreferred
|
||||
|
||||
|
||||
|
@ -200,6 +291,8 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
|||
m_slaveItvl[0] = m_slaveItvl[2];
|
||||
m_slaveItvl[1] = m_slaveItvl[3];
|
||||
}
|
||||
|
||||
m_advDataSet = false;
|
||||
} // setMaxPreferred
|
||||
|
||||
|
||||
|
@ -209,6 +302,7 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
|||
*/
|
||||
void NimBLEAdvertising::setScanResponse(bool set) {
|
||||
m_scanResp = set;
|
||||
m_advDataSet = false;
|
||||
} // setScanResponse
|
||||
|
||||
|
||||
|
@ -344,12 +438,29 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
if (!m_customAdvData && !m_advDataSet) {
|
||||
//start with 3 bytes for the flags data
|
||||
uint8_t payloadLen = (2 + 1);
|
||||
if(m_advData.mfg_data_len > 0)
|
||||
payloadLen += (2 + m_advData.mfg_data_len);
|
||||
|
||||
if(m_advData.svc_data_uuid16_len > 0)
|
||||
payloadLen += (2 + m_advData.svc_data_uuid16_len);
|
||||
|
||||
if(m_advData.svc_data_uuid32_len > 0)
|
||||
payloadLen += (2 + m_advData.svc_data_uuid32_len);
|
||||
|
||||
if(m_advData.svc_data_uuid128_len > 0)
|
||||
payloadLen += (2 + m_advData.svc_data_uuid128_len);
|
||||
|
||||
if(m_advData.uri_len > 0)
|
||||
payloadLen += (2 + m_advData.uri_len);
|
||||
|
||||
if(m_advData.appearance_is_present)
|
||||
payloadLen += (2 + BLE_HS_ADV_APPEARANCE_LEN);
|
||||
|
||||
if(m_advData.tx_pwr_lvl_is_present)
|
||||
payloadLen += (2 + 1);
|
||||
payloadLen += (2 + BLE_HS_ADV_TX_PWR_LVL_LEN);
|
||||
|
||||
if(m_advData.slave_itvl_range != nullptr)
|
||||
payloadLen += (2 + 4);
|
||||
payloadLen += (2 + BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
|
||||
for(auto &it : m_serviceUUIDs) {
|
||||
if(it.getNative()->u.type == BLE_UUID_TYPE_16) {
|
||||
|
@ -419,7 +530,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
|
||||
// check if there is room for the name, if not put it in scan data
|
||||
if((payloadLen + (2 + m_advData.name_len)) > BLE_HS_ADV_MAX_SZ) {
|
||||
if(m_scanResp){
|
||||
if(m_scanResp && !m_customScanResponseData){
|
||||
m_scanData.name = m_advData.name;
|
||||
m_scanData.name_len = m_advData.name_len;
|
||||
if(m_scanData.name_len > BLE_HS_ADV_MAX_SZ - 2) {
|
||||
|
@ -433,7 +544,6 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
m_advData.name_is_complete = 0;
|
||||
} else {
|
||||
if(m_advData.tx_pwr_lvl_is_present) {
|
||||
m_advData.tx_pwr_lvl = 0;
|
||||
m_advData.tx_pwr_lvl_is_present = 0;
|
||||
payloadLen -= (2 + 1);
|
||||
}
|
||||
|
@ -446,7 +556,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
}
|
||||
}
|
||||
|
||||
if(m_scanResp) {
|
||||
if(m_scanResp && !m_customScanResponseData) {
|
||||
rc = ble_gap_adv_rsp_set_fields(&m_scanData);
|
||||
switch(rc) {
|
||||
case 0:
|
||||
|
@ -581,7 +691,7 @@ void NimBLEAdvertising::advCompleteCB() {
|
|||
if(m_advCompCB != nullptr) {
|
||||
m_advCompCB(this);
|
||||
}
|
||||
}
|
||||
} // advCompleteCB
|
||||
|
||||
|
||||
/**
|
||||
|
@ -590,7 +700,7 @@ void NimBLEAdvertising::advCompleteCB() {
|
|||
*/
|
||||
bool NimBLEAdvertising::isAdvertising() {
|
||||
return ble_gap_adv_active();
|
||||
}
|
||||
} // isAdvertising
|
||||
|
||||
|
||||
/*
|
||||
|
@ -608,7 +718,7 @@ void NimBLEAdvertising::onHostSync() {
|
|||
// Otherwise we should tell the app that advertising stopped.
|
||||
advCompleteCB();
|
||||
}
|
||||
}
|
||||
} // onHostSync
|
||||
|
||||
|
||||
/**
|
||||
|
@ -646,6 +756,7 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
*/
|
||||
void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceded");
|
||||
return;
|
||||
}
|
||||
m_payload.append(data);
|
||||
|
@ -657,11 +768,8 @@ void NimBLEAdvertisementData::addData(const std::string &data) {
|
|||
* @param [in] data The data to be added to the payload.
|
||||
* @param [in] length The size of data to be added to the payload.
|
||||
*/
|
||||
void NimBLEAdvertisementData::addData(char * data, size_t length){
|
||||
if ((m_payload.length() + length) > BLE_HS_ADV_MAX_SZ) {
|
||||
return;
|
||||
}
|
||||
m_payload.append(data,length);
|
||||
void NimBLEAdvertisementData::addData(char * data, size_t length) {
|
||||
addData(std::string(data, length));
|
||||
} // addData
|
||||
|
||||
|
||||
|
@ -680,43 +788,6 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
|||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete services to advertise.
|
||||
* @param [in] uuid The UUID of the service.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07
|
||||
addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setCompleteServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisement flags.
|
||||
* @param [in] flag The flags to be set in the advertisement.
|
||||
|
@ -738,64 +809,141 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) {
|
|||
* @param [in] data The manufacturer data to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
||||
char cdata[2];
|
||||
cdata[0] = data.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||
addData(std::string(cdata, 2) + data);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData");
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the URI to advertise.
|
||||
* @param [in] uri The uri to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setURI(const std::string &uri) {
|
||||
char cdata[2];
|
||||
cdata[0] = uri.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_URI;
|
||||
addData(std::string(cdata, 2) + uri);
|
||||
} // setURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete name of this device.
|
||||
* @param [in] name The name to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setName(const std::string &name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName");
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial services to advertise.
|
||||
* @param [in] uuid The single service to advertise.
|
||||
* @brief Set a single service to advertise as a complete list of services.
|
||||
* @param [in] uuid The service to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
|
||||
setServices(true, uuid.bitSize(), {uuid});
|
||||
} // setCompleteServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete list of 16 bit services to advertise.
|
||||
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(true, 16, v_uuid);
|
||||
} // setCompleteServices16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete list of 32 bit services to advertise.
|
||||
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(true, 32, v_uuid);
|
||||
} // setCompleteServices32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set a single service to advertise as a partial list of services.
|
||||
* @param [in] uuid The service to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
|
||||
setServices(false, uuid.bitSize(), {uuid});
|
||||
} // setPartialServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial list of services to advertise.
|
||||
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(false, 16, v_uuid);
|
||||
} // setPartialServices16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial list of services to advertise.
|
||||
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(false, 32, v_uuid);
|
||||
} // setPartialServices32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Utility function to create the list of service UUID's from a vector.
|
||||
* @param [in] complete If true the vector is the complete set of services.
|
||||
* @param [in] size The bit size of the UUID's in the vector. (16, 32, or 128).
|
||||
* @param [in] v_uuid The vector of service UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setServices(const bool complete, const uint8_t size,
|
||||
const std::vector<NimBLEUUID> &v_uuid)
|
||||
{
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2));
|
||||
cdata[0] = (size / 8) * v_uuid.size() + 1;
|
||||
switch(size) {
|
||||
case 16:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4));
|
||||
case 32:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16));
|
||||
case 128:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setPartialServices
|
||||
|
||||
std::string uuids;
|
||||
|
||||
for(auto &it : v_uuid){
|
||||
if(it.bitSize() != size) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
|
||||
return;
|
||||
} else {
|
||||
switch(size) {
|
||||
case 16:
|
||||
uuids += std::string((char*)&it.getNative()->u16.value, 2);
|
||||
break;
|
||||
case 32:
|
||||
uuids += std::string((char*)&it.getNative()->u32.value, 4);
|
||||
break;
|
||||
case 128:
|
||||
uuids += std::string((char*)&it.getNative()->u128.value, 16);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addData(std::string(cdata, 2) + uuids);
|
||||
} // setServices
|
||||
|
||||
|
||||
/**
|
||||
|
@ -841,15 +989,42 @@ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::
|
|||
* @param [in] name The short name of the device.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setShortName(const std::string &name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName");
|
||||
} // setShortName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds Tx power level to the advertisement data.
|
||||
*/
|
||||
void NimBLEAdvertisementData::addTxPower() {
|
||||
char cdata[3];
|
||||
cdata[0] = BLE_HS_ADV_TX_PWR_LVL_LEN + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_TX_PWR_LVL;
|
||||
cdata[2] = NimBLEDevice::getPower();
|
||||
addData(cdata, 3);
|
||||
} // addTxPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the preferred connection interval parameters.
|
||||
* @param [in] min The minimum interval desired.
|
||||
* @param [in] max The maximum interval desired.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPreferredParams(uint16_t min, uint16_t max) {
|
||||
char cdata[6];
|
||||
cdata[0] = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE;
|
||||
cdata[2] = min;
|
||||
cdata[3] = min >> 8;
|
||||
cdata[4] = max;
|
||||
cdata[5] = max >> 8;
|
||||
addData(cdata, 6);
|
||||
} // setPreferredParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the payload that is to be advertised.
|
||||
* @return The payload that is to be advertised.
|
||||
|
|
|
@ -50,18 +50,27 @@ class NimBLEAdvertisementData {
|
|||
public:
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setCompleteServices(const NimBLEUUID &uuid);
|
||||
void setCompleteServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setFlags(uint8_t);
|
||||
void setManufacturerData(const std::string &data);
|
||||
void setURI(const std::string &uri);
|
||||
void setName(const std::string &name);
|
||||
void setPartialServices(const NimBLEUUID &uuid);
|
||||
void setPartialServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setPartialServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setShortName(const std::string &name);
|
||||
void addData(const std::string &data); // Add data to the payload.
|
||||
void addData(char * data, size_t length);
|
||||
void addTxPower();
|
||||
void setPreferredParams(uint16_t min, uint16_t max);
|
||||
std::string getPayload(); // Retrieve the current advert payload.
|
||||
|
||||
private:
|
||||
friend class NimBLEAdvertising;
|
||||
void setServices(const bool complete, const uint8_t size,
|
||||
const std::vector<NimBLEUUID> &v_uuid);
|
||||
std::string m_payload; // The payload of the advertisement.
|
||||
}; // NimBLEAdvertisementData
|
||||
|
||||
|
@ -80,6 +89,10 @@ public:
|
|||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||
void stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setName(const std::string &name);
|
||||
void setManufacturerData(const std::string &data);
|
||||
void setURI(const std::string &uri);
|
||||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setAdvertisementType(uint8_t adv_type);
|
||||
void setMaxInterval(uint16_t maxinterval);
|
||||
void setMinInterval(uint16_t mininterval);
|
||||
|
@ -89,6 +102,8 @@ public:
|
|||
void setScanResponse(bool);
|
||||
void setMinPreferred(uint16_t);
|
||||
void setMaxPreferred(uint16_t);
|
||||
void addTxPower();
|
||||
void reset();
|
||||
void advCompleteCB();
|
||||
bool isAdvertising();
|
||||
|
||||
|
@ -109,6 +124,12 @@ private:
|
|||
void (*m_advCompCB)(NimBLEAdvertising *pAdv);
|
||||
uint8_t m_slaveItvl[4];
|
||||
uint32_t m_duration;
|
||||
std::vector<uint8_t> m_svcData16;
|
||||
std::vector<uint8_t> m_svcData32;
|
||||
std::vector<uint8_t> m_svcData128;
|
||||
std::vector<uint8_t> m_name;
|
||||
std::vector<uint8_t> m_mfgData;
|
||||
std::vector<uint8_t> m_uri;
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
|
|
@ -101,9 +101,9 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
|
|||
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
* @brief Return the BLE Descriptor for the given UUID.
|
||||
* @param [in] uuid The UUID of the descriptor.
|
||||
* @return A pointer to the descriptor object or nullptr if not found.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||
return getDescriptorByUUID(NimBLEUUID(uuid));
|
||||
|
@ -111,9 +111,9 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
* @brief Return the BLE Descriptor for the given UUID.
|
||||
* @param [in] uuid The UUID of the descriptor.
|
||||
* @return A pointer to the descriptor object or nullptr if not found.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
||||
for (auto &it : m_dscVec) {
|
||||
|
@ -124,6 +124,20 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uu
|
|||
return nullptr;
|
||||
} // getDescriptorByUUID
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given handle.
|
||||
* @param [in] handle The handle of the descriptor.
|
||||
* @return A pointer to the descriptor object or nullptr if not found.
|
||||
*/
|
||||
NimBLEDescriptor *NimBLECharacteristic::getDescriptorByHandle(uint16_t handle) {
|
||||
for (auto &it : m_dscVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the handle of the characteristic.
|
||||
|
|
|
@ -59,6 +59,17 @@ class NimBLECharacteristicCallbacks;
|
|||
*/
|
||||
class NimBLECharacteristic {
|
||||
public:
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
size_t getSubscribedCount();
|
||||
|
||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||
uint32_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
|
@ -72,9 +83,10 @@ public:
|
|||
|
||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
||||
NimBLEUUID getUUID();
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
|
||||
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
size_t getDataLength();
|
||||
/**
|
||||
* @brief A template to convert the characteristic data to <type\>.
|
||||
* @tparam T The type to convert the data to.
|
||||
|
@ -92,25 +104,20 @@ public:
|
|||
return *((T *)pData);
|
||||
}
|
||||
|
||||
size_t getDataLength();
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
|
||||
/**
|
||||
* @brief Convenience template to set the characteristic value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
size_t getSubscribedCount();
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -122,11 +122,17 @@ uint8_t* NimBLEDescriptor::getValue() {
|
|||
return m_value.attr_value;
|
||||
} // getValue
|
||||
|
||||
/**
|
||||
* @brief Get the value of this descriptor as a string.
|
||||
* @return A std::string instance containing a copy of the descriptor's value.
|
||||
*/
|
||||
std::string NimBLEDescriptor::getStringValue() {
|
||||
return std::string((char *) m_value.attr_value, m_value.attr_len);
|
||||
}
|
||||
|
||||
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
void *arg) {
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
|
|
|
@ -44,20 +44,23 @@ class NimBLEDescriptorCallbacks;
|
|||
class NimBLEDescriptor {
|
||||
public:
|
||||
uint16_t getHandle();
|
||||
size_t getLength();
|
||||
NimBLEUUID getUUID();
|
||||
uint8_t* getValue();
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
|
||||
size_t getLength();
|
||||
uint8_t* getValue();
|
||||
std::string getStringValue();
|
||||
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
/**
|
||||
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
|||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
||||
uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE;
|
||||
uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -303,7 +305,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Set the transmission power.
|
||||
* @brief Get the transmission power.
|
||||
* @param [in] powerType The power level to set, can be one of:
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, For connection handle 0
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, For connection handle 1
|
||||
|
@ -342,7 +344,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
default:
|
||||
return BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
||||
}
|
||||
} // setPower
|
||||
} // getPower
|
||||
|
||||
|
||||
/**
|
||||
|
@ -400,6 +402,53 @@ void NimBLEDevice::stopAdvertising() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the duplicate filter cache size for filtering scanned devices.
|
||||
* @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n
|
||||
* Range is 10-1000, a larger value will reduce how often the same devices are reported.
|
||||
* @details Must only be called before calling NimBLEDevice::init.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::setScanDuplicateCacheSize(uint16_t cacheSize) {
|
||||
if(initialized) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot change scan cache size while initialized");
|
||||
return;
|
||||
} else if(cacheSize > 1000 || cacheSize <10) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid scan cache size; min=10 max=1000");
|
||||
return;
|
||||
}
|
||||
|
||||
m_scanDuplicateSize = cacheSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the duplicate filter mode for filtering scanned devices.
|
||||
* @param [in] mode One of three possible options:
|
||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE (0) (default)\n
|
||||
Filter by device address only, advertisements from the same address will be reported only once.
|
||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DATA (1)\n
|
||||
Filter by data only, advertisements with the same data will only be reported once,\n
|
||||
even from different addresses.
|
||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE (2)\n
|
||||
Filter by address and data, advertisements from the same address will be reported only once,\n
|
||||
except if the data in the advertisement has changed, then it will be reported again.
|
||||
* @details Must only be called before calling NimBLEDevice::init.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
if(initialized) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot change scan duplicate type while initialized");
|
||||
return;
|
||||
} else if(mode > 2) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid scan duplicate type");
|
||||
return;
|
||||
}
|
||||
|
||||
m_scanFilterMode = mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Host reset, we pass the message so we don't make calls until resynced.
|
||||
* @param [in] reason The reason code for the reset.
|
||||
|
@ -499,8 +548,17 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
ESP_ERROR_CHECK(errRc);
|
||||
|
||||
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
bt_cfg.mode = ESP_BT_MODE_BLE;
|
||||
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
|
||||
bt_cfg.normal_adv_size = m_scanDuplicateSize;
|
||||
bt_cfg.scan_duplicate_type = m_scanFilterMode;
|
||||
|
||||
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
|
||||
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
|
||||
ESP_ERROR_CHECK(esp_nimble_hci_init());
|
||||
nimble_port_init();
|
||||
|
||||
// Setup callbacks for host events
|
||||
|
|
|
@ -123,6 +123,8 @@ public:
|
|||
static bool isIgnored(const NimBLEAddress &address);
|
||||
static void addIgnored(const NimBLEAddress &address);
|
||||
static void removeIgnored(const NimBLEAddress &address);
|
||||
static void setScanDuplicateCacheSize(uint16_t cacheSize);
|
||||
static void setScanFilterMode(uint8_t type);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
static NimBLEAdvertising* getAdvertising();
|
||||
|
@ -184,6 +186,8 @@ private:
|
|||
static ble_gap_event_listener m_listener;
|
||||
static gap_event_handler m_customGapHandler;
|
||||
static uint8_t m_own_addr_type;
|
||||
static uint16_t m_scanDuplicateSize;
|
||||
static uint8_t m_scanFilterMode;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ void NimBLEHIDDevice::manufacturer(std::string name) {
|
|||
/**
|
||||
* @brief Sets the Plug n Play characterisc value.
|
||||
* @param [in] sig The vendor ID source number.
|
||||
* @param [in[ vid The vendor ID number.
|
||||
* @param [in] vid The vendor ID number.
|
||||
* @param [in] pid The product ID number.
|
||||
* @param [in] version The produce version number.
|
||||
*/
|
||||
|
@ -128,8 +128,8 @@ void NimBLEHIDDevice::hidInfo(uint8_t country, uint8_t flags) {
|
|||
* @return pointer to new input report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||
NimBLECharacteristic* inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
||||
NimBLEDescriptor* inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t) 0x2908);
|
||||
NimBLECharacteristic* inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ_ENC);
|
||||
NimBLEDescriptor* inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);
|
||||
|
||||
uint8_t desc1_val[] = { reportID, 0x01 };
|
||||
inputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||
|
@ -144,7 +144,7 @@ NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
|||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
||||
NimBLECharacteristic* outputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
NimBLEDescriptor* outputReportDescriptor = outputReportCharacteristic->createDescriptor((uint16_t) 0x2908);
|
||||
NimBLEDescriptor* outputReportDescriptor = outputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
|
||||
uint8_t desc1_val[] = { reportID, 0x02 };
|
||||
outputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||
|
@ -159,7 +159,7 @@ NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
|||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
||||
NimBLECharacteristic* featureReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
NimBLEDescriptor* featureReportDescriptor = featureReportCharacteristic->createDescriptor((uint16_t) 0x2908);
|
||||
NimBLEDescriptor* featureReportDescriptor = featureReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
|
||||
uint8_t desc1_val[] = { reportID, 0x03 };
|
||||
featureReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||
|
|
|
@ -38,9 +38,9 @@ NimBLEScan::NimBLEScan() {
|
|||
m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
|
||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||
m_ignoreResults = false;
|
||||
m_wantDuplicates = false;
|
||||
m_pTaskData = nullptr;
|
||||
m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset
|
||||
m_maxResults = 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ NimBLEScan::~NimBLEScan() {
|
|||
|
||||
case BLE_GAP_EVENT_DISC: {
|
||||
if(pScan->m_ignoreResults) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Scan op in progress - ignoring results");
|
||||
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -88,34 +88,49 @@ NimBLEScan::~NimBLEScan() {
|
|||
|
||||
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||
// Otherwise just update the relevant parameters of the already known device.
|
||||
if(advertisedDevice == nullptr){
|
||||
if(advertisedDevice == nullptr && event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP){
|
||||
// Check if we have reach the scan results limit, ignore this one if so.
|
||||
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
||||
if(pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||
advertisedDevice->setAddress(advertisedAddress);
|
||||
advertisedDevice->setAdvType(event->disc.event_type);
|
||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str());
|
||||
}
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
if(event->disc.length_data > 0) {
|
||||
advertisedDevice->parseAdvertisement(event->disc.data, event->disc.length_data);
|
||||
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||
} else if(advertisedDevice != nullptr) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
||||
} else {
|
||||
// Scan response from unknown device
|
||||
return 0;
|
||||
}
|
||||
|
||||
advertisedDevice->m_timestamp = time(nullptr);
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
||||
event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
|
||||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) {
|
||||
// If not active scanning report the result to the listener.
|
||||
if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
// If not active scanning or scan response is not available
|
||||
// report the result to the callback now.
|
||||
if(pScan->m_scan_params.passive ||
|
||||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
||||
{
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
|
||||
// Otherwise wait for the scan response so we can report all of the data at once.
|
||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
// Otherwise, wait for the scan response so we can report the complete data.
|
||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
// If not storing results and we have invoked the callback, delete the device.
|
||||
if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent) {
|
||||
pScan->erase(advertisedAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +138,21 @@ NimBLEScan::~NimBLEScan() {
|
|||
}
|
||||
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
||||
event->disc_complete.reason);
|
||||
event->disc_complete.reason);
|
||||
|
||||
// If a device advertised with scan reponse available and it was not received
|
||||
// the callback would not have been invoked, so do it here.
|
||||
if(pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
for(auto &it : pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||
if(!it->m_callbackSent) {
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pScan->m_maxResults == 0) {
|
||||
pScan->clearResults();
|
||||
}
|
||||
|
||||
if (pScan->m_scanCompleteCB != nullptr) {
|
||||
pScan->m_scanCompleteCB(pScan->m_scanResults);
|
||||
|
@ -145,15 +174,11 @@ NimBLEScan::~NimBLEScan() {
|
|||
|
||||
/**
|
||||
* @brief Should we perform an active or passive scan?
|
||||
* The default is a passive scan. An active scan means that we will wish a scan response.
|
||||
* The default is a passive scan. An active scan means that we will request a scan response.
|
||||
* @param [in] active If true, we perform an active scan otherwise a passive scan.
|
||||
*/
|
||||
void NimBLEScan::setActiveScan(bool active) {
|
||||
if (active) {
|
||||
m_scan_params.passive = 0;
|
||||
} else {
|
||||
m_scan_params.passive = 1;
|
||||
}
|
||||
m_scan_params.passive = !active;
|
||||
} // setActiveScan
|
||||
|
||||
|
||||
|
@ -202,6 +227,16 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
|||
} // setFilterPolicy
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the max number of results to store.
|
||||
* @param [in] maxResults The number of results to limit storage to\n
|
||||
* 0 == none (callbacks only) 0xFF == unlimited, any other value is the limit.
|
||||
*/
|
||||
void NimBLEScan::setMaxResults(uint8_t maxResults) {
|
||||
m_maxResults = maxResults;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the call backs to be invoked.
|
||||
* @param [in] pAdvertisedDeviceCallbacks Call backs to be invoked.
|
||||
|
@ -209,7 +244,7 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
|||
*/
|
||||
void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks,
|
||||
bool wantDuplicates) {
|
||||
m_wantDuplicates = wantDuplicates;
|
||||
setDuplicateFilter(!wantDuplicates);
|
||||
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
|
||||
} // setAdvertisedDeviceCallbacks
|
||||
|
||||
|
@ -342,10 +377,14 @@ bool NimBLEScan::stop() {
|
|||
|
||||
int rc = ble_gap_disc_cancel();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc);
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_maxResults == 0) {
|
||||
clearResults();
|
||||
}
|
||||
|
||||
if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) {
|
||||
m_scanCompleteCB(m_scanResults);
|
||||
}
|
||||
|
@ -365,7 +404,7 @@ bool NimBLEScan::stop() {
|
|||
* @details After disconnecting, it may be required in the case we were connected to a device without a public address.
|
||||
*/
|
||||
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||
NIMBLE_LOGD(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||
|
||||
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
||||
if((*it)->getAddress() == address) {
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
bool stop();
|
||||
void clearResults();
|
||||
NimBLEScanResults getResults();
|
||||
void setMaxResults(uint8_t maxResults);
|
||||
void erase(const NimBLEAddress &address);
|
||||
|
||||
|
||||
|
@ -89,10 +90,10 @@ private:
|
|||
void (*m_scanCompleteCB)(NimBLEScanResults scanResults);
|
||||
ble_gap_disc_params m_scan_params;
|
||||
bool m_ignoreResults;
|
||||
bool m_wantDuplicates;
|
||||
NimBLEScanResults m_scanResults;
|
||||
uint32_t m_duration;
|
||||
ble_task_data_t *m_pTaskData;
|
||||
uint8_t m_maxResults;
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
|
|
@ -104,28 +104,47 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
|
|||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its UUID
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the service object.
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
|
||||
return getServiceByUUID(NimBLEUUID(uuid));
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
|
||||
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
|
||||
} // getServiceByUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its UUID
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the service object.
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||
uint16_t position = 0;
|
||||
for (auto &it : m_svcVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
return it;
|
||||
if (position == instanceId){
|
||||
return it;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
} // getServiceByUUID
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its handle
|
||||
* @param handle The handle of the service.
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
||||
for (auto &it : m_svcVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||
|
@ -646,7 +665,7 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
|||
if(rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
} // updateConnParams
|
||||
}// updateConnParams
|
||||
|
||||
|
||||
/** Default callback handlers */
|
||||
|
|
|
@ -49,8 +49,9 @@ public:
|
|||
void startAdvertising();
|
||||
void stopAdvertising();
|
||||
void start();
|
||||
NimBLEService* getServiceByUUID(const char* uuid);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
|
||||
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByHandle(uint16_t handle);
|
||||
int disconnect(uint16_t connID,
|
||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
void updateConnParams(uint16_t conn_handle,
|
||||
|
|
|
@ -233,9 +233,9 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
|
|||
*/
|
||||
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||
// Check that we don't add the same characteristic twice.
|
||||
|
||||
if (getCharacteristic(uuid) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
|
||||
std::string(uuid).c_str());
|
||||
}
|
||||
|
||||
|
@ -249,28 +249,72 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
|
|||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
||||
return getCharacteristic(NimBLEUUID(uuid));
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t instanceId) {
|
||||
return getCharacteristic(NimBLEUUID(uuid), instanceId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||
uint16_t position = 0;
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
return it;
|
||||
if (position == instanceId) {
|
||||
return it;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified handle.
|
||||
* @param handle The handle of the characteristic.
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic *NimBLEService::getCharacteristicByHandle(uint16_t handle) {
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to each characteristic associated with this service.
|
||||
*/
|
||||
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics() {
|
||||
return m_chrVec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
|
||||
*/
|
||||
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const char *uuid) {
|
||||
return getCharacteristics(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
|
||||
*/
|
||||
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const NimBLEUUID &uuid) {
|
||||
std::vector<NimBLECharacteristic*> result;
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
result.push_back(it);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of this service.
|
||||
|
@ -295,7 +339,7 @@ std::string NimBLEService::toString() {
|
|||
*/
|
||||
NimBLEServer* NimBLEService::getServer() {
|
||||
return m_pServer;
|
||||
} // getServer
|
||||
}// getServer
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
|
|
@ -35,6 +35,16 @@ class NimBLECharacteristic;
|
|||
*/
|
||||
class NimBLEService {
|
||||
public:
|
||||
|
||||
NimBLEServer* getServer();
|
||||
|
||||
NimBLEUUID getUUID();
|
||||
uint16_t getHandle();
|
||||
std::string toString();
|
||||
void dump();
|
||||
|
||||
bool start();
|
||||
|
||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||
uint32_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
|
@ -45,14 +55,14 @@ public:
|
|||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
|
||||
void dump();
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
||||
NimBLEUUID getUUID();
|
||||
NimBLEServer* getServer();
|
||||
bool start();
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
|
||||
|
||||
std::vector<NimBLECharacteristic*> getCharacteristics();
|
||||
std::vector<NimBLECharacteristic*> getCharacteristics(const char* uuid);
|
||||
std::vector<NimBLECharacteristic*> getCharacteristics(const NimBLEUUID &uuid);
|
||||
|
||||
|
||||
private:
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
|
|
|
@ -65,29 +65,42 @@ static const char* LOG_TAG = "NimBLEUUID";
|
|||
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||
}
|
||||
else {
|
||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
||||
m_valueSet = false;
|
||||
}
|
||||
} // NimBLEUUID(std::string)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from 16 bytes of memory.
|
||||
* @brief Create a UUID from 2, 4, 16 bytes of memory.
|
||||
* @param [in] pData The pointer to the start of the UUID.
|
||||
* @param [in] size The size of the data.
|
||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||
if (size != 16) {
|
||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID length not 16 bytes");
|
||||
return;
|
||||
}
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
uint8_t *uuidValue = nullptr;
|
||||
|
||||
switch(size) {
|
||||
case 2:
|
||||
uuidValue = (uint8_t*)&m_uuid.u16.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
break;
|
||||
case 4:
|
||||
uuidValue = (uint8_t*)&m_uuid.u32.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
break;
|
||||
case 16:
|
||||
uuidValue = m_uuid.u128.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
break;
|
||||
default:
|
||||
m_valueSet = false;
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid UUID size");
|
||||
return;
|
||||
}
|
||||
if (msbFirst) {
|
||||
std::reverse_copy(pData, pData + 16, m_uuid.u128.value);
|
||||
std::reverse_copy(pData, pData + size, uuidValue);
|
||||
} else {
|
||||
memcpy(m_uuid.u128.value, pData, 16);
|
||||
memcpy(uuidValue, pData, size);
|
||||
}
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
|
|
|
@ -523,10 +523,6 @@ esp_err_t esp_nimble_hci_and_controller_init(void)
|
|||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
/* Added to ensure BLE only mode */
|
||||
bt_cfg.mode = ESP_BT_MODE_BLE;
|
||||
/* Added to set max connections from nimconfig */
|
||||
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
|
||||
|
||||
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
return ret;
|
||||
|
|
|
@ -1,145 +1,156 @@
|
|||
/** @file
|
||||
*
|
||||
* IGNORE THIS FILE IF USING ESP-IDF, USE MENUCONFIG TO SET NIMBLE OPTIONS.
|
||||
*
|
||||
* The config options here are for Arduino use only.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/*
|
||||
* For ESP-IDF compatibility
|
||||
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||
*/
|
||||
|
||||
/* Detect if using ESP-IDF or Arduino (Arduino won't have these defines in sdkconfig)
|
||||
*
|
||||
* Note: We do not use #ifdef CONFIG_BT_NIMBLE_ENABLED since we cannot enable NimBLE when using
|
||||
* Arduino as a component and the esp-nimble-compnent, so we check if other config options are defined.
|
||||
* We also need to use a config parameter that must be present and not likely defined in the command line.
|
||||
*/
|
||||
#if defined(CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN) || defined(CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN)
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ENABLED) && !defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
#define CONFIG_BT_NIMBLE_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_DEBUG) && !defined(CONFIG_BT_NIMBLE_DEBUG)
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
#endif
|
||||
|
||||
#else // Using Arduino
|
||||
#include "nimconfig_rename.h"
|
||||
|
||||
/***********************************************
|
||||
* Arduino config options start here
|
||||
* Arduino user-config options start here
|
||||
**********************************************/
|
||||
|
||||
/** @brief Comment out if not using NimBLE Client functions \n
|
||||
* Reduces flash size by approx. 7kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
/** @brief Un-comment to change the number of simultaneous connections (esp controller max is 9) */
|
||||
// #define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
|
||||
/** @brief Comment out if not using NimBLE Scan functions \n
|
||||
* Reduces flash size by approx. 26kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
/** @brief Un-comment to change the default MTU size */
|
||||
// #define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
||||
|
||||
/** @brief Comment out if not using NimBLE Server functions \n
|
||||
* Reduces flash size by approx. 16kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
/** @brief Un-comment to change default device name */
|
||||
// #define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||
|
||||
/** @brief Comment out if not using NimBLE Advertising functions \n
|
||||
* Reduces flash size by approx. 5kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
/* Uncomment to see debug log messages from the NimBLE host
|
||||
/** @brief Un-comment to see debug log messages from the NimBLE host
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/* Uncomment to see NimBLE host return codes as text debug log messages.
|
||||
/** @brief Un-comment to see NimBLE host return codes as text debug log messages.
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/* Uncomment to see GAP event codes as text in debug log messages.
|
||||
/** @brief Un-comment to see GAP event codes as text in debug log messages.
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/* Uncomment to see advertisment types as text while scanning in debug log messages.
|
||||
/** @brief Un-comment to see advertisment types as text while scanning in debug log messages.
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
|
||||
/** @brief Sets the core NimBLE host runs on */
|
||||
/** @brief Un-comment to change the default GAP appearance */
|
||||
// #define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Client functions \n
|
||||
* Reduces flash size by approx. 7kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Scan functions \n
|
||||
* Reduces flash size by approx. 26kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Server functions \n
|
||||
* Reduces flash size by approx. 16kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Advertising functions \n
|
||||
* Reduces flash size by approx. 5kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED
|
||||
|
||||
/** @brief Un-comment to change the number of devices allowed to store/bond with */
|
||||
// #define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||
|
||||
/** @brief Un-comment to change the maximum number of CCCD subscriptions to store */
|
||||
// #define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||
|
||||
/** @brief Un-comment to change the random address refresh time (in seconds) */
|
||||
// #define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
|
||||
/**
|
||||
* @brief Un-comment to change the number of MSYS buffers available.
|
||||
* @details MSYS is a system level mbuf registry. For prepare write & prepare \n
|
||||
* responses MBUFs are allocated out of msys_1 pool. This may need to be increased if\n
|
||||
* you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
|
||||
|
||||
/** @brief Un-comment to use external PSRAM for the NimBLE host */
|
||||
// #define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL 1
|
||||
|
||||
/** @brief Un-comment to change the core NimBLE host runs on */
|
||||
// #define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||
|
||||
/** @brief Un-comment to change the stack size for the NimBLE host task */
|
||||
// #define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||
|
||||
/**********************************
|
||||
End Arduino user-config
|
||||
**********************************/
|
||||
|
||||
/* This section should not be altered */
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_PINNED_TO_CORE
|
||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||
#endif
|
||||
|
||||
/** @brief Sets the stack size for the NimBLE host task */
|
||||
#ifndef CONFIG_BT_NIMBLE_TASK_STACK_SIZE
|
||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sets the memory pool where NimBLE will be loaded
|
||||
* @details By default NimBLE is loaded in internal ram.\n
|
||||
* To use external PSRAM you must change this to `#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL 1`
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
#endif
|
||||
|
||||
/** @brief Sets the number of simultaneous connections (esp controller max is 9) */
|
||||
#ifndef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
#endif
|
||||
|
||||
/** @brief Sets the number of devices allowed to store/bond with */
|
||||
#ifndef CONFIG_BT_NIMBLE_MAX_BONDS
|
||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||
#endif
|
||||
|
||||
/** @brief Sets the maximum number of CCCD subscriptions to store */
|
||||
#ifndef CONFIG_BT_NIMBLE_MAX_CCCDS
|
||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||
#endif
|
||||
|
||||
/** @brief Default device name */
|
||||
#ifndef CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU
|
||||
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT
|
||||
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_NIMBLE_RPA_TIMEOUT
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Set if CCCD's and bond data should be stored in NVS */
|
||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
|
||||
|
||||
|
@ -152,12 +163,6 @@
|
|||
/** @brief Max device name length (bytes) */
|
||||
#define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31
|
||||
|
||||
/** @brief Default MTU size */
|
||||
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 256
|
||||
|
||||
/** @brief Default GAP appearance */
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
|
||||
|
||||
/** @brief ACL Buffer count */
|
||||
#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12
|
||||
|
||||
|
@ -173,21 +178,9 @@
|
|||
/** @brief Number of low priority HCI event buffers */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT 8
|
||||
|
||||
/**
|
||||
* @brief Sets the number of MSYS buffers available.
|
||||
* @details MSYS is a system level mbuf registry. For prepare write & prepare \n
|
||||
* responses MBUFs are allocated out of msys_1 pool. This may need to be increased if\n
|
||||
* you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
|
||||
|
||||
/** @brief Random address refresh time in seconds */
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
|
||||
/** @brief Maximum number of connection oriented channels */
|
||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||
|
||||
/* These should not be altered */
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL 1
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
||||
|
@ -197,14 +190,9 @@
|
|||
#define CONFIG_BT_ENABLED
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||
|
||||
/**********************************
|
||||
End Arduino config
|
||||
**********************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Cannot use client without scan */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
@ -216,26 +204,3 @@
|
|||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _DOXYGEN_
|
||||
/** @brief Uncomment to see debug log messages from the NimBLE host \n
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/** @brief Uncomment to see NimBLE host return codes as text debug log messages. \n
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/** @brief Uncomment to see GAP event codes as text in debug log messages. \n
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/** @brief Uncomment to see advertisment types as text while scanning in debug log messages. \n
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
#endif // _DOXYGEN_
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* For ESP-IDF compatibility
|
||||
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ENABLED) && !defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
#define CONFIG_BT_NIMBLE_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_DEBUG) && !defined(CONFIG_BT_NIMBLE_DEBUG)
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_BY_ADV_DATA ) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA CONFIG_SCAN_DUPLICATE_BY_ADV_DATA
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_TYPE) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE CONFIG_SCAN_DUPLICATE_TYPE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DUPLICATE_SCAN_CACHE_SIZE) && !defined(CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE CONFIG_DUPLICATE_SCAN_CACHE_SIZE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_MAX_CONNECTIONS ) && !defined(CONFIG_BT_NIMBLE_MAX_CONNECTIONS)
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
|
||||
Copyright (C) 2020 Christian Baars and Theo Arends
|
||||
Also Simon Hailes and Robert Klauco
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -23,6 +24,9 @@
|
|||
--------------------------------------------------------------------------------------------
|
||||
Version yyyymmdd Action Description
|
||||
--------------------------------------------------------------------------------------------
|
||||
0.9.2.1 20210217 changed - make features alos depend on received data - i.e. 'unknown' devices will show what they send.
|
||||
Add MI32Option6 1 to switch to tele/tasmota_ble/<somename> style MQTT independent of HASS discovery.
|
||||
-------
|
||||
0.9.2.0 20210127 changed - Officially includes as the mi driver when using USE_BLE_ESP32.
|
||||
-------
|
||||
0.9.1.9 20201226 changed - All change now.
|
||||
|
@ -124,6 +128,7 @@ struct {
|
|||
uint32_t ignoreBogusBattery:1;
|
||||
uint32_t minimalSummary:1; // DEPRECATED!!
|
||||
uint32_t onlyAliased:1; // only include sensors that are aliased
|
||||
uint32_t MQTTType:1;
|
||||
} option;
|
||||
} MI32;
|
||||
|
||||
|
@ -279,6 +284,8 @@ struct mi_sensor_t{
|
|||
uint32_t NMT:1;
|
||||
uint32_t PIR:1;
|
||||
uint32_t Btn:1;
|
||||
uint32_t events:1;
|
||||
uint32_t pairing:1;
|
||||
};
|
||||
uint32_t raw;
|
||||
} feature;
|
||||
|
@ -1409,6 +1416,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
|||
_newSensor.events=0x00;
|
||||
_newSensor.feature.PIR=1;
|
||||
_newSensor.feature.NMT=1;
|
||||
_newSensor.feature.events=1;
|
||||
break;
|
||||
case MI_MJYD2S:
|
||||
_newSensor.NMT=0;
|
||||
|
@ -1417,6 +1425,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
|||
_newSensor.feature.NMT=1;
|
||||
_newSensor.feature.lux=1;
|
||||
_newSensor.feature.bat=1;
|
||||
_newSensor.feature.events=1;
|
||||
break;
|
||||
case MI_YEERC:
|
||||
case MI_DOOR:
|
||||
|
@ -1637,15 +1646,25 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
char tmp[20];
|
||||
BLE_ESP32::dump(tmp, 20, (uint8_t*)&(parsed->payload), parsed->payload.size+3);
|
||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: MI%d payload %s"), _slot, tmp);
|
||||
|
||||
// clear this for every payload
|
||||
MIBLEsensors[_slot].pairing = 0;
|
||||
MIBLEsensors[_slot].eventType.PairBtn = 0;
|
||||
|
||||
switch(parsed->payload.type){
|
||||
case 0x01: // button press
|
||||
MIBLEsensors[_slot].Btn = pld->Btn.num + (pld->Btn.longPress/2)*6;
|
||||
MIBLEsensors[_slot].feature.Btn = 1;
|
||||
MIBLEsensors[_slot].eventType.Btn = 1;
|
||||
MI32.mode.shallTriggerTele = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
break;
|
||||
case 0x02:
|
||||
res = 0;
|
||||
case 0x02: // related to pair button?
|
||||
MIBLEsensors[_slot].pairing = 1;
|
||||
MIBLEsensors[_slot].eventType.PairBtn = 1;
|
||||
MIBLEsensors[_slot].feature.pairing = 1;
|
||||
MI32.mode.shallTriggerTele = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
break;
|
||||
case 0x03: {// motion? 1 byte
|
||||
uint8_t motion = parsed->payload.data[0];
|
||||
|
@ -1655,6 +1674,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
float _tempFloat=(float)(pld->temp)/10.0f;
|
||||
if(_tempFloat<60){
|
||||
MIBLEsensors[_slot].temp=_tempFloat;
|
||||
MIBLEsensors[_slot].feature.temp = 1;
|
||||
MIBLEsensors[_slot].eventType.temp = 1;
|
||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp updated"));
|
||||
} else {
|
||||
|
@ -1666,6 +1686,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
float _tempFloat=(float)(pld->hum)/10.0f;
|
||||
if(_tempFloat<101){
|
||||
MIBLEsensors[_slot].hum=_tempFloat;
|
||||
MIBLEsensors[_slot].feature.hum = 1;
|
||||
MIBLEsensors[_slot].eventType.hum = 1;
|
||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum updated"));
|
||||
} else {
|
||||
|
@ -1679,17 +1700,20 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
MIBLEsensors[_slot].eventType.noMotion = 1;
|
||||
}
|
||||
MIBLEsensors[_slot].eventType.lux = 1;
|
||||
MIBLEsensors[_slot].feature.lux = 1;
|
||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff);
|
||||
break;
|
||||
case 0x08:
|
||||
MIBLEsensors[_slot].moisture=pld->moist;
|
||||
MIBLEsensors[_slot].eventType.moist = 1;
|
||||
MIBLEsensors[_slot].feature.moist = 1;
|
||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 8: moisture updated"));
|
||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 8: U8: %u Moisture"), _beacon.moist);
|
||||
break;
|
||||
case 0x09: // 'conductivity'
|
||||
MIBLEsensors[_slot].fertility=pld->fert;
|
||||
MIBLEsensors[_slot].eventType.fert = 1;
|
||||
MIBLEsensors[_slot].feature.fert = 1;
|
||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 9: fertility updated"));
|
||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 9: U16: %u Fertility"), _beacon.fert);
|
||||
break;
|
||||
|
@ -1700,6 +1724,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
break;
|
||||
}
|
||||
}
|
||||
MIBLEsensors[_slot].feature.bat = 1;
|
||||
if(pld->bat<101){
|
||||
MIBLEsensors[_slot].bat = pld->bat;
|
||||
MIBLEsensors[_slot].eventType.bat = 1;
|
||||
|
@ -1712,6 +1737,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode a: U8: %u %%"), _beacon.bat);
|
||||
break;
|
||||
case 0x0d:{
|
||||
MIBLEsensors[_slot].feature.tempHum = 1;
|
||||
float _tempFloat=(float)(pld->HT.temp)/10.0f;
|
||||
if(_tempFloat < 60){
|
||||
MIBLEsensors[_slot].temp = _tempFloat;
|
||||
|
@ -1738,6 +1764,11 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
MIBLEsensors[_slot].eventType.lux = 1;
|
||||
MIBLEsensors[_slot].NMT = 0;
|
||||
MI32.mode.shallTriggerTele = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
MIBLEsensors[_slot].feature.lux = 1;
|
||||
MIBLEsensors[_slot].feature.NMT = 1;
|
||||
MIBLEsensors[_slot].feature.events=1;
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: PIR: primary"),MIBLEsensors[_slot].lux );
|
||||
break;
|
||||
case 0x10:{ // 'formaldehide'
|
||||
|
@ -1762,6 +1793,9 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
MIBLEsensors[_slot].NMT = pld->NMT;
|
||||
MIBLEsensors[_slot].eventType.NMT = 1;
|
||||
MI32.mode.shallTriggerTele = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
MIBLEsensors[_slot].feature.NMT = 1;
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 17: NMT: %u seconds"), _beacon.NMT);
|
||||
} break;
|
||||
|
||||
|
@ -1769,6 +1803,8 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||
MIBLEsensors[_slot].Btn = uint8_t(parsed->payload.data[0]); // just an 8 bit value in a union.
|
||||
MIBLEsensors[_slot].eventType.Btn = 1;
|
||||
MI32.mode.shallTriggerTele = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
MIBLEsensors[_slot].feature.Btn = 1;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
|
@ -1904,10 +1940,12 @@ void MI32EverySecond(bool restart){
|
|||
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: onesec"));
|
||||
MI32TimeoutSensors();
|
||||
|
||||
MI32ShowSomeSensors();
|
||||
|
||||
MI32DiscoveryOneMISensor();
|
||||
MI32ShowOneMISensor();
|
||||
if (MI32.option.MQTTType == 0){
|
||||
MI32ShowSomeSensors();
|
||||
} else {
|
||||
MI32DiscoveryOneMISensor();
|
||||
MI32ShowOneMISensor();
|
||||
}
|
||||
|
||||
// read a battery if
|
||||
// MI32.batteryreader.slot < filled and !MI32.batteryreader.active
|
||||
|
@ -2132,16 +2170,24 @@ void CmndMi32Option(void){
|
|||
bool onOff = atoi(XdrvMailbox.data);
|
||||
switch(XdrvMailbox.index) {
|
||||
case 0:
|
||||
MI32.option.allwaysAggregate = onOff;
|
||||
MI32.option.allwaysAggregate = onOff;
|
||||
ResponseCmndNumber(onOff);
|
||||
return;
|
||||
break;
|
||||
case 1:
|
||||
MI32.option.noSummary = onOff;
|
||||
ResponseCmndNumber(onOff);
|
||||
return;
|
||||
break;
|
||||
case 2:
|
||||
MI32.option.directBridgeMode = onOff;
|
||||
ResponseCmndNumber(onOff);
|
||||
return;
|
||||
break;
|
||||
case 4:{
|
||||
MI32.option.ignoreBogusBattery = onOff;
|
||||
ResponseCmndNumber(onOff);
|
||||
return;
|
||||
} break;
|
||||
case 5:{
|
||||
MI32.option.onlyAliased = onOff;
|
||||
|
@ -2149,7 +2195,15 @@ void CmndMi32Option(void){
|
|||
// discard all sensors for a restart
|
||||
MIBLEsensors.clear();
|
||||
}
|
||||
ResponseCmndNumber(onOff);
|
||||
return;
|
||||
} break;
|
||||
case 6:{
|
||||
MI32.option.MQTTType = onOff;
|
||||
ResponseCmndNumber(onOff);
|
||||
return;
|
||||
} break;
|
||||
|
||||
}
|
||||
ResponseCmndDone();
|
||||
}
|
||||
|
@ -2249,7 +2303,7 @@ void CmndMi32Keys(void){
|
|||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0920{m}%u%s / %u{e}";
|
||||
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0921{m}%u%s / %u{e}";
|
||||
const char HTTP_MI32_ALIAS[] PROGMEM = "{s}%s Alias {m}%s{e}";
|
||||
const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}";
|
||||
const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
|
||||
|
@ -2527,9 +2581,13 @@ void MI32ShowSomeSensors(){
|
|||
|
||||
ResponseTime_P(PSTR(""));
|
||||
int cnt = 0;
|
||||
for (; (MI32.mqttCurrentSlot < numsensors) && (cnt < 4); MI32.mqttCurrentSlot++, cnt++) {
|
||||
int maxcnt = 4;
|
||||
mi_sensor_t *p;
|
||||
for (; (MI32.mqttCurrentSlot < numsensors) && (cnt < maxcnt); MI32.mqttCurrentSlot++, cnt++) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
MI32GetOneSensorJson(MI32.mqttCurrentSlot, 0);
|
||||
p = &MIBLEsensors[MI32.mqttCurrentSlot];
|
||||
|
||||
MI32GetOneSensorJson(MI32.mqttCurrentSlot, (maxcnt == 1));
|
||||
int mlen = strlen(TasmotaGlobal.mqtt_data);
|
||||
|
||||
// if we ran out of room, leave here.
|
||||
|
@ -2537,6 +2595,7 @@ void MI32ShowSomeSensors(){
|
|||
MI32.mqttCurrentSlot++;
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
ResponseAppend_P(PSTR("}"));
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
|
@ -2567,8 +2626,13 @@ void MI32ShowOneMISensor(){
|
|||
return;
|
||||
}
|
||||
|
||||
if(
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if(Settings.flag.hass_discovery){
|
||||
Settings.flag.hass_discovery
|
||||
||
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
MI32.option.MQTTType == 1
|
||||
){
|
||||
|
||||
ResponseTime_P(PSTR(","));
|
||||
MI32GetOneSensorJson(MI32.mqttCurrentSingleSlot, 1);
|
||||
|
@ -2594,7 +2658,6 @@ void MI32ShowOneMISensor(){
|
|||
MqttPublish(SensorTopic);
|
||||
//AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, TasmotaGlobal.mqtt_data);
|
||||
}
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
MI32.mqttCurrentSingleSlot++;
|
||||
}
|
||||
|
||||
|
@ -2749,11 +2812,23 @@ void MI32ShowTriggeredSensors(){
|
|||
|
||||
int sensor = 0;
|
||||
|
||||
int maxcnt = 4;
|
||||
if(
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
Settings.flag.hass_discovery
|
||||
||
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
MI32.option.MQTTType == 1
|
||||
){
|
||||
maxcnt = 1;
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
ResponseTime_P(PSTR(""));
|
||||
int cnt = 0;
|
||||
for (; (sensor < numsensors) && (cnt < 4); sensor++) {
|
||||
mi_sensor_t *p;
|
||||
mi_sensor_t *p;
|
||||
for (; (sensor < numsensors) && (cnt < maxcnt); sensor++) {
|
||||
p = &MIBLEsensors[sensor];
|
||||
if(p->eventType.raw == 0) continue;
|
||||
if(p->shallSendMQTT==0) continue;
|
||||
|
@ -2771,7 +2846,30 @@ void MI32ShowTriggeredSensors(){
|
|||
}
|
||||
if (cnt){ // if we got one, then publish
|
||||
ResponseAppend_P(PSTR("}"));
|
||||
MqttPublishPrefixTopic_P(STAT, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
if(
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
Settings.flag.hass_discovery
|
||||
||
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
MI32.option.MQTTType == 1
|
||||
){
|
||||
char SensorTopic[60];
|
||||
char idstr[32];
|
||||
const char *alias = BLE_ESP32::getAlias(p->MAC);
|
||||
const char *id = idstr;
|
||||
if (alias && *alias){
|
||||
id = alias;
|
||||
} else {
|
||||
sprintf(idstr, PSTR("%s%02x%02x%02x"),
|
||||
kMI32DeviceType[p->type-1],
|
||||
p->MAC[3], p->MAC[4], p->MAC[5]);
|
||||
}
|
||||
sprintf(SensorTopic, "tele/tasmota_ble/%s",
|
||||
id);
|
||||
MqttPublish(SensorTopic);
|
||||
} else {
|
||||
MqttPublishPrefixTopic_P(STAT, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: triggered %d %s"),D_CMND_MI32, sensor, TasmotaGlobal.mqtt_data);
|
||||
|
||||
#ifdef USE_RULES
|
||||
|
@ -2887,21 +2985,25 @@ void MI32Show(bool json)
|
|||
WSContentSend_PD(HTTP_NEEDKEY, typeName, _MAC, Webserver->client().localIP().toString().c_str(), tmp );
|
||||
}
|
||||
|
||||
if (p->type==MI_NLIGHT || p->type==MI_MJYD2S) {
|
||||
#else
|
||||
if (p->type==MI_NLIGHT) {
|
||||
#endif //USE_MI_DECRYPTION
|
||||
|
||||
if (p->feature.events){
|
||||
WSContentSend_PD(HTTP_EVENTS, typeName, p->events);
|
||||
}
|
||||
if (p->feature.NMT){
|
||||
// no motion time
|
||||
if(p->NMT>0) WSContentSend_PD(HTTP_NMT, typeName, p->NMT);
|
||||
}
|
||||
|
||||
if (p->lux!=0x00ffffff) { // this is the error code -> no valid value
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, typeName, p->lux);
|
||||
if (p->feature.lux){
|
||||
if (p->lux!=0x00ffffff) { // this is the error code -> no valid value
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, typeName, p->lux);
|
||||
}
|
||||
}
|
||||
if(p->bat!=0x00){
|
||||
WSContentSend_PD(HTTP_BATTERY, typeName, p->bat);
|
||||
}
|
||||
if (p->type==MI_YEERC || p->type==MI_DOOR){
|
||||
if (p->feature.Btn){
|
||||
WSContentSend_PD(HTTP_LASTBUTTON, typeName, p->Btn);
|
||||
}
|
||||
if (p->pairing){
|
||||
|
|
Loading…
Reference in New Issue