diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h
index e89903cee..1189620b8 100644
--- a/tasmota/language/bg-BG.h
+++ b/tasmota/language/bg-BG.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h
index d7e8e188e..aeff6b45a 100644
--- a/tasmota/language/cs-CZ.h
+++ b/tasmota/language/cs-CZ.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h
index b710e2975..ff6cfc2e4 100644
--- a/tasmota/language/de-DE.h
+++ b/tasmota/language/de-DE.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h
index 1c76125fa..e82e3dc53 100644
--- a/tasmota/language/el-GR.h
+++ b/tasmota/language/el-GR.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h
index b994b0409..df4fb86da 100644
--- a/tasmota/language/en-GB.h
+++ b/tasmota/language/en-GB.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h
index 6b8d60d01..89e8bb849 100644
--- a/tasmota/language/es-ES.h
+++ b/tasmota/language/es-ES.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h
index 4a861bd82..847e831ef 100644
--- a/tasmota/language/fr-FR.h
+++ b/tasmota/language/fr-FR.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Esclave Rst"
#define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_GPS_RX "GPS RX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h
index 166c5c735..abf6a640b 100644
--- a/tasmota/language/he-HE.h
+++ b/tasmota/language/he-HE.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h
index e1cec813a..8c3b63402 100644
--- a/tasmota/language/hu-HU.h
+++ b/tasmota/language/hu-HU.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h
index d7ec1e0e5..54c0a03d8 100644
--- a/tasmota/language/it-IT.h
+++ b/tasmota/language/it-IT.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h
index 55b8dba97..cc0b0443a 100644
--- a/tasmota/language/ko-KO.h
+++ b/tasmota/language/ko-KO.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h
index c0b5a9862..7362b3b76 100644
--- a/tasmota/language/nl-NL.h
+++ b/tasmota/language/nl-NL.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h
index 237bc66f1..403ac0908 100644
--- a/tasmota/language/pl-PL.h
+++ b/tasmota/language/pl-PL.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h
index c56262b11..2d60d1352 100644
--- a/tasmota/language/pt-BR.h
+++ b/tasmota/language/pt-BR.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h
index be9c6d493..b171eb997 100644
--- a/tasmota/language/pt-PT.h
+++ b/tasmota/language/pt-PT.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h
index 57dfa40e1..ccbe91c36 100644
--- a/tasmota/language/ru-RU.h
+++ b/tasmota/language/ru-RU.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "А"
diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h
index ee7afb49f..860082464 100644
--- a/tasmota/language/sk-SK.h
+++ b/tasmota/language/sk-SK.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h
index 351bf6dbb..d05bfd179 100644
--- a/tasmota/language/sv-SE.h
+++ b/tasmota/language/sv-SE.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h
index fced504d3..88e8bfe54 100644
--- a/tasmota/language/tr-TR.h
+++ b/tasmota/language/tr-TR.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "A"
diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h
index 81d02a8b3..f88ef9cb8 100644
--- a/tasmota/language/uk-UA.h
+++ b/tasmota/language/uk-UA.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "А"
diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h
index 12c368cd3..f14dc7ec9 100644
--- a/tasmota/language/zh-CN.h
+++ b/tasmota/language/zh-CN.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "安"
diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h
index 7c1b2e3fb..afb92d25c 100644
--- a/tasmota/language/zh-TW.h
+++ b/tasmota/language/zh-TW.h
@@ -635,6 +635,8 @@
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"
+#define D_SENSOR_HM10_RX "HM10 RX"
+#define D_SENSOR_HM10_TX "HM10 TX"
// Units
#define D_UNIT_AMPERE "安"
diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h
index 8b52aa7a7..0e01ffb8c 100644
--- a/tasmota/my_user_config.h
+++ b/tasmota/my_user_config.h
@@ -542,6 +542,7 @@
//#define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module)
//#define USE_GPS // Add support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM)
// #define USE_FLOG // Add support for GPS logging in OTA's Flash (Experimental) (+ 2.9kb flash, +8 bytes RAM)
+#define USE_HM10 // Add support for HM-10 as a BLE-bridge for the LYWSD03 (+... code)
// -- Power monitoring sensors --------------------
#define USE_ENERGY_MARGIN_DETECTION // Add support for Energy Margin detection (+1k6 code)
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index 59c09e177..4b30c2b55 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -218,6 +218,8 @@ enum UserSelectablePins {
GPIO_GPS_TX, // GPS serial interface
GPIO_DSB_OUT, // Pseudo Single wire DS18B20 or DS18S20
GPIO_DHT11_OUT, // Pseudo Single wire DHT11, DHT21, DHT22, AM2301, AM2302, AM2321
+ GPIO_HM10_RX, // HM10-BLE-Mijia-bridge serial interface
+ GPIO_HM10_TX, // HM10-BLE-Mijia-bridge serial interface
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality
@@ -300,6 +302,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|"
D_SENSOR_DS18X20 "o|" D_SENSOR_DHT11 "o|"
+ D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX
;
const char kSensorNamesFixed[] PROGMEM =
@@ -742,6 +745,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_GPS_RX, // GPS serial interface
GPIO_GPS_TX, // GPS serial interface
#endif
+#ifdef USE_HM10
+ GPIO_HM10_RX, // GPS serial interface
+ GPIO_HM10_TX, // GPS serial interface
+#endif
#ifdef USE_MGC3130
GPIO_MGC3130_XFER,
diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino
new file mode 100644
index 000000000..6255da01f
--- /dev/null
+++ b/tasmota/xsns_62_MI_HM10.ino
@@ -0,0 +1,764 @@
+/*
+ xsns_92_Ml_BLE.ino - MI-BLE-sensors via HM-10 support for Tasmota
+
+ Copyright (C) 2020 Christian Baars and Theo Arends
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+
+ --------------------------------------------------------------------------------------------
+ Version yyyymmdd Action Description
+ --------------------------------------------------------------------------------------------
+
+ ---
+ 0.9.0.0 20200130 started - initial development by Christian Baars (support LYWSD03 only)
+ forked - from arendst/tasmota - https://github.com/arendst/Tasmota
+
+*/
+#ifdef USE_HM10
+
+#define XSNS_62 62
+
+#include
+#include
+
+TasmotaSerial *HM10Serial;
+#define HM10_BAUDRATE 115200 // default with FW>700 is 115200
+
+#define HM10_MAX_TASK_NUMBER 12
+uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms
+
+#define HM10_MAX_RX_BUF 512
+char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0};
+
+struct {
+ uint8_t current_task_delay; // number of 100ms-cycles
+ uint8_t last_command;
+ uint16_t firmware;
+ uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
+ uint32_t serialSpeed;
+ struct {
+ uint32_t init:1;
+ uint32_t pending_task:1;
+ uint32_t subscribed:1;
+ uint32_t awaitingHT:1;
+ uint32_t awaitingB:1;
+ // TODO: more to come
+ } mode;
+ struct {
+ uint8_t sensor; // points to to the number 0...255
+ // TODO: more to come
+ } state;
+} HM10;
+
+#pragma pack(1)
+struct {
+ uint16_t temp;
+ uint8_t hum;
+} LYWSD03_HT;
+#pragma pack(0)
+
+struct mi_sensor_t{
+ uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4
+ uint8_t serial[6];
+ uint8_t showedUp;
+ float temp; //Flora, MJ_HT_V1, LYWSD0x
+ union {
+ struct {
+ float moisture;
+ float fertility;
+ uint16_t lux;
+ }; // Flora
+ struct {
+ float hum;
+ uint8_t bat;
+ }; // MJ_HT_V1, LYWSD0x
+ };
+};
+
+std::vector MIBLEsensors;
+
+/*********************************************************************************************\
+ * constants
+\*********************************************************************************************/
+
+#define D_CMND_HM10 "HM10"
+
+const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}";
+const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}";
+const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud";
+
+#define FLORA 1
+#define MJ_HT_V1 2
+#define LYWSD02 3
+#define LYWSD03MMC 4
+
+uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, // Flora
+ 0x58,0x2D,0x34, // MJ_HT_V1
+ 0xE7,0x2E,0x00, // LYWSD02
+ 0xA4,0xC1,0x38, // LYWSD03
+ };
+
+const char kHM10SlaveType1[] PROGMEM = "Flora";
+const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1";
+const char kHM10SlaveType3[] PROGMEM = "LYWSD02";
+const char kHM10SlaveType4[] PROGMEM = "LYWSD03";
+const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4};
+
+/*********************************************************************************************\
+ * enumerations
+\*********************************************************************************************/
+
+enum HM10_Commands { // commands useable in console or rules
+ CMND_HM10_DISC_SCAN, // re-scan for sensors
+ CMND_HM10_AT, // send AT-command for debugging and special configuration
+ CMND_HM10_PERIOD, // set period like TELE-period in seconds between read-cycles
+ CMND_HM10_BAUD // serial speed of ESP8266 (<-> HM10), does not change baud rate of HM10
+ };
+
+/*********************************************************************************************\
+ * Task codes defines
+\*********************************************************************************************/
+
+#define TASK_HM10_NOTASK 0 // nothing to be done
+#define TASK_HM10_ROLE1 1 // change role to 1
+#define TASK_HM10_IMME1 2 // change imme to 1
+#define TASK_HM10_RENEW 3 // device factory setting
+#define TASK_HM10_RESET 4 // device reset
+#define TASK_HM10_DISC 5 // device discovery scan
+#define TASK_HM10_CONN 6 // connect to given MAC
+#define TASK_HM10_VERSION 7 // query FW version
+#define TASK_HM10_NAME 8 // query device name
+#define TASK_HM10_FEEDBACK 9 // get device response
+#define TASK_HM10_DISCONN 10 // disconnect
+#define TASK_HM10_SUBSCR 11 // subscribe to service handle 37
+#define TASK_HM10_READ_HT 12 // read from handle 36 -> Hum & Temp
+#define TASK_HM10_FINDALLCHARS 13 // read all available characteristics
+#define TASK_HM10_UNSUBSCR 14 // subscribe service handle 37
+#define TASK_HM10_DELAY_SUB 15 // start reading from subscription delayed
+#define TASK_HM10_READ_BT 16 // read from handle 3A -> Battery
+
+#define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait
+
+/*********************************************************************************************\
+ * Helper functions
+\*********************************************************************************************/
+
+void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){
+ HM10_TASK_LIST[slot][0] = task;
+ HM10_TASK_LIST[slot][1] = delay;
+ HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; // the tasks must always be launched in ascending order!!
+ HM10.current_task_delay = HM10_TASK_LIST[0][1];
+}
+
+void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){
+ HM10.last_command = HM10_TASK_LIST[slot][0]; // save command
+ HM10_TASK_LIST[slot][0] = task;
+}
+
+/*********************************************************************************************\
+ * chained tasks
+\*********************************************************************************************/
+
+void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect
+ HM10_Launchtask(TASK_HM10_ROLE1,1,1); // set role to 1
+ HM10_Launchtask(TASK_HM10_IMME1,2,1); // set imme to 1
+ HM10_Launchtask(TASK_HM10_RESET,3,1); // reset Device
+ HM10_Launchtask(TASK_HM10_VERSION,4,10); // read SW Version
+ HM10_Launchtask(TASK_HM10_DISC,5,50); // discovery
+ }
+
+void HM10_Discovery_Scan(void) {
+ HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect
+ HM10_Launchtask(TASK_HM10_DISC,1,1); // discovery
+ }
+
+void HM10_Read_Sensor(void) {
+ HM10_Launchtask(TASK_HM10_CONN,0,1); // connect
+ HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN
+ HM10_Launchtask(TASK_HM10_SUBSCR,2,10); // subscribe
+ HM10_Launchtask(TASK_HM10_UNSUBSCR,3,80); // unsubscribe
+ HM10_Launchtask(TASK_HM10_READ_BT,4,5); // read Battery
+ HM10_Launchtask(TASK_HM10_DISCONN,5,5); // disconnect
+ }
+
+/**
+ * @brief Return the slot number of a known sensor or return create new sensor slot
+ *
+ * @param _serial BLE address of the sensor
+ * @param _type Type number of the sensor, 0xff for Auto-type
+ * @return uint32_t Known or new slot in the sensors-vector
+ */
+uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){
+ if(_type==0xff){
+ DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type"));
+ for (uint32_t i=0;i<4;i++){
+ if(memcmp(_serial,kHM10SlaveID+i,3)==0){
+ DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i);
+ _type = i+1;
+ }
+ else {
+ DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown"));
+ }
+ }
+ }
+ if(_type==0xff) return _type; // error
+
+ DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size());
+ for(uint32_t i=0; ibegin(HM10.serialSpeed)) {
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10);
+ if (HM10Serial->hardwareSerial()) {
+ ClaimSerial();
+ DEBUG_SENSOR_LOG(PSTR("HM10: claim HW"));
+ }
+ HM10_Reset();
+ HM10.mode.pending_task = 1;
+ HM10.mode.init = 1;
+ HM10.period = Settings.tele_period;
+ DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10);
+ }
+ return;
+}
+
+/**
+ * @brief convert Mac-String to byte array
+ *
+ * @param string Hex-string, must contain 12 chars (no error checking)
+ * @param _mac Must be a uint8_t[6], filled with zeros
+ */
+
+void HM10MACStringToBytes(const char* string, uint8_t _mac[]) {
+ uint32_t index = 0;
+ while (index < 12) {
+ char c = string[index];
+ uint32_t value = 0;
+ if(c >= '0' && c <= '9')
+ value = (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ value = (10 + (c - 'A'));
+ _mac[(index/2)] += value << (((index + 1) % 2) * 4);
+ // DEBUG_SENSOR_LOG(PSTR("HM10: Char: %c, Value: %x, Index/2: %u, valueadded: %x, MAC-index: %x"), c, value,(index/2),value << (((index + 1) % 2) * 4), _mac[index/2]);
+ index++;
+ }
+ DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]);
+}
+
+
+/*********************************************************************************************\
+ * parse the response
+\*********************************************************************************************/
+
+void HM10ParseResponse(char *buf) {
+ if (!strncmp(buf,"OK",2)) {
+ DEBUG_SENSOR_LOG(PSTR("HM10: got OK"));
+ }
+ if (!strncmp(buf,"HMSoft",6)) { //8
+ const char* _fw = "000";
+ memcpy((void *)_fw,(void *)(buf+8),3);
+ HM10.firmware = atoi(_fw);
+ DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware);
+ return;
+ }
+ char * _pos = strstr(buf, "IS0:");
+ if(_pos) {
+ const char* _mac = "000000000000";
+ memcpy((void *)_mac,(void *)(_pos+4),12);
+ DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac);
+ uint8_t _newMacArray[6] = {0};
+ HM10MACStringToBytes(_mac, _newMacArray);
+ DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]);
+ MIBLEgetSensorSlot(_newMacArray, 0xff);
+ }
+ else {
+ DEBUG_SENSOR_LOG(PSTR("HM10: empty response"));
+ }
+}
+
+void HM10readTempHum(char *_buf){
+ DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]);
+ if(_buf[0] != 0 && _buf[1] != 0){
+ memcpy(&LYWSD03_HT,(void *)_buf,3);
+ DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD03_HT.temp,LYWSD03_HT.hum);
+ uint32_t _slot = HM10.state.sensor;
+
+ DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot);
+ static float _tempFloat;
+ _tempFloat=(float)(LYWSD03_HT.temp)/100.0f;
+ if(_tempFloat<60){
+ MIBLEsensors.at(_slot).temp=_tempFloat;
+ HM10.mode.awaitingHT = false;
+ HM10.current_task_delay = 0;
+ }
+ _tempFloat=(float)LYWSD03_HT.hum;
+ if(_tempFloat<100){
+ MIBLEsensors.at(_slot).hum = _tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated"));
+ }
+ }
+}
+
+void HM10readBat(char *_buf){
+ DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]);
+ if(_buf[0] != 0){
+ DEBUG_SENSOR_LOG(PSTR("HM10: Battery: %u"),_buf[0]);
+ uint32_t _slot = HM10.state.sensor;
+ DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot);
+ if(_buf[0]<101){
+ MIBLEsensors.at(_slot).bat=_buf[0];
+ }
+ }
+}
+
+/*********************************************************************************************\
+ * handle the return value from the HM10
+\*********************************************************************************************/
+
+bool HM10SerialHandleFeedback(){ // every 50 milliseconds
+ bool success = false;
+ uint32_t i = 0;
+ char ret[HM10_MAX_RX_BUF] = {0}; // reset array with zeros
+
+
+ while(HM10Serial->available()) {
+ // delay(0);
+ if(iread();
+ }
+ i++;
+ success = true;
+ }
+ if(HM10.mode.awaitingHT) {
+ HM10readTempHum(ret);
+ }
+ else if(HM10.mode.awaitingB) {
+ HM10readBat(ret);
+ HM10.mode.awaitingB = false;
+ HM10.current_task_delay = 0;
+ }
+ else if(success) {
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret);
+ HM10ParseResponse(ret);
+ }
+ else {
+ // DEBUG_SENSOR_LOG(PSTR("%s got no response"),D_CMND_HM10);
+ }
+ return success;
+}
+
+/*********************************************************************************************\
+ * execute the next Task
+\*********************************************************************************************/
+
+void HM10_TaskEvery100ms(){
+ if (HM10.current_task_delay == 0) {
+ uint8_t i = 0;
+ bool runningTaskLoop = true;
+ while (runningTaskLoop) { // always iterate through the whole task list
+ switch(HM10_TASK_LIST[i][0]) { // handle the kind of task
+ case TASK_HM10_ROLE1:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+ROLE1");
+ break;
+ case TASK_HM10_IMME1:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+IMME1");
+ break;
+ case TASK_HM10_DISC:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10);
+ HM10.current_task_delay = 35; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+DISC?");
+ break;
+ case TASK_HM10_VERSION:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+VERR?");
+ break;
+ case TASK_HM10_NAME:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+NAME?");
+ break;
+ case TASK_HM10_CONN:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10);
+ HM10.current_task_delay = 2; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ char _con[20];
+ sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]);
+ HM10Serial->write(_con);
+ HM10.mode.awaitingB = false;
+ break;
+ case TASK_HM10_DISCONN:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT");
+ break;
+ case TASK_HM10_RESET:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10);
+ HM10Serial->write("AT+RESET");
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ break;
+ case TASK_HM10_SUBSCR:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10);
+ HM10.current_task_delay = 25; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+NOTIFY_ON0037");
+ break;
+ case TASK_HM10_UNSUBSCR:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10.mode.awaitingHT = false;
+ HM10Serial->write("AT+NOTIFYOFF0037");
+ break;
+ case TASK_HM10_READ_HT:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10);
+ HM10.current_task_delay = 0; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+READDATA0036?");
+ HM10.mode.awaitingHT = true;
+ break;
+ case TASK_HM10_READ_BT:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 003A"),D_CMND_HM10);
+ HM10.current_task_delay = 0; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+READDATA003A?");
+ HM10.mode.awaitingB = true;
+ break;
+ case TASK_HM10_FINDALLCHARS:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s find all chars"),D_CMND_HM10);
+ HM10.current_task_delay = 5; // set task delay
+ HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i);
+ runningTaskLoop = false;
+ HM10Serial->write("AT+FINDALLCHARS?");
+ break;
+ case TASK_HM10_FEEDBACK:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10);
+ HM10SerialHandleFeedback();
+ HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay
+ HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset
+ runningTaskLoop = false;
+ break;
+ case TASK_HM10_DELAY_SUB:
+ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10);
+ HM10SerialHandleFeedback();
+ HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay
+ HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset
+ HM10.mode.awaitingHT = true;
+ runningTaskLoop = false;
+ break;
+ case TASK_HM10_DONE: // this entry was already handled
+ // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%sFound done HM10_TASK"),D_CMND_HM10);
+ // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%snext slot:%u, i: %u"),D_CMND_HM10, HM10_TASK_LIST[i+1][0],i);
+ if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { // check the next entry and if there is none
+ DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10);
+ DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i);
+ for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { // do a clean-up:
+ DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j);
+ HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; // reset all task entries
+ HM10_TASK_LIST[j][1] = 0; // reset all delays
+ }
+ runningTaskLoop = false; // return to main loop
+ HM10.mode.pending_task = 0; // back to main loop control
+ break;
+ }
+ }
+ i++;
+ }
+ }
+ else {
+ HM10.current_task_delay--; // count down every 100 ms
+ }
+}
+
+/**
+ * @brief Main loop of the driver, "high level"-loop
+ *
+ */
+
+void HM10EverySecond(){
+ if(HM10.firmware == 0) return;
+ if(HM10.mode.pending_task == 1) return;
+ if (MIBLEsensors.size()==0) return;
+
+ static uint32_t _counter = 0;
+ static uint32_t _nextSensorSlot = 0;
+ if(_counter==0) {
+ HM10.state.sensor = _nextSensorSlot;
+ _nextSensorSlot++;
+ if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD03MMC) { // only this sensor for now
+ HM10.mode.pending_task = 1;
+ HM10_Read_Sensor();
+ }
+ if (HM10.state.sensor==MIBLEsensors.size()-1) {
+ _nextSensorSlot= 0;
+ _counter++;
+ }
+ DEBUG_SENSOR_LOG(PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor);
+ }
+ else _counter++;
+ if (_counter>HM10.period) _counter = 0;
+}
+
+bool HM10Cmd(void) {
+ char command[CMDSZ];
+ bool serviced = true;
+ uint8_t disp_len = strlen(D_CMND_HM10);
+
+ if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { // prefix
+ uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands);
+ switch (command_code) {
+ case CMND_HM10_PERIOD:
+ if (XdrvMailbox.data_len > 0) {
+ if (command_code == CMND_HM10_PERIOD) { HM10.period = XdrvMailbox.payload; }
+ }
+ else {
+ if (command_code == CMND_HM10_PERIOD) XdrvMailbox.payload = HM10.period;
+ }
+ Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload);
+ break;
+ case CMND_HM10_BAUD:
+ if (XdrvMailbox.data_len > 0) {
+ if (command_code == CMND_HM10_BAUD) {
+ HM10.serialSpeed = XdrvMailbox.payload;
+ HM10Serial->begin(HM10.serialSpeed);
+ }
+ }
+ else {
+ if (command_code == CMND_HM10_BAUD) XdrvMailbox.payload = HM10.serialSpeed;
+ }
+ Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload);
+ break;
+ case CMND_HM10_AT:
+ HM10Serial->write("AT"); // without an argument this will disconnect
+ if (strlen(XdrvMailbox.data)!=0) {
+ HM10Serial->write("+");
+ HM10Serial->write(XdrvMailbox.data); // pass everything without checks
+ Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data);
+ }
+ else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data);
+ break;
+ case CMND_HM10_DISC_SCAN:
+ if (command_code == CMND_HM10_DISC_SCAN) { HM10_Discovery_Scan(); }
+ Response_P(S_JSON_HM10_COMMAND, command, "");
+ break;
+ default:
+ // else for Unknown command
+ serviced = false;
+ break;
+ }
+ } else {
+ return false;
+ }
+ return serviced;
+}
+
+
+/*********************************************************************************************\
+ * Presentation
+\*********************************************************************************************/
+
+const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}";
+const char HTTP_HM10_SERIAL[] 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_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}";
+const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}";
+
+void HM10Show(bool json)
+{
+ if (json) {
+ for (uint32_t i = 0; i < MIBLEsensors.size(); i++) {
+ char slave[33];
+ sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]);
+ char temperature[33]; // all sensors have temperature
+ dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature);
+
+ ResponseAppend_P(PSTR(",\"%s\":{"),slave);
+ if(MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no temperature
+ ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature);
+ }
+ if (MIBLEsensors.at(i).type==FLORA){
+ char lux[33];
+ char moisture[33];
+ char fertility[33];
+ dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux);
+ dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture);
+ dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility);
+ if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no temperature
+ ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux);
+ }
+ if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no temperature
+ ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture);
+ }
+ if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no temperature
+ ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility);
+ }
+ }
+ if (MIBLEsensors.at(i).type>FLORA){
+ char humidity[33];
+ dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity);
+ if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no temperature
+ ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity);
+ }
+ if(MIBLEsensors.at(i).bat!=0xff){ // this is the error code -> no temperature
+ ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat);
+ }
+ }
+ ResponseAppend_P(PSTR("}"));
+ }
+#ifdef USE_WEBSERVER
+ } else {
+ WSContentSend_PD(HTTP_HM10, HM10.firmware);
+ for (uint32_t i = 0; i < MIBLEsensors.size(); i++) {
+ WSContentSend_PD(HTTP_HM10_HL);
+ WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]);
+ if(MIBLEsensors.at(i).temp!=-1000.0f){
+ char temperature[33];
+ dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature);
+ WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit());
+ }
+ if (MIBLEsensors.at(i).type==FLORA){
+ if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no valid value
+ WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux);
+ }
+ if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no valid value
+ WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture);
+ }
+ if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no valid value
+ char fertility[33];
+ dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility);
+ WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility);
+ }
+ }
+ if (MIBLEsensors.at(i).type>FLORA){ // everything "above" Flora
+ if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity
+ char humidity[33];
+ dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity);
+ WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity);
+ }
+ if(MIBLEsensors.at(i).bat!=0xff){
+ WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat);
+ }
+ }
+ }
+#endif // USE_WEBSERVER
+ }
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xsns62(uint8_t function)
+{
+ bool result = false;
+
+ if ((pin[GPIO_HM10_RX] < 99) && (pin[GPIO_HM10_TX] < 99)) {
+ switch (function) {
+ case FUNC_INIT:
+ HM10SerialInit(); // init and start communication
+ break;
+ case FUNC_EVERY_50_MSECOND:
+ HM10SerialHandleFeedback(); // check for device feedback very often
+ break;
+ case FUNC_EVERY_100_MSECOND:
+ if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) {
+ HM10_TaskEvery100ms(); // something has to be done, we'll check in the next step
+ }
+ break;
+ case FUNC_EVERY_SECOND:
+ HM10EverySecond();
+ break;
+ case FUNC_COMMAND:
+ result = HM10Cmd();
+ break;
+ case FUNC_JSON_APPEND:
+ HM10Show(1);
+ break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_SENSOR:
+ HM10Show(0);
+ break;
+#endif // USE_WEBSERVER
+ }
+ }
+ return result;
+}
+#endif //USE_HM10
\ No newline at end of file