mirror of https://github.com/arendst/Tasmota.git
Merge pull request #9892 from Staars/mi32
MI_ESP32: add new commands, add mqtt output
This commit is contained in:
commit
8fab895eca
|
@ -20,6 +20,8 @@
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
Version yyyymmdd Action Description
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
|
0.9.1.7 20201116 changed - small bugfixes, add BLOCK and OPTION command, send BLE scan via MQTT
|
||||||
|
-------
|
||||||
0.9.1.6 20201022 changed - Beacon support, RSSI at TELEPERIOD, refactoring
|
0.9.1.6 20201022 changed - Beacon support, RSSI at TELEPERIOD, refactoring
|
||||||
-------
|
-------
|
||||||
0.9.1.5 20201021 changed - HASS related ('null', hold back discovery), number of found sensors for RULES
|
0.9.1.5 20201021 changed - HASS related ('null', hold back discovery), number of found sensors for RULES
|
||||||
|
@ -80,10 +82,12 @@ struct {
|
||||||
uint32_t willSetUnit:1;
|
uint32_t willSetUnit:1;
|
||||||
uint32_t shallTriggerTele:1;
|
uint32_t shallTriggerTele:1;
|
||||||
uint32_t triggeredTele:1;
|
uint32_t triggeredTele:1;
|
||||||
uint32_t shallClearResults:1; // BLE scan results
|
uint32_t shallClearResults:1; // BLE scan results
|
||||||
uint32_t shallShowStatusInfo:1; // react to amount of found sensors via RULES
|
uint32_t shallShowStatusInfo:1; // react to amount of found sensors via RULES
|
||||||
uint32_t firstAutodiscoveryDone:1;
|
uint32_t firstAutodiscoveryDone:1;
|
||||||
uint32_t activeBeacon;
|
uint32_t activeBeacon:1;
|
||||||
|
uint32_t shallShowScanResult:1;
|
||||||
|
uint32_t shallShowBlockList:1;
|
||||||
};
|
};
|
||||||
uint32_t all = 0;
|
uint32_t all = 0;
|
||||||
} mode;
|
} mode;
|
||||||
|
@ -271,10 +275,15 @@ struct generic_beacon_t {
|
||||||
bool active = false;
|
bool active = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MAC_t {
|
||||||
|
uint8_t buf[6];
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<mi_sensor_t> MIBLEsensors;
|
std::vector<mi_sensor_t> MIBLEsensors;
|
||||||
std::vector<mi_bindKey_t> MIBLEbindKeys;
|
std::vector<mi_bindKey_t> MIBLEbindKeys;
|
||||||
std::array<generic_beacon_t,4> MIBLEbeacons; // we support a fixed number
|
std::array<generic_beacon_t,4> MIBLEbeacons; // we support a fixed number
|
||||||
std::vector<scan_entry_t> MINBLEscanResult;
|
std::vector<scan_entry_t> MIBLEscanResult;
|
||||||
|
std::vector<MAC_t> MIBLEBlockList;
|
||||||
|
|
||||||
static BLEScan* MI32Scan;
|
static BLEScan* MI32Scan;
|
||||||
|
|
||||||
|
@ -288,13 +297,13 @@ const char kMI32_Commands[] PROGMEM = D_CMND_MI32 "|"
|
||||||
#ifdef USE_MI_DECRYPTION
|
#ifdef USE_MI_DECRYPTION
|
||||||
"Key|"
|
"Key|"
|
||||||
#endif // USE_MI_DECRYPTION
|
#endif // USE_MI_DECRYPTION
|
||||||
"Period|Time|Page|Battery|Unit|Beacon";
|
"Period|Time|Page|Battery|Unit|Beacon|Block|Option";
|
||||||
|
|
||||||
void (*const MI32_Commands[])(void) PROGMEM = {
|
void (*const MI32_Commands[])(void) PROGMEM = {
|
||||||
#ifdef USE_MI_DECRYPTION
|
#ifdef USE_MI_DECRYPTION
|
||||||
&CmndMi32Key,
|
&CmndMi32Key,
|
||||||
#endif // USE_MI_DECRYPTION
|
#endif // USE_MI_DECRYPTION
|
||||||
&CmndMi32Period, &CmndMi32Time, &CmndMi32Page, &CmndMi32Battery, &CmndMi32Unit, &CmndMi32Beacon };
|
&CmndMi32Period, &CmndMi32Time, &CmndMi32Page, &CmndMi32Battery, &CmndMi32Unit, &CmndMi32Beacon, &CmndMi32Block, &CmndMi32Option };
|
||||||
|
|
||||||
#define FLORA 1
|
#define FLORA 1
|
||||||
#define MJ_HT_V1 2
|
#define MJ_HT_V1 2
|
||||||
|
@ -350,7 +359,9 @@ enum MI32_Commands { // commands useable in console or rules
|
||||||
CMND_MI32_BATTERY, // read all battery levels
|
CMND_MI32_BATTERY, // read all battery levels
|
||||||
CMND_MI32_UNIT, // toggles the displayed unit between C/F (LYWSD02)
|
CMND_MI32_UNIT, // toggles the displayed unit between C/F (LYWSD02)
|
||||||
CMND_MI32_KEY, // add bind key to a mac for packet decryption
|
CMND_MI32_KEY, // add bind key to a mac for packet decryption
|
||||||
CMND_MI32_BEACON // add up to 4 beacons defined by their MAC addresses
|
CMND_MI32_BEACON, // add up to 4 beacons defined by their MAC addresses
|
||||||
|
CMND_MI32_BLOCK, // block BLE sensors defined by their MAC addresses
|
||||||
|
CMND_MI32_OPTION // change driver options at runtime
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MI32_TASK {
|
enum MI32_TASK {
|
||||||
|
@ -420,12 +431,15 @@ class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
||||||
|
|
||||||
size_t ServiceDataLength = advertisedDevice->getServiceData(0).length();
|
size_t ServiceDataLength = advertisedDevice->getServiceData(0).length();
|
||||||
if(UUID==0xfe95) {
|
if(UUID==0xfe95) {
|
||||||
|
if(MI32isInBlockList(addr) == true) return;
|
||||||
MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
||||||
}
|
}
|
||||||
else if(UUID==0xfdcd) {
|
else if(UUID==0xfdcd) {
|
||||||
|
if(MI32isInBlockList(addr) == true) return;
|
||||||
MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
||||||
}
|
}
|
||||||
else if(UUID==0x181a) { //ATC
|
else if(UUID==0x181a) { //ATC
|
||||||
|
if(MI32isInBlockList(addr) == true) return;
|
||||||
MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -754,7 +768,7 @@ void MI32StatusInfo() {
|
||||||
void MI32PreInit(void) {
|
void MI32PreInit(void) {
|
||||||
MIBLEsensors.reserve(10);
|
MIBLEsensors.reserve(10);
|
||||||
MIBLEbindKeys.reserve(10);
|
MIBLEbindKeys.reserve(10);
|
||||||
MINBLEscanResult.reserve(20);
|
MIBLEscanResult.reserve(20);
|
||||||
MI32.mode.init = false;
|
MI32.mode.init = false;
|
||||||
|
|
||||||
//test section for options
|
//test section for options
|
||||||
|
@ -1534,12 +1548,12 @@ void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, u
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// else handle scan
|
// else handle scan
|
||||||
if(MINBLEscanResult.size()>19) {
|
if(MIBLEscanResult.size()>19) {
|
||||||
AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: Scan buffer full"));
|
AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: Scan buffer full"));
|
||||||
MI32.state.beaconScanCounter = 1;
|
MI32.state.beaconScanCounter = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(auto _scanResult : MINBLEscanResult){
|
for(auto _scanResult : MIBLEscanResult){
|
||||||
if(memcmp(addr,_scanResult.MAC,6)==0){
|
if(memcmp(addr,_scanResult.MAC,6)==0){
|
||||||
// AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: known device"));
|
// AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: known device"));
|
||||||
return;
|
return;
|
||||||
|
@ -1552,7 +1566,7 @@ void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, u
|
||||||
_new.UUID = 0;
|
_new.UUID = 0;
|
||||||
memcpy(_new.MAC,addr,sizeof(_new.MAC));
|
memcpy(_new.MAC,addr,sizeof(_new.MAC));
|
||||||
MI32ParseGenericBeacon(payload,payloadLength,&_new.CID,&_new.SVC,&_new.UUID);
|
MI32ParseGenericBeacon(payload,payloadLength,&_new.CID,&_new.SVC,&_new.UUID);
|
||||||
MINBLEscanResult.push_back(_new);
|
MIBLEscanResult.push_back(_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1585,13 +1599,43 @@ void MI32addBeacon(uint8_t index, char* data){
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void MI32showScanResults(){
|
void MI32showScanResults(){
|
||||||
AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: found %u devices in scan:"), MINBLEscanResult.size());
|
size_t _size = MIBLEscanResult.size();
|
||||||
for(auto _scanResult : MINBLEscanResult){
|
ResponseAppend_P(PSTR(",\"BLEScan\":{\"Found\":%u,\"Devices\":["), _size);
|
||||||
|
for(auto _scanResult : MIBLEscanResult){
|
||||||
char _MAC[18];
|
char _MAC[18];
|
||||||
ToHex_P(_scanResult.MAC,6,_MAC,18,':');
|
ToHex_P(_scanResult.MAC,6,_MAC,18,':');
|
||||||
AddLog_P(LOG_LEVEL_INFO,PSTR("MAC: %s _ CID: %04x _ SVC: %04x _ UUID: %04x _ RSSI: %d"), _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.RSSI);
|
ResponseAppend_P(PSTR("{\"MAC\":\"%s\",\"CID\":\"0x%04x\",\"SVC\":\"0x%04x\",\"UUID\":\"0x%04x\",\"RSSI\":%d},"), _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.RSSI);
|
||||||
}
|
}
|
||||||
MINBLEscanResult.clear();
|
if(_size != 0)TasmotaGlobal.mqtt_data[strlen(TasmotaGlobal.mqtt_data)-1] = 0; // delete last comma
|
||||||
|
ResponseAppend_P(PSTR("]}"));
|
||||||
|
MIBLEscanResult.clear();
|
||||||
|
MI32.mode.shallShowScanResult = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MI32showBlockList(){
|
||||||
|
ResponseAppend_P(PSTR(",\"Block\":["));
|
||||||
|
for(auto _scanResult : MIBLEBlockList){
|
||||||
|
char _MAC[18];
|
||||||
|
ToHex_P(_scanResult.buf,6,_MAC,18,':');
|
||||||
|
ResponseAppend_P(PSTR("\"%s\","), _MAC);
|
||||||
|
}
|
||||||
|
if(MIBLEBlockList.size()!=0) TasmotaGlobal.mqtt_data[strlen(TasmotaGlobal.mqtt_data)-1] = 0; // delete last comma
|
||||||
|
ResponseAppend_P(PSTR("]"));
|
||||||
|
MI32.mode.shallShowBlockList = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MI32isInBlockList(uint8_t* MAC){
|
||||||
|
bool isBlocked = false;
|
||||||
|
for(auto &_blockedMAC : MIBLEBlockList){
|
||||||
|
if(memcmp(_blockedMAC.buf,MAC,6) == 0) isBlocked = true;
|
||||||
|
}
|
||||||
|
return isBlocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MI32removeMIBLEsensor(uint8_t* MAC){
|
||||||
|
MIBLEsensors.erase( std::remove_if( MIBLEsensors.begin() , MIBLEsensors.end(), [MAC]( mi_sensor_t _sensor )->bool
|
||||||
|
{ return (memcmp(_sensor.MAC,MAC,6) == 0); }
|
||||||
|
), end( MIBLEsensors ) );
|
||||||
}
|
}
|
||||||
/***********************************************************************\
|
/***********************************************************************\
|
||||||
* Read data from connections
|
* Read data from connections
|
||||||
|
@ -1691,7 +1735,8 @@ void MI32EverySecond(bool restart){
|
||||||
if(MI32.state.beaconScanCounter!=0){
|
if(MI32.state.beaconScanCounter!=0){
|
||||||
MI32.state.beaconScanCounter--;
|
MI32.state.beaconScanCounter--;
|
||||||
if(MI32.state.beaconScanCounter==0){
|
if(MI32.state.beaconScanCounter==0){
|
||||||
MI32showScanResults();
|
MI32.mode.shallShowScanResult = 1;
|
||||||
|
MI32triggerTele();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1875,11 +1920,70 @@ void CmndMi32Beacon(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CmndMi32Block(void){
|
||||||
|
if (XdrvMailbox.data_len == 0) {
|
||||||
|
switch (XdrvMailbox.index) {
|
||||||
|
case 0:
|
||||||
|
MIBLEBlockList.clear();
|
||||||
|
// AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: size of ilist: %u"), MIBLEBlockList.size());
|
||||||
|
ResponseCmndIdxChar(PSTR("block list cleared"));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ResponseCmndIdxChar(PSTR("show block list"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MAC_t _MACasBytes;
|
||||||
|
MI32HexStringToBytes(XdrvMailbox.data,_MACasBytes.buf);
|
||||||
|
switch (XdrvMailbox.index) {
|
||||||
|
case 0:
|
||||||
|
MIBLEBlockList.erase( std::remove_if( begin( MIBLEBlockList ), end( MIBLEBlockList ), [_MACasBytes]( MAC_t& _entry )->bool
|
||||||
|
{ return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); }
|
||||||
|
), end( MIBLEBlockList ) );
|
||||||
|
ResponseCmndIdxChar(PSTR("MAC not blocked anymore"));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
bool _notYetInList = true;
|
||||||
|
for (auto &_entry : MIBLEBlockList) {
|
||||||
|
if (memcmp(_entry.buf,_MACasBytes.buf,6) == 0){
|
||||||
|
_notYetInList = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_notYetInList) {
|
||||||
|
MIBLEBlockList.push_back(_MACasBytes);
|
||||||
|
ResponseCmndIdxChar(XdrvMailbox.data);
|
||||||
|
MI32removeMIBLEsensor(_MACasBytes.buf);
|
||||||
|
}
|
||||||
|
// AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: size of ilist: %u"), MIBLEBlockList.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MI32.mode.shallShowBlockList = 1;
|
||||||
|
MI32triggerTele();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CmndMi32Option(void){
|
||||||
|
bool onOff = atoi(XdrvMailbox.data);
|
||||||
|
switch(XdrvMailbox.index) {
|
||||||
|
case 0:
|
||||||
|
MI32.option.allwaysAggregate = onOff;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
MI32.option.noSummary = onOff;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
MI32.option.directBridgeMode = onOff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ResponseCmndDone();
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Presentation
|
* Presentation
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916a{m}%u%s / %u{e}";
|
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0917{m}%u%s / %u{e}";
|
||||||
const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}";
|
const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}";
|
||||||
const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
|
const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
|
||||||
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}";
|
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}";
|
||||||
|
@ -1892,6 +1996,12 @@ const char HTTP_MI32_HL[] PROGMEM = "{s}<hr>{m}<hr>{e}";
|
||||||
void MI32Show(bool json)
|
void MI32Show(bool json)
|
||||||
{
|
{
|
||||||
if (json) {
|
if (json) {
|
||||||
|
if(MI32.mode.shallShowScanResult) {
|
||||||
|
return MI32showScanResults();
|
||||||
|
}
|
||||||
|
else if(MI32.mode.shallShowBlockList) {
|
||||||
|
return MI32showBlockList();
|
||||||
|
}
|
||||||
#ifdef USE_HOME_ASSISTANT
|
#ifdef USE_HOME_ASSISTANT
|
||||||
bool _noSummarySave = MI32.option.noSummary;
|
bool _noSummarySave = MI32.option.noSummary;
|
||||||
bool _minimalSummarySave = MI32.option.minimalSummary;
|
bool _minimalSummarySave = MI32.option.minimalSummary;
|
||||||
|
|
Loading…
Reference in New Issue