feature update, fix Flora values

This commit is contained in:
Staars 2020-08-07 15:22:53 +02:00
parent 497be768c8
commit 8a9af14fad

View File

@ -20,6 +20,9 @@
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
Version yyyymmdd Action Description Version yyyymmdd Action Description
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
0.9.4.0 20200807 added - multiple backports from the HM10-driver (NLIGHT,MJYD2S,YEERC,MHOC401,MHOC303),
fixing Flora values, adding realtime-bridge, better battery for LYWSD03 and MHOC401
---
0.9.3.1 20200412 added - clean ups, code shrink, battery bugfix 0.9.3.1 20200412 added - clean ups, code shrink, battery bugfix
--- ---
0.9.3.0 20200322 added - multi page web view, command HM10PAGE, polling for MJ_HT_V1, 0.9.3.0 20200322 added - multi page web view, command HM10PAGE, polling for MJ_HT_V1,
@ -70,12 +73,23 @@ struct {
uint32_t connected:1; uint32_t connected:1;
uint32_t subscribed:1; uint32_t subscribed:1;
uint32_t autoScan:1; uint32_t autoScan:1;
uint32_t shallTriggerTele:1;
uint32_t triggeredTele:1;
// uint32_t shallClearResults:1; // BLE scan results
// TODO: more to come // TODO: more to come
} mode; } mode;
struct { struct {
uint8_t sensor; // points to to the number 0...255 uint8_t sensor; // points to to the number 0...255
// TODO: more to come // TODO: more to come
} state; } state;
struct {
uint32_t allwaysAggregate:1;
uint32_t showRSSI:1;
uint32_t ignoreBogusBattery:1;
uint32_t noSummary:1;
uint32_t minimalSummary:1;
uint32_t noRealTime:1;
} option;
} HM10; } HM10;
#pragma pack(1) // byte-aligned structures to read the sensor data #pragma pack(1) // byte-aligned structures to read the sensor data
@ -83,6 +97,7 @@ struct {
struct { struct {
uint16_t temp; uint16_t temp;
uint8_t hum; uint8_t hum;
uint16_t volt;
} LYWSD0x_HT; } LYWSD0x_HT;
struct { struct {
uint8_t spare; uint8_t spare;
@ -102,7 +117,7 @@ struct mi_beacon_t{
uint16_t frame; uint16_t frame;
uint16_t productID; uint16_t productID;
uint8_t counter; uint8_t counter;
uint8_t Mac[6]; uint8_t MAC[6];
uint8_t spare; uint8_t spare;
uint8_t type; uint8_t type;
uint8_t ten; uint8_t ten;
@ -118,28 +133,79 @@ struct mi_beacon_t{
uint32_t lux; //07 uint32_t lux; //07
uint8_t moist; //08 uint8_t moist; //08
uint16_t fert; //09 uint16_t fert; //09
uint32_t NMT; //17
struct{ //01
uint16_t num;
uint8_t longPress;
}Btn;
}; };
uint8_t padding[12];
}; };
#pragma pack(0) #pragma pack(0)
struct mi_sensor_t{ struct mi_sensor_t{
uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6 uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6
uint8_t serial[6]; uint8_t lastCnt; //device generated counter of the packet
uint8_t shallSendMQTT;
uint8_t showedUp; uint8_t showedUp;
uint8_t MAC[6];
union {
struct {
uint32_t temp:1;
uint32_t hum:1;
uint32_t tempHum:1; //every hum sensor has temp too, easier to use Tasmota dew point functions
uint32_t lux:1;
uint32_t moist:1;
uint32_t fert:1;
uint32_t bat:1;
uint32_t NMT:1;
uint32_t PIR:1;
uint32_t Btn:1;
};
uint32_t raw;
} feature;
union {
struct {
uint32_t temp:1;
uint32_t hum:1;
uint32_t tempHum:1; //can be combined from the sensor
uint32_t lux:1;
uint32_t moist:1;
uint32_t fert:1;
uint32_t bat:1;
uint32_t NMT:1;
uint32_t motion:1;
uint32_t noMotion:1;
uint32_t Btn:1;
};
uint32_t raw;
} eventType;
int rssi;
uint32_t lastTime;
uint32_t lux;
float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx
union { union {
struct { struct {
float moisture; uint8_t moisture;
float fertility; uint16_t fertility;
uint32_t lux; char firmware[6]; // actually only for FLORA but hopefully we can add for more devices
}; // Flora }; // Flora
struct { struct {
float hum; float hum;
}; // MJ_HT_V1, LYWSD0x }; // MJ_HT_V1, LYWSD0x
struct {
uint16_t events; //"alarms" since boot
uint32_t NMT; // no motion time in seconds for the MJYD2S
};
uint16_t Btn;
};
union {
uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1)
}; };
uint8_t bat; // all sensors
}; };
std::vector<mi_sensor_t> MIBLEsensors; std::vector<mi_sensor_t> MIBLEsensors;
/*********************************************************************************************\ /*********************************************************************************************\
@ -158,22 +224,41 @@ const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto
#define LYWSD03MMC 4 #define LYWSD03MMC 4
#define CGG1 5 #define CGG1 5
#define CGD1 6 #define CGD1 6
#define NLIGHT 7
#define MJYD2S 8
#define YEERC 9
#define MHOC401 10
#define MHOC303 11
const uint16_t kHM10SlaveID[6]={ 0x0098, // Flora #define HM10_TYPES 11 //count this manually
const uint16_t kHM10SlaveID[HM10_TYPES]={
0x0098, // Flora
0x01aa, // MJ_HT_V1 0x01aa, // MJ_HT_V1
0x045b, // LYWSD02 0x045b, // LYWSD02
0x055b, // LYWSD03 0x055b, // LYWSD03
0x0347, // CGG1 0x0347, // CGG1
0x0576 // CGD1 0x0576, // CGD1
0x03dd, // NLIGHT
0x07f6, // MJYD2S
0x0153, // yee-rc
0x0387, // MHO-C401
0x06d3 // MHO-C303
}; };
const char kHM10SlaveType1[] PROGMEM = "Flora"; const char kHM10DeviceType1[] PROGMEM = "Flora";
const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; const char kHM10DeviceType2[] PROGMEM = "MJ_HT_V1";
const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; const char kHM10DeviceType3[] PROGMEM = "LYWSD02";
const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; const char kHM10DeviceType4[] PROGMEM = "LYWSD03";
const char kHM10SlaveType5[] PROGMEM = "CGG1"; const char kHM10DeviceType5[] PROGMEM = "CGG1";
const char kHM10SlaveType6[] PROGMEM = "CGD1"; const char kHM10DeviceType6[] PROGMEM = "CGD1";
const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4,kHM10SlaveType5,kHM10SlaveType6}; const char kHM10DeviceType7[] PROGMEM = "NLIGHT";
const char kHM10DeviceType8[] PROGMEM = "MJYD2S";
const char kHM10DeviceType9[] PROGMEM = "YEERC";
const char kHM10DeviceType10[] PROGMEM ="MHOC401";
const char kHM10DeviceType11[] PROGMEM ="MHOC303";
const char * kHM10DeviceType[] PROGMEM = {kHM10DeviceType1,kHM10DeviceType2,kHM10DeviceType3,kHM10DeviceType4,kHM10DeviceType5,kHM10DeviceType6,kHM10DeviceType7,kHM10DeviceType8,kHM10DeviceType9,kHM10DeviceType10,kHM10DeviceType11};
/*********************************************************************************************\ /*********************************************************************************************\
* enumerations * enumerations
@ -283,16 +368,16 @@ void HM10_Discovery_Scan(void) {
HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,2); // status HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,2); // status
} }
void HM10_Read_LYWSD03(void) { void HM10_Read_LYWSD03(void) { //and MHO-C401
HM10_Launchtask(TASK_HM10_CONN,0,1); // connect HM10_Launchtask(TASK_HM10_CONN,0,1); // connect
HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN
HM10_Launchtask(TASK_HM10_SUB_L3,2,20); // subscribe HM10_Launchtask(TASK_HM10_SUB_L3,2,20); // subscribe
HM10_Launchtask(TASK_HM10_UN_L3,3,80); // unsubscribe HM10_Launchtask(TASK_HM10_UN_L3,3,80); // unsubscribe
HM10_Launchtask(TASK_HM10_READ_BT_L3,4,5); // read Battery // HM10_Launchtask(TASK_HM10_READ_BT_L3,4,5); // read Battery
HM10_Launchtask(TASK_HM10_DISCONN,5,5); // disconnect HM10_Launchtask(TASK_HM10_DISCONN,4,5); // disconnect
} }
void HM10_Read_LYWSD02(void) { void HM10_Read_LYWSD02(void) { //and MHO-C303
HM10_Launchtask(TASK_HM10_CONN,0,1); // connect HM10_Launchtask(TASK_HM10_CONN,0,1); // connect
HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN
HM10_Launchtask(TASK_HM10_SUB_L2,2,20); // subscribe HM10_Launchtask(TASK_HM10_SUB_L2,2,20); // subscribe
@ -338,15 +423,15 @@ void HM10_Read_MJ_HT_V1(void) {
/** /**
* @brief Return the slot number of a known sensor or return create new sensor slot * @brief Return the slot number of a known sensor or return create new sensor slot
* *
* @param _serial BLE address of the sensor * @param _MAC BLE address of the sensor
* @param _type Type number of the sensor * @param _type Type number of the sensor
* @return uint32_t Known or new slot in the sensors-vector * @return uint32_t Known or new slot in the sensors-vector
*/ */
uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){
DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type); DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type);
bool _success = false; bool _success = false;
for (uint32_t i=0;i<6;i++){ // i < sizeof(kHM10SlaveID) gives compiler warning for (uint32_t i=0;i<HM10_TYPES;i++){
if(_type == kHM10SlaveID[i]){ if(_type == kHM10SlaveID[i]){
DEBUG_SENSOR_LOG(PSTR("HM10: ID is type %u"), i); DEBUG_SENSOR_LOG(PSTR("HM10: ID is type %u"), i);
_type = i+1; _type = i+1;
@ -360,38 +445,63 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){
DEBUG_SENSOR_LOG(PSTR("%s: vector size %u"),D_CMND_HM10, MIBLEsensors.size()); DEBUG_SENSOR_LOG(PSTR("%s: vector size %u"),D_CMND_HM10, MIBLEsensors.size());
for(uint32_t i=0; i<MIBLEsensors.size(); i++){ for(uint32_t i=0; i<MIBLEsensors.size(); i++){
if(memcmp(_serial,MIBLEsensors[i].serial,sizeof(_serial))==0){ if(memcmp(_MAC,MIBLEsensors[i].MAC,sizeof(_MAC))==0){
DEBUG_SENSOR_LOG(PSTR("%s: known sensor at slot: %u"),D_CMND_HM10, i); DEBUG_SENSOR_LOG(PSTR("%s: known sensor at slot: %u"),D_CMND_HM10, i);
if(MIBLEsensors[i].showedUp < 4){ // if we got an intact packet, the sensor should show up several times if(MIBLEsensors[i].showedUp < 4){ // if we got an intact packet, the sensor should show up several times
MIBLEsensors[i].showedUp++; // count up to the above number ... now we are pretty sure MIBLEsensors[i].showedUp++; // count up to the above number ... now we are pretty sure
} }
return i; return i;
} }
DEBUG_SENSOR_LOG(PSTR("%s: i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors[i].serial[5], MIBLEsensors[i].serial[4],MIBLEsensors[i].serial[3],MIBLEsensors[i].serial[2],MIBLEsensors[i].serial[1],MIBLEsensors[i].serial[0]); DEBUG_SENSOR_LOG(PSTR("%s: i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors[i].MAC[5], MIBLEsensors[i].MAC[4],MIBLEsensors[i].MAC[3],MIBLEsensors[i].MAC[2],MIBLEsensors[i].MAC[1],MIBLEsensors[i].MAC[0]);
DEBUG_SENSOR_LOG(PSTR("%s: n: %x %x %x %x %x %x"),D_CMND_HM10, _serial[5], _serial[4], _serial[3],_serial[2],_serial[1],_serial[0]); DEBUG_SENSOR_LOG(PSTR("%s: n: %x %x %x %x %x %x"),D_CMND_HM10, _MAC[5], _MAC[4], _MAC[3],_MAC[2],_MAC[1],_MAC[0]);
} }
DEBUG_SENSOR_LOG(PSTR("%s: found new sensor"),D_CMND_HM10); DEBUG_SENSOR_LOG(PSTR("%s: found new sensor"),D_CMND_HM10);
mi_sensor_t _newSensor; mi_sensor_t _newSensor;
memcpy(_newSensor.serial,_serial, sizeof(_serial)); memcpy(_newSensor.MAC,_MAC, sizeof(_MAC));
_newSensor.type = _type; _newSensor.type = _type;
_newSensor.showedUp = 1; _newSensor.eventType.raw = 0;
_newSensor.feature.raw = 0;
_newSensor.temp =NAN; _newSensor.temp =NAN;
_newSensor.bat=0x00; _newSensor.bat=0x00;
switch (_type) _newSensor.rssi=_rssi * -1;
{ _newSensor.lux = 0x00ffffff;
case 1: switch (_type){
_newSensor.moisture =NAN; case FLORA:
_newSensor.fertility =NAN; _newSensor.moisture =0xff;
_newSensor.lux = 0x00ffffff; _newSensor.fertility =0xffff;
_newSensor.firmware[0]='\0';
_newSensor.feature.temp=1;
_newSensor.feature.moist=1;
_newSensor.feature.fert=1;
_newSensor.feature.lux=1;
_newSensor.feature.bat=1;
break; break;
case 2: case 3: case 4: case 5: case 6: case NLIGHT:
_newSensor.hum=NAN; _newSensor.events=0x00;
_newSensor.feature.PIR=1;
_newSensor.feature.NMT=1;
break;
case MJYD2S:
_newSensor.NMT=0;
_newSensor.events=0x00;
_newSensor.feature.PIR=1;
_newSensor.feature.NMT=1;
_newSensor.feature.lux=1;
_newSensor.feature.bat=1;
break;
case YEERC:
_newSensor.feature.Btn=1;
break; break;
default: default:
_newSensor.hum=NAN;
_newSensor.feature.temp=1;
_newSensor.feature.hum=1;
_newSensor.feature.tempHum=1;
_newSensor.feature.bat=1;
break; break;
} }
MIBLEsensors.push_back(_newSensor); MIBLEsensors.push_back(_newSensor);
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: new %s at slot: %u"),D_CMND_HM10, kHM10SlaveType[_type-1],MIBLEsensors.size()-1); AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: new %s at slot: %u"),D_CMND_HM10, kHM10DeviceType[_type-1],MIBLEsensors.size()-1);
return MIBLEsensors.size()-1; return MIBLEsensors.size()-1;
}; };
@ -415,6 +525,14 @@ void HM10SerialInit(void) {
HM10.mode.init = 1; HM10.mode.init = 1;
HM10.period = Settings.tele_period; HM10.period = Settings.tele_period;
DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10);
//test section for options - TODO: make a real interface for it
HM10.option.noRealTime = 1;
HM10.option.allwaysAggregate = 1;
HM10.option.showRSSI = 0;
HM10.option.ignoreBogusBattery = 1;
HM10.option.noSummary = 0;
HM10.option.minimalSummary = 0;
} }
return; return;
} }
@ -424,21 +542,23 @@ void HM10SerialInit(void) {
\*********************************************************************************************/ \*********************************************************************************************/
void HM10parseMiBeacon(char * _buf, uint32_t _slot){ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
// uint8_t _rssi;
// memcpy(&_rssi,_buf-1,1);
float _tempFloat; float _tempFloat;
mi_beacon_t _beacon; mi_beacon_t _beacon;
if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1){ if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1){
memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); // shift by one byte for the MJ_HT_V1 memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); // shift by one byte for the MJ_HT_V1
memcpy((uint8_t*)&_beacon.Mac,(uint8_t*)&_beacon.Mac+1,6); // but shift back the MAC memcpy((uint8_t*)&_beacon.MAC,(uint8_t*)&_beacon.MAC+1,6); // but shift back the MAC
} }
else{ else{
memcpy((void*)&_beacon,(void*)_buf, sizeof(_beacon)); memcpy((void*)&_beacon,(void*)_buf, sizeof(_beacon));
} }
HM10_ReverseMAC(_beacon.Mac); HM10_ReverseMAC(_beacon.MAC);
if(memcmp(_beacon.Mac,MIBLEsensors[_slot].serial,sizeof(_beacon.Mac))!=0){ if(memcmp(_beacon.MAC,MIBLEsensors[_slot].MAC,sizeof(_beacon.MAC))!=0){
if (MIBLEsensors[_slot].showedUp>3) return; // probably false alarm from a damaged packet if (MIBLEsensors[_slot].showedUp>3) return; // probably false alarm from a damaged packet
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: remove garbage sensor"),D_CMND_HM10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: remove garbage sensor"),D_CMND_HM10);
DEBUG_SENSOR_LOG(PSTR("%s i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors[_slot].serial[5], MIBLEsensors[_slot].serial[4],MIBLEsensors[_slot].serial[3],MIBLEsensors[_slot].serial[2],MIBLEsensors[_slot].serial[1],MIBLEsensors[_slot].serial[0]); DEBUG_SENSOR_LOG(PSTR("%s i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors[_slot].MAC[5], MIBLEsensors[_slot].MAC[4],MIBLEsensors[_slot].MAC[3],MIBLEsensors[_slot].MAC[2],MIBLEsensors[_slot].MAC[1],MIBLEsensors[_slot].MAC[0]);
DEBUG_SENSOR_LOG(PSTR("%s n: %x %x %x %x %x %x"),D_CMND_HM10, _beacon.Mac[5], _beacon.Mac[4], _beacon.Mac[3],_beacon.Mac[2],_beacon.Mac[1],_beacon.Mac[0]); DEBUG_SENSOR_LOG(PSTR("%s n: %x %x %x %x %x %x"),D_CMND_HM10, _beacon.MAC[5], _beacon.MAC[4], _beacon.MAC[3],_beacon.MAC[2],_beacon.MAC[1],_beacon.MAC[0]);
MIBLEsensors.erase(MIBLEsensors.begin()+_slot); MIBLEsensors.erase(MIBLEsensors.begin()+_slot);
return; return;
} }
@ -447,17 +567,24 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
DEBUG_SENSOR_LOG(PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]); DEBUG_SENSOR_LOG(PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]);
DEBUG_SENSOR_LOG(PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]); DEBUG_SENSOR_LOG(PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]);
// MIBLEsensors[_slot].rssi = _rssi;
if(MIBLEsensors[_slot].type==4 || MIBLEsensors[_slot].type==6){ if(MIBLEsensors[_slot].type==4 || MIBLEsensors[_slot].type==6){
DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type);
return; return;
} }
DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10SlaveType[MIBLEsensors[_slot].type-1],_slot); DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot);
switch(_beacon.type){ switch(_beacon.type){
case 0x01:
MIBLEsensors[_slot].Btn=_beacon.Btn.num + (_beacon.Btn.longPress/2)*6;
MIBLEsensors[_slot].eventType.Btn = 1;
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode 1: U16: %u Button"), MIBLEsensors[_slot].Btn );
break;
case 0x04: case 0x04:
_tempFloat=(float)(_beacon.temp)/10.0f; _tempFloat=(float)(_beacon.temp)/10.0f;
if(_tempFloat<60){ if(_tempFloat<60){
MIBLEsensors[_slot].temp=_tempFloat; MIBLEsensors[_slot].temp=_tempFloat;
DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated"));
MIBLEsensors[_slot].eventType.temp = 1;
} }
DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), _beacon.temp );
break; break;
@ -466,26 +593,30 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
if(_tempFloat<101){ if(_tempFloat<101){
MIBLEsensors[_slot].hum=_tempFloat; MIBLEsensors[_slot].hum=_tempFloat;
DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated"));
MIBLEsensors[_slot].eventType.hum = 1;
} }
DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), _beacon.hum); DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), _beacon.hum);
break; break;
case 0x07: case 0x07:
if(MIBLEsensors[_slot].type==MJYD2S){
MIBLEsensors[_slot].eventType.noMotion = 1;
}
MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff;
DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff);
break; break;
case 0x08: case 0x08:
_tempFloat =(float)_beacon.moist; if(_beacon.moist<101){
if(_tempFloat<100){ MIBLEsensors[_slot].moisture=_beacon.moist;
MIBLEsensors[_slot].moisture=_tempFloat;
DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated"));
MIBLEsensors[_slot].eventType.moist = 1;
} }
DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), _beacon.moist);
break; break;
case 0x09: case 0x09:
_tempFloat=(float)(_beacon.fert); if(_beacon.fert<65535){
if(_tempFloat<65535){ // ??? MIBLEsensors[_slot].fertility=_beacon.fert;
MIBLEsensors[_slot].fertility=_tempFloat;
DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated"));
MIBLEsensors[_slot].eventType.fert = 1;
} }
DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), _beacon.fert);
break; break;
@ -493,6 +624,7 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
if(_beacon.bat<101){ if(_beacon.bat<101){
MIBLEsensors[_slot].bat = _beacon.bat; MIBLEsensors[_slot].bat = _beacon.bat;
DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated"));
MIBLEsensors[_slot].eventType.bat = 1;
} }
DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), _beacon.bat); DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), _beacon.bat);
break; break;
@ -507,9 +639,13 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
MIBLEsensors[_slot].hum = _tempFloat; MIBLEsensors[_slot].hum = _tempFloat;
DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated"));
} }
MIBLEsensors[_slot].eventType.tempHum = 1;
DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum);
break; break;
} }
if(MIBLEsensors[_slot].eventType.raw == 0) return;
MIBLEsensors[_slot].shallSendMQTT = 1;
HM10.mode.shallTriggerTele = 1;
} }
void HM10ParseResponse(char *buf, uint16_t bufsize) { void HM10ParseResponse(char *buf, uint16_t bufsize) {
@ -527,6 +663,8 @@ void HM10ParseResponse(char *buf, uint16_t bufsize) {
if(_pos) { if(_pos) {
uint8_t _newMacArray[6] = {0}; uint8_t _newMacArray[6] = {0};
memcpy((void *)_newMacArray,(void *)(_pos+4),6); memcpy((void *)_newMacArray,(void *)(_pos+4),6);
uint32_t _rssi = 255- (uint8_t)(_pos[11]);
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("rssi: %u"),(255- (uint8_t)(_pos[11])));
HM10_ReverseMAC(_newMacArray); HM10_ReverseMAC(_newMacArray);
DEBUG_SENSOR_LOG(PSTR("%s: MAC-array: %02x%02x%02x%02x%02x%02x"),D_CMND_HM10,_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); DEBUG_SENSOR_LOG(PSTR("%s: MAC-array: %02x%02x%02x%02x%02x%02x"),D_CMND_HM10,_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]);
uint16_t _type=0xffff; uint16_t _type=0xffff;
@ -541,7 +679,7 @@ void HM10ParseResponse(char *buf, uint16_t bufsize) {
} }
} }
} }
uint16_t _slot = MIBLEgetSensorSlot(_newMacArray, _type); uint16_t _slot = MIBLEgetSensorSlot(_newMacArray, _type, _rssi);
if(_slot!=0xff) HM10parseMiBeacon(_pos,_slot); if(_slot!=0xff) HM10parseMiBeacon(_pos,_slot);
} }
else if (strstr(buf, "LOST")){ else if (strstr(buf, "LOST")){
@ -556,10 +694,10 @@ void HM10ParseResponse(char *buf, uint16_t bufsize) {
} }
void HM10readHT_LY(char *_buf){ void HM10readHT_LY(char *_buf){
DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]);
if(_buf[0]==0x4f && _buf[1]==0x4b) return; // "OK" if(_buf[0]==0x4f && _buf[1]==0x4b) return; // "OK"
if(_buf[0] != 0 && _buf[1] != 0){ if(_buf[0] != 0 && _buf[1] != 0){
memcpy(&LYWSD0x_HT,(void *)_buf,3); memcpy(&LYWSD0x_HT,(void *)_buf,sizeof(LYWSD0x_HT));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u"),D_CMND_HM10,LYWSD0x_HT.temp,LYWSD0x_HT.hum); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u"),D_CMND_HM10,LYWSD0x_HT.temp,LYWSD0x_HT.hum);
uint32_t _slot = HM10.state.sensor; uint32_t _slot = HM10.state.sensor;
@ -577,6 +715,13 @@ void HM10readHT_LY(char *_buf){
MIBLEsensors[_slot].hum = _tempFloat; MIBLEsensors[_slot].hum = _tempFloat;
DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated")); DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated"));
} }
MIBLEsensors[_slot].eventType.tempHum = 1;
if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401){
MIBLEsensors[_slot].bat = ((float)LYWSD0x_HT.volt-2100.0f)/12.0f;
MIBLEsensors[_slot].eventType.bat = 1;
}
MIBLEsensors[_slot].shallSendMQTT = 1;
HM10.mode.shallTriggerTele = 1;
} }
} }
@ -603,6 +748,9 @@ void HM10readHT_CGD1(char *_buf){
MIBLEsensors[_slot].hum = _tempFloat; MIBLEsensors[_slot].hum = _tempFloat;
DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated"));
} }
MIBLEsensors[_slot].eventType.tempHum = 1;
MIBLEsensors[_slot].shallSendMQTT = 1;
HM10.mode.shallTriggerTele = 1;
} }
} }
@ -630,6 +778,9 @@ void HM10readHT_MJ_HT_V1(char *_buf){
MIBLEsensors[_slot].hum = _tempFloat; MIBLEsensors[_slot].hum = _tempFloat;
DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated")); DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated"));
} }
MIBLEsensors[_slot].eventType.tempHum = 1;
MIBLEsensors[_slot].shallSendMQTT = 1;
HM10.mode.shallTriggerTele = 1;
} }
void HM10readTLMF(char *_buf){ void HM10readTLMF(char *_buf){
@ -648,12 +799,14 @@ void HM10readTLMF(char *_buf){
MIBLEsensors[_slot].showedUp=255; // this sensor is real MIBLEsensors[_slot].showedUp=255; // this sensor is real
} }
MIBLEsensors[_slot].lux = Flora_TLMF.lux; MIBLEsensors[_slot].lux = Flora_TLMF.lux;
_tempFloat=(float)Flora_TLMF.moist; MIBLEsensors[_slot].moisture = Flora_TLMF.moist;
if(_tempFloat<100){ MIBLEsensors[_slot].fertility = Flora_TLMF.fert;
MIBLEsensors[_slot].moisture = _tempFloat; MIBLEsensors[_slot].eventType.temp = 1;
} MIBLEsensors[_slot].eventType.lux = 1;
MIBLEsensors[_slot].eventType.moist = 1;
MIBLEsensors[_slot].fertility = (float)Flora_TLMF.fert; MIBLEsensors[_slot].eventType.fert = 1;
MIBLEsensors[_slot].shallSendMQTT = 1;
HM10.mode.shallTriggerTele = 1;
HM10.mode.awaiting = none; HM10.mode.awaiting = none;
HM10.current_task_delay = 0; HM10.current_task_delay = 0;
@ -663,13 +816,19 @@ void HM10readTLMF(char *_buf){
bool HM10readBat(char *_buf){ bool HM10readBat(char *_buf){
DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]);
if(_buf[0]==0x4f && _buf[1]==0x4b) return false; // "OK" if(_buf[0]==0x4f && _buf[1]==0x4b) return false; // "OK"
uint32_t _slot = HM10.state.sensor;
// if(HM10.option.ignoreBogusBattery){
// if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401) return true;
// }
if(_buf[0] != 0){ if(_buf[0] != 0){
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_HM10,_buf[0]); AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_HM10,_buf[0]);
uint32_t _slot = HM10.state.sensor;
DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot);
if(_buf[0]<101){ if(_buf[0]<101){
MIBLEsensors[_slot].bat=_buf[0]; MIBLEsensors[_slot].bat=_buf[0];
MIBLEsensors[_slot].showedUp=255; // this sensor is real MIBLEsensors[_slot].showedUp=255; // this sensor is real
MIBLEsensors[_slot].eventType.bat = 1;
MIBLEsensors[_slot].shallSendMQTT = 1;
HM10.mode.shallTriggerTele = 1;
return true; return true;
} }
} }
@ -694,7 +853,18 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds
success = true; success = true;
} }
if(i==0) return success; if(i==0){
if(HM10.mode.shallTriggerTele){ // let us use the spare time for other things
HM10.mode.shallTriggerTele=0;
if(HM10.option.noRealTime){
HM10.mode.triggeredTele=0;
return success;
}
HM10.mode.triggeredTele=1;
HM10triggerTele();
}
return success;
}
switch (HM10.mode.awaiting){ switch (HM10.mode.awaiting){
case bat: case bat:
@ -784,8 +954,8 @@ void HM10_TaskEvery100ms(){
break; break;
case TASK_HM10_CONN: case TASK_HM10_CONN:
char _con[20]; char _con[20];
sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors[HM10.state.sensor].serial[0],MIBLEsensors[HM10.state.sensor].serial[1],MIBLEsensors[HM10.state.sensor].serial[2],MIBLEsensors[HM10.state.sensor].serial[3],MIBLEsensors[HM10.state.sensor].serial[4],MIBLEsensors[HM10.state.sensor].serial[5]); sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors[HM10.state.sensor].MAC[0],MIBLEsensors[HM10.state.sensor].MAC[1],MIBLEsensors[HM10.state.sensor].MAC[2],MIBLEsensors[HM10.state.sensor].MAC[3],MIBLEsensors[HM10.state.sensor].MAC[4],MIBLEsensors[HM10.state.sensor].MAC[5]);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: connect %s"),D_CMND_HM10, _con); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: %s connect %s"),D_CMND_HM10,kHM10DeviceType[MIBLEsensors[HM10.state.sensor].type-1],_con);
HM10.current_task_delay = 2; // set task delay HM10.current_task_delay = 2; // set task delay
HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
runningTaskLoop = false; runningTaskLoop = false;
@ -825,11 +995,12 @@ void HM10_TaskEvery100ms(){
break; break;
case TASK_HM10_SUB_L2: case TASK_HM10_SUB_L2:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10);
HM10.current_task_delay = 25; // set task delay HM10.current_task_delay = 85; // set task delay
HM10.mode.awaiting = tempHumLY; HM10.mode.awaiting = tempHumLY;
HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
runningTaskLoop = false; runningTaskLoop = false;
HM10Serial->write("AT+NOTIFY_ON003C"); if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+NOTIFY_ON003C");
else HM10Serial->write("AT+NOTIFY_ON004B"); //MHO-C303
break; break;
case TASK_HM10_UN_L2: case TASK_HM10_UN_L2:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10);
@ -837,7 +1008,8 @@ void HM10_TaskEvery100ms(){
HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
runningTaskLoop = false; runningTaskLoop = false;
HM10.mode.awaiting = none; HM10.mode.awaiting = none;
HM10Serial->write("AT+NOTIFYOFF003C"); if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+NOTIFY_OFF003C");
else HM10Serial->write("AT+NOTIFY_OFF004B"); //MHO-C303
break; break;
case TASK_HM10_TIME_L2: case TASK_HM10_TIME_L2:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set time"),D_CMND_HM10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set time"),D_CMND_HM10);
@ -850,20 +1022,21 @@ void HM10_TaskEvery100ms(){
HM10Serial->write(Rtc.time_timezone / 60); HM10Serial->write(Rtc.time_timezone / 60);
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60));
break; break;
case TASK_HM10_READ_BT_L3: // case TASK_HM10_READ_BT_L3:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 003A"),D_CMND_HM10); // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 003A"),D_CMND_HM10);
HM10.current_task_delay = 2; // set task delay // HM10.current_task_delay = 2; // set task delay
HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); // HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
runningTaskLoop = false; // runningTaskLoop = false;
HM10Serial->write("AT+READDATA003A?"); // HM10Serial->write("AT+READDATA003A?");
HM10.mode.awaiting = bat; // HM10.mode.awaiting = bat;
break; // break;
case TASK_HM10_READ_BT_L2: case TASK_HM10_READ_BT_L2:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0043"),D_CMND_HM10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0043"),D_CMND_HM10);
HM10.current_task_delay = 2; // set task delay HM10.current_task_delay = 2; // set task delay
HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
runningTaskLoop = false; runningTaskLoop = false;
HM10Serial->write("AT+READDATA0043?"); if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+READDATA0043?");
else HM10Serial->write("AT+READDATA0052?"); //MHO-C303
HM10.mode.awaiting = bat; HM10.mode.awaiting = bat;
break; break;
case TASK_HM10_READ_BF_FL: case TASK_HM10_READ_BF_FL:
@ -1029,10 +1202,10 @@ void HM10EverySecond(bool restart){
case MJ_HT_V1: case CGG1: case MJ_HT_V1: case CGG1:
HM10_Read_MJ_HT_V1(); HM10_Read_MJ_HT_V1();
break; break;
case LYWSD02: case LYWSD02: case MHOC303:
HM10_Read_LYWSD02(); HM10_Read_LYWSD02();
break; break;
case LYWSD03MMC: case LYWSD03MMC: case MHOC401:
HM10_Read_LYWSD03(); HM10_Read_LYWSD03();
break; break;
case CGD1: case CGD1:
@ -1150,54 +1323,147 @@ bool HM10Cmd(void) {
return serviced; return serviced;
} }
/**
* @brief trigger real-time message
*
*/
void HM10triggerTele(void){
HM10.mode.triggeredTele = 1;
mqtt_data[0] = '\0';
if (MqttShowSensor()) {
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
#ifdef USE_RULES
RulesTeleperiod(); // Allow rule based HA messages
#endif // USE_RULES
}
}
/*********************************************************************************************\ /*********************************************************************************************\
* Presentation * Presentation
\*********************************************************************************************/ \*********************************************************************************************/
const char HTTP_HM10[] PROGMEM = "{s}HM10 V%u{m}%u%s / %u{e}"; const char HTTP_HM10[] PROGMEM = "{s}HM10 V%u{m}%u%s / %u{e}";
const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; const char HTTP_HM10_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}";
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}";
const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%uus/cm{e}"; const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}";
const char HTTP_HM10_HL[] PROGMEM = "{s}<hr>{m}<hr>{e}"; const char HTTP_HM10_HL[] PROGMEM = "{s}<hr>{m}<hr>{e}";
void HM10Show(bool json) void HM10Show(bool json)
{ {
if (json) { if (json) {
if(!HM10.mode.triggeredTele){
if(HM10.option.noSummary) return; // no message at TELEPERIOD
}
for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { for (uint32_t i = 0; i < MIBLEsensors.size(); i++) {
char slave[33]; if(HM10.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue;
sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors[i].type-1],MIBLEsensors[i].serial[3],MIBLEsensors[i].serial[4],MIBLEsensors[i].serial[5]); if(HM10.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue;
ResponseAppend_P(PSTR(",\"%s\":{"),slave);
if (MIBLEsensors[i].type==FLORA){ ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), // do not add the '{' now ...
if(!isnan(MIBLEsensors[i].temp)){ // this is the error code -> no temperature kHM10DeviceType[MIBLEsensors[i].type-1],
char temperature[FLOATSZ]; // all sensors have temperature MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]);
dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); uint32_t _positionCurlyBracket = strlen(mqtt_data); // ... this will be a ',' first, but later be replaced
if((!HM10.mode.triggeredTele && !HM10.option.minimalSummary)||HM10.mode.triggeredTele){
bool tempHumSended = false;
if(MIBLEsensors[i].feature.tempHum){
if(MIBLEsensors[i].eventType.tempHum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)) {
ResponseAppend_P(PSTR(","));
ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum);
tempHumSended = true;
} }
else {
ResponseAppend_P(PSTR("}"));
continue;
}
if(MIBLEsensors[i].lux!=0x0ffffff){ // this is the error code -> no lux
ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux);
}
if(!isnan(MIBLEsensors[i].moisture)){
ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%d"), MIBLEsensors[i].moisture);
}
if(!isnan(MIBLEsensors[i].fertility)){
ResponseAppend_P(PSTR(",\"Fertility\":%d"), MIBLEsensors[i].fertility);
} }
} }
if (MIBLEsensors[i].type>FLORA){ if(MIBLEsensors[i].feature.temp && !tempHumSended){
if(!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)){ if(MIBLEsensors[i].eventType.temp || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) {
ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); if (!isnan(MIBLEsensors[i].temp)) {
char temperature[FLOATSZ];
dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature);
}
} }
} }
if(MIBLEsensors[i].bat!=0x00){ // this is the error code -> no battery if(MIBLEsensors[i].feature.hum && !tempHumSended){
if(MIBLEsensors[i].eventType.hum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) {
if (!isnan(MIBLEsensors[i].hum)) {
char hum[FLOATSZ];
dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum);
ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum);
}
}
}
if (MIBLEsensors[i].feature.lux){
if(MIBLEsensors[i].eventType.lux || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
if (MIBLEsensors[i].lux!=0x0ffffff) { // this is the error code -> no lux
ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux);
}
}
}
if (MIBLEsensors[i].feature.moist){
if(MIBLEsensors[i].eventType.moist || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
if (MIBLEsensors[i].moisture!=0xff) {
ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture);
}
}
}
if (MIBLEsensors[i].feature.fert){
if(MIBLEsensors[i].eventType.fert || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
if (MIBLEsensors[i].fertility!=0xffff) {
ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility);
}
}
}
if (MIBLEsensors[i].feature.Btn){
if(MIBLEsensors[i].eventType.Btn){
ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn);
}
}
} // minimal summary
if (MIBLEsensors[i].feature.PIR){
if(MIBLEsensors[i].eventType.motion || !HM10.mode.triggeredTele){
if(HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); // only real-time
ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events);
}
else if(MIBLEsensors[i].eventType.noMotion && HM10.mode.triggeredTele){
ResponseAppend_P(PSTR(",\"PIR\":0"));
}
}
if (MIBLEsensors[i].type == FLORA && !HM10.mode.triggeredTele) {
if (MIBLEsensors[i].firmware[0] != '\0') { // this is the error code -> no firmware
ResponseAppend_P(PSTR(",\"Firmware\":\"%s\""), MIBLEsensors[i].firmware);
}
}
if (MIBLEsensors[i].feature.NMT || !HM10.mode.triggeredTele){
if(MIBLEsensors[i].eventType.NMT){
ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT);
}
}
if (MIBLEsensors[i].feature.bat){
if(MIBLEsensors[i].eventType.bat || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
if (MIBLEsensors[i].bat != 0x00) { // this is the error code -> no battery
ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat);
}
} }
ResponseAppend_P(PSTR("}")); }
if (HM10.option.showRSSI && HM10.mode.triggeredTele) 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
ResponseAppend_P(PSTR("}"));
mqtt_data[_positionCurlyBracket] = '{';
MIBLEsensors[i].eventType.raw = 0;
if(MIBLEsensors[i].shallSendMQTT==1){
MIBLEsensors[i].shallSendMQTT = 0;
break;
}
} }
HM10.mode.triggeredTele = 0;
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} else { } else {
static uint16_t _page = 0; static uint16_t _page = 0;
@ -1216,31 +1482,32 @@ void HM10Show(bool json)
WSContentSend_PD(HTTP_HM10, HM10.firmware, i+1,stemp,MIBLEsensors.size()); WSContentSend_PD(HTTP_HM10, HM10.firmware, i+1,stemp,MIBLEsensors.size());
for (i; i<j; i++) { for (i; i<j; i++) {
WSContentSend_PD(HTTP_HM10_HL); WSContentSend_PD(HTTP_HM10_HL);
WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors[i].type-1], D_MAC_ADDRESS, MIBLEsensors[i].serial[0], MIBLEsensors[i].serial[1],MIBLEsensors[i].serial[2],MIBLEsensors[i].serial[3],MIBLEsensors[i].serial[4],MIBLEsensors[i].serial[5]); WSContentSend_PD(HTTP_HM10_MAC, kHM10DeviceType[MIBLEsensors[i].type-1], D_MAC_ADDRESS, MIBLEsensors[i].MAC[0], MIBLEsensors[i].MAC[1],MIBLEsensors[i].MAC[2],MIBLEsensors[i].MAC[3],MIBLEsensors[i].MAC[4],MIBLEsensors[i].MAC[5]);
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];
dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors[i].type-1], temperature, TempUnit()); WSContentSend_PD(HTTP_SNS_TEMP, kHM10DeviceType[MIBLEsensors[i].type-1], temperature, TempUnit());
} }
if(MIBLEsensors[i].lux!=0x00ffffff){ // this is the error code -> no valid value if(MIBLEsensors[i].lux!=0x00ffffff){ // this is the error code -> no valid value
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].lux); WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].lux);
} }
if(!isnan(MIBLEsensors[i].moisture)){ if(MIBLEsensors[i].moisture!=0xff){
WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].moisture); WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].moisture);
} }
if(!isnan(MIBLEsensors[i].fertility)){ if(MIBLEsensors[i].fertility!=0xffff){
WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].fertility); WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].fertility);
} }
} }
if (MIBLEsensors[i].type>FLORA){ // everything "above" Flora if (MIBLEsensors[i].type>FLORA){ // everything "above" Flora
if(!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)){ if(!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)){
WSContentSend_THD(kHM10SlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); WSContentSend_THD(kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum);
} }
} }
if(MIBLEsensors[i].bat!=0x00){ if(MIBLEsensors[i].bat!=0x00){
WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); WSContentSend_PD(HTTP_BATTERY, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat);
} }
WSContentSend_PD(HTTP_RSSI, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].rssi);
} }
_counter++; _counter++;
if(_counter>3) { if(_counter>3) {