mirror of https://github.com/arendst/Tasmota.git
v3.9.22
3.9.22 20170228 * Update web console * Fix Status 4 JSON message * Add Exception info during restart if available * Add osWatch service to detect loop hangs that might happen during (OTA) upgrades * Add WiOn support for relay and switch only (#82, #102) * Allow for user specified relay count up to four in sonoff_template.h (#109) * Add support for HTU21 compatible I2C sensors SI7013, SI7020 and SI7021 (#118) * Add NodeMCU or Wemos configuration option (#119)
This commit is contained in:
parent
3fefb9b931
commit
fc3b7e22ab
|
@ -1,7 +1,7 @@
|
||||||
## Sonoff-Tasmota
|
## Sonoff-Tasmota
|
||||||
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
|
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
|
||||||
|
|
||||||
Current version is **3.9.21** - See ```sonoff/_releasenotes.ino``` for change information.
|
Current version is **3.9.22** - See ```sonoff/_releasenotes.ino``` for change information.
|
||||||
|
|
||||||
- This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic.
|
- This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic.
|
||||||
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```.
|
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```.
|
||||||
|
|
Binary file not shown.
|
@ -1,4 +1,14 @@
|
||||||
/* 3.9.21 20170224
|
/* 3.9.22 20170228
|
||||||
|
* Update web console
|
||||||
|
* Fix Status 4 JSON message
|
||||||
|
* Add Exception info during restart if available
|
||||||
|
* Add osWatch service to detect loop hangs that might happen during (OTA) upgrades
|
||||||
|
* Add WiOn support for relay and switch only (#82, #102)
|
||||||
|
* Allow for user specified relay count up to four in sonoff_template.h (#109)
|
||||||
|
* Add support for HTU21 compatible I2C sensors SI7013, SI7020 and SI7021 (#118)
|
||||||
|
* Add NodeMCU or Wemos configuration option (#119)
|
||||||
|
*
|
||||||
|
* 3.9.21 20170224
|
||||||
* Add ajax to web root page and web console (#79)
|
* Add ajax to web root page and web console (#79)
|
||||||
* Add commands SwitchMode1..4 and enable user switches 2, 3 and 4 (#84, #88)
|
* Add commands SwitchMode1..4 and enable user switches 2, 3 and 4 (#84, #88)
|
||||||
* Fix MQTT upgrade when webserver is active
|
* Fix MQTT upgrade when webserver is active
|
||||||
|
|
|
@ -189,3 +189,10 @@ struct SYSCFG {
|
||||||
|
|
||||||
} sysCfg;
|
} sysCfg;
|
||||||
|
|
||||||
|
struct RTCMEM {
|
||||||
|
uint16_t valid;
|
||||||
|
byte osw_flag;
|
||||||
|
byte nu1;
|
||||||
|
unsigned long hlw_kWhtoday;
|
||||||
|
} rtcMem;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,85 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* RTC memory
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define RTC_MEM_VALID 0xA55A
|
||||||
|
|
||||||
|
uint32_t _rtcHash = 0;
|
||||||
|
|
||||||
|
uint32_t getRtcHash()
|
||||||
|
{
|
||||||
|
uint32_t hash = 0;
|
||||||
|
uint8_t *bytes = (uint8_t*)&rtcMem;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < sizeof(RTCMEM); i++) hash += bytes[i]*(i+1);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTC_Save()
|
||||||
|
{
|
||||||
|
if (getRtcHash() != _rtcHash) {
|
||||||
|
rtcMem.valid = RTC_MEM_VALID;
|
||||||
|
ESP.rtcUserMemoryWrite(100, (uint32_t*)&rtcMem, sizeof(RTCMEM));
|
||||||
|
_rtcHash = getRtcHash();
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
addLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Save"));
|
||||||
|
RTC_Dump();
|
||||||
|
#endif // DEBUG_THEO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTC_Load()
|
||||||
|
{
|
||||||
|
ESP.rtcUserMemoryRead(100, (uint32_t*)&rtcMem, sizeof(RTCMEM));
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
addLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Load"));
|
||||||
|
RTC_Dump();
|
||||||
|
#endif // DEBUG_THEO
|
||||||
|
if (rtcMem.valid != RTC_MEM_VALID) {
|
||||||
|
memset(&rtcMem, 0x00, sizeof(RTCMEM));
|
||||||
|
rtcMem.valid = RTC_MEM_VALID;
|
||||||
|
RTC_Save();
|
||||||
|
}
|
||||||
|
_rtcHash = getRtcHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean RTC_Valid()
|
||||||
|
{
|
||||||
|
return (rtcMem.valid == RTC_MEM_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
void RTC_Dump()
|
||||||
|
{
|
||||||
|
#define CFG_COLS 16
|
||||||
|
|
||||||
|
char log[LOGSZ];
|
||||||
|
uint16_t idx, maxrow, row, col;
|
||||||
|
|
||||||
|
uint8_t *buffer = (uint8_t *) &rtcMem;
|
||||||
|
maxrow = ((sizeof(RTCMEM)+CFG_COLS)/CFG_COLS);
|
||||||
|
|
||||||
|
for (row = 0; row < maxrow; row++) {
|
||||||
|
idx = row * CFG_COLS;
|
||||||
|
snprintf_P(log, sizeof(log), PSTR("%04X:"), idx);
|
||||||
|
for (col = 0; col < CFG_COLS; col++) {
|
||||||
|
if (!(col%4)) snprintf_P(log, sizeof(log), PSTR("%s "), log);
|
||||||
|
snprintf_P(log, sizeof(log), PSTR("%s %02X"), log, buffer[idx + col]);
|
||||||
|
}
|
||||||
|
snprintf_P(log, sizeof(log), PSTR("%s |"), log);
|
||||||
|
for (col = 0; col < CFG_COLS; col++) {
|
||||||
|
// if (!(col%4)) snprintf_P(log, sizeof(log), PSTR("%s "), log);
|
||||||
|
snprintf_P(log, sizeof(log), PSTR("%s%c"), log, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' ');
|
||||||
|
}
|
||||||
|
snprintf_P(log, sizeof(log), PSTR("%s|"), log);
|
||||||
|
addLog(LOG_LEVEL_INFO, log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // DEBUG_THEO
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Config - Flash or Spiffs
|
* Config - Flash or Spiffs
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -131,6 +210,7 @@ void CFG_Save()
|
||||||
}
|
}
|
||||||
_cfgHash = getHash();
|
_cfgHash = getHash();
|
||||||
}
|
}
|
||||||
|
RTC_Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFG_Load()
|
void CFG_Load()
|
||||||
|
@ -177,6 +257,8 @@ void CFG_Load()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_cfgHash = getHash();
|
_cfgHash = getHash();
|
||||||
|
|
||||||
|
RTC_Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFG_Migrate()
|
void CFG_Migrate()
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
* ====================================================
|
* ====================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERSION 0x03091500 // 3.9.21
|
#define VERSION 0x03091600 // 3.9.22
|
||||||
|
|
||||||
//#define BE_MINIMAL // Compile a minimal version if upgrade memory gets tight (still 404k)
|
//#define BE_MINIMAL // Compile a minimal version if upgrade memory gets tight (still 404k)
|
||||||
// To be used as step 1. Next step is compile and use desired version
|
// To be used as step 1. Next step is compile and use desired version
|
||||||
|
@ -45,6 +45,7 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
|
||||||
#ifndef USE_DS18x20
|
#ifndef USE_DS18x20
|
||||||
#define USE_DS18B20 // Default DS18B20 sensor needs no external library
|
#define USE_DS18B20 // Default DS18B20 sensor needs no external library
|
||||||
#endif
|
#endif
|
||||||
|
//#define DEBUG_THEO // Add debug code
|
||||||
|
|
||||||
#ifdef BE_MINIMAL
|
#ifdef BE_MINIMAL
|
||||||
//#ifdef USE_MQTT_TLS
|
//#ifdef USE_MQTT_TLS
|
||||||
|
@ -80,6 +81,9 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
|
||||||
#ifdef USE_IR_REMOTE
|
#ifdef USE_IR_REMOTE
|
||||||
#undef USE_IR_REMOTE // Disable IR driver
|
#undef USE_IR_REMOTE // Disable IR driver
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
#undef DEBUG_THEO // Disable debug code
|
||||||
|
#endif
|
||||||
#endif // BE_MINIMAL
|
#endif // BE_MINIMAL
|
||||||
|
|
||||||
#ifndef SWITCH_MODE
|
#ifndef SWITCH_MODE
|
||||||
|
@ -497,6 +501,9 @@ void mqtt_connected()
|
||||||
mqtt_publish_topic_P(1, PSTR("INFO2"), svalue);
|
mqtt_publish_topic_P(1, PSTR("INFO2"), svalue);
|
||||||
}
|
}
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Started\":\"%s\"}"),
|
||||||
|
(getResetReason() == "Exception") ? ESP.getResetInfo().c_str() : getResetReason().c_str());
|
||||||
|
mqtt_publish_topic_P(1, PSTR("INFO3"), svalue);
|
||||||
if (sysCfg.mqtt_enabled && (MQTT_MAX_PACKET_SIZE < (TOPSZ+MESSZ))) {
|
if (sysCfg.mqtt_enabled && (MQTT_MAX_PACKET_SIZE < (TOPSZ+MESSZ))) {
|
||||||
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Warning1\":\"Change MQTT_MAX_PACKET_SIZE in libraries/PubSubClient.h to at least %d\"}"), TOPSZ+MESSZ);
|
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Warning1\":\"Change MQTT_MAX_PACKET_SIZE in libraries/PubSubClient.h to at least %d\"}"), TOPSZ+MESSZ);
|
||||||
mqtt_publish_topic_P(1, PSTR("WARNING1"), svalue);
|
mqtt_publish_topic_P(1, PSTR("WARNING1"), svalue);
|
||||||
|
@ -1168,6 +1175,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
|
||||||
// Serviced
|
// Serviced
|
||||||
}
|
}
|
||||||
#endif // USE_IR_REMOTE
|
#endif // USE_IR_REMOTE
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
else if (!strcmp(type,"EXCEPTION")) {
|
||||||
|
if (data_len > 0) exception_tst(payload);
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Exception\":\"Triggered\"}"));
|
||||||
|
}
|
||||||
|
#endif // DEBUG_THEO
|
||||||
else {
|
else {
|
||||||
type = NULL;
|
type = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1382,7 @@ void publish_status(uint8_t payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((payload == 0) || (payload == 4)) {
|
if ((payload == 0) || (payload == 4)) {
|
||||||
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusMEM\":{\"ProgramSize\":%d, \"Free\":%d, \"Heap\":%d, \"SpiffsStart\":%d, \"SpiffsSize\":%d, \"FlashSize\":%d, \"ProgramFlashSize\":%d, \"FlashChipMode\",%d}}"),
|
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusMEM\":{\"ProgramSize\":%d, \"Free\":%d, \"Heap\":%d, \"SpiffsStart\":%d, \"SpiffsSize\":%d, \"FlashSize\":%d, \"ProgramFlashSize\":%d, \"FlashChipMode\":%d}}"),
|
||||||
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ((uint32_t)&_SPIFFS_start - 0x40200000)/1024,
|
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ((uint32_t)&_SPIFFS_start - 0x40200000)/1024,
|
||||||
(((uint32_t)&_SPIFFS_end - 0x40200000) - ((uint32_t)&_SPIFFS_start - 0x40200000))/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipMode());
|
(((uint32_t)&_SPIFFS_end - 0x40200000) - ((uint32_t)&_SPIFFS_start - 0x40200000))/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipMode());
|
||||||
mqtt_publish_topic_P(option, PSTR("STATUS4"), svalue);
|
mqtt_publish_topic_P(option, PSTR("STATUS4"), svalue);
|
||||||
|
@ -1916,20 +1929,12 @@ void GPIO_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxdevice = 1;
|
Maxdevice = 1;
|
||||||
switch (sysCfg.module) {
|
if (sysCfg.module == SONOFF_DUAL) {
|
||||||
case SONOFF_DUAL:
|
|
||||||
case ELECTRODRAGON:
|
|
||||||
Maxdevice = 2;
|
Maxdevice = 2;
|
||||||
break;
|
Baudrate = 19200;
|
||||||
case SONOFF_4CH:
|
|
||||||
case CH4:
|
|
||||||
Maxdevice = 4;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (sysCfg.module == CH4) {
|
||||||
swt_flg = ((pin[GPIO_SWT1] < 99) || (pin[GPIO_SWT2] < 99) || (pin[GPIO_SWT3] < 99) || (pin[GPIO_SWT4] < 99));
|
Maxdevice = 4;
|
||||||
|
|
||||||
if ((sysCfg.module == SONOFF_DUAL) || (sysCfg.module == CH4)) {
|
|
||||||
Baudrate = 19200;
|
Baudrate = 19200;
|
||||||
}
|
}
|
||||||
else if (sysCfg.module == SONOFF_LED) {
|
else if (sysCfg.module == SONOFF_LED) {
|
||||||
|
@ -1937,9 +1942,13 @@ void GPIO_init()
|
||||||
sl_init();
|
sl_init();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Maxdevice = 0;
|
||||||
for (byte i = 0; i < 4; i++) {
|
for (byte i = 0; i < 4; i++) {
|
||||||
|
if (pin[GPIO_REL1 +i] < 99) {
|
||||||
|
pinMode(pin[GPIO_REL1 +i], OUTPUT);
|
||||||
|
Maxdevice++;
|
||||||
|
}
|
||||||
if (pin[GPIO_KEY1 +i] < 99) pinMode(pin[GPIO_KEY1 +i], INPUT_PULLUP);
|
if (pin[GPIO_KEY1 +i] < 99) pinMode(pin[GPIO_KEY1 +i], INPUT_PULLUP);
|
||||||
if (pin[GPIO_REL1 +i] < 99) pinMode(pin[GPIO_REL1 +i], OUTPUT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (byte i = 0; i < 4; i++) {
|
for (byte i = 0; i < 4; i++) {
|
||||||
|
@ -1948,6 +1957,7 @@ void GPIO_init()
|
||||||
digitalWrite(pin[GPIO_LED1 +i], led_inverted[i]);
|
digitalWrite(pin[GPIO_LED1 +i], led_inverted[i]);
|
||||||
}
|
}
|
||||||
if (pin[GPIO_SWT1 +i] < 99) {
|
if (pin[GPIO_SWT1 +i] < 99) {
|
||||||
|
swt_flg = 1;
|
||||||
pinMode(pin[GPIO_SWT1 +i], INPUT_PULLUP);
|
pinMode(pin[GPIO_SWT1 +i], INPUT_PULLUP);
|
||||||
lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check
|
lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check
|
||||||
}
|
}
|
||||||
|
@ -2007,6 +2017,8 @@ void setup()
|
||||||
CFG_Load();
|
CFG_Load();
|
||||||
CFG_Delta();
|
CFG_Delta();
|
||||||
|
|
||||||
|
osw_init();
|
||||||
|
|
||||||
sysCfg.bootcount++;
|
sysCfg.bootcount++;
|
||||||
snprintf_P(log, sizeof(log), PSTR("APP: Bootcount %d"), sysCfg.bootcount);
|
snprintf_P(log, sizeof(log), PSTR("APP: Bootcount %d"), sysCfg.bootcount);
|
||||||
addLog(LOG_LEVEL_DEBUG, log);
|
addLog(LOG_LEVEL_DEBUG, log);
|
||||||
|
@ -2073,6 +2085,8 @@ void setup()
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
|
osw_loop();
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
pollDnsWeb();
|
pollDnsWeb();
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
|
|
|
@ -90,6 +90,8 @@ enum module_t {
|
||||||
MOTOR,
|
MOTOR,
|
||||||
ELECTRODRAGON,
|
ELECTRODRAGON,
|
||||||
EXS_RELAY,
|
EXS_RELAY,
|
||||||
|
WION,
|
||||||
|
NODEMCU,
|
||||||
USER_TEST,
|
USER_TEST,
|
||||||
MAXMODULE };
|
MAXMODULE };
|
||||||
|
|
||||||
|
@ -283,6 +285,34 @@ const mytmplt modules[MAXMODULE] PROGMEM = {
|
||||||
0,
|
0,
|
||||||
GPIO_USER // GPIO16 Module Pin 4
|
GPIO_USER // GPIO16 Module Pin 4
|
||||||
},
|
},
|
||||||
|
{ "WiOn", // Indoor Tap https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w
|
||||||
|
GPIO_USER, // GPIO00 Optional sensor (pm clock)
|
||||||
|
0,
|
||||||
|
GPIO_LED1, // GPIO02 Green Led (1 = On, 0 = Off)
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
GPIO_USER, // GPIO12 Optional sensor (pm data)
|
||||||
|
GPIO_KEY1, // GPIO13 Button
|
||||||
|
0,
|
||||||
|
GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On)
|
||||||
|
0
|
||||||
|
},
|
||||||
|
{ "NodeMCU", // NodeMCU and Wemos hardware
|
||||||
|
GPIO_KEY1, // GPIO00 Button
|
||||||
|
GPIO_USER, // GPIO01 Serial RXD
|
||||||
|
GPIO_USER, // GPIO02
|
||||||
|
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
||||||
|
GPIO_USER, // GPIO04 Optional sensor
|
||||||
|
GPIO_USER, // GPIO05
|
||||||
|
0, 0, 0,
|
||||||
|
GPIO_USER, // GPIO09
|
||||||
|
GPIO_USER, // GPIO10
|
||||||
|
0,
|
||||||
|
GPIO_USER, // GPIO12
|
||||||
|
GPIO_USER, // GPIO13
|
||||||
|
GPIO_USER, // GPIO14
|
||||||
|
GPIO_USER, // GPIO15
|
||||||
|
0
|
||||||
|
},
|
||||||
{ "User Test", // Sonoff Basic User Test
|
{ "User Test", // Sonoff Basic User Test
|
||||||
GPIO_KEY1, // GPIO00 Button
|
GPIO_KEY1, // GPIO00 Button
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -23,6 +23,127 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Watchdog extension (https://github.com/esp8266/Arduino/issues/1532)
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
Ticker tickerOSWatch;
|
||||||
|
|
||||||
|
#define OSWATCH_RESET_TIME 30
|
||||||
|
|
||||||
|
static unsigned long osw_last_loop;
|
||||||
|
byte osw_flag = 0;
|
||||||
|
|
||||||
|
void ICACHE_RAM_ATTR osw_osWatch(void)
|
||||||
|
{
|
||||||
|
unsigned long t = millis();
|
||||||
|
unsigned long last_run = abs(t - osw_last_loop);
|
||||||
|
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
char log[LOGSZ];
|
||||||
|
snprintf_P(log, sizeof(log), PSTR("osWatch: FreeRam %d, rssi %d, last_run %d"), ESP.getFreeHeap(), WIFI_getRSSIasQuality(WiFi.RSSI()), last_run);
|
||||||
|
addLog(LOG_LEVEL_DEBUG, log);
|
||||||
|
#endif // DEBUG_THEO
|
||||||
|
if(last_run >= (OSWATCH_RESET_TIME * 1000)) {
|
||||||
|
addLog_P(LOG_LEVEL_INFO, PSTR("osWatch: Warning, loop blocked. Restart now"));
|
||||||
|
rtcMem.osw_flag = 1;
|
||||||
|
RTC_Save();
|
||||||
|
// ESP.restart(); // normal reboot
|
||||||
|
ESP.reset(); // hard reset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void osw_init()
|
||||||
|
{
|
||||||
|
osw_flag = rtcMem.osw_flag;
|
||||||
|
rtcMem.osw_flag = 0;
|
||||||
|
osw_last_loop = millis();
|
||||||
|
tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), osw_osWatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void osw_loop()
|
||||||
|
{
|
||||||
|
osw_last_loop = millis();
|
||||||
|
// while(1) delay(1000); // this will trigger the os watch
|
||||||
|
}
|
||||||
|
|
||||||
|
String getResetReason()
|
||||||
|
{
|
||||||
|
char buff[32];
|
||||||
|
if (osw_flag) {
|
||||||
|
strcpy_P(buff, PSTR("Blocked Loop"));
|
||||||
|
return String(buff);
|
||||||
|
} else {
|
||||||
|
return ESP.getResetReason();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_THEO
|
||||||
|
void exception_tst(byte type)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Exception (28):
|
||||||
|
epc1=0x4000bf64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000007 depc=0x00000000
|
||||||
|
|
||||||
|
ctx: cont
|
||||||
|
sp: 3fff1f30 end: 3fff2840 offset: 01a0
|
||||||
|
|
||||||
|
>>>stack>>>
|
||||||
|
3fff20d0: 202c3573 756f7247 2c302070 646e4920
|
||||||
|
3fff20e0: 40236a6e 7954202c 45206570 00454358
|
||||||
|
3fff20f0: 00000010 00000007 00000000 3fff2180
|
||||||
|
3fff2100: 3fff2190 40107bfc 3fff3e4c 3fff22c0
|
||||||
|
3fff2110: 40261934 000000f0 3fff22c0 401004d8
|
||||||
|
3fff2120: 40238fcf 00000050 3fff2100 4021fc10
|
||||||
|
3fff2130: 3fff32bc 4021680c 3ffeade1 4021ff7d
|
||||||
|
3fff2140: 3fff2190 3fff2180 0000000c 7fffffff
|
||||||
|
3fff2150: 00000019 00000000 00000000 3fff21c0
|
||||||
|
3fff2160: 3fff23f3 3ffe8e08 00000000 4021ffb4
|
||||||
|
3fff2170: 3fff2190 3fff2180 0000000c 40201118
|
||||||
|
3fff2180: 3fff21c0 0000003c 3ffef840 00000007
|
||||||
|
3fff2190: 00000000 00000000 00000000 40201128
|
||||||
|
3fff21a0: 3fff23f3 000000f1 3fff23ec 4020fafb
|
||||||
|
3fff21b0: 3fff23f3 3fff21c0 3fff21d0 3fff23f6
|
||||||
|
3fff21c0: 00000000 3fff23fb 4022321b 00000000
|
||||||
|
|
||||||
|
Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
|
||||||
|
Decoding 14 results
|
||||||
|
0x40236a6e: ets_vsnprintf at ?? line ?
|
||||||
|
0x40107bfc: vsnprintf at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/libc_replacements.c line 387
|
||||||
|
0x40261934: bignum_exptmod at ?? line ?
|
||||||
|
0x401004d8: malloc at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc/umm_malloc.c line 1664
|
||||||
|
0x40238fcf: wifi_station_get_connect_status at ?? line ?
|
||||||
|
0x4021fc10: operator new[](unsigned int) at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/abi.cpp line 57
|
||||||
|
0x4021680c: ESP8266WiFiSTAClass::status() at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/ESP8266WiFiSTA.cpp line 569
|
||||||
|
0x4021ff7d: vsnprintf_P(char*, unsigned int, char const*, __va_list_tag) at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/pgmspace.cpp line 146
|
||||||
|
0x4021ffb4: snprintf_P(char*, unsigned int, char const*, ...) at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/pgmspace.cpp line 146
|
||||||
|
0x40201118: atol at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/core_esp8266_noniso.c line 45
|
||||||
|
0x40201128: atoi at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/core_esp8266_noniso.c line 45
|
||||||
|
0x4020fafb: mqttDataCb(char*, unsigned char*, unsigned int) at R:\Arduino\Work-ESP8266\Theo\sonoff\sonoff-4\sonoff/sonoff.ino line 679 (discriminator 1)
|
||||||
|
0x4022321b: pp_attach at ?? line ?
|
||||||
|
|
||||||
|
00:00:08 MQTT: tele/sonoff/INFO3 = {"Started":"Fatal exception:28 flag:2 (EXCEPTION) epc1:0x4000bf64 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000007 depc:0x00000000"}
|
||||||
|
*/
|
||||||
|
if (type == 1) {
|
||||||
|
char svalue[10];
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); // Exception 28 as number in string (7 in excvaddr)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
14:50:52 osWatch: FreeRam 25896, rssi 68, last_run 0
|
||||||
|
14:51:02 osWatch: FreeRam 25896, rssi 58, last_run 0
|
||||||
|
14:51:03 CMND: exception 2
|
||||||
|
14:51:12 osWatch: FreeRam 25360, rssi 60, last_run 8771
|
||||||
|
14:51:22 osWatch: FreeRam 25360, rssi 62, last_run 18771
|
||||||
|
14:51:32 osWatch: FreeRam 25360, rssi 62, last_run 28771
|
||||||
|
14:51:42 osWatch: FreeRam 25360, rssi 62, last_run 38771
|
||||||
|
14:51:42 osWatch: Warning, loop blocked. Restart now
|
||||||
|
*/
|
||||||
|
if (type == 2) {
|
||||||
|
while(1) delay(1000); // this will trigger the os watch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // DEBUG_THEO
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Wifi
|
* Wifi
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -703,9 +824,6 @@ void addLog(byte loglevel, const char *line)
|
||||||
|
|
||||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d:%02d:%02d"), rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
|
snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d:%02d:%02d"), rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
|
||||||
|
|
||||||
#ifdef DEBUG_ESP_PORT
|
|
||||||
DEBUG_ESP_PORT.printf("%s %s\n", mxtime, line);
|
|
||||||
#endif // DEBUG_ESP_PORT
|
|
||||||
if (loglevel <= seriallog_level) Serial.printf("%s %s\n", mxtime, line);
|
if (loglevel <= seriallog_level) Serial.printf("%s %s\n", mxtime, line);
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
if (sysCfg.webserver && (loglevel <= sysCfg.weblog_level)) {
|
if (sysCfg.webserver && (loglevel <= sysCfg.weblog_level)) {
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
#define USE_I2C // I2C using library wire (+10k code, 0.2k mem) - Disable by //
|
#define USE_I2C // I2C using library wire (+10k code, 0.2k mem) - Disable by //
|
||||||
#define USE_BH1750 // Add I2C code for BH1750 sensor
|
#define USE_BH1750 // Add I2C code for BH1750 sensor
|
||||||
#define USE_BMP // Add I2C code for BMP/BME280 sensor
|
#define USE_BMP // Add I2C code for BMP/BME280 sensor
|
||||||
#define USE_HTU // Add I2C code for HTU21 sensor
|
#define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor
|
||||||
|
|
||||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0.3k mem)
|
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0.3k mem)
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,22 @@ const char HTTP_HEAD[] PROGMEM =
|
||||||
"};"
|
"};"
|
||||||
"x.open('GET','ay'+a,true);"
|
"x.open('GET','ay'+a,true);"
|
||||||
"x.send();"
|
"x.send();"
|
||||||
"lt=setTimeout(la,2000);"
|
"lt=setTimeout(la,2345);"
|
||||||
"}"
|
"}"
|
||||||
"var sn=0;" // Scroll position
|
"var sn=0;" // Scroll position
|
||||||
"var id=99;" // Get most of weblog initially
|
"var id=99;" // Get most of weblog initially
|
||||||
"function l(){"
|
"function l(p){" // Console log and command service
|
||||||
"var e=document.getElementById('t1');"
|
"var c,o,t;"
|
||||||
"if(e.scrollTop>=sn){" // User scrolled back so no updates
|
"clearTimeout(lt);"
|
||||||
|
"o='';"
|
||||||
|
"t=document.getElementById('t1');"
|
||||||
|
"if(p==1){"
|
||||||
|
"c=document.getElementById('c1');"
|
||||||
|
"o='&c1='+c.value;"
|
||||||
|
"c.value='';"
|
||||||
|
"t.scrollTop=sn;"
|
||||||
|
"}"
|
||||||
|
"if(t.scrollTop>=sn){" // User scrolled back so no updates
|
||||||
"if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
|
"if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
|
||||||
"x=new XMLHttpRequest();"
|
"x=new XMLHttpRequest();"
|
||||||
"x.onreadystatechange=function(){"
|
"x.onreadystatechange=function(){"
|
||||||
|
@ -84,25 +93,17 @@ const char HTTP_HEAD[] PROGMEM =
|
||||||
"var z,d;"
|
"var z,d;"
|
||||||
"d=x.responseXML;"
|
"d=x.responseXML;"
|
||||||
"id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue;"
|
"id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue;"
|
||||||
"if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){e.value=\"\";}"
|
"if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){t.value='';}"
|
||||||
"z=d.getElementsByTagName('l')[0].childNodes;"
|
"z=d.getElementsByTagName('l')[0].childNodes;"
|
||||||
"if(z.length>0){e.value+=z[0].nodeValue;}"
|
"if(z.length>0){t.value+=z[0].nodeValue;}"
|
||||||
"e.scrollTop=99999;"
|
"t.scrollTop=99999;"
|
||||||
"sn=e.scrollTop;"
|
"sn=t.scrollTop;"
|
||||||
"}"
|
"}"
|
||||||
"};"
|
"};"
|
||||||
"x.open('GET','ax?c2='+id,true);"
|
"x.open('GET','ax?c2='+id+o,true);"
|
||||||
"x.send();"
|
"x.send();"
|
||||||
"}"
|
"}"
|
||||||
"setTimeout(l,2000);"
|
"lt=setTimeout(l,2345);"
|
||||||
"}"
|
|
||||||
"function lc(){"
|
|
||||||
"var e=document.getElementById('c1');"
|
|
||||||
// "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
|
|
||||||
"var x=new XMLHttpRequest();"
|
|
||||||
"x.open('GET','ax?c1='+e.value+'&c2='+id,true);"
|
|
||||||
"x.send();"
|
|
||||||
"e.value=\"\";"
|
|
||||||
"return false;"
|
"return false;"
|
||||||
"}"
|
"}"
|
||||||
"</script>"
|
"</script>"
|
||||||
|
@ -122,7 +123,7 @@ const char HTTP_HEAD[] PROGMEM =
|
||||||
"</style>"
|
"</style>"
|
||||||
"</head>"
|
"</head>"
|
||||||
"<body>"
|
"<body>"
|
||||||
"<div style='text-align:left;display:inline-block;min-width:260px;'>"
|
"<div style='text-align:left;display:inline-block;min-width:320px;'>"
|
||||||
"<div style='text-align:center;'><h3>{ha} Module</h3><h2>{h}</h2></div>";
|
"<div style='text-align:center;'><h3>{ha} Module</h3><h2>{h}</h2></div>";
|
||||||
const char HTTP_MSG_RSTRT[] PROGMEM =
|
const char HTTP_MSG_RSTRT[] PROGMEM =
|
||||||
"<br/><div style='text-align:center;'>Device will restart in a few seconds</div><br/>";
|
"<br/><div style='text-align:center;'>Device will restart in a few seconds</div><br/>";
|
||||||
|
@ -234,12 +235,18 @@ const char HTTP_FORM_UPG[] PROGMEM =
|
||||||
"<div id='f2' name='f2' style='display:none;text-align:center;'><b>Upload started ...</b></div>";
|
"<div id='f2' name='f2' style='display:none;text-align:center;'><b>Upload started ...</b></div>";
|
||||||
const char HTTP_FORM_CMND[] PROGMEM =
|
const char HTTP_FORM_CMND[] PROGMEM =
|
||||||
"<br/><textarea readonly id='t1' name='t1' cols='99' wrap='off'></textarea><br/><br/>"
|
"<br/><textarea readonly id='t1' name='t1' cols='99' wrap='off'></textarea><br/><br/>"
|
||||||
"<form method='get' onsubmit='return lc();'>"
|
"<form method='get' onsubmit='return l(1);'>"
|
||||||
"<input style='width:98%' id='c1' name='c1' length='99' placeholder='Enter command' autofocus><br/>"
|
"<input style='width:98%' id='c1' name='c1' length='99' placeholder='Enter command' autofocus><br/>"
|
||||||
// "<br/><button type='submit'>Send command</button>"
|
// "<br/><button type='submit'>Send command</button>"
|
||||||
"</form>";
|
"</form>";
|
||||||
const char HTTP_COUNTER[] PROGMEM =
|
const char HTTP_COUNTER[] PROGMEM =
|
||||||
"<br/><div id='t' name='t' style='text-align:center;'></div>";
|
"<br/><div id='t' name='t' style='text-align:center;'></div>";
|
||||||
|
const char HTTP_SNS_TEMP[] PROGMEM =
|
||||||
|
"<tr><th>%s Temperature</th><td>%s°%c</td></tr>";
|
||||||
|
const char HTTP_SNS_HUM[] PROGMEM =
|
||||||
|
"<tr><th>%s Humidity</th><td>%s%</td></tr>";
|
||||||
|
const char HTTP_SNS_PRESSURE[] PROGMEM =
|
||||||
|
"<tr><th>%s Pressure</th><td>%s hPa</td></tr>";
|
||||||
const char HTTP_END[] PROGMEM =
|
const char HTTP_END[] PROGMEM =
|
||||||
"</div>"
|
"</div>"
|
||||||
"</body>"
|
"</body>"
|
||||||
|
@ -1168,7 +1175,7 @@ void handleAjax()
|
||||||
{
|
{
|
||||||
if (httpUser()) return;
|
if (httpUser()) return;
|
||||||
char svalue[MESSZ], log[LOGSZ];
|
char svalue[MESSZ], log[LOGSZ];
|
||||||
byte counter = 99;
|
byte cflg = 1, counter = 99;
|
||||||
|
|
||||||
if (strlen(webServer->arg("c1").c_str())) {
|
if (strlen(webServer->arg("c1").c_str())) {
|
||||||
snprintf_P(svalue, sizeof(svalue), webServer->arg("c1").c_str());
|
snprintf_P(svalue, sizeof(svalue), webServer->arg("c1").c_str());
|
||||||
|
@ -1189,10 +1196,13 @@ void handleAjax()
|
||||||
}
|
}
|
||||||
message += F("</j><l>");
|
message += F("</j><l>");
|
||||||
if (counter != logidx) {
|
if (counter != logidx) {
|
||||||
if (counter == 99) counter = logidx;
|
if (counter == 99) {
|
||||||
|
counter = logidx;
|
||||||
|
cflg = 0;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
if (Log[counter].length()) {
|
if (Log[counter].length()) {
|
||||||
message += F("\n");
|
if (cflg) message += F("\n"); else cflg = 1;
|
||||||
message += Log[counter];
|
message += Log[counter];
|
||||||
}
|
}
|
||||||
counter++;
|
counter++;
|
||||||
|
@ -1227,7 +1237,7 @@ void handleInfo()
|
||||||
page += F("<tr><th>Uptime</th><td>"); page += String(uptime); page += F(" Hours</td></tr>");
|
page += F("<tr><th>Uptime</th><td>"); page += String(uptime); page += F(" Hours</td></tr>");
|
||||||
page += F("<tr><th>Flash write count</th><td>"); page += String(sysCfg.saveFlag); page += F("</td></tr>");
|
page += F("<tr><th>Flash write count</th><td>"); page += String(sysCfg.saveFlag); page += F("</td></tr>");
|
||||||
page += F("<tr><th>Boot count</th><td>"); page += String(sysCfg.bootcount); page += F("</td></tr>");
|
page += F("<tr><th>Boot count</th><td>"); page += String(sysCfg.bootcount); page += F("</td></tr>");
|
||||||
page += F("<tr><th>Reset reason</th><td>"); page += ESP.getResetReason(); page += F("</td></tr>");
|
page += F("<tr><th>Reset reason</th><td>"); page += getResetReason(); page += F("</td></tr>");
|
||||||
for (byte i = 0; i < Maxdevice; i++) {
|
for (byte i = 0; i < Maxdevice; i++) {
|
||||||
page += F("<tr><th>Friendly name ");
|
page += F("<tr><th>Friendly name ");
|
||||||
page += i +1;
|
page += i +1;
|
||||||
|
|
|
@ -67,7 +67,7 @@ boolean bh1750_detect()
|
||||||
if (!status) {
|
if (!status) {
|
||||||
success = true;
|
success = true;
|
||||||
bh1750type = 1;
|
bh1750type = 1;
|
||||||
snprintf_P(bh1750stype, sizeof(bh1750stype), PSTR("BH1750"));
|
strcpy(bh1750stype, "BH1750");
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
snprintf_P(log, sizeof(log), PSTR("I2C: %s found at address 0x%x"), bh1750stype, bh1750addr);
|
snprintf_P(log, sizeof(log), PSTR("I2C: %s found at address 0x%x"), bh1750stype, bh1750addr);
|
||||||
|
@ -95,12 +95,16 @@ void bh1750_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
|
const char HTTP_SNS_ILLUMINANCE[] PROGMEM =
|
||||||
|
"<tr><th>BH1750 Illuminance</th><td>%d lx</td></tr>";
|
||||||
|
|
||||||
String bh1750_webPresent()
|
String bh1750_webPresent()
|
||||||
{
|
{
|
||||||
String page = "";
|
String page = "";
|
||||||
if (bh1750type) {
|
if (bh1750type) {
|
||||||
uint16_t l = bh1750_readLux();
|
char sensor[80];
|
||||||
page += F("<tr><td>Illuminance: </td><td>"); page += String(l); page += F(" lx</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ILLUMINANCE, bh1750_readLux());
|
||||||
|
page += sensor;
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,19 +397,19 @@ boolean bmp_detect()
|
||||||
bmpaddr--;
|
bmpaddr--;
|
||||||
bmptype = i2c_read8(bmpaddr, BMP_REGISTER_CHIPID);
|
bmptype = i2c_read8(bmpaddr, BMP_REGISTER_CHIPID);
|
||||||
}
|
}
|
||||||
snprintf_P(bmpstype, sizeof(bmpstype), PSTR("BMP"));
|
strcpy_P(bmpstype, PSTR("BMP"));
|
||||||
switch (bmptype) {
|
switch (bmptype) {
|
||||||
case BMP180_CHIPID:
|
case BMP180_CHIPID:
|
||||||
success = bmp180_calibration();
|
success = bmp180_calibration();
|
||||||
snprintf_P(bmpstype, sizeof(bmpstype), PSTR("BMP180"));
|
strcpy_P(bmpstype, PSTR("BMP180"));
|
||||||
break;
|
break;
|
||||||
case BMP280_CHIPID:
|
case BMP280_CHIPID:
|
||||||
success = bmp280_calibrate();
|
success = bmp280_calibrate();
|
||||||
snprintf_P(bmpstype, sizeof(bmpstype), PSTR("BMP280"));
|
strcpy_P(bmpstype, PSTR("BMP280"));
|
||||||
break;
|
break;
|
||||||
case BME280_CHIPID:
|
case BME280_CHIPID:
|
||||||
success = bme280_calibrate();
|
success = bme280_calibrate();
|
||||||
snprintf_P(bmpstype, sizeof(bmpstype), PSTR("BME280"));
|
strcpy_P(bmpstype, PSTR("BME280"));
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
snprintf_P(log, sizeof(log), PSTR("I2C: %s found at address 0x%x"), bmpstype, bmpaddr);
|
snprintf_P(log, sizeof(log), PSTR("I2C: %s found at address 0x%x"), bmpstype, bmpaddr);
|
||||||
|
@ -454,20 +454,22 @@ String bmp_webPresent()
|
||||||
{
|
{
|
||||||
String page = "";
|
String page = "";
|
||||||
if (bmptype) {
|
if (bmptype) {
|
||||||
char itemp[10], iconv[10];
|
char stemp[10], sensor[80];
|
||||||
|
|
||||||
snprintf_P(iconv, sizeof(iconv), PSTR("°%c"), (TEMP_CONVERSION) ? 'F' : 'C');
|
|
||||||
double t_bmp = bmp_readTemperature(TEMP_CONVERSION);
|
double t_bmp = bmp_readTemperature(TEMP_CONVERSION);
|
||||||
double p_bmp = bmp_readPressure();
|
double p_bmp = bmp_readPressure();
|
||||||
double h_bmp = bmp_readHumidity();
|
double h_bmp = bmp_readHumidity();
|
||||||
dtostrf(t_bmp, 1, TEMP_RESOLUTION &3, itemp);
|
dtostrf(t_bmp, 1, TEMP_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>BMP Temperature: </td><td>"); page += itemp; page += iconv; page += F("</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, bmpstype, stemp, (TEMP_CONVERSION) ? 'F' : 'C');
|
||||||
|
page += sensor;
|
||||||
if (!strcmp(bmpstype,"BME280")) {
|
if (!strcmp(bmpstype,"BME280")) {
|
||||||
dtostrf(h_bmp, 1, HUMIDITY_RESOLUTION &3, itemp);
|
dtostrf(h_bmp, 1, HUMIDITY_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>BMP Humidity: </td><td>"); page += itemp; page += F("%</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, bmpstype, stemp);
|
||||||
|
page += sensor;
|
||||||
}
|
}
|
||||||
dtostrf(p_bmp, 1, PRESSURE_RESOLUTION &3, itemp);
|
dtostrf(p_bmp, 1, PRESSURE_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>BMP Pressure: </td><td>"); page += itemp; page += F(" hPa</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSURE, bmpstype, stemp);
|
||||||
|
page += sensor;
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define MIN_INTERVAL 2000
|
#define MIN_INTERVAL 2000
|
||||||
|
|
||||||
uint8_t data[5];
|
uint8_t data[5];
|
||||||
|
char dhtstype[7];
|
||||||
uint32_t _lastreadtime, _maxcycles;
|
uint32_t _lastreadtime, _maxcycles;
|
||||||
bool _lastresult;
|
bool _lastresult;
|
||||||
float mt, mh = 0;
|
float mt, mh = 0;
|
||||||
|
@ -170,6 +171,17 @@ void dht_init()
|
||||||
pinMode(pin[GPIO_DHT11], INPUT_PULLUP);
|
pinMode(pin[GPIO_DHT11], INPUT_PULLUP);
|
||||||
_lastreadtime = -MIN_INTERVAL;
|
_lastreadtime = -MIN_INTERVAL;
|
||||||
|
|
||||||
|
switch (dht_type) {
|
||||||
|
case GPIO_DHT11:
|
||||||
|
strcpy(dhtstype, "DHT11");
|
||||||
|
break;
|
||||||
|
case GPIO_DHT21:
|
||||||
|
strcpy(dhtstype, "AM2301");
|
||||||
|
break;
|
||||||
|
case GPIO_DHT22:
|
||||||
|
strcpy(dhtstype, "DHT22");
|
||||||
|
}
|
||||||
|
|
||||||
snprintf_P(log, sizeof(log), PSTR("DHT: Max clock cycles %d"), _maxcycles);
|
snprintf_P(log, sizeof(log), PSTR("DHT: Max clock cycles %d"), _maxcycles);
|
||||||
addLog(LOG_LEVEL_DEBUG, log);
|
addLog(LOG_LEVEL_DEBUG, log);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +198,8 @@ void dht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
if (dht_readTempHum(TEMP_CONVERSION, t, h)) { // Read temperature
|
if (dht_readTempHum(TEMP_CONVERSION, t, h)) { // Read temperature
|
||||||
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp1);
|
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp1);
|
||||||
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, stemp2);
|
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, stemp2);
|
||||||
snprintf_P(svalue, ssvalue, PSTR("%s, \"DHT\":{\"Temperature\":%s, \"Humidity\":%s}"), svalue, stemp1, stemp2);
|
snprintf_P(svalue, ssvalue, PSTR("%s, \"%s\":{\"Temperature\":%s, \"Humidity\":%s}"),
|
||||||
|
svalue, dhtstype, stemp1, stemp2);
|
||||||
*djson = 1;
|
*djson = 1;
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
domoticz_sensor2(stemp1, stemp2);
|
domoticz_sensor2(stemp1, stemp2);
|
||||||
|
@ -197,16 +210,18 @@ void dht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
String dht_webPresent()
|
String dht_webPresent()
|
||||||
{
|
{
|
||||||
char stemp[10], sconv[10];
|
|
||||||
float t, h;
|
|
||||||
String page = "";
|
String page = "";
|
||||||
|
float t, h;
|
||||||
|
|
||||||
if (dht_readTempHum(TEMP_CONVERSION, t, h)) { // Read temperature as Celsius (the default)
|
if (dht_readTempHum(TEMP_CONVERSION, t, h)) { // Read temperature as Celsius (the default)
|
||||||
snprintf_P(sconv, sizeof(sconv), PSTR("°%c"), (TEMP_CONVERSION) ? 'F' : 'C');
|
char stemp[10], sensor[128];
|
||||||
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp);
|
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>DHT Temperature: </td><td>"); page += stemp; page += sconv; page += F("</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, dhtstype, stemp, (TEMP_CONVERSION) ? 'F' : 'C');
|
||||||
|
page += sensor;
|
||||||
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, stemp);
|
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>DHT Humidity: </td><td>"); page += stemp; page += F("%</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, dhtstype, stemp);
|
||||||
|
page += sensor;
|
||||||
|
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,14 +191,14 @@ void dsb_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
String dsb_webPresent()
|
String dsb_webPresent()
|
||||||
{
|
{
|
||||||
// Needs TelePeriod to refresh data (Do not do it here as it takes too much time)
|
// Needs TelePeriod to refresh data (Do not do it here as it takes too much time)
|
||||||
char stemp[10], sconv[10];
|
|
||||||
float st;
|
|
||||||
String page = "";
|
String page = "";
|
||||||
|
float st;
|
||||||
|
|
||||||
if (dsb_readTemp(TEMP_CONVERSION, st)) { // Check if read failed
|
if (dsb_readTemp(TEMP_CONVERSION, st)) { // Check if read failed
|
||||||
snprintf_P(sconv, sizeof(sconv), PSTR("°%c"), (TEMP_CONVERSION) ? 'F' : 'C');
|
char stemp[10], sensor[80];
|
||||||
dtostrf(st, 1, TEMP_RESOLUTION &3, stemp);
|
dtostrf(st, 1, TEMP_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>DSB Temperature: </td><td>"); page += stemp; page += sconv; page += F("</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "DS18B20", stemp, (TEMP_CONVERSION) ? 'F' : 'C');
|
||||||
|
page += sensor;
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ OneWire *ds = NULL;
|
||||||
uint8_t ds18x20_addr[DS18X20_MAX_SENSORS][8];
|
uint8_t ds18x20_addr[DS18X20_MAX_SENSORS][8];
|
||||||
uint8_t ds18x20_idx[DS18X20_MAX_SENSORS];
|
uint8_t ds18x20_idx[DS18X20_MAX_SENSORS];
|
||||||
uint8_t ds18x20_snsrs = 0;
|
uint8_t ds18x20_snsrs = 0;
|
||||||
|
char dsbstype[8];
|
||||||
|
|
||||||
void ds18x20_init()
|
void ds18x20_init()
|
||||||
{
|
{
|
||||||
|
@ -90,23 +91,6 @@ String ds18x20_address(uint8_t sensor)
|
||||||
return String(addrStr);
|
return String(addrStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
String ds18x20_type(uint8_t sensor)
|
|
||||||
{
|
|
||||||
char typeStr[10];
|
|
||||||
|
|
||||||
switch(ds18x20_addr[ds18x20_idx[sensor]][0]) {
|
|
||||||
case 0x10:
|
|
||||||
strcpy(typeStr, "DS18S20");
|
|
||||||
break;
|
|
||||||
case 0x28:
|
|
||||||
strcpy(typeStr, "DS18B20");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strcpy(typeStr, "DS18x20");
|
|
||||||
}
|
|
||||||
return String(typeStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds18x20_convert()
|
void ds18x20_convert()
|
||||||
{
|
{
|
||||||
ds->reset();
|
ds->reset();
|
||||||
|
@ -160,6 +144,19 @@ boolean ds18x20_read(uint8_t sensor, bool S, float &t)
|
||||||
* Presentation
|
* Presentation
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
void ds18x20_type(uint8_t sensor)
|
||||||
|
{
|
||||||
|
strcpy_P(dsbstype, PSTR("DS18x20"));
|
||||||
|
switch(ds18x20_addr[ds18x20_idx[sensor]][0]) {
|
||||||
|
case 0x10:
|
||||||
|
strcpy_P(dsbstype, PSTR("DS18S20"));
|
||||||
|
break;
|
||||||
|
case 0x28:
|
||||||
|
strcpy_P(dsbstype, PSTR("DS18B20"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
{
|
{
|
||||||
char stemp1[10], stemp2[10];
|
char stemp1[10], stemp2[10];
|
||||||
|
@ -168,6 +165,7 @@ void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
byte dsxflg = 0;
|
byte dsxflg = 0;
|
||||||
for (byte i = 0; i < ds18x20_sensors(); i++) {
|
for (byte i = 0; i < ds18x20_sensors(); i++) {
|
||||||
if (ds18x20_read(i, TEMP_CONVERSION, t)) { // Check if read failed
|
if (ds18x20_read(i, TEMP_CONVERSION, t)) { // Check if read failed
|
||||||
|
ds18x20_type(i);
|
||||||
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp2);
|
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp2);
|
||||||
if (!dsxflg) {
|
if (!dsxflg) {
|
||||||
snprintf_P(svalue, ssvalue, PSTR("%s, \"DS18x20\":{"), svalue);
|
snprintf_P(svalue, ssvalue, PSTR("%s, \"DS18x20\":{"), svalue);
|
||||||
|
@ -176,7 +174,7 @@ void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
}
|
}
|
||||||
dsxflg++;
|
dsxflg++;
|
||||||
snprintf_P(svalue, ssvalue, PSTR("%s%s\"DS%d\":{\"Type\":\"%s\", \"Address\":\"%s\", \"Temperature\":%s}"),
|
snprintf_P(svalue, ssvalue, PSTR("%s%s\"DS%d\":{\"Type\":\"%s\", \"Address\":\"%s\", \"Temperature\":%s}"),
|
||||||
svalue, stemp1, i +1, ds18x20_type(i).c_str(), ds18x20_address(i).c_str(), stemp2);
|
svalue, stemp1, i +1, dsbstype, ds18x20_address(i).c_str(), stemp2);
|
||||||
strcpy(stemp1, ", ");
|
strcpy(stemp1, ", ");
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
if (dsxflg == 1) domoticz_sensor1(stemp2);
|
if (dsxflg == 1) domoticz_sensor1(stemp2);
|
||||||
|
@ -189,15 +187,17 @@ void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
String ds18x20_webPresent()
|
String ds18x20_webPresent()
|
||||||
{
|
{
|
||||||
char stemp[10], sconv[10];
|
|
||||||
float t;
|
|
||||||
String page = "";
|
String page = "";
|
||||||
|
char stemp[10], stemp2[16], sensor[80];
|
||||||
|
float t;
|
||||||
|
|
||||||
snprintf_P(sconv, sizeof(sconv), PSTR("°%c"), (TEMP_CONVERSION) ? 'F' : 'C');
|
|
||||||
for (byte i = 0; i < ds18x20_sensors(); i++) {
|
for (byte i = 0; i < ds18x20_sensors(); i++) {
|
||||||
if (ds18x20_read(i, TEMP_CONVERSION, t)) { // Check if read failed
|
if (ds18x20_read(i, TEMP_CONVERSION, t)) { // Check if read failed
|
||||||
|
ds18x20_type(i);
|
||||||
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp);
|
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>DS"); page += String(i +1); page += F(" Temperature: </td><td>"); page += stemp; page += sconv; page += F("</td></tr>");
|
snprintf_P(stemp2, sizeof(stemp2), PSTR("%s-%d"), dsbstype, i +1);
|
||||||
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, stemp2, stemp, (TEMP_CONVERSION) ? 'F' : 'C');
|
||||||
|
page += sensor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
|
|
|
@ -102,11 +102,13 @@ void hlw_200mS()
|
||||||
hlw_EDcntr = 0;
|
hlw_EDcntr = 0;
|
||||||
hlw_temp = (HLW_PREF * sysCfg.hlw_pcal) / hlw_len;
|
hlw_temp = (HLW_PREF * sysCfg.hlw_pcal) / hlw_len;
|
||||||
hlw_kWhtoday += (hlw_temp * 100) / 36;
|
hlw_kWhtoday += (hlw_temp * 100) / 36;
|
||||||
|
rtcMem.hlw_kWhtoday = hlw_kWhtoday;
|
||||||
}
|
}
|
||||||
if (rtcTime.Valid) {
|
if (rtcTime.Valid) {
|
||||||
if (rtc_loctime() == rtc_midnight()) {
|
if (rtc_loctime() == rtc_midnight()) {
|
||||||
sysCfg.hlw_kWhyesterday = hlw_kWhtoday;
|
sysCfg.hlw_kWhyesterday = hlw_kWhtoday;
|
||||||
hlw_kWhtoday = 0;
|
hlw_kWhtoday = 0;
|
||||||
|
rtcMem.hlw_kWhtoday = hlw_kWhtoday;
|
||||||
hlw_mkwh_state = 3;
|
hlw_mkwh_state = 3;
|
||||||
}
|
}
|
||||||
if ((rtcTime.Hour == sysCfg.hlw_mkwhs) && (hlw_mkwh_state == 3)) {
|
if ((rtcTime.Hour == sysCfg.hlw_mkwhs) && (hlw_mkwh_state == 3)) {
|
||||||
|
@ -114,6 +116,7 @@ void hlw_200mS()
|
||||||
}
|
}
|
||||||
if (hlw_startup && (rtcTime.DayOfYear == sysCfg.hlw_kWhdoy)) {
|
if (hlw_startup && (rtcTime.DayOfYear == sysCfg.hlw_kWhdoy)) {
|
||||||
hlw_kWhtoday = sysCfg.hlw_kWhtoday;
|
hlw_kWhtoday = sysCfg.hlw_kWhtoday;
|
||||||
|
rtcMem.hlw_kWhtoday = hlw_kWhtoday;
|
||||||
hlw_startup = 0;
|
hlw_startup = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +239,7 @@ void hlw_init()
|
||||||
|
|
||||||
hlw_Ecntr = 0;
|
hlw_Ecntr = 0;
|
||||||
hlw_EDcntr = 0;
|
hlw_EDcntr = 0;
|
||||||
hlw_kWhtoday = 0;
|
hlw_kWhtoday = (RTC_Valid()) ? rtcMem.hlw_kWhtoday : 0;
|
||||||
|
|
||||||
hlw_SELflag = 0; // Voltage;
|
hlw_SELflag = 0; // Voltage;
|
||||||
|
|
||||||
|
@ -540,18 +543,16 @@ void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue)
|
||||||
|
|
||||||
void hlw_mqttPresent()
|
void hlw_mqttPresent()
|
||||||
{
|
{
|
||||||
char svalue[MESSZ], stime[21];
|
char svalue[MESSZ];
|
||||||
|
|
||||||
snprintf_P(stime, sizeof(stime), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
|
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%04d-%02d-%02dT%02d:%02d:%02d\", "),
|
||||||
rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
|
rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
|
||||||
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", "), stime);
|
|
||||||
hlw_mqttStat(1, svalue, sizeof(svalue));
|
hlw_mqttStat(1, svalue, sizeof(svalue));
|
||||||
|
|
||||||
// snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/ENERGY"), PUB_PREFIX2, sysCfg.mqtt_topic);
|
// snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/ENERGY"), PUB_PREFIX2, sysCfg.mqtt_topic);
|
||||||
// mqtt_publish(stopic, svalue);
|
// mqtt_publish(stopic, svalue);
|
||||||
|
|
||||||
mqtt_publish_topic_P(1, PSTR("ENERGY"), svalue);
|
mqtt_publish_topic_P(1, PSTR("ENERGY"), svalue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hlw_mqttStatus(char* svalue, uint16_t ssvalue)
|
void hlw_mqttStatus(char* svalue, uint16_t ssvalue)
|
||||||
|
@ -562,24 +563,29 @@ void hlw_mqttStatus(char* svalue, uint16_t ssvalue)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
|
const char HTTP_ENERGY_SNS[] PROGMEM =
|
||||||
|
"<tr><th>Voltage</th><td>%d V</td></tr>"
|
||||||
|
"<tr><th>Current</th><td>%s A</td></tr>"
|
||||||
|
"<tr><th>Power</th><td>%d W</td></tr>"
|
||||||
|
"<tr><th>Power Factor</th><td>%s</td></tr>"
|
||||||
|
"<tr><th>Energy Today</th><td>%s kWh</td></tr>"
|
||||||
|
"<tr><th>Energy Yesterday</th><td>%s kWh</td></tr>";
|
||||||
|
|
||||||
String hlw_webPresent()
|
String hlw_webPresent()
|
||||||
{
|
{
|
||||||
char stemp[10];
|
String page = "";
|
||||||
|
char stemp[10], stemp2[10], stemp3[10], stemp4[10], sensor[300];
|
||||||
float ped, pi, pc;
|
float ped, pi, pc;
|
||||||
uint16_t pe, pw, pu;
|
uint16_t pe, pw, pu;
|
||||||
String page = "";
|
|
||||||
|
|
||||||
hlw_readEnergy(0, ped, pe, pw, pu, pi, pc);
|
hlw_readEnergy(0, ped, pe, pw, pu, pi, pc);
|
||||||
page += F("<tr><td>Voltage: </td><td>"); page += String(pu); page += F(" V</td></tr>");
|
|
||||||
dtostrf(pi, 1, 3, stemp);
|
dtostrf(pi, 1, 3, stemp);
|
||||||
page += F("<tr><td>Current: </td><td>"); page += stemp; page += F(" A</td></tr>");
|
dtostrf(pc, 1, 2, stemp2);
|
||||||
page += F("<tr><td>Power: </td><td>"); page += String(pw); page += F(" W</td></tr>");
|
dtostrf(ped, 1, 3, stemp3);
|
||||||
dtostrf(pc, 1, 2, stemp);
|
dtostrf((float)sysCfg.hlw_kWhyesterday / 100000000, 1, 3, stemp4);
|
||||||
page += F("<tr><td>Power Factor: </td><td>"); page += stemp; page += F("</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, pu, stemp, pw, stemp2, stemp3, stemp4);
|
||||||
dtostrf(ped, 1, 3, stemp);
|
page += sensor;
|
||||||
page += F("<tr><td>Energy Today: </td><td>"); page += stemp; page += F(" kWh</td></tr>");
|
|
||||||
dtostrf((float)sysCfg.hlw_kWhyesterday / 100000000, 1, 3, stemp);
|
|
||||||
page += F("<tr><td>Energy Yesterday: </td><td>"); page += stemp; page += F(" kWh</td></tr>");
|
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
|
|
||||||
#define HTU21_ADDR 0x40
|
#define HTU21_ADDR 0x40
|
||||||
|
|
||||||
|
#define SI7013_CHIPID 0x0D
|
||||||
|
#define SI7020_CHIPID 0x14
|
||||||
|
#define SI7021_CHIPID 0x15
|
||||||
#define HTU21_CHIPID 0x32
|
#define HTU21_CHIPID 0x32
|
||||||
|
|
||||||
#define HTU21_READTEMP 0xE3
|
#define HTU21_READTEMP 0xE3
|
||||||
|
@ -53,12 +56,10 @@
|
||||||
#define HTU21_RES_RH10_T13 0x80
|
#define HTU21_RES_RH10_T13 0x80
|
||||||
#define HTU21_RES_RH11_T11 0x81
|
#define HTU21_RES_RH11_T11 0x81
|
||||||
|
|
||||||
#define HTU21_MAX_HUM 16 // 16ms max time
|
|
||||||
#define HTU21_MAX_TEMP 50 // 50ms max time
|
|
||||||
|
|
||||||
#define HTU21_CRC8_POLYNOM 0x13100
|
#define HTU21_CRC8_POLYNOM 0x13100
|
||||||
|
|
||||||
uint8_t htuaddr, htutype = 0;
|
uint8_t htuaddr, htutype = 0;
|
||||||
|
uint8_t delayT, delayH = 50;
|
||||||
char htustype[7];
|
char htustype[7];
|
||||||
|
|
||||||
uint8_t check_crc8(uint16_t data)
|
uint8_t check_crc8(uint16_t data)
|
||||||
|
@ -149,7 +150,7 @@ float htu21_readHumidity(void)
|
||||||
Wire.beginTransmission(HTU21_ADDR);
|
Wire.beginTransmission(HTU21_ADDR);
|
||||||
Wire.write(HTU21_READHUM);
|
Wire.write(HTU21_READHUM);
|
||||||
if(Wire.endTransmission() != 0) return 0.0; // In case of error
|
if(Wire.endTransmission() != 0) return 0.0; // In case of error
|
||||||
delay(HTU21_MAX_HUM); // HTU21 time at max resolution
|
delay(delayH); // Sensor time at max resolution
|
||||||
|
|
||||||
Wire.requestFrom(HTU21_ADDR, 3);
|
Wire.requestFrom(HTU21_ADDR, 3);
|
||||||
if(3 <= Wire.available())
|
if(3 <= Wire.available())
|
||||||
|
@ -163,8 +164,8 @@ float htu21_readHumidity(void)
|
||||||
sensorval ^= 0x02; // clear status bits
|
sensorval ^= 0x02; // clear status bits
|
||||||
humidity = 0.001907 * (float)sensorval - 6;
|
humidity = 0.001907 * (float)sensorval - 6;
|
||||||
|
|
||||||
if(humidity>100) return 100.0;
|
if(humidity > 100) return 100.0;
|
||||||
if(humidity<0) return 0.01;
|
if(humidity < 0) return 0.01;
|
||||||
|
|
||||||
return humidity;
|
return humidity;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +179,7 @@ float htu21_readTemperature(bool S)
|
||||||
Wire.beginTransmission(HTU21_ADDR);
|
Wire.beginTransmission(HTU21_ADDR);
|
||||||
Wire.write(HTU21_READTEMP);
|
Wire.write(HTU21_READTEMP);
|
||||||
if(Wire.endTransmission() != 0) return 0.0; // In case of error
|
if(Wire.endTransmission() != 0) return 0.0; // In case of error
|
||||||
delay(HTU21_MAX_TEMP); // HTU21 time at max resolution
|
delay(delayT); // Sensor time at max resolution
|
||||||
|
|
||||||
Wire.requestFrom(HTU21_ADDR, 3);
|
Wire.requestFrom(HTU21_ADDR, 3);
|
||||||
if(3 == Wire.available())
|
if(3 == Wire.available())
|
||||||
|
@ -210,11 +211,32 @@ uint8_t htu_detect()
|
||||||
|
|
||||||
htuaddr = HTU21_ADDR;
|
htuaddr = HTU21_ADDR;
|
||||||
htutype = htu21_readDeviceID();
|
htutype = htu21_readDeviceID();
|
||||||
snprintf_P(htustype, sizeof(htustype), PSTR("HTU"));
|
success = htu21_init();
|
||||||
switch (htutype) {
|
switch (htutype) {
|
||||||
case HTU21_CHIPID:
|
case HTU21_CHIPID:
|
||||||
success = htu21_init();
|
strcpy_P(htustype, PSTR("HTU21"));
|
||||||
snprintf_P(htustype, sizeof(htustype), PSTR("HTU21"));
|
delayT=50;
|
||||||
|
delayH=16;
|
||||||
|
break;
|
||||||
|
case SI7013_CHIPID:
|
||||||
|
strcpy_P(htustype, PSTR("SI7013"));
|
||||||
|
delayT=12;
|
||||||
|
delayH=23;
|
||||||
|
break;
|
||||||
|
case SI7020_CHIPID:
|
||||||
|
strcpy_P(htustype, PSTR("SI7020"));
|
||||||
|
delayT=12;
|
||||||
|
delayH=23;
|
||||||
|
break;
|
||||||
|
case SI7021_CHIPID:
|
||||||
|
strcpy_P(htustype, PSTR("SI7021"));
|
||||||
|
delayT=12;
|
||||||
|
delayH=23;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy_P(htustype, PSTR("T/RH?"));
|
||||||
|
delayT=50;
|
||||||
|
delayH=23;
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
snprintf_P(log, sizeof(log), PSTR("I2C: %s found at address 0x%x"), htustype, htuaddr);
|
snprintf_P(log, sizeof(log), PSTR("I2C: %s found at address 0x%x"), htustype, htuaddr);
|
||||||
|
@ -240,7 +262,8 @@ void htu_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||||
h = htu21_compensatedHumidity(h, t);
|
h = htu21_compensatedHumidity(h, t);
|
||||||
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp1);
|
dtostrf(t, 1, TEMP_RESOLUTION &3, stemp1);
|
||||||
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, stemp2);
|
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, stemp2);
|
||||||
snprintf_P(svalue, ssvalue, PSTR("%s, \"%s\":{\"Temperature\":%s, \"Humidity\":%s}"), svalue, htustype, stemp1, stemp2);
|
snprintf_P(svalue, ssvalue, PSTR("%s, \"%s\":{\"Temperature\":%s, \"Humidity\":%s}"),
|
||||||
|
svalue, htustype, stemp1, stemp2);
|
||||||
*djson = 1;
|
*djson = 1;
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
domoticz_sensor2(stemp1, stemp2);
|
domoticz_sensor2(stemp1, stemp2);
|
||||||
|
@ -252,16 +275,17 @@ String htu_webPresent()
|
||||||
{
|
{
|
||||||
String page = "";
|
String page = "";
|
||||||
if (htutype) {
|
if (htutype) {
|
||||||
char itemp[10], iconv[10];
|
char stemp[10], sensor[128];
|
||||||
|
|
||||||
snprintf_P(iconv, sizeof(iconv), PSTR("°%c"), (TEMP_CONVERSION) ? 'F' : 'C');
|
|
||||||
float t_htu21 = htu21_readTemperature(TEMP_CONVERSION);
|
float t_htu21 = htu21_readTemperature(TEMP_CONVERSION);
|
||||||
float h_htu21 = htu21_readHumidity();
|
float h_htu21 = htu21_readHumidity();
|
||||||
h_htu21 = htu21_compensatedHumidity(h_htu21, t_htu21);
|
h_htu21 = htu21_compensatedHumidity(h_htu21, t_htu21);
|
||||||
dtostrf(t_htu21, 1, TEMP_RESOLUTION &3, itemp);
|
dtostrf(t_htu21, 1, TEMP_RESOLUTION &3, stemp);
|
||||||
page += F("<tr><td>HTU Temperature: </td><td>"); page += itemp; page += iconv; page += F("</td></tr>");
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, htustype, stemp, (TEMP_CONVERSION) ? 'F' : 'C');
|
||||||
dtostrf(h_htu21, 1, HUMIDITY_RESOLUTION &3, itemp);
|
page += sensor;
|
||||||
page += F("<tr><td>HTU Humidity: </td><td>"); page += itemp; page += F("%</td></tr>");
|
dtostrf(h_htu21, 1, HUMIDITY_RESOLUTION &3, stemp);
|
||||||
|
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, htustype, stemp);
|
||||||
|
page += sensor;
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue