mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' of github.com:arendst/Tasmota into pr2_tm1637
This commit is contained in:
commit
78e1051b32
|
@ -10,9 +10,9 @@ All notable changes to this project will be documented in this file.
|
||||||
- Support for Frysk language translations by Christiaan Heerze
|
- Support for Frysk language translations by Christiaan Heerze
|
||||||
- ESP8266 Fallback to ``*.bin.gz`` binary when OTA upload of ``*.bin`` binary fails
|
- ESP8266 Fallback to ``*.bin.gz`` binary when OTA upload of ``*.bin`` binary fails
|
||||||
- Berry language improved Tasmota integration
|
- Berry language improved Tasmota integration
|
||||||
|
- Berry file system support
|
||||||
- Filesystem commands ``Ufs``, ``UfsType``, ``UfsSize``, ``UfsFree``, ``UfsDelete``, ``UfsRename`` and ``UfsRun``
|
- Filesystem commands ``Ufs``, ``UfsType``, ``UfsSize``, ``UfsFree``, ``UfsDelete``, ``UfsRename`` and ``UfsRun``
|
||||||
- Basic support for filesystem ``autoexec.bat``
|
- Support for filesystem ``autoexec.bat`` to execute sequential commands like backlog
|
||||||
- Berry add file system support
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- IRremoteESP8266 library from v2.7.14 to v2.7.15
|
- IRremoteESP8266 library from v2.7.14 to v2.7.15
|
||||||
|
|
|
@ -96,7 +96,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||||
- Commands ``ZbNoAutoBind``, ``ZbReceivedTopic`` and ``ZbOmitDevice`` as synonyms for ``SetOption116, 118`` and ``119``
|
- Commands ``ZbNoAutoBind``, ``ZbReceivedTopic`` and ``ZbOmitDevice`` as synonyms for ``SetOption116, 118`` and ``119``
|
||||||
- Commands ``BuzzerActive`` and ``BuzzerPwm`` as synonyms for ``SetOption67`` and ``111``
|
- Commands ``BuzzerActive`` and ``BuzzerPwm`` as synonyms for ``SetOption67`` and ``111``
|
||||||
- Filesystem commands ``Ufs``, ``UfsType``, ``UfsSize``, ``UfsFree``, ``UfsDelete``, ``UfsRename`` and ``UfsRun``
|
- Filesystem commands ``Ufs``, ``UfsType``, ``UfsSize``, ``UfsFree``, ``UfsDelete``, ``UfsRename`` and ``UfsRun``
|
||||||
- Basic support for filesystem ``autoexec.bat``
|
- Support for filesystem ``autoexec.bat`` to execute sequential commands like backlog
|
||||||
- Milliseconds to console output [#10152](https://github.com/arendst/Tasmota/issues/10152)
|
- Milliseconds to console output [#10152](https://github.com/arendst/Tasmota/issues/10152)
|
||||||
- Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs [#10196](https://github.com/arendst/Tasmota/issues/10196)
|
- Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs [#10196](https://github.com/arendst/Tasmota/issues/10196)
|
||||||
- Rotary No Pullup GPIO selection ``Rotary A/B_n`` [#10407](https://github.com/arendst/Tasmota/issues/10407)
|
- Rotary No Pullup GPIO selection ``Rotary A/B_n`` [#10407](https://github.com/arendst/Tasmota/issues/10407)
|
||||||
|
@ -121,6 +121,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||||
- Support for ESP32 ``Module 3`` Odroid Go 16MB binary tasmota32-odroidgo.bin [#8630](https://github.com/arendst/Tasmota/issues/8630)
|
- Support for ESP32 ``Module 3`` Odroid Go 16MB binary tasmota32-odroidgo.bin [#8630](https://github.com/arendst/Tasmota/issues/8630)
|
||||||
- Support for ESP32 ``Module 5`` Wireless Tag Eth01 [#9496](https://github.com/arendst/Tasmota/issues/9496)
|
- Support for ESP32 ``Module 5`` Wireless Tag Eth01 [#9496](https://github.com/arendst/Tasmota/issues/9496)
|
||||||
- Support for ESP32 ``Module 7`` M5stack core2 16MB binary tasmota32-core2.bin [#10635](https://github.com/arendst/Tasmota/issues/10635)
|
- Support for ESP32 ``Module 7`` M5stack core2 16MB binary tasmota32-core2.bin [#10635](https://github.com/arendst/Tasmota/issues/10635)
|
||||||
|
- Support for Berry language on ESP32
|
||||||
- Support rotary encoder on Shelly Dimmer [#10407](https://github.com/arendst/Tasmota/issues/10407#issuecomment-756240920)
|
- Support rotary encoder on Shelly Dimmer [#10407](https://github.com/arendst/Tasmota/issues/10407#issuecomment-756240920)
|
||||||
- Support character `#` to be replaced by `space`-character in command ``Publish`` topic [#10258](https://github.com/arendst/Tasmota/issues/10258)
|
- Support character `#` to be replaced by `space`-character in command ``Publish`` topic [#10258](https://github.com/arendst/Tasmota/issues/10258)
|
||||||
- Support trailing silence in buzzer tune [#10694](https://github.com/arendst/Tasmota/issues/10694)
|
- Support trailing silence in buzzer tune [#10694](https://github.com/arendst/Tasmota/issues/10694)
|
||||||
|
|
|
@ -2,6 +2,70 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
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
|
## [1.1.0] - 2021-01-20
|
||||||
|
|
||||||
### Added
|
### 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.
|
- 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.
|
- 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.
|
- (Arduino) Ensure controller mode is set to BLE Only.
|
||||||
|
|
||||||
|
|
||||||
## [1.0.2] - 2020-09-13
|
## [1.0.2] - 2020-09-13
|
||||||
|
|
||||||
### Changed
|
### 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
|
- (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.
|
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
|
## [1.0.1] - 2020-09-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,93 +1,117 @@
|
||||||
# Arduino command line and platformio config options
|
# Arduino command line and platformio config options
|
||||||
|
|
||||||
`CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED`
|
`CONFIG_BT_NIMBLE_MAX_CONNECTIONS`
|
||||||
|
|
||||||
If defined, NimBLE Client functions will not be included.
|
|
||||||
- Reduces flash size by approx. 7kB.
|
|
||||||
<br>
|
|
||||||
|
|
||||||
`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.
|
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
||||||
- Reduces flash size by approx. 26kB.
|
|
||||||
<br>
|
|
||||||
|
|
||||||
`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.
|
`CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME`
|
||||||
- Reduces flash size by approx. 16kB.
|
|
||||||
<br>
|
|
||||||
|
|
||||||
`CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED`
|
Set the default device name
|
||||||
|
- Default value is "nimble"
|
||||||
If defined, NimBLE Advertising functions will not be included.
|
<br/>
|
||||||
- Reduces flash size by approx. 5kB.
|
|
||||||
<br>
|
|
||||||
|
|
||||||
`CONFIG_BT_NIMBLE_DEBUG`
|
`CONFIG_BT_NIMBLE_DEBUG`
|
||||||
|
|
||||||
If defined, enables debug log messages from the NimBLE host
|
If defined, enables debug log messages from the NimBLE host
|
||||||
- Uses approx. 32kB of flash memory.
|
- Uses approx. 32kB of flash memory.
|
||||||
<br>
|
<br/>
|
||||||
|
|
||||||
`CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT`
|
`CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT`
|
||||||
|
|
||||||
If defined, NimBLE host return codes will be printed as text in debug log messages.
|
If defined, NimBLE host return codes will be printed as text in debug log messages.
|
||||||
- Uses approx. 7kB of flash memory.
|
- Uses approx. 7kB of flash memory.
|
||||||
<br>
|
<br/>
|
||||||
|
|
||||||
`CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT`
|
`CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT`
|
||||||
|
|
||||||
If defined, GAP event codes will be printed as text in debug log messages.
|
If defined, GAP event codes will be printed as text in debug log messages.
|
||||||
- Uses approx. 1kB of flash memory.
|
- Uses approx. 1kB of flash memory.
|
||||||
<br>
|
<br/>
|
||||||
|
|
||||||
`CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT`
|
`CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT`
|
||||||
|
|
||||||
If defined, advertisment types will be printed as text while scanning in debug log messages.
|
If defined, advertisment types will be printed as text while scanning in debug log messages.
|
||||||
- Uses approx. 250 bytes of flash memory.
|
- 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`
|
`CONFIG_BT_NIMBLE_PINNED_TO_CORE`
|
||||||
|
|
||||||
Sets the core the NimBLE host stack will run on
|
Sets the core the NimBLE host stack will run on
|
||||||
- Options: 0 or 1
|
- Options: 0 or 1
|
||||||
<br>
|
<br/>
|
||||||
|
|
||||||
`CONFIG_BT_NIMBLE_TASK_STACK_SIZE`
|
`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
|
- Default is 4096
|
||||||
<br>
|
<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>
|
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ For example `BLEServer::createService(SERVICE_UUID)` will work just as it did be
|
||||||
|
|
||||||
<a name="characteristics"></a>
|
<a name="characteristics"></a>
|
||||||
### Characteristics
|
### 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.
|
`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`.
|
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/>
|
<br/>
|
||||||
|
|
||||||
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
|
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.
|
~~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.
|
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/>
|
<br/>
|
||||||
|
|
||||||
> BLEAdvertising::start (NimBLEAdvertising::start)
|
> 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",
|
"name": "NimBLE-Arduino",
|
||||||
"keywords": "esp32, bluetooth",
|
"keywords": "esp32, bluetooth",
|
||||||
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
|
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"frameworks": "arduino",
|
"frameworks": "arduino",
|
||||||
"platforms": "espressif32"
|
"platforms": "espressif32"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name=NimBLE-Arduino
|
name=NimBLE-Arduino
|
||||||
version=1.1.0
|
version=1.2.0
|
||||||
author=h2zero
|
author=h2zero
|
||||||
maintainer=h2zero <powellperalta@gmail.com>
|
maintainer=h2zero <powellperalta@gmail.com>
|
||||||
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
||||||
|
|
|
@ -28,25 +28,14 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() {
|
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() :
|
||||||
|
m_payload(62,0)
|
||||||
|
{
|
||||||
m_advType = 0;
|
m_advType = 0;
|
||||||
m_appearance = 0;
|
|
||||||
m_manufacturerData = "";
|
|
||||||
m_name = "";
|
|
||||||
m_rssi = -9999;
|
m_rssi = -9999;
|
||||||
m_txPower = 0;
|
m_callbackSent = false;
|
||||||
m_payloadLength = 0;
|
m_timestamp = 0;
|
||||||
m_payload = nullptr;
|
m_advLength = 0;
|
||||||
|
|
||||||
m_haveAppearance = false;
|
|
||||||
m_haveManufacturerData = false;
|
|
||||||
m_haveName = false;
|
|
||||||
m_haveRSSI = false;
|
|
||||||
m_haveServiceData = false;
|
|
||||||
m_haveServiceUUID = false;
|
|
||||||
m_haveTXPower = false;
|
|
||||||
m_callbackSent = false;
|
|
||||||
|
|
||||||
} // NimBLEAdvertisedDevice
|
} // NimBLEAdvertisedDevice
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,25 +71,126 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
||||||
* @return The appearance of the advertised device.
|
* @return The appearance of the advertised device.
|
||||||
*/
|
*/
|
||||||
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
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
|
} // 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.
|
* @brief Get the manufacturer data.
|
||||||
* @return The manufacturer data of the advertised device.
|
* @return The manufacturer data of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
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
|
} // 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.
|
* @brief Get the advertised name.
|
||||||
* @return The name of the advertised device.
|
* @return The name of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getName() {
|
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
|
} // getName
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,17 +212,70 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
|
||||||
} // 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.
|
* @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.
|
* @return The advertised service data or empty string if no data.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||||
if(index > m_serviceDataVec.size()) {
|
ble_hs_adv_field *field = nullptr;
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: index out of range");
|
uint8_t bytes;
|
||||||
return "";
|
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
|
} //getServiceData
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,51 +284,148 @@ std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||||
* @param [in] uuid The uuid of the service data requested.
|
* @param [in] uuid The uuid of the service data requested.
|
||||||
* @return The advertised service data or empty string if no data.
|
* @return The advertised service data or empty string if no data.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) const {
|
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
||||||
for(auto &it : m_serviceDataVec) {
|
ble_hs_adv_field *field = nullptr;
|
||||||
if(it.first == uuid) {
|
uint8_t bytes;
|
||||||
return it.second;
|
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 "";
|
return "";
|
||||||
} //getServiceData
|
} //getServiceData
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the advertised service UUID.
|
* @brief Get the UUID of the serice data at the index.
|
||||||
* @param [in] index The vector index of the service data UUID requested.
|
* @param [in] index The index of the service data UUID requested.
|
||||||
* @return The advertised service UUID or an empty UUID if not found.
|
* @return The advertised service data UUID or an empty UUID if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||||
if(!haveServiceData() || index > m_serviceDataVec.size()) {
|
ble_hs_adv_field *field = nullptr;
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceDataUUID: index out of range");
|
uint8_t bytes;
|
||||||
return NimBLEUUID("");
|
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
|
} // 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
|
* @brief Get the count of advertised service data UUIDS
|
||||||
* @return The number of service data UUIDS in the vector.
|
* @return The number of service data UUIDS in the vector.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
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
|
} // getServiceDataCount
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Service UUID.
|
* @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.
|
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||||
if(!haveServiceUUID() || index > m_serviceUUIDs.size()) {
|
uint8_t count = 0;
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceUUID: index out of range");
|
uint8_t data_loc = 0;
|
||||||
return NimBLEUUID("");
|
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
|
} // getServiceUUID
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,18 +434,32 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||||
* @return The count of services in the advertising packet.
|
* @return The count of services in the advertising packet.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
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
|
} // getServiceUUIDCount
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check advertised services for existance of the required UUID
|
* @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
|
* @return Return true if service is advertised
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const {
|
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
|
||||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
size_t count = getServiceUUIDCount();
|
||||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
for(size_t i = 0; i < count; i++) {
|
||||||
|
if(uuid == getServiceUUID(i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} // isAdvertisingService
|
} // isAdvertisingService
|
||||||
|
|
||||||
|
@ -215,16 +469,43 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const
|
||||||
* @return The TX Power of the advertised device.
|
* @return The TX Power of the advertised device.
|
||||||
*/
|
*/
|
||||||
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
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
|
} // 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?
|
* @brief Does this advertisement have an appearance value?
|
||||||
* @return True if there is an appearance value present.
|
* @return True if there is an appearance value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveAppearance() {
|
bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||||
return m_haveAppearance;
|
return findAdvField(BLE_HS_ADV_TYPE_APPEARANCE) > 0;
|
||||||
} // haveAppearance
|
} // haveAppearance
|
||||||
|
|
||||||
|
|
||||||
|
@ -233,16 +514,36 @@ bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||||
* @return True if there is manufacturer data present.
|
* @return True if there is manufacturer data present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveManufacturerData() {
|
bool NimBLEAdvertisedDevice::haveManufacturerData() {
|
||||||
return m_haveManufacturerData;
|
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA) > 0;
|
||||||
} // haveManufacturerData
|
} // 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?
|
* @brief Does this advertisement have a name value?
|
||||||
* @return True if there is a name value present.
|
* @return True if there is a name value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveName() {
|
bool NimBLEAdvertisedDevice::haveName() {
|
||||||
return m_haveName;
|
return findAdvField(BLE_HS_ADV_TYPE_COMP_NAME) > 0 ||
|
||||||
|
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME) > 0;
|
||||||
} // haveName
|
} // haveName
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,7 +552,7 @@ bool NimBLEAdvertisedDevice::haveName() {
|
||||||
* @return True if there is a signal strength value present.
|
* @return True if there is a signal strength value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveRSSI() {
|
bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||||
return m_haveRSSI;
|
return m_rssi != -9999;
|
||||||
} // haveRSSI
|
} // haveRSSI
|
||||||
|
|
||||||
|
|
||||||
|
@ -260,7 +561,7 @@ bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||||
* @return True if there is a service data value present.
|
* @return True if there is a service data value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveServiceData() {
|
bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||||
return m_haveServiceData;
|
return getServiceDataCount() > 0;
|
||||||
} // haveServiceData
|
} // haveServiceData
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +570,7 @@ bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||||
* @return True if there is a service UUID value present.
|
* @return True if there is a service UUID value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||||
return m_haveServiceUUID;
|
return getServiceUUIDCount() > 0;
|
||||||
} // haveServiceUUID
|
} // haveServiceUUID
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,143 +579,71 @@ bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||||
* @return True if there is a transmission power value present.
|
* @return True if there is a transmission power value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveTXPower() {
|
bool NimBLEAdvertisedDevice::haveTXPower() {
|
||||||
return m_haveTXPower;
|
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
|
||||||
} // haveTXPower
|
} // haveTXPower
|
||||||
|
|
||||||
|
|
||||||
/**
|
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
||||||
* @brief Parse the advertising pay load.
|
ble_hs_adv_field *field = nullptr;
|
||||||
*
|
uint8_t data = 0;
|
||||||
* The pay load is a buffer of bytes that is either 31 bytes long or terminated by
|
uint8_t length = m_payload.size();
|
||||||
* a 0 length value. Each entry in the buffer has the format:
|
uint8_t count = 0;
|
||||||
* [length][type][data...]
|
|
||||||
*
|
if(length < 2) {
|
||||||
* The length does not include itself but does include everything after it until the next record. A record
|
return count;
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_payload = payload;
|
while (length > 1) {
|
||||||
m_payloadLength = length;
|
field = (ble_hs_adv_field*)&m_payload[data];
|
||||||
|
|
||||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
if (field->length >= length) {
|
||||||
char* pHex = NimBLEUtils::buildHexData(nullptr, m_payload, m_payloadLength);
|
return count;
|
||||||
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 (fields.uuids32 != NULL) {
|
if (field->type == type) {
|
||||||
for (int i = 0; i < fields.num_uuids32; i++) {
|
switch(type) {
|
||||||
setServiceUUID(NimBLEUUID(fields.uuids32[i].value));
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||||
}
|
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||||
}
|
count += field->length / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
if (fields.uuids128 != NULL) {
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS32:
|
||||||
for (int i = 0; i < fields.num_uuids128; i++) {
|
case BLE_HS_ADV_TYPE_COMP_UUIDS32:
|
||||||
setServiceUUID(NimBLEUUID(&fields.uuids128[i]));
|
count += field->length / 4;
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.name != NULL) {
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS128:
|
||||||
setName(std::string(reinterpret_cast<char*>(fields.name), fields.name_len));
|
case BLE_HS_ADV_TYPE_COMP_UUIDS128:
|
||||||
}
|
count += field->length / 16;
|
||||||
|
break;
|
||||||
|
|
||||||
if (fields.tx_pwr_lvl_is_present) {
|
case BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR:
|
||||||
setTXPower(fields.tx_pwr_lvl);
|
case BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR:
|
||||||
}
|
count += field->length / 6;
|
||||||
|
break;
|
||||||
|
|
||||||
if (fields.svc_data_uuid16 != NULL ||
|
default:
|
||||||
fields.svc_data_uuid32 != NULL ||
|
count++;
|
||||||
fields.svc_data_uuid128 != NULL)
|
break;
|
||||||
{
|
|
||||||
ble_hs_adv_field *field;
|
|
||||||
uint8_t *data = payload;
|
|
||||||
while(length > 1) {
|
|
||||||
field = (ble_hs_adv_field*)data;
|
|
||||||
|
|
||||||
if(field->length > length) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID16) {
|
if(data_loc != nullptr) {
|
||||||
if(field->length > 2) {
|
if(index == 0 || count >= index) {
|
||||||
uint16_t uuid;
|
break;
|
||||||
memcpy(&uuid, field->value, 2);
|
|
||||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 2), field->length - 3));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if(data_loc != nullptr && field != nullptr) {
|
||||||
setAppearance(fields.appearance);
|
*data_loc = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields.mfg_data != NULL) {
|
return count;
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -428,106 +657,22 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the adFlag for this device.
|
* @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) {
|
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
||||||
m_advType = advType;
|
m_advType = advType;
|
||||||
} // setAdvType
|
} // 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.
|
* @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) {
|
void NimBLEAdvertisedDevice::setRSSI(int rssi) {
|
||||||
m_rssi = rssi;
|
m_rssi = rssi;
|
||||||
m_haveRSSI = true;
|
|
||||||
} // setRSSI
|
} // 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.
|
* @brief Create a string representation of this device.
|
||||||
* @return 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.
|
* @return The advertisement payload.
|
||||||
*/
|
*/
|
||||||
uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
||||||
return m_payload;
|
return &m_payload[0];
|
||||||
} // getPayload
|
} // 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.
|
* @brief Get the advertised device address type.
|
||||||
* @return The device address type:
|
* @return The device address type:
|
||||||
|
@ -610,7 +780,7 @@ time_t NimBLEAdvertisedDevice::getTimestamp() {
|
||||||
* @return The size of the payload in bytes.
|
* @return The size of the payload in bytes.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
||||||
return m_payloadLength;
|
return m_payload.size();
|
||||||
} // getPayloadLength
|
} // getPayloadLength
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,11 @@ public:
|
||||||
NimBLEAddress getAddress();
|
NimBLEAddress getAddress();
|
||||||
uint8_t getAdvType();
|
uint8_t getAdvType();
|
||||||
uint16_t getAppearance();
|
uint16_t getAppearance();
|
||||||
|
uint16_t getAdvInterval();
|
||||||
|
uint16_t getMinInterval();
|
||||||
|
uint16_t getMaxInterval();
|
||||||
std::string getManufacturerData();
|
std::string getManufacturerData();
|
||||||
|
std::string getURI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A template to convert the service data to <type\>.
|
* @brief A template to convert the service data to <type\>.
|
||||||
|
@ -67,7 +71,7 @@ public:
|
||||||
NimBLEScan* getScan();
|
NimBLEScan* getScan();
|
||||||
size_t getServiceDataCount();
|
size_t getServiceDataCount();
|
||||||
std::string getServiceData(uint8_t index = 0);
|
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>.
|
* @brief A template to convert the service data to <tt><type\></tt>.
|
||||||
|
@ -106,12 +110,15 @@ public:
|
||||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||||
size_t getServiceUUIDCount();
|
size_t getServiceUUIDCount();
|
||||||
|
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||||
|
size_t getTargetAddressCount();
|
||||||
int8_t getTXPower();
|
int8_t getTXPower();
|
||||||
uint8_t* getPayload();
|
uint8_t* getPayload();
|
||||||
|
uint8_t getAdvLength();
|
||||||
size_t getPayloadLength();
|
size_t getPayloadLength();
|
||||||
uint8_t getAddressType();
|
uint8_t getAddressType();
|
||||||
time_t getTimestamp();
|
time_t getTimestamp();
|
||||||
bool isAdvertisingService(const NimBLEUUID &uuid) const;
|
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||||
bool haveAppearance();
|
bool haveAppearance();
|
||||||
bool haveManufacturerData();
|
bool haveManufacturerData();
|
||||||
bool haveName();
|
bool haveName();
|
||||||
|
@ -119,46 +126,30 @@ public:
|
||||||
bool haveServiceData();
|
bool haveServiceData();
|
||||||
bool haveServiceUUID();
|
bool haveServiceUUID();
|
||||||
bool haveTXPower();
|
bool haveTXPower();
|
||||||
|
bool haveConnParams();
|
||||||
|
bool haveAdvInterval();
|
||||||
|
bool haveTargetAddress();
|
||||||
|
bool haveURI();
|
||||||
std::string toString();
|
std::string toString();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEScan;
|
friend class NimBLEScan;
|
||||||
|
|
||||||
void parseAdvertisement(uint8_t* payload, uint8_t length);
|
void setAddress(NimBLEAddress address);
|
||||||
void setAddress(NimBLEAddress address);
|
void setAdvType(uint8_t advType);
|
||||||
void setAdvType(uint8_t advType);
|
void setPayload(uint8_t *payload, uint8_t length, bool append);
|
||||||
void setAppearance(uint16_t appearance);
|
void setRSSI(int rssi);
|
||||||
void setManufacturerData(std::string manufacturerData);
|
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||||
void setName(std::string name);
|
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
NimBLEAddress m_address = NimBLEAddress("");
|
NimBLEAddress m_address = NimBLEAddress("");
|
||||||
uint8_t m_advType;
|
uint8_t m_advType;
|
||||||
uint16_t m_appearance;
|
|
||||||
std::string m_manufacturerData;
|
|
||||||
std::string m_name;
|
|
||||||
int m_rssi;
|
int m_rssi;
|
||||||
int8_t m_txPower;
|
|
||||||
uint8_t* m_payload;
|
|
||||||
size_t m_payloadLength;
|
|
||||||
time_t m_timestamp;
|
time_t m_timestamp;
|
||||||
bool m_callbackSent;
|
bool m_callbackSent;
|
||||||
|
uint8_t m_advLength;
|
||||||
|
|
||||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
std::vector<uint8_t> m_payload;
|
||||||
std::vector<std::pair<NimBLEUUID, std::string>>m_serviceDataVec;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,23 +32,29 @@ static const char* LOG_TAG = "NimBLEAdvertising";
|
||||||
/**
|
/**
|
||||||
* @brief Construct a default advertising object.
|
* @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_advData, 0, sizeof m_advData);
|
||||||
memset(&m_scanData, 0, sizeof m_scanData);
|
memset(&m_scanData, 0, sizeof m_scanData);
|
||||||
memset(&m_advParams, 0, sizeof m_advParams);
|
memset(&m_advParams, 0, sizeof m_advParams);
|
||||||
|
memset(&m_slaveItvl, 0, sizeof m_slaveItvl);
|
||||||
const char *name = ble_svc_gap_device_name();
|
const char *name = ble_svc_gap_device_name();
|
||||||
|
|
||||||
m_advData.name = (uint8_t *)name;
|
m_advData.name = (uint8_t *)name;
|
||||||
m_advData.name_len = strlen(name);
|
m_advData.name_len = strlen(name);
|
||||||
m_advData.name_is_complete = 1;
|
m_advData.name_is_complete = 1;
|
||||||
m_advData.tx_pwr_lvl_is_present = 1;
|
|
||||||
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
|
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
|
||||||
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
|
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)
|
#if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON;
|
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;
|
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||||
#endif
|
#endif
|
||||||
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||||
m_advParams.itvl_min = 0;
|
|
||||||
m_advParams.itvl_max = 0;
|
|
||||||
|
|
||||||
m_customAdvData = false;
|
m_customAdvData = false;
|
||||||
m_customScanResponseData = false;
|
m_customScanResponseData = false;
|
||||||
m_scanResp = true;
|
m_scanResp = true;
|
||||||
m_advDataSet = false;
|
m_advDataSet = false;
|
||||||
// Set this to non-zero to prevent auto start if host reset before started by app.
|
// Set this to non-zero to prevent auto start if host reset before started by app.
|
||||||
m_duration = BLE_HS_FOREVER;
|
m_duration = BLE_HS_FOREVER;
|
||||||
|
} // reset
|
||||||
} // NimBLEAdvertising
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,6 +87,7 @@ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
||||||
addServiceUUID(NimBLEUUID(serviceUUID));
|
addServiceUUID(NimBLEUUID(serviceUUID));
|
||||||
|
m_advDataSet = false;
|
||||||
} // addServiceUUID
|
} // addServiceUUID
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,9 +115,95 @@ void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||||
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||||
m_advData.appearance = appearance;
|
m_advData.appearance = appearance;
|
||||||
m_advData.appearance_is_present = 1;
|
m_advData.appearance_is_present = 1;
|
||||||
|
m_advDataSet = false;
|
||||||
} // setAppearance
|
} // 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.
|
* @brief Set the type of advertisment to use.
|
||||||
* @param [in] adv_type:
|
* @param [in] adv_type:
|
||||||
|
@ -172,6 +261,8 @@ void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
|
||||||
m_slaveItvl[2] = m_slaveItvl[0];
|
m_slaveItvl[2] = m_slaveItvl[0];
|
||||||
m_slaveItvl[3] = m_slaveItvl[1];
|
m_slaveItvl[3] = m_slaveItvl[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_advDataSet = false;
|
||||||
} // setMinPreferred
|
} // setMinPreferred
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,6 +291,8 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
||||||
m_slaveItvl[0] = m_slaveItvl[2];
|
m_slaveItvl[0] = m_slaveItvl[2];
|
||||||
m_slaveItvl[1] = m_slaveItvl[3];
|
m_slaveItvl[1] = m_slaveItvl[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_advDataSet = false;
|
||||||
} // setMaxPreferred
|
} // setMaxPreferred
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,6 +302,7 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::setScanResponse(bool set) {
|
void NimBLEAdvertising::setScanResponse(bool set) {
|
||||||
m_scanResp = set;
|
m_scanResp = set;
|
||||||
|
m_advDataSet = false;
|
||||||
} // setScanResponse
|
} // setScanResponse
|
||||||
|
|
||||||
|
|
||||||
|
@ -344,12 +438,29 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||||
if (!m_customAdvData && !m_advDataSet) {
|
if (!m_customAdvData && !m_advDataSet) {
|
||||||
//start with 3 bytes for the flags data
|
//start with 3 bytes for the flags data
|
||||||
uint8_t payloadLen = (2 + 1);
|
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)
|
if(m_advData.appearance_is_present)
|
||||||
payloadLen += (2 + BLE_HS_ADV_APPEARANCE_LEN);
|
payloadLen += (2 + BLE_HS_ADV_APPEARANCE_LEN);
|
||||||
|
|
||||||
if(m_advData.tx_pwr_lvl_is_present)
|
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)
|
if(m_advData.slave_itvl_range != nullptr)
|
||||||
payloadLen += (2 + 4);
|
payloadLen += (2 + BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||||
|
|
||||||
for(auto &it : m_serviceUUIDs) {
|
for(auto &it : m_serviceUUIDs) {
|
||||||
if(it.getNative()->u.type == BLE_UUID_TYPE_16) {
|
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
|
// 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((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 = m_advData.name;
|
||||||
m_scanData.name_len = m_advData.name_len;
|
m_scanData.name_len = m_advData.name_len;
|
||||||
if(m_scanData.name_len > BLE_HS_ADV_MAX_SZ - 2) {
|
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;
|
m_advData.name_is_complete = 0;
|
||||||
} else {
|
} else {
|
||||||
if(m_advData.tx_pwr_lvl_is_present) {
|
if(m_advData.tx_pwr_lvl_is_present) {
|
||||||
m_advData.tx_pwr_lvl = 0;
|
|
||||||
m_advData.tx_pwr_lvl_is_present = 0;
|
m_advData.tx_pwr_lvl_is_present = 0;
|
||||||
payloadLen -= (2 + 1);
|
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);
|
rc = ble_gap_adv_rsp_set_fields(&m_scanData);
|
||||||
switch(rc) {
|
switch(rc) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -581,7 +691,7 @@ void NimBLEAdvertising::advCompleteCB() {
|
||||||
if(m_advCompCB != nullptr) {
|
if(m_advCompCB != nullptr) {
|
||||||
m_advCompCB(this);
|
m_advCompCB(this);
|
||||||
}
|
}
|
||||||
}
|
} // advCompleteCB
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -590,7 +700,7 @@ void NimBLEAdvertising::advCompleteCB() {
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertising::isAdvertising() {
|
bool NimBLEAdvertising::isAdvertising() {
|
||||||
return ble_gap_adv_active();
|
return ble_gap_adv_active();
|
||||||
}
|
} // isAdvertising
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -608,7 +718,7 @@ void NimBLEAdvertising::onHostSync() {
|
||||||
// Otherwise we should tell the app that advertising stopped.
|
// Otherwise we should tell the app that advertising stopped.
|
||||||
advCompleteCB();
|
advCompleteCB();
|
||||||
}
|
}
|
||||||
}
|
} // onHostSync
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -646,6 +756,7 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::addData(const std::string &data) {
|
void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_payload.append(data);
|
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] data The data to be added to the payload.
|
||||||
* @param [in] length The size of 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){
|
void NimBLEAdvertisementData::addData(char * data, size_t length) {
|
||||||
if ((m_payload.length() + length) > BLE_HS_ADV_MAX_SZ) {
|
addData(std::string(data, length));
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_payload.append(data,length);
|
|
||||||
} // addData
|
} // addData
|
||||||
|
|
||||||
|
|
||||||
|
@ -680,43 +788,6 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
||||||
} // setAppearance
|
} // 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.
|
* @brief Set the advertisement flags.
|
||||||
* @param [in] flag The flags to be set in the advertisement.
|
* @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.
|
* @param [in] data The manufacturer data to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
|
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
cdata[0] = data.length() + 1;
|
cdata[0] = data.length() + 1;
|
||||||
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||||
addData(std::string(cdata, 2) + data);
|
addData(std::string(cdata, 2) + data);
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData");
|
|
||||||
} // 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.
|
* @brief Set the complete name of this device.
|
||||||
* @param [in] name The name to advertise.
|
* @param [in] name The name to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setName(const std::string &name) {
|
void NimBLEAdvertisementData::setName(const std::string &name) {
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
cdata[0] = name.length() + 1;
|
cdata[0] = name.length() + 1;
|
||||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||||
addData(std::string(cdata, 2) + name);
|
addData(std::string(cdata, 2) + name);
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName");
|
|
||||||
} // setName
|
} // setName
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the partial services to advertise.
|
* @brief Set a single service to advertise as a complete list of services.
|
||||||
* @param [in] uuid The single service to advertise.
|
* @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) {
|
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];
|
char cdata[2];
|
||||||
switch (uuid.bitSize()) {
|
cdata[0] = (size / 8) * v_uuid.size() + 1;
|
||||||
case 16: {
|
switch(size) {
|
||||||
// [Len] [0x02] [LL] [HH]
|
case 16:
|
||||||
cdata[0] = 3;
|
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02
|
|
||||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2));
|
|
||||||
break;
|
break;
|
||||||
}
|
case 32:
|
||||||
|
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
|
||||||
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));
|
|
||||||
break;
|
break;
|
||||||
}
|
case 128:
|
||||||
|
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||||
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));
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
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.
|
* @param [in] name The short name of the device.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setShortName(const std::string &name) {
|
void NimBLEAdvertisementData::setShortName(const std::string &name) {
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
cdata[0] = name.length() + 1;
|
cdata[0] = name.length() + 1;
|
||||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||||
addData(std::string(cdata, 2) + name);
|
addData(std::string(cdata, 2) + name);
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName");
|
|
||||||
} // 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.
|
* @brief Retrieve the payload that is to be advertised.
|
||||||
* @return The payload that is to be advertised.
|
* @return The payload that is to be advertised.
|
||||||
|
|
|
@ -50,18 +50,27 @@ class NimBLEAdvertisementData {
|
||||||
public:
|
public:
|
||||||
void setAppearance(uint16_t appearance);
|
void setAppearance(uint16_t appearance);
|
||||||
void setCompleteServices(const NimBLEUUID &uuid);
|
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 setFlags(uint8_t);
|
||||||
void setManufacturerData(const std::string &data);
|
void setManufacturerData(const std::string &data);
|
||||||
|
void setURI(const std::string &uri);
|
||||||
void setName(const std::string &name);
|
void setName(const std::string &name);
|
||||||
void setPartialServices(const NimBLEUUID &uuid);
|
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 setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||||
void setShortName(const std::string &name);
|
void setShortName(const std::string &name);
|
||||||
void addData(const std::string &data); // Add data to the payload.
|
void addData(const std::string &data); // Add data to the payload.
|
||||||
void addData(char * data, size_t length);
|
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.
|
std::string getPayload(); // Retrieve the current advert payload.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEAdvertising;
|
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.
|
std::string m_payload; // The payload of the advertisement.
|
||||||
}; // NimBLEAdvertisementData
|
}; // NimBLEAdvertisementData
|
||||||
|
|
||||||
|
@ -80,6 +89,10 @@ public:
|
||||||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||||
void stop();
|
void stop();
|
||||||
void setAppearance(uint16_t appearance);
|
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 setAdvertisementType(uint8_t adv_type);
|
||||||
void setMaxInterval(uint16_t maxinterval);
|
void setMaxInterval(uint16_t maxinterval);
|
||||||
void setMinInterval(uint16_t mininterval);
|
void setMinInterval(uint16_t mininterval);
|
||||||
|
@ -89,6 +102,8 @@ public:
|
||||||
void setScanResponse(bool);
|
void setScanResponse(bool);
|
||||||
void setMinPreferred(uint16_t);
|
void setMinPreferred(uint16_t);
|
||||||
void setMaxPreferred(uint16_t);
|
void setMaxPreferred(uint16_t);
|
||||||
|
void addTxPower();
|
||||||
|
void reset();
|
||||||
void advCompleteCB();
|
void advCompleteCB();
|
||||||
bool isAdvertising();
|
bool isAdvertising();
|
||||||
|
|
||||||
|
@ -109,6 +124,12 @@ private:
|
||||||
void (*m_advCompCB)(NimBLEAdvertising *pAdv);
|
void (*m_advCompCB)(NimBLEAdvertising *pAdv);
|
||||||
uint8_t m_slaveItvl[4];
|
uint8_t m_slaveItvl[4];
|
||||||
uint32_t m_duration;
|
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)
|
#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.
|
* @brief Return the BLE Descriptor for the given UUID.
|
||||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
* @param [in] uuid The UUID of the descriptor.
|
||||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
* @return A pointer to the descriptor object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||||
return getDescriptorByUUID(NimBLEUUID(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.
|
* @brief Return the BLE Descriptor for the given UUID.
|
||||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
* @param [in] uuid The UUID of the descriptor.
|
||||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
* @return A pointer to the descriptor object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
||||||
for (auto &it : m_dscVec) {
|
for (auto &it : m_dscVec) {
|
||||||
|
@ -124,6 +124,20 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uu
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getDescriptorByUUID
|
} // 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.
|
* @brief Get the handle of the characteristic.
|
||||||
|
|
|
@ -59,6 +59,17 @@ class NimBLECharacteristicCallbacks;
|
||||||
*/
|
*/
|
||||||
class NimBLECharacteristic {
|
class NimBLECharacteristic {
|
||||||
public:
|
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,
|
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||||
uint32_t properties =
|
uint32_t properties =
|
||||||
NIMBLE_PROPERTY::READ |
|
NIMBLE_PROPERTY::READ |
|
||||||
|
@ -72,9 +83,10 @@ public:
|
||||||
|
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
||||||
NimBLEUUID getUUID();
|
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
|
||||||
std::string getValue(time_t *timestamp = nullptr);
|
|
||||||
|
|
||||||
|
std::string getValue(time_t *timestamp = nullptr);
|
||||||
|
size_t getDataLength();
|
||||||
/**
|
/**
|
||||||
* @brief A template to convert the characteristic data to <type\>.
|
* @brief A template to convert the characteristic data to <type\>.
|
||||||
* @tparam T The type to convert the data to.
|
* @tparam T The type to convert the data to.
|
||||||
|
@ -92,25 +104,20 @@ public:
|
||||||
return *((T *)pData);
|
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 uint8_t* data, size_t size);
|
||||||
void setValue(const std::string &value);
|
void setValue(const std::string &value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convenience template to set the characteristic value to <type\>val.
|
* @brief Convenience template to set the characteristic value to <type\>val.
|
||||||
* @param [in] s The value to set.
|
* @param [in] s The value to set.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setValue(const T &s) {
|
void setValue(const T &s) {
|
||||||
setValue((uint8_t*)&s, sizeof(T));
|
setValue((uint8_t*)&s, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString();
|
|
||||||
uint16_t getHandle();
|
|
||||||
size_t getSubscribedCount();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -122,11 +122,17 @@ uint8_t* NimBLEDescriptor::getValue() {
|
||||||
return m_value.attr_value;
|
return m_value.attr_value;
|
||||||
} // getValue
|
} // 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,
|
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
struct ble_gatt_access_ctxt *ctxt,
|
struct ble_gatt_access_ctxt *ctxt,
|
||||||
void *arg)
|
void *arg) {
|
||||||
{
|
|
||||||
const ble_uuid_t *uuid;
|
const ble_uuid_t *uuid;
|
||||||
int rc;
|
int rc;
|
||||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||||
|
|
|
@ -44,20 +44,23 @@ class NimBLEDescriptorCallbacks;
|
||||||
class NimBLEDescriptor {
|
class NimBLEDescriptor {
|
||||||
public:
|
public:
|
||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
size_t getLength();
|
|
||||||
NimBLEUUID getUUID();
|
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();
|
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.
|
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||||
* @param [in] s The value to set.
|
* @param [in] s The value to set.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setValue(const T &s) {
|
void setValue(const T &s) {
|
||||||
setValue((uint8_t*)&s, sizeof(T));
|
setValue((uint8_t*)&s, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,8 @@ std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
||||||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||||
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
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:
|
* @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_HDL0 = 0, For connection handle 0
|
||||||
* * ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, For connection handle 1
|
* * ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, For connection handle 1
|
||||||
|
@ -342,7 +344,7 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
default:
|
default:
|
||||||
return BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
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.
|
* @brief Host reset, we pass the message so we don't make calls until resynced.
|
||||||
* @param [in] reason The reason code for the reset.
|
* @param [in] reason The reason code for the reset.
|
||||||
|
@ -499,8 +548,17 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
|
|
||||||
ESP_ERROR_CHECK(errRc);
|
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();
|
nimble_port_init();
|
||||||
|
|
||||||
// Setup callbacks for host events
|
// Setup callbacks for host events
|
||||||
|
|
|
@ -123,6 +123,8 @@ public:
|
||||||
static bool isIgnored(const NimBLEAddress &address);
|
static bool isIgnored(const NimBLEAddress &address);
|
||||||
static void addIgnored(const NimBLEAddress &address);
|
static void addIgnored(const NimBLEAddress &address);
|
||||||
static void removeIgnored(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)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
static NimBLEAdvertising* getAdvertising();
|
static NimBLEAdvertising* getAdvertising();
|
||||||
|
@ -184,6 +186,8 @@ private:
|
||||||
static ble_gap_event_listener m_listener;
|
static ble_gap_event_listener m_listener;
|
||||||
static gap_event_handler m_customGapHandler;
|
static gap_event_handler m_customGapHandler;
|
||||||
static uint8_t m_own_addr_type;
|
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.
|
* @brief Sets the Plug n Play characterisc value.
|
||||||
* @param [in] sig The vendor ID source number.
|
* @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] pid The product ID number.
|
||||||
* @param [in] version The produce version 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
|
* @return pointer to new input report characteristic
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||||
NimBLECharacteristic* inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
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);
|
NimBLEDescriptor* inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);
|
||||||
|
|
||||||
uint8_t desc1_val[] = { reportID, 0x01 };
|
uint8_t desc1_val[] = { reportID, 0x01 };
|
||||||
inputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
inputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||||
|
@ -144,7 +144,7 @@ NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::outputReport(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);
|
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 };
|
uint8_t desc1_val[] = { reportID, 0x02 };
|
||||||
outputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
outputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||||
|
@ -159,7 +159,7 @@ NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::featureReport(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);
|
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 };
|
uint8_t desc1_val[] = { reportID, 0x03 };
|
||||||
featureReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
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_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
|
||||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||||
m_ignoreResults = false;
|
m_ignoreResults = false;
|
||||||
m_wantDuplicates = false;
|
|
||||||
m_pTaskData = nullptr;
|
m_pTaskData = nullptr;
|
||||||
m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset
|
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: {
|
case BLE_GAP_EVENT_DISC: {
|
||||||
if(pScan->m_ignoreResults) {
|
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;
|
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.
|
// 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.
|
// 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 = new NimBLEAdvertisedDevice();
|
||||||
advertisedDevice->setAddress(advertisedAddress);
|
advertisedDevice->setAddress(advertisedAddress);
|
||||||
advertisedDevice->setAdvType(event->disc.event_type);
|
advertisedDevice->setAdvType(event->disc.event_type);
|
||||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||||
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
}
|
} else if(advertisedDevice != nullptr) {
|
||||||
else{
|
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str());
|
} else {
|
||||||
}
|
// Scan response from unknown device
|
||||||
advertisedDevice->setRSSI(event->disc.rssi);
|
return 0;
|
||||||
if(event->disc.length_data > 0) {
|
|
||||||
advertisedDevice->parseAdvertisement(event->disc.data, event->disc.length_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
advertisedDevice->m_timestamp = time(nullptr);
|
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_pAdvertisedDeviceCallbacks) {
|
||||||
if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) {
|
// If not active scanning or scan response is not available
|
||||||
// If not active scanning report the result to the listener.
|
// report the result to the callback now.
|
||||||
if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
if(pScan->m_scan_params.passive ||
|
||||||
advertisedDevice->m_callbackSent = true;
|
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
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.
|
// 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) {
|
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
advertisedDevice->m_callbackSent = true;
|
advertisedDevice->m_callbackSent = true;
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
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: {
|
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
||||||
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
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) {
|
if (pScan->m_scanCompleteCB != nullptr) {
|
||||||
pScan->m_scanCompleteCB(pScan->m_scanResults);
|
pScan->m_scanCompleteCB(pScan->m_scanResults);
|
||||||
|
@ -145,15 +174,11 @@ NimBLEScan::~NimBLEScan() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Should we perform an active or passive scan?
|
* @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.
|
* @param [in] active If true, we perform an active scan otherwise a passive scan.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setActiveScan(bool active) {
|
void NimBLEScan::setActiveScan(bool active) {
|
||||||
if (active) {
|
m_scan_params.passive = !active;
|
||||||
m_scan_params.passive = 0;
|
|
||||||
} else {
|
|
||||||
m_scan_params.passive = 1;
|
|
||||||
}
|
|
||||||
} // setActiveScan
|
} // setActiveScan
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,6 +227,16 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
||||||
} // setFilterPolicy
|
} // 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.
|
* @brief Set the call backs to be invoked.
|
||||||
* @param [in] pAdvertisedDeviceCallbacks 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,
|
void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks,
|
||||||
bool wantDuplicates) {
|
bool wantDuplicates) {
|
||||||
m_wantDuplicates = wantDuplicates;
|
setDuplicateFilter(!wantDuplicates);
|
||||||
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
|
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
|
||||||
} // setAdvertisedDeviceCallbacks
|
} // setAdvertisedDeviceCallbacks
|
||||||
|
|
||||||
|
@ -342,10 +377,14 @@ bool NimBLEScan::stop() {
|
||||||
|
|
||||||
int rc = ble_gap_disc_cancel();
|
int rc = ble_gap_disc_cancel();
|
||||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_maxResults == 0) {
|
||||||
|
clearResults();
|
||||||
|
}
|
||||||
|
|
||||||
if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) {
|
if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) {
|
||||||
m_scanCompleteCB(m_scanResults);
|
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.
|
* @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) {
|
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) {
|
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
||||||
if((*it)->getAddress() == address) {
|
if((*it)->getAddress() == address) {
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
bool stop();
|
bool stop();
|
||||||
void clearResults();
|
void clearResults();
|
||||||
NimBLEScanResults getResults();
|
NimBLEScanResults getResults();
|
||||||
|
void setMaxResults(uint8_t maxResults);
|
||||||
void erase(const NimBLEAddress &address);
|
void erase(const NimBLEAddress &address);
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,10 +90,10 @@ private:
|
||||||
void (*m_scanCompleteCB)(NimBLEScanResults scanResults);
|
void (*m_scanCompleteCB)(NimBLEScanResults scanResults);
|
||||||
ble_gap_disc_params m_scan_params;
|
ble_gap_disc_params m_scan_params;
|
||||||
bool m_ignoreResults;
|
bool m_ignoreResults;
|
||||||
bool m_wantDuplicates;
|
|
||||||
NimBLEScanResults m_scanResults;
|
NimBLEScanResults m_scanResults;
|
||||||
uint32_t m_duration;
|
uint32_t m_duration;
|
||||||
ble_task_data_t *m_pTaskData;
|
ble_task_data_t *m_pTaskData;
|
||||||
|
uint8_t m_maxResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#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
|
* @brief Get a %BLE Service by its UUID
|
||||||
* @param [in] uuid The UUID of the new service.
|
* @param [in] uuid The UUID of the service.
|
||||||
* @return A reference to the service object.
|
* @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) {
|
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
|
||||||
return getServiceByUUID(NimBLEUUID(uuid));
|
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
|
||||||
} // getServiceByUUID
|
} // getServiceByUUID
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a %BLE Service by its UUID
|
* @brief Get a %BLE Service by its UUID
|
||||||
* @param [in] uuid The UUID of the new service.
|
* @param [in] uuid The UUID of the service.
|
||||||
* @return A reference to the service object.
|
* @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) {
|
for (auto &it : m_svcVec) {
|
||||||
if (it->getUUID() == uuid) {
|
if (it->getUUID() == uuid) {
|
||||||
return it;
|
if (position == instanceId){
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getServiceByUUID
|
} // 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.
|
* @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) {
|
if(rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
}
|
}
|
||||||
} // updateConnParams
|
}// updateConnParams
|
||||||
|
|
||||||
|
|
||||||
/** Default callback handlers */
|
/** Default callback handlers */
|
||||||
|
|
|
@ -49,8 +49,9 @@ public:
|
||||||
void startAdvertising();
|
void startAdvertising();
|
||||||
void stopAdvertising();
|
void stopAdvertising();
|
||||||
void start();
|
void start();
|
||||||
NimBLEService* getServiceByUUID(const char* uuid);
|
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
|
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||||
|
NimBLEService* getServiceByHandle(uint16_t handle);
|
||||||
int disconnect(uint16_t connID,
|
int disconnect(uint16_t connID,
|
||||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||||
void updateConnParams(uint16_t conn_handle,
|
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* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
||||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||||
// Check that we don't add the same characteristic twice.
|
|
||||||
if (getCharacteristic(uuid) != nullptr) {
|
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());
|
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.
|
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||||
* @param [in] uuid The UUID of the characteristic.
|
* @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.
|
* @return A pointer to the characteristic object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t instanceId) {
|
||||||
return getCharacteristic(NimBLEUUID(uuid));
|
return getCharacteristic(NimBLEUUID(uuid), instanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||||
* @param [in] uuid The UUID of the characteristic.
|
* @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.
|
* @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) {
|
for (auto &it : m_chrVec) {
|
||||||
if (it->getUUID() == uuid) {
|
if (it->getUUID() == uuid) {
|
||||||
return it;
|
if (position == instanceId) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
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.
|
* @brief Return a string representation of this service.
|
||||||
|
@ -295,7 +339,7 @@ std::string NimBLEService::toString() {
|
||||||
*/
|
*/
|
||||||
NimBLEServer* NimBLEService::getServer() {
|
NimBLEServer* NimBLEService::getServer() {
|
||||||
return m_pServer;
|
return m_pServer;
|
||||||
} // getServer
|
}// getServer
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
|
|
|
@ -35,6 +35,16 @@ class NimBLECharacteristic;
|
||||||
*/
|
*/
|
||||||
class NimBLEService {
|
class NimBLEService {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
NimBLEServer* getServer();
|
||||||
|
|
||||||
|
NimBLEUUID getUUID();
|
||||||
|
uint16_t getHandle();
|
||||||
|
std::string toString();
|
||||||
|
void dump();
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
|
||||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||||
uint32_t properties =
|
uint32_t properties =
|
||||||
NIMBLE_PROPERTY::READ |
|
NIMBLE_PROPERTY::READ |
|
||||||
|
@ -45,14 +55,14 @@ public:
|
||||||
NIMBLE_PROPERTY::READ |
|
NIMBLE_PROPERTY::READ |
|
||||||
NIMBLE_PROPERTY::WRITE);
|
NIMBLE_PROPERTY::WRITE);
|
||||||
|
|
||||||
void dump();
|
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
|
||||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
|
||||||
NimBLEUUID getUUID();
|
|
||||||
NimBLEServer* getServer();
|
std::vector<NimBLECharacteristic*> getCharacteristics();
|
||||||
bool start();
|
std::vector<NimBLECharacteristic*> getCharacteristics(const char* uuid);
|
||||||
std::string toString();
|
std::vector<NimBLECharacteristic*> getCharacteristics(const NimBLEUUID &uuid);
|
||||||
uint16_t getHandle();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
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);
|
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
|
||||||
m_valueSet = false;
|
m_valueSet = false;
|
||||||
}
|
}
|
||||||
} // NimBLEUUID(std::string)
|
} // 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] pData The pointer to the start of the UUID.
|
||||||
* @param [in] size The size of the data.
|
* @param [in] size The size of the data.
|
||||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||||
*/
|
*/
|
||||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||||
if (size != 16) {
|
uint8_t *uuidValue = nullptr;
|
||||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID length not 16 bytes");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
|
||||||
|
|
||||||
|
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) {
|
if (msbFirst) {
|
||||||
std::reverse_copy(pData, pData + 16, m_uuid.u128.value);
|
std::reverse_copy(pData, pData + size, uuidValue);
|
||||||
} else {
|
} else {
|
||||||
memcpy(m_uuid.u128.value, pData, 16);
|
memcpy(uuidValue, pData, size);
|
||||||
}
|
}
|
||||||
m_valueSet = true;
|
m_valueSet = true;
|
||||||
} // NimBLEUUID
|
} // 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_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||||
|
|
||||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
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) {
|
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1,145 +1,156 @@
|
||||||
/** @file
|
#pragma once
|
||||||
*
|
|
||||||
* IGNORE THIS FILE IF USING ESP-IDF, USE MENUCONFIG TO SET NIMBLE OPTIONS.
|
|
||||||
*
|
|
||||||
* The config options here are for Arduino use only.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "nimconfig_rename.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
|
|
||||||
|
|
||||||
/***********************************************
|
/***********************************************
|
||||||
* Arduino config options start here
|
* Arduino user-config options start here
|
||||||
**********************************************/
|
**********************************************/
|
||||||
|
|
||||||
/** @brief Comment out if not using NimBLE Client functions \n
|
/** @brief Un-comment to change the number of simultaneous connections (esp controller max is 9) */
|
||||||
* Reduces flash size by approx. 7kB.
|
// #define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||||
*/
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
|
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @brief Comment out if not using NimBLE Scan functions \n
|
/** @brief Un-comment to change the default MTU size */
|
||||||
* Reduces flash size by approx. 26kB.
|
// #define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
||||||
*/
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
|
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @brief Comment out if not using NimBLE Server functions \n
|
/** @brief Un-comment to change default device name */
|
||||||
* Reduces flash size by approx. 16kB.
|
// #define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||||
*/
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
|
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @brief Comment out if not using NimBLE Advertising functions \n
|
/** @brief Un-comment to see debug log messages from the NimBLE host
|
||||||
* 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
|
|
||||||
* Uses approx. 32kB of flash memory.
|
* Uses approx. 32kB of flash memory.
|
||||||
*/
|
*/
|
||||||
// #define CONFIG_BT_NIMBLE_DEBUG
|
// #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.
|
* Uses approx. 7kB of flash memory.
|
||||||
*/
|
*/
|
||||||
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
// #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.
|
* Uses approx. 1kB of flash memory.
|
||||||
*/
|
*/
|
||||||
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
// #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.
|
* Uses approx. 250 bytes of flash memory.
|
||||||
*/
|
*/
|
||||||
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
// #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
|
#ifndef CONFIG_BT_NIMBLE_PINNED_TO_CORE
|
||||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief Sets the stack size for the NimBLE host task */
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_TASK_STACK_SIZE
|
#ifndef CONFIG_BT_NIMBLE_TASK_STACK_SIZE
|
||||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||||
#endif
|
#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
|
#ifndef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief Sets the number of simultaneous connections (esp controller max is 9) */
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
|
#ifndef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
|
||||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief Sets the number of devices allowed to store/bond with */
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_MAX_BONDS
|
#ifndef CONFIG_BT_NIMBLE_MAX_BONDS
|
||||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief Sets the maximum number of CCCD subscriptions to store */
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_MAX_CCCDS
|
#ifndef CONFIG_BT_NIMBLE_MAX_CCCDS
|
||||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief Default device name */
|
|
||||||
#ifndef CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME
|
#ifndef CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME
|
||||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||||
#endif
|
#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 */
|
/** @brief Set if CCCD's and bond data should be stored in NVS */
|
||||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
|
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
|
||||||
|
|
||||||
|
@ -152,12 +163,6 @@
|
||||||
/** @brief Max device name length (bytes) */
|
/** @brief Max device name length (bytes) */
|
||||||
#define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31
|
#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 */
|
/** @brief ACL Buffer count */
|
||||||
#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12
|
#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12
|
||||||
|
|
||||||
|
@ -173,21 +178,9 @@
|
||||||
/** @brief Number of low priority HCI event buffers */
|
/** @brief Number of low priority HCI event buffers */
|
||||||
#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT 8
|
#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 */
|
/** @brief Maximum number of connection oriented channels */
|
||||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
#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 1
|
||||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000
|
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000
|
||||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
||||||
|
@ -197,14 +190,9 @@
|
||||||
#define CONFIG_BT_ENABLED
|
#define CONFIG_BT_ENABLED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||||
|
#endif
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
|
||||||
|
|
||||||
/**********************************
|
|
||||||
End Arduino config
|
|
||||||
**********************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* Cannot use client without scan */
|
/* Cannot use client without scan */
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
@ -216,26 +204,3 @@
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||||
#endif
|
#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
|
|
@ -124,12 +124,12 @@ lib_extra_dirs = ${library.lib_extra_dirs}
|
||||||
|
|
||||||
[core32]
|
[core32]
|
||||||
; Activate Stage Core32 by removing ";" in next 3 lines, if you want to override the standard core32
|
; Activate Stage Core32 by removing ";" in next 3 lines, if you want to override the standard core32
|
||||||
;platform_packages = ${core32_stage.platform_packages}
|
platform_packages = ${core32_stage.platform_packages}
|
||||||
;build_unflags = ${core32_stage.build_unflags}
|
build_unflags = ${core32_stage.build_unflags}
|
||||||
;build_flags = ${core32_stage.build_flags}
|
build_flags = ${core32_stage.build_flags}
|
||||||
|
|
||||||
[core32_stage]
|
[core32_stage]
|
||||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/1.0.5-rc6/esp32-1.0.5-rc6.zip
|
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/1.0.5-rc7/esp32-1.0.5-rc7.zip
|
||||||
platformio/tool-mklittlefs @ ~1.203.200522
|
platformio/tool-mklittlefs @ ~1.203.200522
|
||||||
build_unflags = ${esp32_defaults.build_unflags}
|
build_unflags = ${esp32_defaults.build_unflags}
|
||||||
build_flags = ${esp32_defaults.build_flags}
|
build_flags = ${esp32_defaults.build_flags}
|
||||||
|
|
|
@ -480,7 +480,7 @@ cleanup:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _SendDeviceGroupMessage(uint32_t device, DevGroupMessageType message_type, ...)
|
bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, ...)
|
||||||
{
|
{
|
||||||
// If device groups is not up, ignore this request.
|
// If device groups is not up, ignore this request.
|
||||||
if (!device_groups_up) return 1;
|
if (!device_groups_up) return 1;
|
||||||
|
|
|
@ -603,11 +603,10 @@ void HueLightStatus2(uint8_t device, String *response)
|
||||||
// last 24 bits of Mac address + 4 bits of local light + high bit for relays 16-31, relay 32 is mapped to 0
|
// last 24 bits of Mac address + 4 bits of local light + high bit for relays 16-31, relay 32 is mapped to 0
|
||||||
// Zigbee extension: bit 29 = 1, and last 16 bits = short address of Zigbee device
|
// Zigbee extension: bit 29 = 1, and last 16 bits = short address of Zigbee device
|
||||||
#ifndef USE_ZIGBEE
|
#ifndef USE_ZIGBEE
|
||||||
uint32_t EncodeLightId(uint8_t relay_id)
|
uint32_t EncodeLightId(uint8_t relay_id) {
|
||||||
#else
|
#else
|
||||||
uint32_t EncodeLightId(uint8_t relay_id, uint16_t z_shortaddr = 0)
|
uint32_t EncodeLightId(uint8_t relay_id, uint16_t z_shortaddr = 0) {
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
WiFi.macAddress(mac);
|
WiFi.macAddress(mac);
|
||||||
uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4);
|
uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4);
|
||||||
|
@ -636,11 +635,10 @@ uint32_t EncodeLightId(uint8_t relay_id, uint16_t z_shortaddr = 0)
|
||||||
// If the Id encodes a Zigbee device (meaning bit 29 is set)
|
// If the Id encodes a Zigbee device (meaning bit 29 is set)
|
||||||
// it returns 0 and sets the 'shortaddr' to the device short address
|
// it returns 0 and sets the 'shortaddr' to the device short address
|
||||||
#ifndef USE_ZIGBEE
|
#ifndef USE_ZIGBEE
|
||||||
uint32_t DecodeLightId(uint32_t hue_id)
|
uint32_t DecodeLightId(uint32_t hue_id) {
|
||||||
#else
|
#else
|
||||||
uint32_t DecodeLightId(uint32_t hue_id, uint16_t * shortaddr = nullptr)
|
uint32_t DecodeLightId(uint32_t hue_id, uint16_t * shortaddr = nullptr) {
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
uint8_t relay_id = hue_id & 0xF;
|
uint8_t relay_id = hue_id & 0xF;
|
||||||
if (hue_id & (1 << 28)) { // check if bit 25 is set, if so we have
|
if (hue_id & (1 << 28)) { // check if bit 25 is set, if so we have
|
||||||
relay_id += 16;
|
relay_id += 16;
|
||||||
|
|
|
@ -491,7 +491,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we need to adjust the brightness, do it.
|
// If we need to adjust the brightness, do it.
|
||||||
uint32_t negated_device_group_index = -power_button_index;
|
int32_t negated_device_group_index = -power_button_index;
|
||||||
if (bri_offset) {
|
if (bri_offset) {
|
||||||
int32_t bri;
|
int32_t bri;
|
||||||
#ifdef USE_PWM_DIMMER_REMOTE
|
#ifdef USE_PWM_DIMMER_REMOTE
|
||||||
|
@ -510,7 +510,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
|
||||||
}
|
}
|
||||||
if (new_bri != bri) {
|
if (new_bri != bri) {
|
||||||
#ifdef USE_DEVICE_GROUPS
|
#ifdef USE_DEVICE_GROUPS
|
||||||
SendDeviceGroupMessage(negated_device_group_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE_DIRECT), DGR_ITEM_LIGHT_BRI, new_bri);
|
SendDeviceGroupMessage(negated_device_group_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE_DIRECT), DGR_ITEM_LIGHT_BRI, new_bri, DGR_ITEM_BRI_POWER_ON, new_bri);
|
||||||
#endif // USE_DEVICE_GROUPS
|
#endif // USE_DEVICE_GROUPS
|
||||||
#ifdef USE_PWM_DIMMER_REMOTE
|
#ifdef USE_PWM_DIMMER_REMOTE
|
||||||
if (active_remote_pwm_dimmer) {
|
if (active_remote_pwm_dimmer) {
|
||||||
|
|
|
@ -360,7 +360,7 @@ bool UfsExecuteCommandFileReady(void) {
|
||||||
void UfsExecuteCommandFileLoop(void) {
|
void UfsExecuteCommandFileLoop(void) {
|
||||||
if (UfsExecuteCommandFileReady() || !ffs_type) { return; }
|
if (UfsExecuteCommandFileReady() || !ffs_type) { return; }
|
||||||
|
|
||||||
if (strlen(UfsData.run_file) && !UfsData.run_file_mutex) {
|
if (TimeReached(TasmotaGlobal.backlog_timer) && strlen(UfsData.run_file) && !UfsData.run_file_mutex) {
|
||||||
File file = ffsp->open(UfsData.run_file, "r");
|
File file = ffsp->open(UfsData.run_file, "r");
|
||||||
if (!file || !file.seek(UfsData.run_file_pos)) {
|
if (!file || !file.seek(UfsData.run_file_pos)) {
|
||||||
UfsData.run_file_pos = -1; // Signal file ready
|
UfsData.run_file_pos = -1; // Signal file ready
|
||||||
|
@ -401,7 +401,11 @@ void UfsExecuteCommandFileLoop(void) {
|
||||||
UfsData.run_file_pos = (file.available()) ? file.position() : -1;
|
UfsData.run_file_pos = (file.available()) ? file.position() : -1;
|
||||||
file.close();
|
file.close();
|
||||||
if (strlen(cmd_line)) {
|
if (strlen(cmd_line)) {
|
||||||
|
bool nodelay = (!(!strncasecmp_P(cmd_line, PSTR(D_CMND_DELAY), strlen(D_CMND_DELAY))));
|
||||||
ExecuteCommand(cmd_line, SRC_FILE);
|
ExecuteCommand(cmd_line, SRC_FILE);
|
||||||
|
if (nodelay) {
|
||||||
|
TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UfsData.run_file_mutex = false;
|
UfsData.run_file_mutex = false;
|
||||||
|
@ -507,6 +511,10 @@ void UFSRun(void) {
|
||||||
} else {
|
} else {
|
||||||
ResponseCmndFailed();
|
ResponseCmndFailed();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bool not_active = UfsExecuteCommandFileReady();
|
||||||
|
UfsData.run_file_pos = -1;
|
||||||
|
ResponseCmndChar(not_active ? PSTR(D_JSON_DONE) : PSTR(D_JSON_ABORTED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2020 Christian Baars and Theo Arends
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -23,6 +24,9 @@
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
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.2.0 20210127 changed - Officially includes as the mi driver when using USE_BLE_ESP32.
|
||||||
-------
|
-------
|
||||||
0.9.1.9 20201226 changed - All change now.
|
0.9.1.9 20201226 changed - All change now.
|
||||||
|
@ -124,6 +128,7 @@ struct {
|
||||||
uint32_t ignoreBogusBattery:1;
|
uint32_t ignoreBogusBattery:1;
|
||||||
uint32_t minimalSummary:1; // DEPRECATED!!
|
uint32_t minimalSummary:1; // DEPRECATED!!
|
||||||
uint32_t onlyAliased:1; // only include sensors that are aliased
|
uint32_t onlyAliased:1; // only include sensors that are aliased
|
||||||
|
uint32_t MQTTType:1;
|
||||||
} option;
|
} option;
|
||||||
} MI32;
|
} MI32;
|
||||||
|
|
||||||
|
@ -279,6 +284,8 @@ struct mi_sensor_t{
|
||||||
uint32_t NMT:1;
|
uint32_t NMT:1;
|
||||||
uint32_t PIR:1;
|
uint32_t PIR:1;
|
||||||
uint32_t Btn:1;
|
uint32_t Btn:1;
|
||||||
|
uint32_t events:1;
|
||||||
|
uint32_t pairing:1;
|
||||||
};
|
};
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
} feature;
|
} feature;
|
||||||
|
@ -369,8 +376,9 @@ void (*const MI32_Commands[])(void) PROGMEM = {
|
||||||
#define MI_MHOC401 11
|
#define MI_MHOC401 11
|
||||||
#define MI_MHOC303 12
|
#define MI_MHOC303 12
|
||||||
#define MI_ATC 13
|
#define MI_ATC 13
|
||||||
|
#define MI_DOOR 14
|
||||||
|
|
||||||
#define MI_MI32_TYPES 13 //count this manually
|
#define MI_MI32_TYPES 14 //count this manually
|
||||||
|
|
||||||
const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
|
const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
|
||||||
0x0000, // Unkown
|
0x0000, // Unkown
|
||||||
|
@ -385,7 +393,8 @@ const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
|
||||||
0x0153, // yee-rc
|
0x0153, // yee-rc
|
||||||
0x0387, // MHO-C401
|
0x0387, // MHO-C401
|
||||||
0x06d3, // MHO-C303
|
0x06d3, // MHO-C303
|
||||||
0x0a1c // ATC -> this is a fake ID
|
0x0a1c, // ATC -> this is a fake ID
|
||||||
|
0x098b // door/window sensor
|
||||||
};
|
};
|
||||||
|
|
||||||
const char kMI32DeviceType0[] PROGMEM = "Unknown";
|
const char kMI32DeviceType0[] PROGMEM = "Unknown";
|
||||||
|
@ -401,7 +410,8 @@ const char kMI32DeviceType9[] PROGMEM = "YEERC";
|
||||||
const char kMI32DeviceType10[] PROGMEM ="MHOC401";
|
const char kMI32DeviceType10[] PROGMEM ="MHOC401";
|
||||||
const char kMI32DeviceType11[] PROGMEM ="MHOC303";
|
const char kMI32DeviceType11[] PROGMEM ="MHOC303";
|
||||||
const char kMI32DeviceType12[] PROGMEM ="ATC";
|
const char kMI32DeviceType12[] PROGMEM ="ATC";
|
||||||
const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12};
|
const char kMI32DeviceType13[] PROGMEM ="DOOR";
|
||||||
|
const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13};
|
||||||
|
|
||||||
typedef int BATREAD_FUNCTION(int slot);
|
typedef int BATREAD_FUNCTION(int slot);
|
||||||
typedef int UNITWRITE_FUNCTION(int slot, int unit);
|
typedef int UNITWRITE_FUNCTION(int slot, int unit);
|
||||||
|
@ -1406,6 +1416,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
||||||
_newSensor.events=0x00;
|
_newSensor.events=0x00;
|
||||||
_newSensor.feature.PIR=1;
|
_newSensor.feature.PIR=1;
|
||||||
_newSensor.feature.NMT=1;
|
_newSensor.feature.NMT=1;
|
||||||
|
_newSensor.feature.events=1;
|
||||||
break;
|
break;
|
||||||
case MI_MJYD2S:
|
case MI_MJYD2S:
|
||||||
_newSensor.NMT=0;
|
_newSensor.NMT=0;
|
||||||
|
@ -1414,8 +1425,10 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
||||||
_newSensor.feature.NMT=1;
|
_newSensor.feature.NMT=1;
|
||||||
_newSensor.feature.lux=1;
|
_newSensor.feature.lux=1;
|
||||||
_newSensor.feature.bat=1;
|
_newSensor.feature.bat=1;
|
||||||
|
_newSensor.feature.events=1;
|
||||||
break;
|
break;
|
||||||
case MI_YEERC:
|
case MI_YEERC:
|
||||||
|
case MI_DOOR:
|
||||||
_newSensor.feature.Btn=1;
|
_newSensor.feature.Btn=1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1633,15 +1646,25 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
char tmp[20];
|
char tmp[20];
|
||||||
BLE_ESP32::dump(tmp, 20, (uint8_t*)&(parsed->payload), parsed->payload.size+3);
|
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);
|
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){
|
switch(parsed->payload.type){
|
||||||
case 0x01: // button press
|
case 0x01: // button press
|
||||||
MIBLEsensors[_slot].Btn = pld->Btn.num + (pld->Btn.longPress/2)*6;
|
MIBLEsensors[_slot].Btn = pld->Btn.num + (pld->Btn.longPress/2)*6;
|
||||||
|
MIBLEsensors[_slot].feature.Btn = 1;
|
||||||
MIBLEsensors[_slot].eventType.Btn = 1;
|
MIBLEsensors[_slot].eventType.Btn = 1;
|
||||||
MI32.mode.shallTriggerTele = 1;
|
MI32.mode.shallTriggerTele = 1;
|
||||||
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02: // related to pair button?
|
||||||
res = 0;
|
MIBLEsensors[_slot].pairing = 1;
|
||||||
|
MIBLEsensors[_slot].eventType.PairBtn = 1;
|
||||||
|
MIBLEsensors[_slot].feature.pairing = 1;
|
||||||
|
MI32.mode.shallTriggerTele = 1;
|
||||||
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
break;
|
break;
|
||||||
case 0x03: {// motion? 1 byte
|
case 0x03: {// motion? 1 byte
|
||||||
uint8_t motion = parsed->payload.data[0];
|
uint8_t motion = parsed->payload.data[0];
|
||||||
|
@ -1651,6 +1674,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
float _tempFloat=(float)(pld->temp)/10.0f;
|
float _tempFloat=(float)(pld->temp)/10.0f;
|
||||||
if(_tempFloat<60){
|
if(_tempFloat<60){
|
||||||
MIBLEsensors[_slot].temp=_tempFloat;
|
MIBLEsensors[_slot].temp=_tempFloat;
|
||||||
|
MIBLEsensors[_slot].feature.temp = 1;
|
||||||
MIBLEsensors[_slot].eventType.temp = 1;
|
MIBLEsensors[_slot].eventType.temp = 1;
|
||||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp updated"));
|
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp updated"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1662,6 +1686,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
float _tempFloat=(float)(pld->hum)/10.0f;
|
float _tempFloat=(float)(pld->hum)/10.0f;
|
||||||
if(_tempFloat<101){
|
if(_tempFloat<101){
|
||||||
MIBLEsensors[_slot].hum=_tempFloat;
|
MIBLEsensors[_slot].hum=_tempFloat;
|
||||||
|
MIBLEsensors[_slot].feature.hum = 1;
|
||||||
MIBLEsensors[_slot].eventType.hum = 1;
|
MIBLEsensors[_slot].eventType.hum = 1;
|
||||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum updated"));
|
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum updated"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1675,17 +1700,20 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
MIBLEsensors[_slot].eventType.noMotion = 1;
|
MIBLEsensors[_slot].eventType.noMotion = 1;
|
||||||
}
|
}
|
||||||
MIBLEsensors[_slot].eventType.lux = 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);
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff);
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
MIBLEsensors[_slot].moisture=pld->moist;
|
MIBLEsensors[_slot].moisture=pld->moist;
|
||||||
MIBLEsensors[_slot].eventType.moist = 1;
|
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"));
|
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);
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 8: U8: %u Moisture"), _beacon.moist);
|
||||||
break;
|
break;
|
||||||
case 0x09: // 'conductivity'
|
case 0x09: // 'conductivity'
|
||||||
MIBLEsensors[_slot].fertility=pld->fert;
|
MIBLEsensors[_slot].fertility=pld->fert;
|
||||||
MIBLEsensors[_slot].eventType.fert = 1;
|
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"));
|
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);
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 9: U16: %u Fertility"), _beacon.fert);
|
||||||
break;
|
break;
|
||||||
|
@ -1696,6 +1724,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MIBLEsensors[_slot].feature.bat = 1;
|
||||||
if(pld->bat<101){
|
if(pld->bat<101){
|
||||||
MIBLEsensors[_slot].bat = pld->bat;
|
MIBLEsensors[_slot].bat = pld->bat;
|
||||||
MIBLEsensors[_slot].eventType.bat = 1;
|
MIBLEsensors[_slot].eventType.bat = 1;
|
||||||
|
@ -1708,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);
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode a: U8: %u %%"), _beacon.bat);
|
||||||
break;
|
break;
|
||||||
case 0x0d:{
|
case 0x0d:{
|
||||||
|
MIBLEsensors[_slot].feature.tempHum = 1;
|
||||||
float _tempFloat=(float)(pld->HT.temp)/10.0f;
|
float _tempFloat=(float)(pld->HT.temp)/10.0f;
|
||||||
if(_tempFloat < 60){
|
if(_tempFloat < 60){
|
||||||
MIBLEsensors[_slot].temp = _tempFloat;
|
MIBLEsensors[_slot].temp = _tempFloat;
|
||||||
|
@ -1734,6 +1764,11 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
MIBLEsensors[_slot].eventType.lux = 1;
|
MIBLEsensors[_slot].eventType.lux = 1;
|
||||||
MIBLEsensors[_slot].NMT = 0;
|
MIBLEsensors[_slot].NMT = 0;
|
||||||
MI32.mode.shallTriggerTele = 1;
|
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 );
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: PIR: primary"),MIBLEsensors[_slot].lux );
|
||||||
break;
|
break;
|
||||||
case 0x10:{ // 'formaldehide'
|
case 0x10:{ // 'formaldehide'
|
||||||
|
@ -1758,9 +1793,20 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
||||||
MIBLEsensors[_slot].NMT = pld->NMT;
|
MIBLEsensors[_slot].NMT = pld->NMT;
|
||||||
MIBLEsensors[_slot].eventType.NMT = 1;
|
MIBLEsensors[_slot].eventType.NMT = 1;
|
||||||
MI32.mode.shallTriggerTele = 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);
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 17: NMT: %u seconds"), _beacon.NMT);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case 0x19:{
|
||||||
|
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: {
|
default: {
|
||||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Unknown MI pld"));
|
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Unknown MI pld"));
|
||||||
res = 0;
|
res = 0;
|
||||||
|
@ -1894,10 +1940,12 @@ void MI32EverySecond(bool restart){
|
||||||
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: onesec"));
|
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: onesec"));
|
||||||
MI32TimeoutSensors();
|
MI32TimeoutSensors();
|
||||||
|
|
||||||
MI32ShowSomeSensors();
|
if (MI32.option.MQTTType == 0){
|
||||||
|
MI32ShowSomeSensors();
|
||||||
MI32DiscoveryOneMISensor();
|
} else {
|
||||||
MI32ShowOneMISensor();
|
MI32DiscoveryOneMISensor();
|
||||||
|
MI32ShowOneMISensor();
|
||||||
|
}
|
||||||
|
|
||||||
// read a battery if
|
// read a battery if
|
||||||
// MI32.batteryreader.slot < filled and !MI32.batteryreader.active
|
// MI32.batteryreader.slot < filled and !MI32.batteryreader.active
|
||||||
|
@ -2122,16 +2170,24 @@ void CmndMi32Option(void){
|
||||||
bool onOff = atoi(XdrvMailbox.data);
|
bool onOff = atoi(XdrvMailbox.data);
|
||||||
switch(XdrvMailbox.index) {
|
switch(XdrvMailbox.index) {
|
||||||
case 0:
|
case 0:
|
||||||
MI32.option.allwaysAggregate = onOff;
|
MI32.option.allwaysAggregate = onOff;
|
||||||
|
ResponseCmndNumber(onOff);
|
||||||
|
return;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
MI32.option.noSummary = onOff;
|
MI32.option.noSummary = onOff;
|
||||||
|
ResponseCmndNumber(onOff);
|
||||||
|
return;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
MI32.option.directBridgeMode = onOff;
|
MI32.option.directBridgeMode = onOff;
|
||||||
|
ResponseCmndNumber(onOff);
|
||||||
|
return;
|
||||||
break;
|
break;
|
||||||
case 4:{
|
case 4:{
|
||||||
MI32.option.ignoreBogusBattery = onOff;
|
MI32.option.ignoreBogusBattery = onOff;
|
||||||
|
ResponseCmndNumber(onOff);
|
||||||
|
return;
|
||||||
} break;
|
} break;
|
||||||
case 5:{
|
case 5:{
|
||||||
MI32.option.onlyAliased = onOff;
|
MI32.option.onlyAliased = onOff;
|
||||||
|
@ -2139,7 +2195,15 @@ void CmndMi32Option(void){
|
||||||
// discard all sensors for a restart
|
// discard all sensors for a restart
|
||||||
MIBLEsensors.clear();
|
MIBLEsensors.clear();
|
||||||
}
|
}
|
||||||
|
ResponseCmndNumber(onOff);
|
||||||
|
return;
|
||||||
} break;
|
} break;
|
||||||
|
case 6:{
|
||||||
|
MI32.option.MQTTType = onOff;
|
||||||
|
ResponseCmndNumber(onOff);
|
||||||
|
return;
|
||||||
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
ResponseCmndDone();
|
ResponseCmndDone();
|
||||||
}
|
}
|
||||||
|
@ -2239,7 +2303,7 @@ void CmndMi32Keys(void){
|
||||||
* Presentation
|
* 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_ALIAS[] PROGMEM = "{s}%s Alias {m}%s{e}";
|
||||||
const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{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}";
|
const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
|
||||||
|
@ -2517,9 +2581,13 @@ void MI32ShowSomeSensors(){
|
||||||
|
|
||||||
ResponseTime_P(PSTR(""));
|
ResponseTime_P(PSTR(""));
|
||||||
int cnt = 0;
|
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(","));
|
ResponseAppend_P(PSTR(","));
|
||||||
MI32GetOneSensorJson(MI32.mqttCurrentSlot, 0);
|
p = &MIBLEsensors[MI32.mqttCurrentSlot];
|
||||||
|
|
||||||
|
MI32GetOneSensorJson(MI32.mqttCurrentSlot, (maxcnt == 1));
|
||||||
int mlen = strlen(TasmotaGlobal.mqtt_data);
|
int mlen = strlen(TasmotaGlobal.mqtt_data);
|
||||||
|
|
||||||
// if we ran out of room, leave here.
|
// if we ran out of room, leave here.
|
||||||
|
@ -2527,6 +2595,7 @@ void MI32ShowSomeSensors(){
|
||||||
MI32.mqttCurrentSlot++;
|
MI32.mqttCurrentSlot++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cnt++;
|
||||||
}
|
}
|
||||||
ResponseAppend_P(PSTR("}"));
|
ResponseAppend_P(PSTR("}"));
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
|
@ -2557,8 +2626,13 @@ void MI32ShowOneMISensor(){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(
|
||||||
#ifdef USE_HOME_ASSISTANT
|
#ifdef USE_HOME_ASSISTANT
|
||||||
if(Settings.flag.hass_discovery){
|
Settings.flag.hass_discovery
|
||||||
|
||
|
||||||
|
#endif //USE_HOME_ASSISTANT
|
||||||
|
MI32.option.MQTTType == 1
|
||||||
|
){
|
||||||
|
|
||||||
ResponseTime_P(PSTR(","));
|
ResponseTime_P(PSTR(","));
|
||||||
MI32GetOneSensorJson(MI32.mqttCurrentSingleSlot, 1);
|
MI32GetOneSensorJson(MI32.mqttCurrentSingleSlot, 1);
|
||||||
|
@ -2584,7 +2658,6 @@ void MI32ShowOneMISensor(){
|
||||||
MqttPublish(SensorTopic);
|
MqttPublish(SensorTopic);
|
||||||
//AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, TasmotaGlobal.mqtt_data);
|
//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++;
|
MI32.mqttCurrentSingleSlot++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2739,11 +2812,23 @@ void MI32ShowTriggeredSensors(){
|
||||||
|
|
||||||
int sensor = 0;
|
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 {
|
do {
|
||||||
ResponseTime_P(PSTR(""));
|
ResponseTime_P(PSTR(""));
|
||||||
int cnt = 0;
|
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];
|
p = &MIBLEsensors[sensor];
|
||||||
if(p->eventType.raw == 0) continue;
|
if(p->eventType.raw == 0) continue;
|
||||||
if(p->shallSendMQTT==0) continue;
|
if(p->shallSendMQTT==0) continue;
|
||||||
|
@ -2761,7 +2846,30 @@ void MI32ShowTriggeredSensors(){
|
||||||
}
|
}
|
||||||
if (cnt){ // if we got one, then publish
|
if (cnt){ // if we got one, then publish
|
||||||
ResponseAppend_P(PSTR("}"));
|
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);
|
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: triggered %d %s"),D_CMND_MI32, sensor, TasmotaGlobal.mqtt_data);
|
||||||
|
|
||||||
#ifdef USE_RULES
|
#ifdef USE_RULES
|
||||||
|
@ -2877,21 +2985,25 @@ void MI32Show(bool json)
|
||||||
WSContentSend_PD(HTTP_NEEDKEY, typeName, _MAC, Webserver->client().localIP().toString().c_str(), tmp );
|
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
|
#endif //USE_MI_DECRYPTION
|
||||||
|
|
||||||
|
if (p->feature.events){
|
||||||
WSContentSend_PD(HTTP_EVENTS, typeName, p->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->NMT>0) WSContentSend_PD(HTTP_NMT, typeName, p->NMT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->lux!=0x00ffffff) { // this is the error code -> no valid value
|
if (p->feature.lux){
|
||||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, typeName, p->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){
|
if(p->bat!=0x00){
|
||||||
WSContentSend_PD(HTTP_BATTERY, typeName, p->bat);
|
WSContentSend_PD(HTTP_BATTERY, typeName, p->bat);
|
||||||
}
|
}
|
||||||
if (p->type==MI_YEERC){
|
if (p->feature.Btn){
|
||||||
WSContentSend_PD(HTTP_LASTBUTTON, typeName, p->Btn);
|
WSContentSend_PD(HTTP_LASTBUTTON, typeName, p->Btn);
|
||||||
}
|
}
|
||||||
if (p->pairing){
|
if (p->pairing){
|
||||||
|
|
Loading…
Reference in New Issue