mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 19:26:37 +00:00
Merge pull request #9609 from Staars/MI32
MI_ESP32: add beacon functions
This commit is contained in:
commit
384d6b2d21
@ -20,6 +20,8 @@
|
|||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
Version yyyymmdd Action Description
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
|
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
|
||||||
-------
|
-------
|
||||||
0.9.1.4 20201020 changed - use BearSSL for decryption, revert to old TELEPERIOD-cycle as default
|
0.9.1.4 20201020 changed - use BearSSL for decryption, revert to old TELEPERIOD-cycle as default
|
||||||
@ -57,7 +59,6 @@
|
|||||||
void MI32scanEndedCB(NimBLEScanResults results);
|
void MI32scanEndedCB(NimBLEScanResults results);
|
||||||
void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify);
|
void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify);
|
||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t perPage = 4;
|
uint16_t perPage = 4;
|
||||||
uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
||||||
@ -82,11 +83,13 @@ struct {
|
|||||||
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 all = 0;
|
uint32_t all = 0;
|
||||||
} mode;
|
} mode;
|
||||||
struct {
|
struct {
|
||||||
uint8_t sensor; // points to to the number 0...255
|
uint8_t sensor; // points to to the number 0...255
|
||||||
|
uint8_t beaconScanCounter; // countdown timer in seconds
|
||||||
} state;
|
} state;
|
||||||
struct {
|
struct {
|
||||||
uint32_t allwaysAggregate:1; // always show all known values of one sensor in brdigemode
|
uint32_t allwaysAggregate:1; // always show all known values of one sensor in brdigemode
|
||||||
@ -226,7 +229,7 @@ struct mi_sensor_t{
|
|||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
} eventType;
|
} eventType;
|
||||||
|
|
||||||
int rssi;
|
int RSSI;
|
||||||
uint32_t lastTime;
|
uint32_t lastTime;
|
||||||
uint32_t lux;
|
uint32_t lux;
|
||||||
float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx
|
float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx
|
||||||
@ -250,8 +253,28 @@ struct mi_sensor_t{
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct scan_entry_t {
|
||||||
|
uint8_t MAC[6];
|
||||||
|
uint16_t CID;
|
||||||
|
uint16_t SVC;
|
||||||
|
uint16_t UUID;
|
||||||
|
int32_t RSSI;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct generic_beacon_t {
|
||||||
|
uint8_t MAC[6];
|
||||||
|
uint32_t time;
|
||||||
|
int32_t RSSI;
|
||||||
|
uint16_t CID; // company identifier
|
||||||
|
uint16_t UUID; // the first, if more than one exists
|
||||||
|
uint16_t SVC;
|
||||||
|
bool active = false;
|
||||||
|
};
|
||||||
|
|
||||||
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::vector<scan_entry_t> MINBLEscanResult;
|
||||||
|
|
||||||
static BLEScan* MI32Scan;
|
static BLEScan* MI32Scan;
|
||||||
|
|
||||||
@ -263,7 +286,9 @@ static BLEScan* MI32Scan;
|
|||||||
|
|
||||||
const char S_JSON_MI32_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s\":%d}";
|
const char S_JSON_MI32_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s\":%d}";
|
||||||
const char S_JSON_MI32_COMMAND[] PROGMEM = "{\"" D_CMND_MI32 "%s%s\"}";
|
const char S_JSON_MI32_COMMAND[] PROGMEM = "{\"" D_CMND_MI32 "%s%s\"}";
|
||||||
const char kMI32_Commands[] PROGMEM = "Period|Time|Page|Battery|Unit|Key";
|
// const char S_JSON_MI32_BCOMMAND_SVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s\":%s}";
|
||||||
|
const char S_JSON_MI32_BCOMMAND_SVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s%u\":\"%s\"}";
|
||||||
|
const char kMI32_Commands[] PROGMEM = "Period|Time|Page|Battery|Unit|Key|Beacon";
|
||||||
|
|
||||||
#define FLORA 1
|
#define FLORA 1
|
||||||
#define MJ_HT_V1 2
|
#define MJ_HT_V1 2
|
||||||
@ -318,7 +343,8 @@ enum MI32_Commands { // commands useable in console or rules
|
|||||||
CMND_MI32_PAGE, // sensor entries per web page, which will be shown alternated
|
CMND_MI32_PAGE, // sensor entries per web page, which will be shown alternated
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MI32_TASK {
|
enum MI32_TASK {
|
||||||
@ -329,6 +355,12 @@ enum MI32_TASK {
|
|||||||
MI32_TASK_UNIT = 4,
|
MI32_TASK_UNIT = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MI32_BEACON_CMND {
|
||||||
|
MI32_BEACON_ON = 0,
|
||||||
|
MI32_BEACON_OFF = 1,
|
||||||
|
MI32_BEACON_DEL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Classes
|
* Classes
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -360,32 +392,40 @@ class MI32SensorCallback : public NimBLEClientCallbacks {
|
|||||||
class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
||||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Advertised Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length());
|
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Advertised Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length());
|
||||||
if (advertisedDevice->getServiceDataCount() == 0) {
|
int RSSI = advertisedDevice->getRSSI();
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length());
|
|
||||||
MI32Scan->erase(advertisedDevice->getAddress());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint16_t uuid = advertisedDevice->getServiceDataUUID(0).getNative()->u16.value;
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("UUID: %x"),uuid);
|
|
||||||
uint8_t addr[6];
|
uint8_t addr[6];
|
||||||
memcpy(addr,advertisedDevice->getAddress().getNative(),6);
|
memcpy(addr,advertisedDevice->getAddress().getNative(),6);
|
||||||
MI32_ReverseMAC(addr);
|
MI32_ReverseMAC(addr);
|
||||||
int rssi = 0xffff;
|
if (advertisedDevice->getServiceDataCount() == 0) {
|
||||||
if(advertisedDevice->haveRSSI()) {
|
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length());
|
||||||
rssi = advertisedDevice->getRSSI();
|
if(MI32.state.beaconScanCounter==0 && !MI32.mode.activeBeacon){
|
||||||
|
MI32Scan->erase(advertisedDevice->getAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("RSSI: %d"),rssi); // actually i never got a 0xffff
|
uint16_t UUID = advertisedDevice->getServiceDataUUID(0).getNative()->u16.value;
|
||||||
if(uuid==0xfe95) {
|
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("UUID: %x"),UUID);
|
||||||
MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),advertisedDevice->getServiceData(0).length(), addr, rssi);
|
|
||||||
|
size_t ServiceDataLength = advertisedDevice->getServiceData(0).length();
|
||||||
|
if(UUID==0xfe95) {
|
||||||
|
MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
||||||
}
|
}
|
||||||
else if(uuid==0xfdcd) {
|
else if(UUID==0xfdcd) {
|
||||||
MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),advertisedDevice->getServiceData(0).length(), addr, rssi);
|
MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
||||||
}
|
}
|
||||||
else if(uuid==0x181a) { //ATC
|
else if(UUID==0x181a) { //ATC
|
||||||
MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),advertisedDevice->getServiceData(0).length(), addr, rssi);
|
MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %x: %s Buffer: %u"), uuid, advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length());
|
if(MI32.state.beaconScanCounter!=0 || MI32.mode.activeBeacon){
|
||||||
|
MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr);
|
||||||
|
}
|
||||||
|
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %x: %s Buffer: %u"), UUID, advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData(0).length());
|
||||||
MI32Scan->erase(advertisedDevice->getAddress());
|
MI32Scan->erase(advertisedDevice->getAddress());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -421,6 +461,54 @@ void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pD
|
|||||||
* Helper functions
|
* Helper functions
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove all colons from null terminated char array
|
||||||
|
*
|
||||||
|
* @param _string Typically representing a MAC-address like AA:BB:CC:DD:EE:FF
|
||||||
|
*/
|
||||||
|
void MI32stripColon(char* _string){
|
||||||
|
uint32_t _length = strlen(_string);
|
||||||
|
uint32_t _index = 0;
|
||||||
|
while (_index < _length) {
|
||||||
|
char c = _string[_index];
|
||||||
|
if(c==':'){
|
||||||
|
memmove(_string+_index,_string+_index+1,_length-_index);
|
||||||
|
}
|
||||||
|
_index++;
|
||||||
|
}
|
||||||
|
_string[_index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert string that repesents a hexadecimal number to a byte array
|
||||||
|
*
|
||||||
|
* @param _string input string in format: AABBCCDDEEFF or AA:BB:CC:DD:EE:FF, caseinsensitive
|
||||||
|
* @param _mac target byte array must match the correct size (i.e. AA:BB -> uint8_t bytes[2])
|
||||||
|
*/
|
||||||
|
|
||||||
|
void MI32HexStringToBytes(char* _string, uint8_t* _byteArray) {
|
||||||
|
MI32stripColon(_string);
|
||||||
|
UpperCase(_string,_string);
|
||||||
|
uint32_t index = 0;
|
||||||
|
uint32_t _end = strlen(_string);
|
||||||
|
memset(_byteArray,0,_end/2);
|
||||||
|
while (index < _end) {
|
||||||
|
char c = _string[index];
|
||||||
|
uint8_t value = 0;
|
||||||
|
if(c >= '0' && c <= '9')
|
||||||
|
value = (c - '0');
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
value = (10 + (c - 'A'));
|
||||||
|
_byteArray[(index/2)] += value << (((index + 1) % 2) * 4);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reverse an array of 6 bytes
|
||||||
|
*
|
||||||
|
* @param _mac a byte array of size 6 (typicalliy representing a MAC address)
|
||||||
|
*/
|
||||||
void MI32_ReverseMAC(uint8_t _mac[]){
|
void MI32_ReverseMAC(uint8_t _mac[]){
|
||||||
uint8_t _reversedMAC[6];
|
uint8_t _reversedMAC[6];
|
||||||
for (uint8_t i=0; i<6; i++){
|
for (uint8_t i=0; i<6; i++){
|
||||||
@ -432,9 +520,7 @@ void MI32_ReverseMAC(uint8_t _mac[]){
|
|||||||
#ifdef USE_MI_DECRYPTION
|
#ifdef USE_MI_DECRYPTION
|
||||||
void MI32AddKey(char* payload){
|
void MI32AddKey(char* payload){
|
||||||
mi_bindKey_t keyMAC;
|
mi_bindKey_t keyMAC;
|
||||||
memset(keyMAC.buf,0,sizeof(keyMAC));
|
MI32HexStringToBytes(payload,keyMAC.buf);
|
||||||
UpperCase(payload,payload);
|
|
||||||
MI32KeyMACStringToBytes(payload,keyMAC.buf);
|
|
||||||
bool unknownKey = true;
|
bool unknownKey = true;
|
||||||
for(uint32_t i=0; i<MIBLEbindKeys.size(); i++){
|
for(uint32_t i=0; i<MIBLEbindKeys.size(); i++){
|
||||||
if(memcmp(keyMAC.MAC,MIBLEbindKeys[i].MAC,sizeof(keyMAC.MAC))==0){
|
if(memcmp(keyMAC.MAC,MIBLEbindKeys[i].MAC,sizeof(keyMAC.MAC))==0){
|
||||||
@ -448,29 +534,6 @@ void MI32AddKey(char* payload){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert combined key-MAC-string to
|
|
||||||
*
|
|
||||||
* @param _string input string in format: AABBCCDDEEFF... (upper case!), must be 44 chars!!
|
|
||||||
* @param _mac target byte array with fixed size of 16 + 6
|
|
||||||
*/
|
|
||||||
void MI32KeyMACStringToBytes(char* _string,uint8_t _keyMAC[]) { //uppercase
|
|
||||||
uint32_t index = 0;
|
|
||||||
while (index < 44) {
|
|
||||||
char c = _string[index];
|
|
||||||
uint8_t value = 0;
|
|
||||||
if(c >= '0' && c <= '9')
|
|
||||||
value = (c - '0');
|
|
||||||
else if (c >= 'A' && c <= 'F')
|
|
||||||
value = (10 + (c - 'A'));
|
|
||||||
_keyMAC[(index/2)] += value << (((index + 1) % 2) * 4);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: %s to:"),_string);
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: key-array: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"),_keyMAC[0],_keyMAC[1],_keyMAC[2],_keyMAC[3],_keyMAC[4],_keyMAC[5],_keyMAC[6],_keyMAC[7],_keyMAC[8],_keyMAC[9],_keyMAC[10],_keyMAC[11],_string,_keyMAC[12],_keyMAC[13],_keyMAC[14],_keyMAC[15]);
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: MAC-array: %02X%02X%02X%02X%02X%02X"),_keyMAC[16],_keyMAC[17],_keyMAC[18],_keyMAC[19],_keyMAC[20],_keyMAC[21]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decrypts payload in place
|
* @brief Decrypts payload in place
|
||||||
*
|
*
|
||||||
@ -533,10 +596,7 @@ int MI32_decryptPacket(char *_buf, uint16_t _bufSize, uint32_t _type){
|
|||||||
br_ccm_run(&ctx, 0, payload, data_len);
|
br_ccm_run(&ctx, 0, payload, data_len);
|
||||||
memcpy((uint8_t*)packet->payload+1,payload,data_len); //back to the packet
|
memcpy((uint8_t*)packet->payload+1,payload,data_len); //back to the packet
|
||||||
|
|
||||||
// br_ccm_get_tag(&ctx, &checkTag);
|
|
||||||
ret = br_ccm_check_tag(&ctx, &tag);
|
ret = br_ccm_check_tag(&ctx, &tag);
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("packetTag: %08x"),tag);
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("computedTag: %08x"),checkTag);
|
|
||||||
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]);
|
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]);
|
||||||
return ret-1;
|
return ret-1;
|
||||||
@ -611,7 +671,7 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter)
|
|||||||
_newSensor.feature.raw = 0;
|
_newSensor.feature.raw = 0;
|
||||||
_newSensor.temp =NAN;
|
_newSensor.temp =NAN;
|
||||||
_newSensor.bat=0x00;
|
_newSensor.bat=0x00;
|
||||||
_newSensor.rssi=0xffff;
|
_newSensor.RSSI=0xffff;
|
||||||
_newSensor.lux = 0x00ffffff;
|
_newSensor.lux = 0x00ffffff;
|
||||||
switch (_type)
|
switch (_type)
|
||||||
{
|
{
|
||||||
@ -670,6 +730,10 @@ void MI32triggerTele(void){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is called after every finding of new BLE sensor
|
||||||
|
*
|
||||||
|
*/
|
||||||
void MI32StatusInfo() {
|
void MI32StatusInfo() {
|
||||||
MI32.mode.shallShowStatusInfo = 0;
|
MI32.mode.shallShowStatusInfo = 0;
|
||||||
Response_P(PSTR("{\"%s\":{\"found\":%u}}"), D_CMND_MI32, MIBLEsensors.size());
|
Response_P(PSTR("{\"%s\":{\"found\":%u}}"), D_CMND_MI32, MIBLEsensors.size());
|
||||||
@ -684,6 +748,7 @@ void MI32Init(void) {
|
|||||||
|
|
||||||
MIBLEsensors.reserve(10);
|
MIBLEsensors.reserve(10);
|
||||||
MIBLEbindKeys.reserve(10);
|
MIBLEbindKeys.reserve(10);
|
||||||
|
MINBLEscanResult.reserve(20);
|
||||||
MI32.mode.init = false;
|
MI32.mode.init = false;
|
||||||
if (!MI32.mode.init) {
|
if (!MI32.mode.init) {
|
||||||
NimBLEDevice::init("");
|
NimBLEDevice::init("");
|
||||||
@ -1167,6 +1232,7 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize){
|
|||||||
decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize, LYWSD03MMC); //start with PID
|
decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize, LYWSD03MMC); //start with PID
|
||||||
// AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)&_beacon.productID,_bufSize);
|
// AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)&_beacon.productID,_bufSize);
|
||||||
}
|
}
|
||||||
|
else return; // 0x3058 holds no data, TODO: check for unpaired devices, that need connections
|
||||||
break;
|
break;
|
||||||
case MJYD2S:
|
case MJYD2S:
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MJYD2S: %x"),_beacon.frame);
|
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MJYD2S: %x"),_beacon.frame);
|
||||||
@ -1180,18 +1246,6 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize){
|
|||||||
if (_beacon.frame != 0x5910){
|
if (_beacon.frame != 0x5910){
|
||||||
decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize,MJYD2S); //start with PID
|
decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize,MJYD2S); //start with PID
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
// This seems to be some kind of wake-up packet only, as it shows up before all kinds of messages, not only motion
|
|
||||||
// if(millis()-MIBLEsensors[_slot].lastTime>120000){
|
|
||||||
// MIBLEsensors[_slot].eventType = 1;
|
|
||||||
// MIBLEsensors[_slot].events++;
|
|
||||||
// MIBLEsensors[_slot].shallSendMQTT = 1;
|
|
||||||
// MIBLEsensors[_slot].lastTime = millis();
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: MJYD2S secondary PIR"));
|
|
||||||
// MIBLEsensors[_slot].NMT = 0;
|
|
||||||
// MI32.mode.shallTriggerTele = 1;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(decryptRet!=0){
|
if(decryptRet!=0){
|
||||||
@ -1315,13 +1369,13 @@ if(decryptRet!=0){
|
|||||||
if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1;
|
if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int rssi){
|
void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){
|
||||||
ATCPacket_t *_packet = (ATCPacket_t*)_buf;
|
ATCPacket_t *_packet = (ATCPacket_t*)_buf;
|
||||||
uint32_t _slot = MIBLEgetSensorSlot(_packet->MAC, 0x0a1c, _packet->frameCnt); // This must be a hard-coded fake ID
|
uint32_t _slot = MIBLEgetSensorSlot(_packet->MAC, 0x0a1c, _packet->frameCnt); // This must be a hard-coded fake ID
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
|
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
|
||||||
if(_slot==0xff) return;
|
if(_slot==0xff) return;
|
||||||
|
|
||||||
MIBLEsensors[_slot].rssi=rssi;
|
MIBLEsensors[_slot].RSSI=RSSI;
|
||||||
|
|
||||||
MIBLEsensors.at(_slot).temp = (float)(__builtin_bswap16(_packet->temp))/10.0f;
|
MIBLEsensors.at(_slot).temp = (float)(__builtin_bswap16(_packet->temp))/10.0f;
|
||||||
MIBLEsensors.at(_slot).hum = (float)_packet->hum;
|
MIBLEsensors.at(_slot).hum = (float)_packet->hum;
|
||||||
@ -1334,13 +1388,13 @@ void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int rssi)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int rssi){ // no MiBeacon
|
void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ // no MiBeacon
|
||||||
uint8_t _addr[6];
|
uint8_t _addr[6];
|
||||||
memcpy(_addr,addr,6);
|
memcpy(_addr,addr,6);
|
||||||
uint32_t _slot = MIBLEgetSensorSlot(_addr, 0x0576, 0); // This must be hard-coded, no object-id in Cleargrass-packet, we have no packet counter too
|
uint32_t _slot = MIBLEgetSensorSlot(_addr, 0x0576, 0); // This must be hard-coded, no object-id in Cleargrass-packet, we have no packet counter too
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
|
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
|
||||||
if(_slot==0xff) return;
|
if(_slot==0xff) return;
|
||||||
MIBLEsensors[_slot].rssi=rssi;
|
MIBLEsensors[_slot].RSSI=RSSI;
|
||||||
cg_packet_t _packet;
|
cg_packet_t _packet;
|
||||||
memcpy((char*)&_packet,_buf,sizeof(_packet));
|
memcpy((char*)&_packet,_buf,sizeof(_packet));
|
||||||
switch (_packet.mode){
|
switch (_packet.mode){
|
||||||
@ -1375,7 +1429,7 @@ void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int rssi
|
|||||||
if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1;
|
if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int rssi) {
|
void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) {
|
||||||
if(bufsize<9) { //9 is from the NLIGHT
|
if(bufsize<9) { //9 is from the NLIGHT
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1385,11 +1439,137 @@ void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int rssi) {
|
|||||||
memcpy(_addr,addr,6);
|
memcpy(_addr,addr,6);
|
||||||
uint16_t _slot = MIBLEgetSensorSlot(_addr, _type, buf[4]);
|
uint16_t _slot = MIBLEgetSensorSlot(_addr, _type, buf[4]);
|
||||||
if(_slot!=0xff) {
|
if(_slot!=0xff) {
|
||||||
MIBLEsensors[_slot].rssi=rssi;
|
MIBLEsensors[_slot].RSSI=RSSI;
|
||||||
MI32parseMiBeacon(buf,_slot,bufsize);
|
MI32parseMiBeacon(buf,_slot,bufsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse a BLE advertisement packet
|
||||||
|
*
|
||||||
|
* @param payload
|
||||||
|
* @param payloadLength
|
||||||
|
* @param CID
|
||||||
|
* @param SVC
|
||||||
|
* @param UUID
|
||||||
|
*/
|
||||||
|
void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID){
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("MI32: Beacon:____________"));
|
||||||
|
for (uint32_t i = 0; i<payloadLength;){
|
||||||
|
uint32_t ADtype = payload[i+1];
|
||||||
|
uint32_t offset = payload[i];
|
||||||
|
switch(ADtype){
|
||||||
|
case 0x01:
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("Flags: %02x"), payload[i+2]);
|
||||||
|
break;
|
||||||
|
case 0x02: case 0x03:
|
||||||
|
*UUID = payload[i+3]*256 + payload[i+2];
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("UUID: %04x"), *UUID);
|
||||||
|
break;
|
||||||
|
case 0x08: case 0x09:
|
||||||
|
{
|
||||||
|
uint8_t _saveChar = payload[i+offset+1];
|
||||||
|
payload[i+offset+1] = 0;
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("Name: %s"), (char*)&payload[i+2]);
|
||||||
|
payload[i+offset+1] = _saveChar;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x0a:
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("TxPow: %02u"), payload[i+2]);
|
||||||
|
break;
|
||||||
|
case 0xff:
|
||||||
|
*CID = payload[i+3]*256 + payload[i+2];
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("CID: %04x"), *CID);
|
||||||
|
break;
|
||||||
|
case 0x16:
|
||||||
|
*SVC = payload[i+3]*256 + payload[i+2];
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("SVC: %04x"), *SVC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i+=offset+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle a generic BLE advertisment in a running scan or to check a beacon
|
||||||
|
*
|
||||||
|
* @param payload
|
||||||
|
* @param payloadLength
|
||||||
|
* @param RSSI
|
||||||
|
* @param addr
|
||||||
|
*/
|
||||||
|
void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, uint8_t* addr){
|
||||||
|
if(MI32.state.beaconScanCounter==0){ //handle beacon
|
||||||
|
for(auto &_beacon : MIBLEbeacons){
|
||||||
|
if(memcmp(addr,_beacon.MAC,6)==0){
|
||||||
|
MI32ParseGenericBeacon(payload,payloadLength,&_beacon.CID,&_beacon.SVC,&_beacon.UUID);
|
||||||
|
_beacon.time = 0;
|
||||||
|
_beacon.RSSI = RSSI;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// else handle scan
|
||||||
|
if(MINBLEscanResult.size()>19) {
|
||||||
|
AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: Scan buffer full"));
|
||||||
|
MI32.state.beaconScanCounter = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(auto _scanResult : MINBLEscanResult){
|
||||||
|
if(memcmp(addr,_scanResult.MAC,6)==0){
|
||||||
|
// AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: known device"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scan_entry_t _new;
|
||||||
|
_new.RSSI = RSSI;
|
||||||
|
_new.CID = 0;
|
||||||
|
_new.SVC = 0;
|
||||||
|
_new.UUID = 0;
|
||||||
|
memcpy(_new.MAC,addr,sizeof(_new.MAC));
|
||||||
|
MI32ParseGenericBeacon(payload,payloadLength,&_new.CID,&_new.SVC,&_new.UUID);
|
||||||
|
MINBLEscanResult.push_back(_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a beacon defined by its MAC-address, if only zeros are given, the beacon will be deactivated
|
||||||
|
*
|
||||||
|
* @param index 1-4 beacons are currently supported
|
||||||
|
* @param data null terminated char array representing a MAC-address in hex
|
||||||
|
*/
|
||||||
|
void MI32addBeacon(uint8_t index, char* data){
|
||||||
|
auto &_new = MIBLEbeacons[index-1]; //TODO: check
|
||||||
|
MI32HexStringToBytes(data,_new.MAC);
|
||||||
|
char _MAC[18];
|
||||||
|
ToHex_P(MIBLEbeacons[index-1].MAC,6,_MAC,18,':');
|
||||||
|
char _empty[6] = {0};
|
||||||
|
_new.time = 0;
|
||||||
|
if(memcmp(_empty,_new.MAC,6) == 0){
|
||||||
|
_new.active = false;
|
||||||
|
AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: beacon%u deactivated"), index);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_new.active = true;
|
||||||
|
MI32.mode.activeBeacon = 1;
|
||||||
|
AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: beacon added with MAC: %s"), _MAC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Present BLE scan in the console, after that deleting the scan data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void MI32showScanResults(){
|
||||||
|
AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: found %u devices in scan:"), MINBLEscanResult.size());
|
||||||
|
for(auto _scanResult : MINBLEscanResult){
|
||||||
|
char _MAC[18];
|
||||||
|
ToHex_P(_scanResult.MAC,6,_MAC,18,':');
|
||||||
|
AddLog_P2(LOG_LEVEL_INFO,PSTR("MAC: %s _ CID: %04x _ SVC: %04x _ UUID: %04x _ RSSI: %d"), _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.RSSI);
|
||||||
|
}
|
||||||
|
MINBLEscanResult.clear();
|
||||||
|
}
|
||||||
/***********************************************************************\
|
/***********************************************************************\
|
||||||
* Read data from connections
|
* Read data from connections
|
||||||
\***********************************************************************/
|
\***********************************************************************/
|
||||||
@ -1473,6 +1653,25 @@ void MI32EverySecond(bool restart){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t _idx = 0;
|
||||||
|
uint32_t _activeBeacons = 0;
|
||||||
|
for (auto &_beacon : MIBLEbeacons){
|
||||||
|
_idx++;
|
||||||
|
if(_beacon.active == false) continue;
|
||||||
|
_activeBeacons++;
|
||||||
|
_beacon.time++;
|
||||||
|
Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _beacon.time);
|
||||||
|
XdrvRulesProcess();
|
||||||
|
}
|
||||||
|
if(_activeBeacons==0) MI32.mode.activeBeacon = 0;
|
||||||
|
|
||||||
|
if(MI32.state.beaconScanCounter!=0){
|
||||||
|
MI32.state.beaconScanCounter--;
|
||||||
|
if(MI32.state.beaconScanCounter==0){
|
||||||
|
MI32showScanResults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(MI32.mode.shallShowStatusInfo == 1){
|
if(MI32.mode.shallShowStatusInfo == 1){
|
||||||
MI32StatusInfo();
|
MI32StatusInfo();
|
||||||
}
|
}
|
||||||
@ -1522,16 +1721,17 @@ void MI32EverySecond(bool restart){
|
|||||||
if(_counter==0) {
|
if(_counter==0) {
|
||||||
|
|
||||||
MI32.state.sensor = _nextSensorSlot;
|
MI32.state.sensor = _nextSensorSlot;
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u of %u"),D_CMND_MI32, MI32.state.sensor, MIBLEsensors.size()-1);
|
|
||||||
MI32.mode.canScan = 0;
|
MI32.mode.canScan = 0;
|
||||||
// if (MI32.mode.runningScan|| MI32.mode.connected || MI32.mode.willConnect) return;
|
// if (MI32.mode.runningScan|| MI32.mode.connected || MI32.mode.willConnect) return;
|
||||||
if (MI32.mode.connected || MI32.mode.willConnect) return;
|
if (MI32.mode.connected || MI32.mode.willConnect) return;
|
||||||
_nextSensorSlot++;
|
_nextSensorSlot++;
|
||||||
MI32.mode.canConnect = 1;
|
MI32.mode.canConnect = 1;
|
||||||
if(MI32.mode.connected == 0) {
|
if(MI32.mode.connected == 0) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("will connect to %s"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] );
|
if (MI32.mode.shallReadBatt) {
|
||||||
|
//TODO: decide automatically, which sensor can not work without connections
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u of %u"),D_CMND_MI32, MI32.state.sensor, MIBLEsensors.size()-1);
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("will connect to %s"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] );
|
||||||
|
|
||||||
if (MI32.mode.shallReadBatt) {
|
|
||||||
MI32StartTask(MI32_TASK_BATT);
|
MI32StartTask(MI32_TASK_BATT);
|
||||||
}
|
}
|
||||||
#ifndef USE_MI_DECRYPTION // turn off connections, because we only listen to advertisements
|
#ifndef USE_MI_DECRYPTION // turn off connections, because we only listen to advertisements
|
||||||
@ -1638,6 +1838,32 @@ bool MI32Cmd(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif //USE_MI_DECRYPTION
|
#endif //USE_MI_DECRYPTION
|
||||||
|
case CMND_MI32_BEACON:
|
||||||
|
if (XdrvMailbox.data_len == 0) {
|
||||||
|
switch(XdrvMailbox.index){
|
||||||
|
case 0:
|
||||||
|
MI32.state.beaconScanCounter = 8;
|
||||||
|
Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("\"scanning\""));
|
||||||
|
break;
|
||||||
|
case 1: case 2: case 3: case 4:
|
||||||
|
char _MAC[18];
|
||||||
|
ToHex_P(MIBLEbeacons[XdrvMailbox.index-1].MAC,6,_MAC,18,':');
|
||||||
|
Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,_MAC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(XdrvMailbox.data_len == 12 || XdrvMailbox.data_len == 17){ // MAC-string without or with colons
|
||||||
|
switch(XdrvMailbox.index){
|
||||||
|
case 1: case 2: case 3: case 4:
|
||||||
|
MI32addBeacon(XdrvMailbox.index,XdrvMailbox.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// else for Unknown command
|
// else for Unknown command
|
||||||
serviced = false;
|
serviced = false;
|
||||||
@ -1654,7 +1880,7 @@ bool MI32Cmd(void) {
|
|||||||
* Presentation
|
* Presentation
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0.9.1.5{m}%u%s / %u{e}";
|
const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916{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}";
|
||||||
@ -1825,8 +2051,7 @@ void MI32Show(bool json)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MI32.option.showRSSI && MI32.mode.triggeredTele) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].rssi);
|
if (MI32.option.showRSSI) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].RSSI);
|
||||||
|
|
||||||
|
|
||||||
if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step
|
if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step
|
||||||
ResponseAppend_P(PSTR("}"));
|
ResponseAppend_P(PSTR("}"));
|
||||||
@ -1838,6 +2063,17 @@ void MI32Show(bool json)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
MI32.mode.triggeredTele = 0;
|
MI32.mode.triggeredTele = 0;
|
||||||
|
// add beacons
|
||||||
|
uint32_t _idx = 0;
|
||||||
|
for (auto _beacon : MIBLEbeacons){
|
||||||
|
_idx++;
|
||||||
|
if(!_beacon.active) continue;
|
||||||
|
char _MAC[18];
|
||||||
|
ToHex_P(_beacon.MAC,6,_MAC,18,':');
|
||||||
|
ResponseAppend_P(PSTR(",\"Beacon%u\":{\"MAC\":\"%s\",\"CID\":\"0x%04x\",\"SVC\":\"0x%04x\","
|
||||||
|
"\"UUID\":\"0x%04x\",\"Time\":%u,\"RSSI\":%d}"),
|
||||||
|
_idx,_MAC,_beacon.CID,_beacon.SVC,_beacon.UUID,_beacon.time,_beacon.RSSI);
|
||||||
|
}
|
||||||
#ifdef USE_HOME_ASSISTANT
|
#ifdef USE_HOME_ASSISTANT
|
||||||
if(hass_mode==2){
|
if(hass_mode==2){
|
||||||
MI32.option.noSummary = _noSummarySave;
|
MI32.option.noSummary = _noSummarySave;
|
||||||
@ -1865,7 +2101,7 @@ void MI32Show(bool json)
|
|||||||
char _MAC[18];
|
char _MAC[18];
|
||||||
ToHex_P(MIBLEsensors[i].MAC,6,_MAC,18,':');
|
ToHex_P(MIBLEsensors[i].MAC,6,_MAC,18,':');
|
||||||
WSContentSend_PD(HTTP_MI32_MAC, kMI32DeviceType[MIBLEsensors[i].type-1], D_MAC_ADDRESS, _MAC);
|
WSContentSend_PD(HTTP_MI32_MAC, kMI32DeviceType[MIBLEsensors[i].type-1], D_MAC_ADDRESS, _MAC);
|
||||||
WSContentSend_PD(HTTP_RSSI, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].rssi);
|
WSContentSend_PD(HTTP_RSSI, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].RSSI);
|
||||||
if (MIBLEsensors[i].type==FLORA) {
|
if (MIBLEsensors[i].type==FLORA) {
|
||||||
if (!isnan(MIBLEsensors[i].temp)) {
|
if (!isnan(MIBLEsensors[i].temp)) {
|
||||||
char temperature[FLOATSZ];
|
char temperature[FLOATSZ];
|
||||||
@ -1909,6 +2145,27 @@ void MI32Show(bool json)
|
|||||||
}
|
}
|
||||||
if (MIBLEsensors.size()%MI32.perPage==0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; }
|
if (MIBLEsensors.size()%MI32.perPage==0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; }
|
||||||
if (_page>MIBLEsensors.size()/MI32.perPage) { _page = 0; }
|
if (_page>MIBLEsensors.size()/MI32.perPage) { _page = 0; }
|
||||||
|
|
||||||
|
//always at the bottom of the page
|
||||||
|
uint32_t _idx=0;
|
||||||
|
if(MI32.mode.activeBeacon){
|
||||||
|
WSContentSend_PD(HTTP_MI32_HL);
|
||||||
|
char _sbeacon[] = "Beacon1";
|
||||||
|
for (auto &_beacon : MIBLEbeacons){
|
||||||
|
_idx++;
|
||||||
|
if(!_beacon.active) continue;
|
||||||
|
WSContentSend_PD(HTTP_MI32_HL);
|
||||||
|
_sbeacon[6] = _idx + 0x30;
|
||||||
|
char _MAC[18];
|
||||||
|
ToHex_P(_beacon.MAC,6,_MAC,18,':');
|
||||||
|
WSContentSend_PD(HTTP_MI32_MAC, _sbeacon, D_MAC_ADDRESS, _MAC);
|
||||||
|
WSContentSend_PD(HTTP_RSSI, _sbeacon, _beacon.RSSI);
|
||||||
|
if(_beacon.CID!=0) WSContentSend_PD(PSTR("{s}Beacon%u CID{m}0x%04X{e}"),_idx, _beacon.CID);
|
||||||
|
if(_beacon.SVC!=0) WSContentSend_PD(PSTR("{s}Beacon%u SVC{m}0x%04X{e}"),_idx, _beacon.SVC);
|
||||||
|
if(_beacon.UUID!=0) WSContentSend_PD(PSTR("{s}Beacon%u UUID{m}0x%04X{e}"),_idx, _beacon.UUID);
|
||||||
|
WSContentSend_PD(PSTR("{s}Beacon%u Time{m}%u seconds{e}"),_idx, _beacon.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user