mirror of https://github.com/arendst/Tasmota.git
Update NimBLE to 1.1.0 release.
Remove BLE stats from Sensor, publish in BLE. Set default address filter to 0 Add HA MQTT discovery to MI
This commit is contained in:
commit
84620f70ea
|
@ -2,7 +2,7 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
## [1.1.0] - 2021-01-20
|
||||
|
||||
### Added
|
||||
- `NimBLEDevice::setOwnAddrType` added to enable the use of random and random-resolvable addresses, by asukiaaa
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
[Latest release ![Release Version](https://img.shields.io/github/release/h2zero/NimBLE-Arduino.svg?style=plastic)
|
||||
![Release Date](https://img.shields.io/github/release-date/h2zero/NimBLE-Arduino.svg?style=plastic)](https://github.com/h2zero/NimBLE-Arduino/releases/latest/)
|
||||
|
||||
Need help? Have questions or suggestions? Join the [![Gitter](https://badges.gitter.im/NimBLE-Arduino/community.svg)](https://gitter.im/NimBLE-Arduino/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
<br/>
|
||||
|
||||
# NimBLE-Arduino
|
||||
|
@ -57,6 +59,8 @@ Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for inform
|
|||
|
||||
[Full API documentation and class list can be found here.](https://h2zero.github.io/esp-nimble-cpp/)
|
||||
|
||||
For added performance and optimizations see [Usage tips](docs/Usage_tips.md).
|
||||
|
||||
Check the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
|
||||
|
||||
More advanced examples highlighting many available features are in examples/ NimBLE_Server, NimBLE_Client.
|
||||
|
|
|
@ -79,27 +79,24 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
|
|||
return;
|
||||
}
|
||||
|
||||
uint8_t *payLoad = advertisedDevice->getPayload();
|
||||
BLEUUID eddyUUID = (uint16_t)0xfeaa;
|
||||
|
||||
BLEUUID checkUrlUUID = (uint16_t)0xfeaa;
|
||||
|
||||
if (advertisedDevice->getServiceUUID().equals(checkUrlUUID))
|
||||
if (advertisedDevice->getServiceUUID().equals(eddyUUID))
|
||||
{
|
||||
if (payLoad[11] == 0x10)
|
||||
std::string serviceData = advertisedDevice->getServiceData(eddyUUID);
|
||||
if (serviceData[0] == 0x10)
|
||||
{
|
||||
Serial.println("Found an EddystoneURL beacon!");
|
||||
BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
|
||||
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
|
||||
|
||||
foundEddyURL.setData(eddyContent);
|
||||
foundEddyURL.setData(serviceData);
|
||||
std::string bareURL = foundEddyURL.getURL();
|
||||
if (bareURL[0] == 0x00)
|
||||
{
|
||||
size_t payLoadLen = advertisedDevice->getPayloadLength();
|
||||
Serial.println("DATA-->");
|
||||
for (int idx = 0; idx < payLoadLen; idx++)
|
||||
for (int idx = 0; idx < serviceData.length(); idx++)
|
||||
{
|
||||
Serial.printf("0x%08X ", payLoad[idx]);
|
||||
Serial.printf("0x%08X ", serviceData[idx]);
|
||||
}
|
||||
Serial.println("\nInvalid Data");
|
||||
return;
|
||||
|
@ -110,23 +107,15 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
|
|||
Serial.printf("TX power %d\n", foundEddyURL.getPower());
|
||||
Serial.println("\n");
|
||||
}
|
||||
else if (payLoad[11] == 0x20)
|
||||
else if (serviceData[0] == 0x20)
|
||||
{
|
||||
Serial.println("Found an EddystoneTLM beacon!");
|
||||
BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();
|
||||
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
|
||||
foundEddyURL.setData(serviceData);
|
||||
|
||||
eddyContent = "01234567890123";
|
||||
|
||||
for (int idx = 0; idx < 14; idx++)
|
||||
{
|
||||
eddyContent[idx] = payLoad[idx + 11];
|
||||
}
|
||||
|
||||
foundEddyURL.setData(eddyContent);
|
||||
Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
|
||||
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
|
||||
int temp = (int)payLoad[16] + (int)(payLoad[15] << 8);
|
||||
int temp = (int)serviceData[5] + (int)(serviceData[4] << 8);
|
||||
float calcTemp = temp / 256.0f;
|
||||
Serial.printf("Reported temperature from data: %.2fC\n", calcTemp);
|
||||
Serial.printf("Reported advertise count: %d\n", foundEddyURL.getCount());
|
||||
|
|
|
@ -201,7 +201,6 @@ bool connectToServer() {
|
|||
pSvc = pClient->getService("DEAD");
|
||||
if(pSvc) { /** make sure it's not null */
|
||||
pChr = pSvc->getCharacteristic("BEEF");
|
||||
}
|
||||
|
||||
if(pChr) { /** make sure it's not null */
|
||||
if(pChr->canRead()) {
|
||||
|
@ -252,14 +251,13 @@ bool connectToServer() {
|
|||
}
|
||||
}
|
||||
|
||||
else{
|
||||
} else {
|
||||
Serial.println("DEAD service not found.");
|
||||
}
|
||||
|
||||
pSvc = pClient->getService("BAAD");
|
||||
if(pSvc) { /** make sure it's not null */
|
||||
pChr = pSvc->getCharacteristic("F00D");
|
||||
}
|
||||
|
||||
if(pChr) { /** make sure it's not null */
|
||||
if(pChr->canRead()) {
|
||||
|
@ -318,7 +316,7 @@ bool connectToServer() {
|
|||
}
|
||||
}
|
||||
|
||||
else{
|
||||
} else {
|
||||
Serial.println("BAAD service not found.");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=NimBLE-Arduino
|
||||
version=1.0.2
|
||||
version=1.1.0
|
||||
author=h2zero
|
||||
maintainer=h2zero <powellperalta@gmail.com>
|
||||
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
||||
|
|
|
@ -100,9 +100,10 @@ NimBLEClient::~NimBLEClient() {
|
|||
* be called to reset the host in the case of a stalled controller.
|
||||
*/
|
||||
void NimBLEClient::dcTimerCb(ble_npl_event *event) {
|
||||
NimBLEClient *pClient = (NimBLEClient*)event->arg;
|
||||
/* NimBLEClient *pClient = (NimBLEClient*)event->arg;
|
||||
NIMBLE_LOGC(LOG_TAG, "Timed out disconnecting from %s - resetting host",
|
||||
std::string(pClient->getPeerAddress()).c_str());
|
||||
*/
|
||||
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
|
||||
}
|
||||
|
||||
|
@ -182,25 +183,30 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if(isConnected() || m_pTaskData != nullptr) {
|
||||
if(isConnected() || m_connEstablished || m_pTaskData != nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Client busy, connected to %s, id=%d",
|
||||
std::string(m_peerAddress).c_str(), getConnId());
|
||||
return false;
|
||||
}
|
||||
|
||||
ble_addr_t peerAddr_t;
|
||||
memcpy(&peerAddr_t.val, address.getNative(),6);
|
||||
peerAddr_t.type = address.getType();
|
||||
if(ble_gap_conn_find_by_addr(&peerAddr_t, NULL) == 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "A connection to %s already exists",
|
||||
address.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(address == NimBLEAddress("")) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid peer address;(NULL)");
|
||||
return false;
|
||||
} else if(m_peerAddress != address) {
|
||||
} else {
|
||||
m_peerAddress = address;
|
||||
}
|
||||
|
||||
ble_addr_t peerAddr_t;
|
||||
memcpy(&peerAddr_t.val, m_peerAddress.getNative(),6);
|
||||
peerAddr_t.type = m_peerAddress.getType();
|
||||
|
||||
|
||||
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||
m_pTaskData = &taskData;
|
||||
int rc = 0;
|
||||
|
||||
/* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
|
||||
|
@ -213,13 +219,12 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||
NimBLEClient::handleGapEvent, this);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
m_pTaskData = &taskData;
|
||||
break;
|
||||
|
||||
case BLE_HS_EBUSY:
|
||||
// Scan was still running, stop it and try again
|
||||
if (!NimBLEDevice::getScan()->stop()) {
|
||||
return false;
|
||||
rc = BLE_HS_EUNKNOWN;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -227,7 +232,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||
// A connection to this device already exists, do not connect twice.
|
||||
NIMBLE_LOGE(LOG_TAG, "Already connected to device; addr=%s",
|
||||
std::string(m_peerAddress).c_str());
|
||||
return false;
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
// Already attemting to connect to this device, cancel the previous
|
||||
|
@ -235,17 +240,22 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||
NIMBLE_LOGE(LOG_TAG, "Already attempting to connect to %s - cancelling",
|
||||
std::string(m_peerAddress).c_str());
|
||||
ble_gap_conn_cancel();
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to connect to %s, rc=%d; %s",
|
||||
std::string(m_peerAddress).c_str(),
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (rc == BLE_HS_EBUSY);
|
||||
|
||||
if(rc != 0) {
|
||||
m_pTaskData = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait for the connect timeout time +1 second for the connection to complete
|
||||
if(ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(m_connectTimeout + 1000)) == pdFALSE) {
|
||||
m_pTaskData = nullptr;
|
||||
|
@ -255,7 +265,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||
disconnect();
|
||||
} else {
|
||||
// workaround; if the controller doesn't cancel the connection
|
||||
// at the timeout cancel it here.
|
||||
// at the timeout, cancel it here.
|
||||
NIMBLE_LOGE(LOG_TAG, "Connect timeout - cancelling");
|
||||
ble_gap_conn_cancel();
|
||||
}
|
||||
|
@ -269,7 +279,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||
// If the failure was not a result of a disconnection
|
||||
// make sure we disconnect now to avoid dangling connections
|
||||
if(isConnected()) {
|
||||
ble_gap_terminate(m_conn_id, BLE_ERR_REM_USER_CONN_TERM);
|
||||
disconnect();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
|
@ -325,26 +335,35 @@ bool NimBLEClient::secureConnection() {
|
|||
*/
|
||||
int NimBLEClient::disconnect(uint8_t reason) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> disconnect()");
|
||||
|
||||
int rc = 0;
|
||||
if(isConnected()) {
|
||||
rc = ble_gap_terminate(m_conn_id, reason);
|
||||
if (rc == 0) {
|
||||
ble_addr_t peerAddr_t;
|
||||
memcpy(&peerAddr_t.val, m_peerAddress.getNative(),6);
|
||||
peerAddr_t.type = m_peerAddress.getType();
|
||||
// If the timer was already started, ignore this call.
|
||||
if(ble_npl_callout_is_active(&m_dcTimer)) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Already disconnecting, timer started");
|
||||
return BLE_HS_EALREADY;
|
||||
}
|
||||
|
||||
// Set the disconnect timeout to the supervison timeout time + 1 second
|
||||
// In case the event triggers shortly after the supervision timeout.
|
||||
// We don't want to prematurely reset the host.
|
||||
ble_gap_conn_desc desc;
|
||||
if(ble_gap_conn_find_by_addr(&peerAddr_t, &desc) == 0){
|
||||
if(ble_gap_conn_find(m_conn_id, &desc) != 0){
|
||||
NIMBLE_LOGI(LOG_TAG, "Connection ID not found");
|
||||
return BLE_HS_EALREADY;
|
||||
}
|
||||
|
||||
// We use a timer to detect a controller error in the event that it does
|
||||
// not inform the stack when disconnection is complete.
|
||||
// This is a common error in certain esp-idf versions.
|
||||
// The disconnect timeout time is the supervison timeout time + 1 second.
|
||||
// In the case that the event happenss shortly after the supervision timeout
|
||||
// we don't want to prematurely reset the host.
|
||||
ble_npl_time_t ticks;
|
||||
ble_npl_time_ms_to_ticks((desc.supervision_timeout + 100) * 10, &ticks);
|
||||
ble_npl_callout_reset(&m_dcTimer, ticks);
|
||||
NIMBLE_LOGD(LOG_TAG, "DC TIMEOUT = %dms", (desc.supervision_timeout + 100) * 10);
|
||||
|
||||
rc = ble_gap_terminate(m_conn_id, reason);
|
||||
if (rc != 0) {
|
||||
if(rc != BLE_HS_EALREADY) {
|
||||
ble_npl_callout_stop(&m_dcTimer);
|
||||
}
|
||||
} else if (rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
|
@ -359,12 +378,12 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
|||
|
||||
/**
|
||||
* @brief Set the connection paramaters to use when connecting to a server.
|
||||
* @param [in] minInterval minimum connection interval in 0.625ms units.
|
||||
* @param [in] maxInterval maximum connection interval in 0.625ms units.
|
||||
* @param [in] latency number of packets allowed to skip (extends max interval)
|
||||
* @param [in] timeout the timeout time in 10ms units before disconnecting
|
||||
* @param [in] scanInterval the scan interval to use when attempting to connect in 0.625ms units.
|
||||
* @param [in] scanWindow the scan window to use when attempting to connect in 0.625ms units.
|
||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||
* @param [in] maxInterval The maximum connection interval in 1.25ms units.
|
||||
* @param [in] latency The number of packets allowed to skip (extends max interval).
|
||||
* @param [in] timeout The timeout time in 10ms units before disconnecting.
|
||||
* @param [in] scanInterval The scan interval to use when attempting to connect in 0.625ms units.
|
||||
* @param [in] scanWindow The scan window to use when attempting to connect in 0.625ms units.
|
||||
*/
|
||||
void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout,
|
||||
|
@ -391,10 +410,10 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
|
|||
/**
|
||||
* @brief Update the connection parameters:
|
||||
* * Can only be used after a connection has been established.
|
||||
* @param [in] minInterval minimum connection interval in 0.625ms units.
|
||||
* @param [in] maxInterval maximum connection interval in 0.625ms units.
|
||||
* @param [in] latency number of packets allowed to skip (extends max interval)
|
||||
* @param [in] timeout the timeout time in 10ms units before disconnecting
|
||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||
* @param [in] maxInterval The maximum connection interval in 1.25ms units.
|
||||
* @param [in] latency The number of packets allowed to skip (extends max interval).
|
||||
* @param [in] timeout The timeout time in 10ms units before disconnecting.
|
||||
*/
|
||||
void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout)
|
||||
|
@ -797,14 +816,15 @@ uint16_t NimBLEClient::getMTU() {
|
|||
break;
|
||||
}
|
||||
|
||||
client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||
|
||||
// Stop the disconnect timer since we are now disconnected.
|
||||
ble_npl_callout_stop(&client->m_dcTimer);
|
||||
|
||||
// Remove the device from ignore list so we will scan it again
|
||||
NimBLEDevice::removeIgnored(client->m_peerAddress);
|
||||
|
||||
// No longer connected, clear the connection ID.
|
||||
client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||
|
||||
// If we received a connected event but did not get established (no PDU)
|
||||
// then a disconnect event will be sent but we should not send it to the
|
||||
// app for processing. Instead we will ensure the task is released
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#include "NimBLEHIDDevice.h"
|
||||
#include "NimBLE2904.h"
|
||||
|
||||
/**
|
||||
* @brief Construct a default NimBLEHIDDevice object.
|
||||
* @param [in] server A pointer to the server instance this HID Device will use.
|
||||
*/
|
||||
NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) {
|
||||
/*
|
||||
* Here we create mandatory services described in bluetooth specification
|
||||
|
@ -61,15 +65,18 @@ NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) {
|
|||
NimBLEHIDDevice::~NimBLEHIDDevice() {
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Set the report map data formatting information.
|
||||
* @param [in] map A pointer to an array with the values to set.
|
||||
* @param [in] size The number of values in the array.
|
||||
*/
|
||||
void NimBLEHIDDevice::reportMap(uint8_t* map, uint16_t size) {
|
||||
m_reportMapCharacteristic->setValue(map, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief This function suppose to be called at the end, when we have created all characteristics we need to build HID service
|
||||
/**
|
||||
* @brief Start the HID device services.\n
|
||||
* This function called when all the services have been created.
|
||||
*/
|
||||
void NimBLEHIDDevice::startServices() {
|
||||
m_deviceInfoService->start();
|
||||
|
@ -77,41 +84,47 @@ void NimBLEHIDDevice::startServices() {
|
|||
m_batteryService->start();
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Create manufacturer characteristic (this characteristic is optional)
|
||||
/**
|
||||
* @brief Create a manufacturer characteristic (this characteristic is optional).
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::manufacturer() {
|
||||
m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a29, NIMBLE_PROPERTY::READ);
|
||||
return m_manufacturerCharacteristic;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief Set manufacturer name
|
||||
* @param [in] name manufacturer name
|
||||
* @param [in] name The manufacturer name of this HID device.
|
||||
*/
|
||||
void NimBLEHIDDevice::manufacturer(std::string name) {
|
||||
m_manufacturerCharacteristic->setValue(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Sets the Plug n Play characterisc value.
|
||||
* @param [in] sig The vendor ID source number.
|
||||
* @param [in[ vid The vendor ID number.
|
||||
* @param [in] pid The product ID number.
|
||||
* @param [in] version The produce version number.
|
||||
*/
|
||||
void NimBLEHIDDevice::pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version) {
|
||||
uint8_t pnp[] = { sig, (uint8_t) (vid >> 8), (uint8_t) vid, (uint8_t) (pid >> 8), (uint8_t) pid, (uint8_t) (version >> 8), (uint8_t) version };
|
||||
m_pnpCharacteristic->setValue(pnp, sizeof(pnp));
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Sets the HID Information characteristic value.
|
||||
* @param [in] country The country code for the device.
|
||||
* @param [in] flags The HID Class Specification release number to use.
|
||||
*/
|
||||
void NimBLEHIDDevice::hidInfo(uint8_t country, uint8_t flags) {
|
||||
uint8_t info[] = { 0x11, 0x1, country, flags };
|
||||
m_hidInfoCharacteristic->setValue(info, sizeof(info));
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Create input report characteristic that need to be saved as new characteristic object so can be further used
|
||||
* @param [in] reportID input report ID, the same as in report map for input object related to created characteristic
|
||||
/**
|
||||
* @brief Create input report characteristic
|
||||
* @param [in] reportID input report ID, the same as in report map for input object related to the characteristic
|
||||
* @return pointer to new input report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||
|
@ -124,9 +137,9 @@ NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
|||
return inputReportCharacteristic;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Create output report characteristic that need to be saved as new characteristic object so can be further used
|
||||
* @param [in] reportID Output report ID, the same as in report map for output object related to created characteristic
|
||||
/**
|
||||
* @brief Create output report characteristic
|
||||
* @param [in] reportID Output report ID, the same as in report map for output object related to the characteristic
|
||||
* @return Pointer to new output report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
||||
|
@ -139,9 +152,9 @@ NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
|||
return outputReportCharacteristic;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Create feature report characteristic that need to be saved as new characteristic object so can be further used
|
||||
* @param [in] reportID Feature report ID, the same as in report map for feature object related to created characteristic
|
||||
/**
|
||||
* @brief Create feature report characteristic.
|
||||
* @param [in] reportID Feature report ID, the same as in report map for feature object related to the characteristic
|
||||
* @return Pointer to new feature report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
||||
|
@ -154,34 +167,38 @@ NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
|||
return featureReportCharacteristic;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Creates a keyboard boot input report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::bootInput() {
|
||||
return m_hidService->createCharacteristic((uint16_t) 0x2a22, NIMBLE_PROPERTY::NOTIFY);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Create a keyboard boot output report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::bootOutput() {
|
||||
return m_hidService->createCharacteristic((uint16_t) 0x2a32, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Returns a pointer to the HID control point characteristic.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::hidControl() {
|
||||
return m_hidControlCharacteristic;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Returns a pointer to the protocol mode characteristic.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::protocolMode() {
|
||||
return m_protocolModeCharacteristic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the battery level characteristic value.
|
||||
* @param [in] level The battery level value.
|
||||
*/
|
||||
void NimBLEHIDDevice::setBatteryLevel(uint8_t level) {
|
||||
m_batteryLevelCharacteristic->setValue(&level, 1);
|
||||
}
|
||||
|
@ -208,22 +225,23 @@ BLECharacteristic* BLEHIDDevice::hidInfo() {
|
|||
return m_hidInfoCharacteristic;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* @brief
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the device information service.
|
||||
*/
|
||||
NimBLEService* NimBLEHIDDevice::deviceInfo() {
|
||||
return m_deviceInfoService;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief Returns a pointer to the HID service.
|
||||
*/
|
||||
NimBLEService* NimBLEHIDDevice::hidService() {
|
||||
return m_hidService;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
/**
|
||||
* @brief @brief Returns a pointer to the battery service.
|
||||
*/
|
||||
NimBLEService* NimBLEHIDDevice::batteryService() {
|
||||
return m_batteryService;
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#define HID_DIGITAL_PEN 0x03C7
|
||||
#define HID_BARCODE 0x03C8
|
||||
|
||||
|
||||
/**
|
||||
* @brief A model of a %BLE Human Interface Device.
|
||||
*/
|
||||
class NimBLEHIDDevice {
|
||||
public:
|
||||
NimBLEHIDDevice(NimBLEServer*);
|
||||
|
|
|
@ -621,7 +621,13 @@ uint16_t NimBLEServer::getPeerMTU(uint16_t conn_id) {
|
|||
|
||||
|
||||
/**
|
||||
* Update connection parameters can be called only after connection has been established
|
||||
* @brief Request an Update the connection parameters:
|
||||
* * Can only be used after a connection has been established.
|
||||
* @param [in] conn_handle The connection handle of the peer to send the request to.
|
||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||
* @param [in] maxInterval The maximum connection interval in 1.25ms units.
|
||||
* @param [in] latency The number of packets allowed to skip (extends max interval).
|
||||
* @param [in] timeout The timeout time in 10ms units before disconnecting.
|
||||
*/
|
||||
void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
||||
uint16_t minInterval, uint16_t maxInterval,
|
||||
|
|
|
@ -320,7 +320,7 @@ static void BLEGenNotifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, ui
|
|||
void BLEPostAdvert(ble_advertisment_t *Advertisment);
|
||||
static void BLEPostMQTTSeenDevices(int type);
|
||||
|
||||
static void BLEShow(bool json);
|
||||
static void BLEShowStats();
|
||||
static void BLEPostMQTT(bool json);
|
||||
static void BLEStartOperationTask();
|
||||
|
||||
|
@ -390,7 +390,7 @@ uint8_t BLEAliasListTrigger = 0;
|
|||
// triggers send for ALL operations known about
|
||||
uint8_t BLEPostMQTTTrigger = 0;
|
||||
int BLEMaxAge = 60*10; // 10 minutes
|
||||
int BLEAddressFilter = 3;
|
||||
int BLEAddressFilter = 0;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -2181,6 +2181,7 @@ static void BLEEverySecond(bool restart){
|
|||
|
||||
if (BLEPublishDevices){
|
||||
BLEPostMQTTSeenDevices(BLEPublishDevices);
|
||||
BLEShowStats();
|
||||
BLEPublishDevices = 0;
|
||||
}
|
||||
|
||||
|
@ -3209,25 +3210,14 @@ static void mainThreadOpCallbacks() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void BLEShow(bool json)
|
||||
{
|
||||
if (json){
|
||||
#ifdef BLE_ESP32_DEBUG
|
||||
if (BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO,PSTR("BLE: show json %d"),json);
|
||||
#endif
|
||||
static void BLEShowStats(){
|
||||
uint32_t totalCount = BLEAdvertisment.totalCount;
|
||||
uint32_t deviceCount = seenDevices.size();
|
||||
ResponseTime_P(PSTR(""));
|
||||
ResponseAppend_P(PSTR(",\"BLE\":{\"scans\":%u,\"adverts\":%u,\"devices\":%u,\"resets\":%u}}"), BLEScanCount, totalCount, deviceCount, BLEResets);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR("BLE"), 0);
|
||||
}
|
||||
|
||||
ResponseAppend_P(PSTR(",\"BLE\":{\"scans\":%u,\"adverts\":%u,\"devices\":%u,\"resets\":%u}"), BLEScanCount, totalCount, deviceCount, BLEResets);
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
else {
|
||||
//WSContentSend_PD(HTTP_MI32, i+1,stemp,MIBLEsensors.size());
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
}
|
||||
|
||||
/*void BLEAliasMqttList(){
|
||||
ResponseTime_P(PSTR(",\"BLEAlias\":["));
|
||||
|
@ -3495,7 +3485,6 @@ bool Xdrv52(uint8_t function)
|
|||
result = DecodeCommand(BLE_ESP32::kBLE_Commands, BLE_ESP32::BLE_Commands);
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
BLE_ESP32::BLEShow(1);
|
||||
break;
|
||||
|
||||
// next second, we will publish to our MQTT topic.
|
||||
|
@ -3510,10 +3499,6 @@ bool Xdrv52(uint8_t function)
|
|||
case FUNC_WEB_ADD_HANDLER:
|
||||
WebServer_on(PSTR("/" WEB_HANDLE_BLE), BLE_ESP32::HandleBleConfiguration);
|
||||
break;
|
||||
|
||||
case FUNC_WEB_SENSOR:
|
||||
BLE_ESP32::BLEShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -79,6 +79,7 @@ void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pD
|
|||
struct {
|
||||
uint16_t perPage = 4;
|
||||
uint8_t mqttCurrentSlot = 0;
|
||||
uint8_t mqttCurrentSingleSlot = 0;
|
||||
uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
||||
int secondsCounter = 0; // counts up in MI32EverySecond to period
|
||||
int secondsCounter2 = 0; // counts up in MI32EverySecond to period
|
||||
|
@ -255,6 +256,8 @@ struct mi_sensor_t{
|
|||
uint8_t type; //MI_Flora = 1; MI_MI-HT_V1=2; MI_LYWSD02=3; MI_LYWSD03=4; MI_CGG1=5; MI_CGD1=6
|
||||
uint8_t needkey; // tells http to display needkey message with link
|
||||
uint8_t lastCnt; //device generated counter of the packet
|
||||
uint8_t nextDiscoveryData; // used to lkimit discovery to one MQTT per sec
|
||||
|
||||
uint8_t shallSendMQTT;
|
||||
uint8_t MAC[6];
|
||||
union {
|
||||
|
@ -1880,6 +1883,9 @@ void MI32EverySecond(bool restart){
|
|||
|
||||
MI32ShowSomeSensors();
|
||||
|
||||
MI32DiscoveryOneMISensor();
|
||||
MI32ShowOneMISensor();
|
||||
|
||||
// read a battery if
|
||||
// MI32.batteryreader.slot < filled and !MI32.batteryreader.active
|
||||
readOneBat();
|
||||
|
@ -1906,10 +1912,12 @@ void MI32EverySecond(bool restart){
|
|||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Kick off tele sending"));
|
||||
MI32.mqttCurrentSlot = 0;
|
||||
MI32.secondsCounter2 = 0;
|
||||
MI32.mqttCurrentSingleSlot = 0;
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Hit tele time, restarted but not finished last - lost from slot %d")+MI32.mqttCurrentSlot);
|
||||
MI32.mqttCurrentSlot = 0;
|
||||
MI32.secondsCounter2 = 0;
|
||||
MI32.mqttCurrentSingleSlot = 0;
|
||||
}
|
||||
}
|
||||
MI32.secondsCounter2++;
|
||||
|
@ -2302,15 +2310,18 @@ void MI32TimeoutSensors(){
|
|||
|
||||
|
||||
// this assumes that we're adding to a ResponseTime_P
|
||||
void MI32GetOneSensorJson(int slot){
|
||||
void MI32GetOneSensorJson(int slot, int hidename){
|
||||
mi_sensor_t *p;
|
||||
p = &MIBLEsensors[slot];
|
||||
|
||||
ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":{"),
|
||||
// remove hyphen - make it difficult to configure HASS
|
||||
if (!hidename) {
|
||||
ResponseAppend_P(PSTR("\"%s%02x%02x%02x\":{"),
|
||||
kMI32DeviceType[p->type-1],
|
||||
p->MAC[3], p->MAC[4], p->MAC[5]);
|
||||
}
|
||||
|
||||
ResponseAppend_P(PSTR("\"MAC\":\"%02x%02x%02x%02x%02x%02x\""),
|
||||
ResponseAppend_P(PSTR("\"mac\":\"%02x%02x%02x%02x%02x%02x\""),
|
||||
p->MAC[0], p->MAC[1], p->MAC[2],
|
||||
p->MAC[3], p->MAC[4], p->MAC[5]);
|
||||
|
||||
|
@ -2449,7 +2460,9 @@ void MI32GetOneSensorJson(int slot){
|
|||
}
|
||||
if (MI32.option.showRSSI) ResponseAppend_P(PSTR(",\"RSSI\":%d"), p->RSSI);
|
||||
|
||||
if (!hidename) {
|
||||
ResponseAppend_P(PSTR("}"));
|
||||
}
|
||||
p->eventType.raw = 0;
|
||||
p->shallSendMQTT = 0;
|
||||
|
||||
|
@ -2486,7 +2499,8 @@ void MI32ShowSomeSensors(){
|
|||
ResponseTime_P(PSTR(""));
|
||||
int cnt = 0;
|
||||
for (; (MI32.mqttCurrentSlot < numsensors) && (cnt < 4); MI32.mqttCurrentSlot++, cnt++) {
|
||||
MI32GetOneSensorJson(MI32.mqttCurrentSlot);
|
||||
ResponseAppend_P(PSTR(","));
|
||||
MI32GetOneSensorJson(MI32.mqttCurrentSlot, 0);
|
||||
int mlen = strlen(TasmotaGlobal.mqtt_data);
|
||||
|
||||
// if we ran out of room, leave here.
|
||||
|
@ -2511,6 +2525,183 @@ void MI32ShowSomeSensors(){
|
|||
#endif //USE_HOME_ASSISTANT
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// starts a completely fresh MQTT message.
|
||||
// sends ONE sensor on a dedicated topic NOT related to this TAS
|
||||
// triggered by setting MI32.mqttCurrentSingleSlot = 0
|
||||
void MI32ShowOneMISensor(){
|
||||
// don't detect half-added ones here
|
||||
int numsensors = MIBLEsensors.size();
|
||||
if (MI32.mqttCurrentSingleSlot >= numsensors){
|
||||
// if we got to the end of the sensors, then don't send more
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if(Settings.flag.hass_discovery){
|
||||
|
||||
ResponseTime_P(PSTR(","));
|
||||
MI32GetOneSensorJson(MI32.mqttCurrentSingleSlot, 1);
|
||||
mi_sensor_t *p;
|
||||
p = &MIBLEsensors[MI32.mqttCurrentSingleSlot];
|
||||
|
||||
ResponseAppend_P(PSTR("}"));
|
||||
|
||||
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]);
|
||||
}
|
||||
char SensorTopic[60];
|
||||
sprintf(SensorTopic, "tele/tasmota_ble/%s",
|
||||
id);
|
||||
|
||||
MqttPublish(SensorTopic);
|
||||
//AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, TasmotaGlobal.mqtt_data);
|
||||
}
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
MI32.mqttCurrentSingleSlot++;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// starts a completely fresh MQTT message.
|
||||
// sends ONE sensor's worth of HA discovery msg
|
||||
#define MI_HA_DISCOVERY_TEMPLATE PSTR("{\"availability\":[],\"device\": \
|
||||
{\"identifiers\":[\"BLE%s\"],\
|
||||
\"name\":\"%s\",\
|
||||
\"manufacturer\":\"tas\",\
|
||||
\"model\":\"%s\",\
|
||||
\"via_device\":\"%s\"\
|
||||
}, \
|
||||
\"dev_cla\":\"%s\",\
|
||||
\"expire_after\":600,\
|
||||
\"json_attr_t\":\"%s\",\
|
||||
\"name\":\"%s_%s\",\
|
||||
\"state_topic\":\"%s\",\
|
||||
\"uniq_id\":\"%s_%s\",\
|
||||
\"unit_of_meas\":\"%s\",\
|
||||
\"val_tpl\":\"{{ value_json.%s }}\"}")
|
||||
void MI32DiscoveryOneMISensor(){
|
||||
// don't detect half-added ones here
|
||||
int numsensors = MIBLEsensors.size();
|
||||
if (MI32.mqttCurrentSingleSlot >= numsensors){
|
||||
// if we got to the end of the sensors, then don't send more
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if(Settings.flag.hass_discovery){
|
||||
mi_sensor_t *p;
|
||||
p = &MIBLEsensors[MI32.mqttCurrentSingleSlot];
|
||||
|
||||
|
||||
// careful - a missing comma causes a crash!!!!
|
||||
// because of the way we loop?
|
||||
const char *classes[] = {
|
||||
"temperature",
|
||||
"Temperature",
|
||||
"°C",
|
||||
"humidity",
|
||||
"Humidity",
|
||||
"%",
|
||||
"temperature",
|
||||
"DewPoint",
|
||||
"°C",
|
||||
"battery",
|
||||
"Battery",
|
||||
"%",
|
||||
"signal_strength",
|
||||
"RSSI",
|
||||
"dB"
|
||||
};
|
||||
|
||||
int datacount = (sizeof(classes)/sizeof(*classes))/3;
|
||||
|
||||
if (p->nextDiscoveryData >= datacount){
|
||||
p->nextDiscoveryData = 0;
|
||||
}
|
||||
|
||||
//int i = p->nextDiscoveryData*3;
|
||||
for (int i = 0; i < datacount*3; i += 3){
|
||||
if (!classes[i] || !classes[i+1] || !classes[i+2]){
|
||||
return;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
char SensorTopic[60];
|
||||
sprintf(SensorTopic, "tele/tasmota_ble/%s",
|
||||
id);
|
||||
|
||||
|
||||
ResponseClear();
|
||||
|
||||
/*
|
||||
{"availability":[],"device":{"identifiers":["TasmotaBLEa4c1387fc1e1"],"manufacturer":"simon","model":"someBLEsensor","name":"TASBLEa4c1387fc1e1","sw_version":"0.0.0"},"dev_cla":"temperature","json_attr_t":"tele/tasmota_esp32/SENSOR","name":"TASLYWSD037fc1e1Temp","state_topic":"tele/tasmota_esp32/SENSOR","uniq_id":"Tasmotaa4c1387fc1e1temp","unit_of_meas":"°C","val_tpl":"{{ value_json.LYWSD037fc1e1.Temperature }}"}
|
||||
{"availability":[],"device":{"identifiers":["TasmotaBLEa4c1387fc1e1"],
|
||||
"name":"TASBLEa4c1387fc1e1"},"dev_cla":"temperature",
|
||||
"json_attr_t":"tele/tasmota_esp32/SENSOR",
|
||||
"name":"TASLYWSD037fc1e1Temp","state_topic": "tele/tasmota_esp32/SENSOR",
|
||||
"uniq_id":"Tasmotaa4c1387fc1e1temp","unit_of_meas":"°C",
|
||||
"val_tpl":"{{ value_json.LYWSD037fc1e1.Temperature }}"}
|
||||
*/
|
||||
|
||||
ResponseAppend_P(MI_HA_DISCOVERY_TEMPLATE,
|
||||
//"{\"identifiers\":[\"BLE%s\"],"
|
||||
id,
|
||||
//"\"name\":\"%s\"},"
|
||||
id,
|
||||
//\"model\":\"%s\",
|
||||
kMI32DeviceType[p->type-1],
|
||||
//\"via_device\":\"%s\"
|
||||
NetworkHostname(),
|
||||
//"\"dev_cla\":\"%s\","
|
||||
classes[i],
|
||||
//"\"json_attr_t\":\"%s\"," - the topic the sensor publishes on
|
||||
SensorTopic,
|
||||
//"\"name\":\"%s_%s\"," - the name of this DATA
|
||||
id, classes[i+1],
|
||||
//"\"state_topic\":\"%s\"," - the topic the sensor publishes on?
|
||||
SensorTopic,
|
||||
//"\"uniq_id\":\"%s_%s\"," - unique for this data,
|
||||
id, classes[i+1],
|
||||
//"\"unit_of_meas\":\"%s\"," - the measure of this type of data
|
||||
classes[i+2],
|
||||
//"\"val_tpl\":\"{{ value_json.%s }}") // e.g. Temperature
|
||||
classes[i+1]
|
||||
//
|
||||
);
|
||||
|
||||
char DiscoveryTopic[80];
|
||||
sprintf(DiscoveryTopic, "homeassistant/sensor/%s/%s/config",
|
||||
id, classes[i+1]);
|
||||
|
||||
MqttPublish(DiscoveryTopic);
|
||||
p->nextDiscoveryData++;
|
||||
//vTaskDelay(100/ portTICK_PERIOD_MS);
|
||||
}
|
||||
} // end if hass discovery
|
||||
//AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, TasmotaGlobal.mqtt_data);
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// starts a completely fresh MQTT message.
|
||||
// sends up to 4 sensors pe5r msg
|
||||
|
@ -2535,7 +2726,8 @@ void MI32ShowTriggeredSensors(){
|
|||
if(p->shallSendMQTT==0) continue;
|
||||
|
||||
cnt++;
|
||||
MI32GetOneSensorJson(sensor);
|
||||
ResponseAppend_P(PSTR(","));
|
||||
MI32GetOneSensorJson(sensor, 0);
|
||||
int mlen = strlen(TasmotaGlobal.mqtt_data);
|
||||
|
||||
// if we ran out of room, leave here.
|
||||
|
|
Loading…
Reference in New Issue