Add BLE pairing to support newer EQ3 TRV firmware (#25008)

* Add BLE pairing to support newer EQ3 TRV firmware

* Verify fwrite result when saving BLE data
This commit is contained in:
SteWers
2026-09-07 11:00:02 +02:00
committed by GitHub
parent a245189808
commit da3bbf3658
2 changed files with 190 additions and 172 deletions
@@ -230,6 +230,7 @@ namespace BLE_ESP32 {
#define BLE_ESP32_MAXNAMELEN 32
#define BLE_ESP32_MAXALIASLEN 32
#define BLE_STORE_DIR "/.blestore"
#define MAX_BLE_DATA_LEN 100
struct generic_sensor_t {
@@ -387,6 +388,7 @@ static void BLEStartOperationTask();
// these are only run from the run task
static void BLETaskRunCurrentOperation(BLE_ESP32::generic_sensor_t** pCurrentOperation, NimBLEClient **ppClient);
static void BLETaskRunTaskDoneOperation(BLE_ESP32::generic_sensor_t** op, NimBLEClient **ppClient);
static void BLEDoPairing(NimBLEClient **ppClient);
int BLETaskStartScan(int time);
@@ -508,7 +510,7 @@ int minRSSI = -100;
#define D_CMND_BLE "BLE"
const char kBLE_Commands[] PROGMEM = D_CMND_BLE "|"
"Period|Adv|Op|Mode|Details|Scan|Alias|Name|Debug|Devices|MaxAge|AddrFilter|EnableUnsaved|FilterNames|MinRssiLevel";
"Period|Adv|Op|Mode|Details|Scan|Alias|Name|Debug|Devices|MaxAge|AddrFilter|EnableUnsaved|FilterNames|MinRssiLevel|Pair";
static void CmndBLEPeriod(void);
static void CmndBLEAdv(void);
@@ -525,6 +527,7 @@ static void CmndBLEAddrFilter(void);
static void CmndBLEEnableUnsaved(void);
static void CmndBleFilterNames(void);
static void CmndSetMinRSSI(void);
static void CmndPair(void);
void (*const BLE_Commands[])(void) PROGMEM = {
&BLE_ESP32::CmndBLEPeriod,
@@ -541,7 +544,8 @@ void (*const BLE_Commands[])(void) PROGMEM = {
&BLE_ESP32::CmndBLEAddrFilter,
&BLE_ESP32::CmndBLEEnableUnsaved,
&BLE_ESP32::CmndBleFilterNames,
&BLE_ESP32::CmndSetMinRSSI
&BLE_ESP32::CmndSetMinRSSI,
&BLE_ESP32::CmndPair
};
const char *successStates[] PROGMEM = {
@@ -614,6 +618,12 @@ enum {
//BLE_ADV_ALL = 2, // driver sends every advert with full data to MQTT
} BLEADVERTMODE;
enum BLE_PAIRING_STATES : uint8_t {
PAIRING_NONE = 0,
PAIRING_REQUESTED,
PAIRING_CONNECTED,
PAIRING_KEY_SENT
};
uint8_t BLEMode = BLEModeRegularScan;
//uint8_t BLEMode = BLEModeScanByCommand;
@@ -621,6 +631,10 @@ uint8_t BLETriggerScan = 0;
uint8_t BLEAdvertMode = BLE_ADV_TELE;
uint8_t BLEdeviceLimitReached = 0;
uint8_t pairingState = PAIRING_NONE;
uint32_t pairingPIN = 0;
NimBLEAddress pairingAddress;
uint8_t BLEStop = 0;
uint64_t BLEStopAt = 0;
@@ -638,6 +652,64 @@ const char *BLE_RESTART_BLE_REASON_CONN_LIMIT = PSTR("connect failed with connec
const char *BLE_RESTART_BLE_REASON_CONN_EXISTS = PSTR("connect failed with connection exists");
const char *BLERestartBLEReason = nullptr;
// Global native hook: Filepath
static void ble_get_bond_filepath(const uint8_t* val, int type, char* out_buf, size_t buf_len) {
// Format: BLE_STORE_DIR/AABBCCDDEEFF.TYPE
snprintf(out_buf, buf_len, BLE_STORE_DIR "/%02X%02X%02X%02X%02X%02X.%03d",
val[5], val[4], val[3], val[2], val[1], val[0], type);
}
// Global native hook: Read stored BLE data
int ble_local_store_read(int type, const union ble_store_key* key, union ble_store_value* value) {
if (type != BLE_STORE_OBJ_TYPE_PEER_SEC) return BLE_HS_ENOENT; // Only that is needed at the moment
char filepath[sizeof(BLE_STORE_DIR) + 20];
// Pass the raw 6-byte MAC array pointer from the internal union struct
ble_get_bond_filepath(key->sec.peer_addr.val, type, filepath, sizeof(filepath));
FILE* file = fopen(filepath, "r");
if (file) {
if (fread(&value->sec, 1, sizeof(ble_store_value_sec), file) == sizeof(ble_store_value_sec)) {
fclose(file);
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: BLE data loaded from %s", filepath);
return 0; // 0 = Success for the NimBLE controller
}
fclose(file);
}
return BLE_HS_ENOENT; // Key not found, falls back to normal pairing workflow
}
// Global native hook: Write BLE data
int ble_local_store_write(int type, const union ble_store_value* value) {
if (type != BLE_STORE_OBJ_TYPE_PEER_SEC) return BLE_HS_ENOMEM; // Only that is needed at the moment
char filepath[sizeof(BLE_STORE_DIR) + 20];
// Pass the raw 6-byte MAC array pointer from the internal union struct
ble_get_bond_filepath(value->sec.peer_addr.val, type, filepath, sizeof(filepath));
FILE* file = fopen(filepath, "w");
if (file) {
size_t written = fwrite(&value->sec, 1, sizeof(ble_store_value_sec), file);
fclose(file);
if (written == sizeof(ble_store_value_sec)) {
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: BLE data saved in %s", filepath);
return 0; // 0 = Success
}
}
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: Save BLE data failed");
return BLE_HS_ENOMEM; // Write failed
}
// Global API: Delete dynamic storage file
void ble_local_store_delete(const uint8_t* mac_addr) {
if (!mac_addr) return;
char filepath[sizeof(BLE_STORE_DIR) + 20];
// Only delete files of BLE_STORE_OBJ_TYPE_PEER_SEC as no others are needed at the moment
ble_get_bond_filepath(mac_addr, BLE_STORE_OBJ_TYPE_PEER_SEC, filepath, sizeof(filepath));
unlink(filepath);
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: Deleted BLE data file %s", filepath);
}
/*********************************************************************************************\
* log of all devices present
@@ -1331,17 +1403,17 @@ void postAdvertismentDetails(){
class BLESensorCallback : public NimBLEClientCallbacks {
void onConnect(NimBLEClient* pClient) {
#ifdef BLE_ESP32_DEBUG
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], PSTR("BLE: onConnect %s"), ((std::string)pClient->getPeerAddress()).c_str());
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: onConnect %s", pClient->getPeerAddress().toString().c_str());
#endif
}
void onDisconnect(NimBLEClient* pClient, int reason) {
#ifdef BLE_ESP32_DEBUG
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], PSTR("BLE: onDisconnect %s"), ((std::string)pClient->getPeerAddress()).c_str());
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: onDisconnect %s, reason: 0x%04X", pClient->getPeerAddress().toString().c_str(), reason);
#endif
}
bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) {
#ifdef BLE_ESP32_DEBUG
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], PSTR("BLE: onConnParamsUpdateRequest %s"), ((std::string)pClient->getPeerAddress()).c_str());
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: onConnParamsUpdateRequest %s", pClient->getPeerAddress().toString().c_str());
#endif
// if(params->itvl_min < 24) { /** 1.25ms units */
@@ -1371,6 +1443,33 @@ class BLESensorCallback : public NimBLEClientCallbacks {
return false;
}
void onPassKeyEntry(NimBLEConnInfo& connInfo) override {
#ifdef BLE_ESP32_DEBUG
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: onPassKeyEntry %s", connInfo.getAddress().toString().c_str());
#endif
if (pairingState == PAIRING_CONNECTED && connInfo.getAddress() == pairingAddress) {
NimBLEDevice::injectPassKey(connInfo, pairingPIN);
AddLog(LOG_LEVEL_INFO, "BLE: PIN %06u sent to %s", pairingPIN, connInfo.getAddress().toString().c_str());
pairingState = PAIRING_KEY_SENT;
}
}
void onAuthenticationComplete(NimBLEConnInfo& connInfo) override {
#ifdef BLE_ESP32_DEBUG
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: onAuthenticationComplete %s", connInfo.getAddress().toString().c_str());
#endif
NimBLEClient* pActiveClient = NimBLEDevice::getClientByPeerAddress(connInfo.getAddress());
if (pActiveClient && pActiveClient->isConnected()) {
if (pairingState == PAIRING_KEY_SENT && connInfo.getAddress() == pairingAddress) {
if (connInfo.isEncrypted()) {
AddLog(LOG_LEVEL_INFO, "BLE: Pairing %s successful.", connInfo.getAddress().toString().c_str());
} else {
AddLog(LOG_LEVEL_ERROR, "BLE: Pairing %s failed!", connInfo.getAddress().toString().c_str());
}
pActiveClient->disconnect();
pairingState = PAIRING_NONE;
}
}
}
};
static BLESensorCallback clientCB;
@@ -1742,6 +1841,17 @@ static void BLETaskStopStartNimBLE(NimBLEClient **ppClient, bool start = true){
AddLog(LOG_LEVEL_INFO, PSTR("BLE: BLETask: Starting NimBLE"));
NimBLEDevice::init("BLE_ESP32");
// --- NEUTRAL ADVANCED STORAGE ROUTING LAYER ---
// Create the physical folder BLE_STORE_DIR in the flash memory
mkdir(BLE_STORE_DIR, 0777);
// Hook the dynamic directory filesystem into the native Apache MyNewT config
ble_hs_cfg.store_read_cb = ble_local_store_read;
ble_hs_cfg.store_write_cb = ble_local_store_write;
// Set default global security capabilities for the Bluetooth stack
NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC);
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY);
*ppClient = NimBLEDevice::createClient();
(*ppClient)->setClientCallbacks(&clientCB, false);
/** Set initial connection parameters: These settings are 15ms interval, 0 latency, 120ms timout.
@@ -1808,6 +1918,33 @@ int BLETaskStartScan(int time){
return 0;
}
static void BLEDoPairing(NimBLEClient **ppClient) {
if (pairingState != PAIRING_REQUESTED) return;
AddLog(BLELogLevel[LOG_LEVEL_DEBUG], "BLE: Pairing requested. PIN: %u", pairingPIN);
NimBLEClient *pClient = *ppClient;
BLERunningScan = 0;
// Delete old bonding
ble_local_store_delete(pairingAddress.getBase()->val);
NimBLEDevice::deleteBond(pairingAddress); // Must be executed after ble_local_store_delete
if (pClient->connect(pairingAddress, false, false, false)) {
AddLog(LOG_LEVEL_DEBUG, "BLE: Connected for pairing. Starting crypto handshake...");
pairingState = PAIRING_CONNECTED;
// secureConnection will rise onPassKeyEntry for transmitting the PairingPIN.
// Abort the pairing prozess, when sending fails.
if (!pClient->secureConnection()) {
pClient->disconnect();
pairingState = PAIRING_NONE;
}
} else {
AddLog(LOG_LEVEL_ERROR, "BLE: Connect for pairing failed.");
pairingState = PAIRING_NONE;
}
}
// this runs one operation
// if the passed pointer is empty, it tries to get a next one.
static void BLETaskRunCurrentOperation(BLE_ESP32::generic_sensor_t** pCurrentOperation, NimBLEClient **ppClient){
@@ -2243,6 +2380,8 @@ static void BLEOperationTask(void *pvParameters){
BLELastLoopTime = esp_timer_get_time();
BLELoopCount++;
BLE_ESP32::BLEDoPairing(&pClient);
BLE_ESP32::BLETaskRunCurrentOperation(&currentOperation, &pClient);
// start a scan if possible
@@ -3074,6 +3213,32 @@ void CmndBLEName(void) {
return;
}
void CmndPair(void) {
// "BLEPair <MAC or Alias> <PairingPIN>"
if (!XdrvMailbox.data_len) {
ResponseCmndError();
return;
}
// Find the separator space between <MACorAlias> and <PairingPIN> to replace it with '\0'
char* space_ptr = strchr(XdrvMailbox.data, ' ');
if (!space_ptr) {
ResponseCmndError();
return;
}
*space_ptr = '\0';
pairingPIN = atoi(space_ptr + 1);
uint8_t addrbin[7];
if (!getAddr(addrbin, XdrvMailbox.data)) {
ResponseCmndError();
return;
}
pairingAddress = NimBLEAddress(addrbin, addrbin[6]);
pairingState = PAIRING_REQUESTED;
Response_P("{\"%s\":\"started\",\"MAC\":\"%s\",\"PIN\":\"%06u\"}", XdrvMailbox.command, pairingAddress.toString().c_str(), pairingPIN);
};
//////////////////////////////////////////////////////////////////////////
@@ -299,7 +299,6 @@ struct eq3_device_t {
uint8_t ValvePos; // 1 Byte
uint8_t Mode; // 1 Byte
uint8_t lastStatusLen; // 1 Byte
bool pairing; // 1 Byte
bool Battery; // 1 Byte
uint8_t addr[6]; // 6 Bytes
uint8_t lastStatus[16]; // 16 Bytes
@@ -312,12 +311,8 @@ int retries = 0;
// allow 240s before timeout of sa device - based on that we restart BLE if we don't see adverts for 120s
#define EQ3_TIMEOUT 240L
uint8_t pairingaddr[6] = {};
char pairingserial[20] = {};
bool pairing = false;
#define EQ3_NUM_DEVICESLOTS 16
eq3_device_t EQ3Devices[EQ3_NUM_DEVICESLOTS];
eq3_device_t EQ3Devices[EQ3_NUM_DEVICESLOTS] = {};
SemaphoreHandle_t EQ3mutex = nullptr;
uint16_t EQ3Period = 300;
@@ -655,7 +650,7 @@ int EQ3GenericOpCompleteFn(BLE_ESP32::generic_sensor_t* op) {
retries--;
if (EQ3Operation(addrev, op->dataToWrite, op->writelen, (int)context)) {
AddLog(LOG_LEVEL_INFO, "EQ3: %s: Operation 1/%u \"%s\" failed - retries left: %d/%d - State: %d", addrStr(addrev), opQueue.size(), IdxToTrvCmd(context & 0x7f), retries, EQ3Retries, op->state);
AddLog(LOG_LEVEL_INFO, "EQ3: %s: Operation 1/%u \"%s\" failed - retries left: %d/%d - State: %s (%d)", addrStr(addrev), opQueue.size(), IdxToTrvCmd(context & 0x7f), retries, EQ3Retries, BLE_ESP32::getStateString(op->state), op->state);
opInProgress = true;
return 0;
}
@@ -663,7 +658,7 @@ int EQ3GenericOpCompleteFn(BLE_ESP32::generic_sensor_t* op) {
}
if (is_failed) {
AddLog(LOG_LEVEL_ERROR, "EQ3: %s: Operation 1/%u \"%s\" final fail - State: %d", addrStr(addrev), opQueue.size(), IdxToTrvCmd(context & 0x7f), op->state);
AddLog(LOG_LEVEL_ERROR, "EQ3: %s: Operation 1/%u \"%s\" final fail - State: %s (%d)", addrStr(addrev), opQueue.size(), IdxToTrvCmd(context & 0x7f), BLE_ESP32::getStateString(op->state), op->state);
} else {
AddLog(LOG_LEVEL_DEBUG, "EQ3: %s: Operation 1/%u \"%s\" done", addrStr(addrev), opQueue.size(), IdxToTrvCmd(context & 0x7f));
}
@@ -682,130 +677,13 @@ int EQ3GenericOpCompleteFn(BLE_ESP32::generic_sensor_t* op) {
}
/*********************************************************************************************\
* Functons actualy called from within the BLE task
* Functions actualy called from within the BLE task
\*********************************************************************************************/
int ispairing2(const uint8_t* payload, int len, char* name, int nameLen, char* serial, int serialLen) {
while (len) {
int l = *payload;
//BLE_ESP32::dump(temp, 40, payload, l+1);
//AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s"), temp);
payload++;
len--;
if (len < l) {
//AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: part len er %d<%d"),len, l);
return 0;
}
switch (*payload) {
case 0xff: {// parse the EQ3 advert payload looking for nnFF01ssssssss
payload++;
len--;
l--;
if (*payload == 1) {
payload++;
len--;
l--;
//char serialstr[20];
//strncpy(serialstr, (const char*)payload, l);
//AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: adv part FF01 detected %s"), serialstr);
// we don;t use these, but that's what they seem to be....
strncpy(serial, (const char*)payload, tmin(l, serialLen));
serial[serialLen - 1] = 0;
payload += l;
len -= l;
return 1;
} else {
payload += l;
len -= l;
}
} break;
case 0x09: {
payload++;
len--;
l--;
if (*payload == 1) {
payload++;
len--;
l--;
//char serialstr[20];
//strncpy(serialstr, (const char*)payload, l);
//AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: adv part FF01 detected %s"), serialstr);
// we don;t use these, but that's what they seem to be....
strncpy(serial, (const char*)payload, tmin(l, serialLen));
name[nameLen - 1] = 0;
payload += l;
len -= l;
//return 1;
} else {
payload += l;
len -= l;
}
} break;
default:{
payload += l;
len -= l;
} break;
}
}
return 0;
}
int ispairing(const uint8_t* payload, int len) {
//char temp[40];
//BLE_ESP32::dump(temp, 40, payload, len);
//AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: pair%d %s"), len, temp);
while (len) {
int l = *payload;
//BLE_ESP32::dump(temp, 40, payload, l+1);
//AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s"), temp);
payload++;
len--;
if (len < l) {
//AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: part len er %d<%d"),len, l);
return 0;
}
if (*payload == 0xff) {
payload++;
len--;
l--;
if (*payload == 1) {
payload++;
len--;
l--;
//char serialstr[20];
//strncpy(serialstr, (const char*)payload, l);
//AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: adv part FF01 detected %s"), serialstr);
// we don;t use these, but that's what they seem to be....
const uint8_t* serial = payload;
uint8_t serialLen = l;
payload += l;
len -= l;
return 1;
} else {
payload += l;
len -= l;
}
} else {
payload += l;
len -= l;
}
}
return 0;
}
void TaskEQ3AddDevice(int8_t RSSI, const uint8_t* addr, char* serial) {
void TaskEQ3AddDevice(int8_t RSSI, const uint8_t* addr) {
eq3_device_t* targetDevice = nullptr;
eq3_device_t* firstFreeSlot = nullptr;
if (serial && *serial && !pairing) {
memcpy(pairingaddr, addr, 6);
strncpy(pairingserial, serial, sizeof(pairingserial));
pairingserial[sizeof(pairingserial) - 1] = 0;
pairing = true;
}
for (auto& device : EQ3Devices) {
if (!memcmp(addr, device.addr, 6)) {
targetDevice = &device;
@@ -830,7 +708,6 @@ void TaskEQ3AddDevice(int8_t RSSI, const uint8_t* addr, char* serial) {
targetDevice->timeoutTime = esp_timer_get_time() + 1000000ULL * EQ3_TIMEOUT;
memcpy(targetDevice->addr, addr, 6);
targetDevice->RSSI = RSSI;
targetDevice->pairing = (serial && *serial);
}
int TaskEQ3advertismentCallback(BLE_ESP32::ble_advertisment_t* pStruct)
@@ -869,17 +746,9 @@ int TaskEQ3advertismentCallback(BLE_ESP32::ble_advertisment_t* pStruct)
AddLog(BLE_ESP32::BLELogLevel[LOG_LEVEL_DEBUG], "EQ3: %s: Device seen", addrStr(addr));
#endif
uint8_t* payload = (uint8_t*)advertisedDevice->getPayload().data();
size_t payloadlen = advertisedDevice->getPayload().size();
char name[20] {};
char serial[20] {};
// bool pairing = false; // Is not used below, so removing should be no problem
ispairing2(payload, payloadlen, name, sizeof(name), serial, sizeof(serial));
// this will take and keep the mutex until the function is over
TasAutoMutex localmutex(&EQ3mutex);
TaskEQ3AddDevice(RSSI, addr, serial);
TaskEQ3AddDevice(RSSI, addr);
return 0;
}
@@ -898,8 +767,6 @@ void EQ3Init(void) {
#endif
EQ3Period = tmax(Settings->tele_period, EQ3_NUM_DEVICESLOTS);
return;
}
/***********************************************************************\
@@ -913,16 +780,6 @@ void EQ3Init(void) {
void EQ3EverySecond(void) {
/// Handle pairing ////
if (pairing) {
Response_P("{\"pairing\":\"%s\",\"serial\":\"%s\"}", addrStr(pairingaddr), pairingserial);
char addrstr[4 + 8 * 2 + 2] = "EQ3/";
BLE_ESP32::dump(&addrstr[4], 8 * 2 + 2, pairingaddr, 6);
char* topic = topicPrefix((int)STAT, pairingaddr, true);
MqttPublish(topic, false);
pairing = false;
}
/// Check for timeout and cleanup devices ////
for (auto& device : EQ3Devices) {
if (device.timeoutTime && (device.timeoutTime < esp_timer_get_time() || !Settings->flag5.mi32_enable)) {
@@ -933,7 +790,7 @@ void EQ3EverySecond(void) {
/// Handle polling ////
if (NextPollSeconds) NextPollSeconds--;
if (!NextPollSeconds && EQ3Period && opQueue.empty() && !opInProgress && !pairing) {
if (!NextPollSeconds && EQ3Period && opQueue.empty() && !opInProgress) {
uint8_t activeDevices = 0;
for (const auto& dev : EQ3Devices) {
if (dev.timeoutTime) activeDevices++;
@@ -962,7 +819,7 @@ void EQ3EverySecond(void) {
//// Simulation ////
#ifdef EQ3_SIMULATION
TaskEQ3AddDevice(-RtcTime.second - 30, TESTADDR1, nullptr);
TaskEQ3AddDevice(-RtcTime.second - 30, TESTADDR1);
if (TasmotaGlobal.uptime < 120) {
for (auto& dev : EQ3Devices) {
if (!memcmp(dev.addr, TESTADDR1, 6)) dev.lastStatusTime = UtcTime();
@@ -1365,23 +1222,19 @@ uint8_t CmndTrvNext(char* data) {
// only allow one command in progress
//if (retries) return TRV_IGNOREDBUSY;
bool useAlias = false;
uint8_t addrbin[6];
int addrres = BLE_ESP32::getAddr(addrbin, p);
if (addrres) {
if (addrres == 2) {
AddLog(LOG_LEVEL_DEBUG, "EQ3: addr used alias: %s", p);
useAlias = true;
}
NimBLEAddress addr(addrbin, addrbin[6]);
#ifdef EQ3_DEBUG
//AddLog(BLE_ESP32::BLELogLevel[LOG_LEVEL_INFO], PSTR("EQ3: cmd addr: %s -> %s"), p, addr.toString().c_str());
#endif
} else {
AddLog(LOG_LEVEL_ERROR, "EQ3: addr invalid: %s", p);
uint8_t addrbin[7]; // Must be 7, because addrbin[6] contains the type
int addrResult = BLE_ESP32::getAddr(addrbin, p);
if (!addrResult) {
AddLog(LOG_LEVEL_ERROR, "EQ3: Address invalid: %s", p);
return TRV_INVADDR;
}
bool useAlias = (addrResult == 2);
if (useAlias) AddLog(LOG_LEVEL_DEBUG, "EQ3: %s: Used alias: %s", addrStr(addrbin), p);
// NimBLEAddress addr(addrbin, addrbin[6]); // Object addr not used, only addrbin. Maybe we use it in future.
#ifdef EQ3_DEBUG
//AddLog(BLE_ESP32::BLELogLevel[LOG_LEVEL_INFO], PSTR("EQ3: cmd addr: %s -> %s"), p, addrStr(addrbin));
#endif
// get index of next part of cmd
char* cmd = strtok(nullptr, " ");
@@ -1527,7 +1380,7 @@ bool mqtt_direct() {
int remains = 120;
memset(tmp, 0, sizeof(tmp));
p = tmp;
uint8_t addr[6];
uint8_t addr[7]; // Must be 7, because addr[6] contains the type
uint8_t res = TRV_INVADDR; // invalid address/alias
// if address or alias valid