mirror of
https://github.com/arendst/Tasmota.git
synced 2026-09-11 09:13:17 +00:00
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:
@@ -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(¤tOperation, &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
|
||||
|
||||
Reference in New Issue
Block a user