mirror of
https://github.com/arendst/Tasmota.git
synced 2026-09-11 09:13:17 +00:00
MI32: improve logging and BLE.info (#24974)
* MI32: improve logging and BLE.info * add declaration to prevent compile error in other environments
This commit is contained in:
@@ -252,7 +252,7 @@ struct {
|
||||
void *beConnCB;
|
||||
void *beAdvCB;
|
||||
uint8_t *beAdvBuf;
|
||||
uint8_t infoMsg = 0;
|
||||
uint16_t queueDrops = 0;
|
||||
uint8_t role = 0; // bitfield of MI32Role values (concurrently active roles)
|
||||
} MI32;
|
||||
|
||||
@@ -407,10 +407,6 @@ const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, // Flora
|
||||
|
||||
const char kMI32DeviceType[] PROGMEM = {"Flora|MJ_HT_V1|LYWSD02|LYWSD03|CGG1|CGD1|NLIGHT|MJYD2S|YLYK01|MHOC401|MHOC303|ATC|MCCGQ02|SJWS01L|PVVX|YLKG08|YLAI003|BTHOME"};
|
||||
|
||||
const char kMI32_ConnErrorMsg[] PROGMEM = "no Error|could not connect|did disconnect|got no service|got no characteristic|can not read|can not notify|can not write|did not write|notify time out";
|
||||
|
||||
const char kMI32_BLEInfoMsg[] PROGMEM = "Scan ended|Got Notification|Did connect|Did disconnect|Still connected|Start passive scanning|Start active scanning|Server characteristic set|Server advertisement set|Server scan response set|Server client did connect|Server client did disconnect| Server client did authenticate";
|
||||
|
||||
const char kMI32_ButtonMsg[] PROGMEM = "Single|Double|Hold"; //mapping: in Tasmota: 1,2,3 ; for HomeKit and Xiaomi 0,1,2
|
||||
/*********************************************************************************************\
|
||||
* enumerations
|
||||
@@ -475,22 +471,6 @@ enum MI32Role : uint8_t {
|
||||
MI32_ROLE_ADVERTISER = 0x08,
|
||||
};
|
||||
|
||||
enum MI32_BLEInfoMsg {
|
||||
MI32_SCAN_ENDED = 1,
|
||||
MI32_GOT_NOTIFICATION,
|
||||
MI32_DID_CONNECT,
|
||||
MI32_DID_DISCONNECT,
|
||||
MI32_STILL_CONNECTED,
|
||||
MI32_START_SCANNING_PASSIVE,
|
||||
MI32_START_SCANNING_ACTIVE,
|
||||
MI32_SERV_CHARACTERISTIC_ADDED,
|
||||
MI32_SERV_ADVERTISEMENT_ADDED,
|
||||
MI32_SERV_SCANRESPONSE_ADDED,
|
||||
MI32_SERV_CLIENT_CONNECTED,
|
||||
MI32_SERV_CLIENT_DISCONNECTED,
|
||||
MI32_SERV_CLIENT_AUTHENTICATED
|
||||
};
|
||||
|
||||
/*********************************************************************************************\
|
||||
* extended web gui
|
||||
\*********************************************************************************************/
|
||||
@@ -509,8 +489,6 @@ const char HTTP_BTN_MENU_MI32[] PROGMEM = "<p></p><form action='m32' method='get
|
||||
"eb('m').innerHTML=(x.querySelector('body')||x).innerHTML;"
|
||||
"}));";
|
||||
|
||||
const char HTTP_MI32_PARENT_BLE_ROLE[] PROGMEM = "None|Observer|Peripheral|Central";
|
||||
|
||||
const char HTTP_MI32_WIDGET[] PROGMEM =
|
||||
"<div class='box' id='box%u' style='opacity:%u.5;'>MAC:%s RSSI:%d %s<br>"
|
||||
"<small>‌%s</small>"
|
||||
|
||||
@@ -274,10 +274,19 @@ int be_BLE_run(bvm *vm) {
|
||||
int32_t be_BLE_info(struct bvm *vm);
|
||||
int32_t be_BLE_info(struct bvm *vm) {
|
||||
be_newobject(vm, "map");
|
||||
char _Role[16];
|
||||
GetTextIndexed(_Role, sizeof(_Role), MI32.role, HTTP_MI32_PARENT_BLE_ROLE);
|
||||
char _role[16];
|
||||
LowerCase(_role,_Role);
|
||||
be_map_insert_int(vm, "role_bits", MI32.role);
|
||||
char _role[40] = "";
|
||||
if(MI32.role == MI32_ROLE_NONE){
|
||||
strcpy(_role, "none");
|
||||
} else {
|
||||
const char *roleNames[] = { "scanner", "client", "server", "advertiser" };
|
||||
for(uint32_t i = 0; i < 4; i++){
|
||||
if(MI32.role & (1 << i)){
|
||||
if(_role[0]) strlcat(_role, "+", sizeof(_role));
|
||||
strlcat(_role, roleNames[i], sizeof(_role));
|
||||
}
|
||||
}
|
||||
}
|
||||
be_map_insert_str(vm, "role", _role);
|
||||
be_map_insert_str(vm, "local_addr", NimBLEDevice::toString().c_str());
|
||||
be_map_insert_int(vm, "power", NimBLEDevice::getPower());
|
||||
@@ -292,6 +301,20 @@ int be_BLE_run(bvm *vm) {
|
||||
// #else
|
||||
// be_map_insert_nil(vm, "bonds");
|
||||
// #endif
|
||||
|
||||
be_pushstring(vm, "debug");
|
||||
be_newobject(vm, "map");
|
||||
be_map_insert_bool(vm, "ready", MI32.ConnTask != nullptr && MI32.mode.readyForNextJob);
|
||||
be_map_insert_bool(vm, "pending", MI32.mode.triggerNextJob || MI32.mode.triggerBerryConnCB ||
|
||||
MI32.mode.triggerBerryAdvCB || (MI32.ConnTask != nullptr && !MI32.mode.readyForNextJob));
|
||||
// The context keeps the most recently staged operation/result until reused.
|
||||
be_map_insert_int(vm, "operation", MI32.conCtx ? MI32.conCtx->operation : 0);
|
||||
be_map_insert_int(vm, "error", MI32.conCtx ? MI32.conCtx->error : 0);
|
||||
be_map_insert_int(vm, "queue_drops", __atomic_load_n(&MI32.queueDrops, __ATOMIC_RELAXED));
|
||||
be_pop(vm, 1);
|
||||
be_data_insert(vm, -3);
|
||||
be_pop(vm, 2);
|
||||
|
||||
NimBLEClient* _serverPeer = MI32.conCtx ? MI32.conCtx->serverPeer : nullptr;
|
||||
if(MI32.mode.connected == 1 || _serverPeer != nullptr){
|
||||
NimBLEClient* _device = nullptr;
|
||||
|
||||
@@ -56,6 +56,7 @@ void MI32ConnectionTask(void *pvParameters);
|
||||
static void MI32EnsureServerInstance(NimBLEServer *&pServer);
|
||||
static void MI32RunClientOp();
|
||||
static bool MI32SetSubscription(NimBLERemoteCharacteristic *pChr, bool subscribe, bool response);
|
||||
static void MI32QueueSend(const void *item, size_t size, TickType_t wait);
|
||||
|
||||
std::vector<mi_sensor_t> MIBLEsensors;
|
||||
RingbufHandle_t BLERingBufferQueue = nullptr;
|
||||
@@ -64,6 +65,13 @@ static std::atomic<bool> MI32ReadingDone{false};
|
||||
static BLEScan* MI32Scan;
|
||||
static NimBLEClient* MI32Client;
|
||||
|
||||
static void MI32QueueSend(const void *item, size_t size, TickType_t wait){
|
||||
if(BLERingBufferQueue == nullptr ||
|
||||
xRingbufferSend(BLERingBufferQueue, item, size, wait) != pdTRUE){
|
||||
__atomic_add_fetch(&MI32.queueDrops, 1, __ATOMIC_RELAXED);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* BLE Callback Classes
|
||||
\*********************************************************************************************/
|
||||
@@ -74,7 +82,6 @@ class MI32SensorCallback : public NimBLEClientCallbacks {
|
||||
MI32.connID = pclient->getConnHandle();
|
||||
return;
|
||||
}
|
||||
MI32.infoMsg = MI32_DID_CONNECT;
|
||||
MI32.mode.willConnect = 0;
|
||||
MI32.mode.connected = 1;
|
||||
MI32.connID = pclient->getConnHandle();
|
||||
@@ -86,7 +93,6 @@ class MI32SensorCallback : public NimBLEClientCallbacks {
|
||||
}
|
||||
MI32.mode.connected = 0;
|
||||
MI32.role &= ~MI32_ROLE_CLIENT;
|
||||
MI32.infoMsg = MI32_DID_DISCONNECT;
|
||||
MI32.conCtx->error = reason;
|
||||
MI32.conCtx->operation = 5; //set for all disconnects that come from the remote device or connection loss
|
||||
MI32.mode.triggerBerryConnCB = 1;
|
||||
@@ -99,7 +105,6 @@ class MI32SensorCallback : public NimBLEClientCallbacks {
|
||||
|
||||
class MI32AdvCallbacks: public NimBLEScanCallbacks {
|
||||
void onScanEnd(const NimBLEScanResults &results, int reason) {
|
||||
MI32.infoMsg = MI32_SCAN_ENDED;
|
||||
MI32.mode.runningScan = 0;
|
||||
MI32.mode.deleteScanTask = 1; // if scan ended dew to a BLE controller error, make sure we stop the task
|
||||
}
|
||||
@@ -167,8 +172,8 @@ class MI32ServerCallbacks: public NimBLEServerCallbacks {
|
||||
item.header.returnCharUUID = 0;
|
||||
item.header.handle = 0;
|
||||
memcpy(item.buffer,connInfo.getAddress().getVal(),6);
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + 6 , pdMS_TO_TICKS(1));
|
||||
MI32.infoMsg = MI32_SERV_CLIENT_CONNECTED;
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t) + 6, pdMS_TO_TICKS(1));
|
||||
MI32.role &= ~MI32_ROLE_ADVERTISER;
|
||||
if(MI32.conCtx == nullptr) return;
|
||||
MI32.conCtx->serverPeer = pServer->getClient(connInfo); // Singleton - do NOT delete via NimBLEDevice::deleteClient.
|
||||
if(MI32.conCtx->itvl_min != 0 && MI32.conCtx->itvl_max != 0){
|
||||
@@ -183,17 +188,16 @@ class MI32ServerCallbacks: public NimBLEServerCallbacks {
|
||||
item.header.type = BLE_OP_ON_DISCONNECT;
|
||||
item.header.returnCharUUID = 0;
|
||||
item.header.handle = 0;
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
MI32.infoMsg = MI32_SERV_CLIENT_DISCONNECTED;
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
if(MI32.conCtx == nullptr) return;
|
||||
memset(MI32.conCtx->MAC,0,6);
|
||||
// Reverse-role client cleanup: pServer owns the singleton, just drop our
|
||||
// borrowed pointer. Never call NimBLEDevice::deleteClient on it.
|
||||
MI32.conCtx->serverPeer = nullptr;
|
||||
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEDevice::startAdvertising(0);
|
||||
if(NimBLEDevice::startAdvertising(0)) MI32.role |= MI32_ROLE_ADVERTISER;
|
||||
#else
|
||||
NimBLEDevice::startAdvertising();
|
||||
if(NimBLEDevice::startAdvertising()) MI32.role |= MI32_ROLE_ADVERTISER;
|
||||
#endif
|
||||
};
|
||||
void onAuthenticationComplete(NimBLEConnInfo& connInfo) {
|
||||
@@ -208,7 +212,6 @@ class MI32ServerCallbacks: public NimBLEServerCallbacks {
|
||||
memset(&peer_security_record, 0, security_record_size);
|
||||
ble_gap_conn_desc connection_desc;
|
||||
if (ble_gap_conn_find(connInfo.getConnHandle(), &connection_desc) != 0) {
|
||||
MI32.infoMsg = MI32_SERV_CLIENT_AUTHENTICATED;
|
||||
return;
|
||||
}
|
||||
ble_store_key_sec security_key;
|
||||
@@ -222,8 +225,7 @@ class MI32ServerCallbacks: public NimBLEServerCallbacks {
|
||||
item.header.type = BLE_OP_ON_AUTHENTICATED;
|
||||
item.header.returnCharUUID = 0;
|
||||
item.header.handle = 0;
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(1));
|
||||
MI32.infoMsg = MI32_SERV_CLIENT_AUTHENTICATED;
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(1));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -236,7 +238,7 @@ class MI32CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
item.header.type = BLE_OP_ON_READ;
|
||||
item.header.returnCharUUID = *reinterpret_cast<const uint16_t*>(pCharacteristic->getUUID().getValue() + 12);
|
||||
item.header.handle = pCharacteristic->getHandle();
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
};
|
||||
|
||||
void onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) {
|
||||
@@ -253,7 +255,7 @@ class MI32CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
item.header.returnCharUUID = *reinterpret_cast<const uint16_t*>(pCharacteristic->getUUID().getValue() + 12);
|
||||
item.header.handle = pCharacteristic->getHandle();
|
||||
memcpy(item.buffer,pCharacteristic->getValue().data(),valSize);
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length , pdMS_TO_TICKS(1));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(1));
|
||||
};
|
||||
|
||||
/** The status returned in status is defined in NimBLECharacteristic.h.
|
||||
@@ -269,7 +271,7 @@ class MI32CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
item.header.returnCharUUID = *reinterpret_cast<const uint16_t*>(pCharacteristic->getUUID().getValue() + 12);
|
||||
item.header.handle = pCharacteristic->getHandle();
|
||||
memcpy(item.buffer,&code,item.header.length);
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(1));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(1));
|
||||
};
|
||||
|
||||
void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue) {
|
||||
@@ -282,7 +284,7 @@ class MI32CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
item.header.type = BLE_OP_ON_UNSUBSCRIBE + subValue;
|
||||
item.header.returnCharUUID = *reinterpret_cast<const uint16_t*>(pCharacteristic->getUUID().getValue() + 12);
|
||||
item.header.handle = pCharacteristic->getHandle();
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
};
|
||||
};
|
||||
|
||||
@@ -291,8 +293,6 @@ void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pD
|
||||
const NimBLEUUID &uuid = pRemoteCharacteristic->getUUID();
|
||||
const uint8_t *uuidValue = uuid.getValue() + (uuid.bitSize() == BLE_UUID_TYPE_128 ? 12 : 0);
|
||||
const uint16_t uuid16 = *reinterpret_cast<const uint16_t*>(uuidValue);
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: notifyCB uuid=%04x handle=%u len=%u isNotify=%u"),
|
||||
uuid16, pRemoteCharacteristic->getHandle(), (unsigned)length, (unsigned)isNotify);
|
||||
struct{
|
||||
BLERingBufferItem_t header;
|
||||
uint8_t buffer[255];
|
||||
@@ -303,9 +303,8 @@ void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pD
|
||||
memcpy(item.buffer,pData,length);
|
||||
item.header.returnCharUUID = uuid16;
|
||||
item.header.handle = pRemoteCharacteristic->getHandle();
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + length , pdMS_TO_TICKS(5));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t) + length, pdMS_TO_TICKS(5));
|
||||
MI32ReadingDone.store(true, std::memory_order_release);
|
||||
MI32.infoMsg = MI32_GOT_NOTIFICATION;
|
||||
}
|
||||
|
||||
static bool MI32SetSubscription(NimBLERemoteCharacteristic *pChr, bool subscribe, bool response){
|
||||
@@ -799,7 +798,6 @@ extern "C" {
|
||||
pAdvertising->stop();
|
||||
if(MI32.conCtx->addrType > 0){
|
||||
ble_hs_id_set_rnd(MI32.conCtx->MAC);
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: set MAC to random"));
|
||||
}
|
||||
NimBLEDevice::setOwnAddrType(MI32.conCtx->addrType);
|
||||
success = true;
|
||||
@@ -812,14 +810,12 @@ extern "C" {
|
||||
pAdvertising->setConnectableMode(MI32.conCtx->buffer[1]);
|
||||
pAdvertising->setMinInterval(MI32.conCtx->itvl_min);
|
||||
pAdvertising->setMaxInterval(MI32.conCtx->itvl_max);
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: adv params: type: %u, min: %u, max: %u"),MI32.conCtx->buffer[1], (uint16_t)(MI32.conCtx->itvl_min * 0.625), (uint16_t)(MI32.conCtx->itvl_max * 0.625)) ;
|
||||
success = true;
|
||||
}
|
||||
#endif //CONFIG_BT_NIMBLE_EXT_ADV
|
||||
break;
|
||||
case 233:
|
||||
int ret = ble_svc_gap_device_name_set((const char*)MI32.conCtx->buffer + 1);
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: new gap device name - %s"),(const char*) MI32.conCtx->buffer + 1);
|
||||
success = (ret == 0);
|
||||
break;
|
||||
}
|
||||
@@ -844,7 +840,6 @@ extern "C" {
|
||||
MI32.conCtx->arg1 = arg1;
|
||||
MI32.conCtx->hasArg1 = hasArg1;
|
||||
MI32.conCtx->response = response;
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: arg1: %u"),MI32.conCtx->arg1);
|
||||
|
||||
if(operation > 230){ // 231..233: runtime config helpers, executed inline
|
||||
return MI32runBerryConfig(operation);
|
||||
@@ -861,16 +856,10 @@ extern "C" {
|
||||
MI32.conCtx->oneOp = false;
|
||||
}
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry op: %d, addrType: %d, oneOp: %u, response: %u"),
|
||||
MI32.conCtx->operation, MI32.conCtx->addrType, MI32.conCtx->oneOp, MI32.conCtx->response);
|
||||
|
||||
if(MI32.ConnTask == nullptr){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("BLE: connection task not running - register conn_cb first"));
|
||||
return false;
|
||||
}
|
||||
if(MI32.mode.readyForNextJob == 0){
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: previous job not finished yet"));
|
||||
}
|
||||
MI32.mode.triggerNextJob = 1;
|
||||
return true;
|
||||
}
|
||||
@@ -879,14 +868,12 @@ extern "C" {
|
||||
if(function == nullptr || buffer == nullptr){
|
||||
MI32.beConnCB = nullptr;
|
||||
MI32.mode.deleteConnectionTask = 1; // request task teardown if alive
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("BLE: Connection callback cleared"));
|
||||
return;
|
||||
}
|
||||
MI32ensureConCtx(buffer);
|
||||
MI32.beConnCB = function;
|
||||
if(MI32.ConnTask != nullptr){
|
||||
// re-registration: keep the running task, just refresh cb/buffer
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("BLE: Connection callback re-registered"));
|
||||
return;
|
||||
}
|
||||
if(BLERingBufferQueue == nullptr){
|
||||
@@ -899,7 +886,7 @@ extern "C" {
|
||||
MI32.mode.readyForNextJob = 0; // task will set to 1 on entry
|
||||
MI32.mode.triggerNextJob = 0;
|
||||
MI32.mode.deleteConnectionTask = 0;
|
||||
xTaskCreatePinnedToCore(
|
||||
BaseType_t taskResult = xTaskCreatePinnedToCore(
|
||||
MI32ConnectionTask, /* Function to implement the task */
|
||||
"MI32ConnectionTask", /* Name of the task */
|
||||
8192, /* Stack size in words */
|
||||
@@ -907,7 +894,10 @@ extern "C" {
|
||||
2, /* Priority */
|
||||
&MI32.ConnTask, /* Task handle */
|
||||
0); /* Core */
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("BLE: Connection task started"));
|
||||
if(taskResult != pdPASS){
|
||||
MI32.ConnTask = nullptr;
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("BLE: failed to create connection task"));
|
||||
}
|
||||
}
|
||||
|
||||
void MI32setBerryServerCB(void* function, uint8_t *buffer){ //deprecated!
|
||||
@@ -917,7 +907,6 @@ extern "C" {
|
||||
bool MI32setBerryCtxSvc(const char *Svc, bool discoverAttributes){
|
||||
if(MI32.conCtx != nullptr){
|
||||
MI32.conCtx->serviceUUID = NimBLEUUID(Svc);
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: SVC: %s"),MI32.conCtx->serviceUUID.toString().c_str());
|
||||
MI32.mode.discoverAttributes = discoverAttributes;
|
||||
return true;
|
||||
}
|
||||
@@ -927,10 +916,8 @@ extern "C" {
|
||||
bool MI32setBerryCtxChr(const char *Chr){
|
||||
if(MI32.conCtx != nullptr){
|
||||
MI32.conCtx->charUUID = NimBLEUUID(Chr).to128();
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: CHR: %s"),MI32.conCtx->charUUID.toString().c_str());
|
||||
uint16_t _uuid = *reinterpret_cast<const uint16_t*>(MI32.conCtx->charUUID.getValue() + 12); //if not "notify op" -> present requested characteristic as return UUID
|
||||
MI32.conCtx->returnCharUUID = _uuid;
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: return 16-bit UUID: %04x"),MI32.conCtx->returnCharUUID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -971,7 +958,6 @@ extern "C" {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: add %s to watchlist of size: %u"),_newAddress.toString().c_str(),NimBLEDevice::getWhiteListCount());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1078,28 +1064,36 @@ void MI32loadCfg(){
|
||||
return;
|
||||
}
|
||||
char * _filebuf = (char*)calloc(_file_size + 1, 1);
|
||||
if (!_filebuf) { return; }
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: found config file"));
|
||||
if (!_filebuf) {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config allocation failed"));
|
||||
return;
|
||||
}
|
||||
if(TfsLoadFile("/mi32cfg",(uint8_t*)_filebuf,_file_size)){
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: %s"),_filebuf);
|
||||
JsonParser parser(_filebuf);
|
||||
JsonParserToken root = parser.getRoot();
|
||||
if (!root) {AddLog(LOG_LEVEL_INFO,PSTR("M32: invalid root "));}
|
||||
if (!root) {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: invalid config root"));
|
||||
free(_filebuf);
|
||||
return;
|
||||
}
|
||||
JsonParserArray arr = root.getArray();
|
||||
if (!arr) {AddLog(LOG_LEVEL_INFO,PSTR("M32: invalid array object"));; }
|
||||
if (!arr) {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config root is not an array"));
|
||||
free(_filebuf);
|
||||
return;
|
||||
}
|
||||
bool _error = true;
|
||||
int32_t _numberOfDevices = -1; // slot of the last successfully parsed MAC/PID; -1 = none yet
|
||||
uint32_t _loadedDevices = 0;
|
||||
for (auto _dev : arr) {
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: found device in config file"));
|
||||
int32_t _numberOfDevices = -1;
|
||||
JsonParserObject _device = _dev.getObject();
|
||||
uint8_t _mac[6];
|
||||
JsonParserToken _val = _device[PSTR("MAC")];
|
||||
_error = true;
|
||||
if (_val) {
|
||||
char *_macStr = (char *)_val.getStr();
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: found MAC: %s"), _macStr);
|
||||
if(strlen(_macStr)!=12){
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: wrong MAC length: %u"), strlen(_macStr));
|
||||
if(!_macStr || strlen(_macStr)!=12){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: invalid config MAC"));
|
||||
break;
|
||||
}
|
||||
MI32HexStringToBytes(_macStr,_mac);
|
||||
@@ -1107,15 +1101,15 @@ void MI32loadCfg(){
|
||||
if(_val){
|
||||
uint8_t _pid[2];
|
||||
char *_pidStr = (char *)_val.getStr();
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: found PID: %s"), _pidStr);
|
||||
if(strlen(_pidStr)!=4){
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: wrong PID length: %u"), strlen(_pidStr));
|
||||
if(!_pidStr || strlen(_pidStr)!=4){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: invalid config PID"));
|
||||
break;
|
||||
}
|
||||
MI32HexStringToBytes(_pidStr,_pid);
|
||||
uint16_t _pid16 = _pid[0]*256 + _pid[1];
|
||||
_numberOfDevices = MIBLEgetSensorSlot(_mac,_pid16,0);
|
||||
if(_numberOfDevices == 0xff){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: sensor allocation failed"));
|
||||
_error = true;
|
||||
break;
|
||||
}
|
||||
@@ -1123,16 +1117,30 @@ void MI32loadCfg(){
|
||||
MI32.option.handleEveryDevice = 1; // if in config, we assume to handle it
|
||||
}
|
||||
_error = false;
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config PID missing"));
|
||||
}
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config MAC missing"));
|
||||
}
|
||||
// Subsequent fields only valid if MAC+PID parsed successfully above.
|
||||
if(_numberOfDevices < 0) continue;
|
||||
if(_numberOfDevices < 0) break;
|
||||
_val = _device[PSTR("key")];
|
||||
if (_val) {
|
||||
char *_keyStr = (char *)_val.getStr();
|
||||
if(!_keyStr){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: invalid config key"));
|
||||
_error = true;
|
||||
break;
|
||||
}
|
||||
if(strlen(_keyStr)>0){
|
||||
if(strlen(_keyStr)==32){
|
||||
uint8_t *_key = (uint8_t*) malloc(16);
|
||||
if(!_key){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: key allocation failed"));
|
||||
_error = true;
|
||||
break;
|
||||
}
|
||||
MI32HexStringToBytes(_keyStr,_key);
|
||||
MIBLEsensors[_numberOfDevices].key = _key;
|
||||
if (MIBLEsensors[_numberOfDevices].PID == 0) { // no Xiaomi sensor
|
||||
@@ -1140,6 +1148,7 @@ void MI32loadCfg(){
|
||||
}
|
||||
}
|
||||
else{
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: invalid config key"));
|
||||
_error = true;
|
||||
break;
|
||||
}
|
||||
@@ -1148,17 +1157,29 @@ void MI32loadCfg(){
|
||||
_val = _device[PSTR("name")];
|
||||
if (_val) {
|
||||
char *_name = (char *)_val.getStr();
|
||||
if(!_name){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: invalid config name"));
|
||||
_error = true;
|
||||
break;
|
||||
}
|
||||
MIBLEsensors[_numberOfDevices].name = strdup(_name);
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: found name: %s"), _name);
|
||||
if(!MIBLEsensors[_numberOfDevices].name){
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: name allocation failed"));
|
||||
_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_val = _device[PSTR("feat")];
|
||||
if (_val) {
|
||||
MIBLEsensors[_numberOfDevices].feature.raw = _val.getUInt();
|
||||
}
|
||||
_loadedDevices++;
|
||||
}
|
||||
if(!_error){
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: added %u devices from config file"), _numberOfDevices + 1);
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: loaded %u sensor configurations"), _loadedDevices);
|
||||
}
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config read failed"));
|
||||
}
|
||||
free(_filebuf);
|
||||
}
|
||||
@@ -1168,7 +1189,10 @@ bool MI32saveConfig(){
|
||||
const size_t _sensor_count = (MIBLEsensors.size() > MI32_CFG_MAX_SENSORS) ? MI32_CFG_MAX_SENSORS : MIBLEsensors.size();
|
||||
const size_t _buf_size = 2 + _sensor_count * MI32_CFG_RECORD_SIZE;
|
||||
char * _filebuf = (char*) malloc(_buf_size);
|
||||
if (!_filebuf) { return false; }
|
||||
if (!_filebuf) {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config allocation failed"));
|
||||
return false;
|
||||
}
|
||||
_filebuf[0] = '[';
|
||||
size_t _pos = 1;
|
||||
bool _error = false;
|
||||
@@ -1203,10 +1227,11 @@ bool MI32saveConfig(){
|
||||
if (!_error && _pos>2){
|
||||
_filebuf[_pos-1] = ']';
|
||||
_filebuf[_pos] = '\0';
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: %s"), _filebuf);
|
||||
_success = TfsSaveFile("/mi32cfg",(uint8_t*)_filebuf,_pos+1);
|
||||
if (_success) {
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: %u bytes written to config"), _pos+1);
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("M32: saved %u sensor configurations"), _sensor_count);
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_ERROR,PSTR("M32: config save failed"));
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -1279,8 +1304,6 @@ void MI32ScanTask(void *pvParameters){
|
||||
// MI32Scan->setInterval(30);
|
||||
// MI32Scan->setWindow(25);
|
||||
MI32Scan->start(0, false); // never stop scanning, will pause automatically while connecting
|
||||
MI32.infoMsg = MI32.option.activeScan?MI32_START_SCANNING_ACTIVE:MI32_START_SCANNING_PASSIVE;
|
||||
|
||||
uint32_t timer = 0;
|
||||
for(;;){
|
||||
vTaskDelay(100/ portTICK_PERIOD_MS);
|
||||
@@ -1294,7 +1317,6 @@ void MI32ScanTask(void *pvParameters){
|
||||
MI32Scan->setActiveScan(MI32.option.activeScan == 1);
|
||||
MI32Scan->start(0, true);
|
||||
MI32.mode.updateScan = 0;
|
||||
MI32.infoMsg = MI32.option.activeScan?MI32_START_SCANNING_ACTIVE:MI32_START_SCANNING_PASSIVE;
|
||||
}
|
||||
}
|
||||
MI32.mode.deleteScanTask = 0;
|
||||
@@ -1376,7 +1398,6 @@ static void MI32EnsureServerInstance(NimBLEServer *&pServer){
|
||||
pServer = NimBLEDevice::createServer();
|
||||
pServer->setCallbacks(new MI32ServerCallbacks(), true);
|
||||
MI32.role |= MI32_ROLE_SERVER;
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: server instance created (lazy)"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1669,6 +1690,7 @@ cleanup:
|
||||
MI32.mode.willConnect = 0;
|
||||
MI32.mode.deleteConnectionTask = 0;
|
||||
MI32.mode.triggerBerryConnCB = 0;
|
||||
MI32.mode.readyForNextJob = 0;
|
||||
MI32.ConnTask = nullptr;
|
||||
MI32StartTask(MI32_TASK_SCAN);
|
||||
vTaskDelete(NULL);
|
||||
@@ -1756,12 +1778,12 @@ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector<NimBLEService*>& servic
|
||||
pAdvertising->enableScanResponse(true);
|
||||
}
|
||||
#endif //CONFIG_BT_NIMBLE_EXT_ADV
|
||||
if(MI32.conCtx->operation == BLE_OP_SET_ADV && pAdvertising->isAdvertising()) MI32.role |= MI32_ROLE_ADVERTISER;
|
||||
|
||||
MI32.infoMsg = MI32_SERV_SCANRESPONSE_ADDED + (MI32.conCtx->operation - BLE_OP_SET_SCAN_RESP); // .. ADV or SCAN RESPONSE
|
||||
item.header.type = MI32.conCtx->operation;
|
||||
item.header.returnCharUUID = 0;
|
||||
item.header.handle = 0;
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(20));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t) + item.header.length, pdMS_TO_TICKS(20));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1803,7 +1825,6 @@ void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vector<NimBLEServic
|
||||
return;
|
||||
}
|
||||
pCharacteristic->setCallbacks(&MI32ChrCallback);
|
||||
MI32.infoMsg = MI32_SERV_CHARACTERISTIC_ADDED;
|
||||
}
|
||||
pCharacteristic->setValue(MI32.conCtx->buffer + 1, MI32.conCtx->buffer[0]); // set value
|
||||
MI32.conCtx->response ? pCharacteristic->indicate() : pCharacteristic->notify(); // use response to select indicate vs notification
|
||||
@@ -1814,7 +1835,7 @@ void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vector<NimBLEServic
|
||||
item.header.type = BLE_OP_SET_CHARACTERISTIC;
|
||||
item.header.returnCharUUID = *reinterpret_cast<const uint16_t*>(pCharacteristic->getUUID().getValue() + 12);
|
||||
item.header.handle = pCharacteristic->getHandle();
|
||||
xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
MI32QueueSend((const void*)&item, sizeof(BLERingBufferItem_t), pdMS_TO_TICKS(1));
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@@ -1863,7 +1884,6 @@ if(decryptRet!=0){
|
||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u with payload type: %02x"), MI32getDeviceName(_slot),_slot,_payload.type);
|
||||
switch(_payload.type){
|
||||
case 0x0002:
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: obj id to pair: %02x"),_payload.objID); // pretty pointless for Tasmota
|
||||
break;
|
||||
case 0x1001:
|
||||
MIBLEsensors[_slot].feature.Btn = 1;
|
||||
@@ -2349,9 +2369,12 @@ void MI32BLELoop()
|
||||
if(MI32.mode.triggerBerryConnCB == 1){
|
||||
if(MI32.beConnCB != nullptr){
|
||||
void (*func_ptr)(int, int, int, int) = (void (*)(int, int, int, int))MI32.beConnCB;
|
||||
char _message[32];
|
||||
GetTextIndexed(_message, sizeof(_message), MI32.conCtx->error, kMI32_ConnErrorMsg);
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: BryCbMsg: %s"),_message);
|
||||
if(MI32.conCtx->error){
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: %s op %u failed %d, uuid %04x, handle %u"),
|
||||
NimBLEAddress(MI32.conCtx->MAC, MI32.conCtx->addrType).toString().c_str(),
|
||||
MI32.conCtx->operation, MI32.conCtx->error,
|
||||
MI32.conCtx->returnCharUUID, MI32.conCtx->handle);
|
||||
}
|
||||
func_ptr(MI32.conCtx->error, MI32.conCtx->operation , MI32.conCtx->returnCharUUID, MI32.conCtx->handle);
|
||||
}
|
||||
MI32.mode.triggerBerryConnCB = 0;
|
||||
@@ -2380,12 +2403,6 @@ void MI32BLELoop()
|
||||
MI32.mode.triggerBerryConnCB = 1;
|
||||
}
|
||||
}
|
||||
if(MI32.infoMsg > 0){
|
||||
char _message[32];
|
||||
GetTextIndexed(_message, sizeof(_message), MI32.infoMsg-1, kMI32_BLEInfoMsg);
|
||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s"),_message);
|
||||
MI32.infoMsg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2433,7 +2450,6 @@ void CmndMi32Key(void) {
|
||||
memmove(keyMAC.buf + 10, keyMAC.buf + 6, 12);
|
||||
const uint8_t _fillbytes[4] = {0x8d,0x3d,0x3c,0x97}; // only valid for YLKG08 and YLKG07 ??
|
||||
memcpy(keyMAC.buf + 6,_fillbytes,4);
|
||||
AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*) keyMAC.buf, 16);
|
||||
}
|
||||
MI32AddKey(keyMAC);
|
||||
ResponseCmndDone();
|
||||
|
||||
Reference in New Issue
Block a user