mirror of https://github.com/arendst/Tasmota.git
Merge branch 'arendst/development' into development
This commit is contained in:
commit
1c7d475d0a
|
@ -1,7 +1,7 @@
|
|||
## 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.
|
||||
|
||||
Current version is **5.11.1e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.11.1g** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
### ATTENTION All versions
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,14 @@
|
|||
/* 5.11.1e
|
||||
/* 5.11.1g
|
||||
* Add support for PMS5003 and PMS7003 particle concentration sensor
|
||||
* Reinstate console weblog to 20 lines after some webpage rewrite
|
||||
* Add command SetOption20 to allow update of Dimmer/Color/Ct without turning power on (#1719)
|
||||
* Update language files nl-NL (#1723) and es-AR (#1722)
|
||||
*
|
||||
* 5.11.1f
|
||||
* Revert chunked webserver pages as it fails on many browsers due to chunks being too small (#1706)
|
||||
* Reduce initial console weblog from 20 to 13 lines due to memory constraints
|
||||
*
|
||||
* 5.11.1e
|
||||
* Replaced command Ina219Mode with command Sensor13
|
||||
* Add chunked webserver pages for large pages saving memory
|
||||
* Fix Non-English JSON temperature unit attachement
|
||||
|
|
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X gefunden"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Standard Concentration"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Environmental Concentration"
|
||||
#define D_PARTICALS_BEYOND "Particals beyond"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Particals"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X found"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Standard Concentration"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Environmental Concentration"
|
||||
#define D_PARTICALS_BEYOND "Particals beyond"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Particals"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#define D_BLINK "Blink"
|
||||
#define D_BLINKOFF "BlinkOff"
|
||||
#define D_BOOT_COUNT "Conteo Reinicios"
|
||||
#define D_BRIGHTLIGHT "Brillo"
|
||||
#define D_BRIGHTLIGHT "Brillante"
|
||||
#define D_BUTTON "Botón"
|
||||
#define D_BY "por" // Written by me
|
||||
#define D_BYTES "Bytes"
|
||||
|
@ -79,7 +79,7 @@
|
|||
#define D_ERASE "Borrar"
|
||||
#define D_ERROR "Error"
|
||||
#define D_FAHRENHEIT "Fahrenheit"
|
||||
#define D_FAILED "Fallo"
|
||||
#define D_FAILED "Falló"
|
||||
#define D_FALLBACK "Fallback"
|
||||
#define D_FALLBACK_TOPIC "FallbackTopic"
|
||||
#define D_FALSE "Falso"
|
||||
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X encontrado"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Concentración Standard"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Concentración en Medio Ambiente"
|
||||
#define D_PARTICALS_BEYOND "Partículas sobre"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Partículas"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X found"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Concentration standard"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Concentration environmentale"
|
||||
#define D_PARTICALS_BEYOND "Particules au-delà"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Particules"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X trovato"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Concentrazione Standard"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Concentrazione Ambientale"
|
||||
#define D_PARTICALS_BEYOND "Particelle oltre"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Particelle"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
// Common
|
||||
#define D_ADMIN "Admin"
|
||||
#define D_AIR_QUALITY "Lucht kwalitiet"
|
||||
#define D_AIR_QUALITY "Lucht kwaliteit"
|
||||
#define D_AP "AP" // Access Point
|
||||
#define D_AS "als"
|
||||
#define D_AUTO "AUTO"
|
||||
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X gevonden"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Standard Concentration"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Environmental Concentration"
|
||||
#define D_PARTICALS_BEYOND "Particals beyond"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Stofdeeltjes"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -376,9 +376,9 @@
|
|||
#define D_SHT1X_FOUND "SHT1X znaleziony"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "Standard Concentration"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "Environmental Concentration"
|
||||
#define D_PARTICALS_BEYOND "Particals beyond"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "Particals"
|
||||
|
||||
// sonoff_template.h
|
||||
// Max string length is 8 characters including suffixes
|
||||
|
|
|
@ -376,8 +376,8 @@
|
|||
#define D_SHT1X_FOUND "发现 SHT1X 传感器"
|
||||
|
||||
// xsns_18_pms5003.ino
|
||||
#define D_STANDARD_CONCENTRATION "标准颗粒物浓度"
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "大气环境下浓度"
|
||||
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
|
||||
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
|
||||
#define D_PARTICALS_BEYOND "颗粒物直径大于"
|
||||
|
||||
// sonoff_template.h
|
||||
|
|
|
@ -45,7 +45,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t decimal_text : 1; // bit 17 (v5.8.1)
|
||||
uint32_t light_signal : 1; // bit 18 (v5.10.0c)
|
||||
uint32_t hass_discovery : 1; // bit 19 (v5.11.1a)
|
||||
uint32_t voltage_resolution : 1; // Replaced by below
|
||||
uint32_t not_power_linked : 1; // bit 20 (v5.11.1f)
|
||||
uint32_t spare21 : 1;
|
||||
uint32_t spare22 : 1;
|
||||
uint32_t spare23 : 1;
|
||||
|
@ -57,15 +57,6 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t spare29 : 1;
|
||||
uint32_t spare30 : 1;
|
||||
uint32_t spare31 : 1;
|
||||
/*
|
||||
uint32_t wattage_resolution : 1;
|
||||
uint32_t voltage_resolution : 1;
|
||||
uint32_t emulation : 2;
|
||||
uint32_t energy_resolution : 3;
|
||||
uint32_t pressure_resolution : 2;
|
||||
uint32_t humidity_resolution : 2;
|
||||
uint32_t temperature_resolution : 2;
|
||||
*/
|
||||
};
|
||||
} SysBitfield;
|
||||
|
||||
|
|
|
@ -430,7 +430,7 @@ void SettingsDefaultSet2()
|
|||
Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN;
|
||||
Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN;
|
||||
Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN;
|
||||
Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE;
|
||||
Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE;
|
||||
|
||||
Settings.flag2.emulation = EMULATION;
|
||||
|
||||
|
@ -845,13 +845,17 @@ void SettingsDelta()
|
|||
if (Settings.version < 0x05090102) {
|
||||
Settings.flag2.data = Settings.flag.data;
|
||||
Settings.flag2.data &= 0xFFE80000;
|
||||
Settings.flag2.voltage_resolution = Settings.flag.voltage_resolution;
|
||||
Settings.flag2.voltage_resolution = Settings.flag.not_power_linked;
|
||||
Settings.flag2.current_resolution = 3;
|
||||
Settings.ina219_mode = 0;
|
||||
}
|
||||
if (Settings.version < 0x050A0009) {
|
||||
SettingsDefaultSet_5_10_1();
|
||||
}
|
||||
if (Settings.version < 0x050B0107) {
|
||||
Settings.flag.not_power_linked = 0;
|
||||
}
|
||||
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
|
|
|
@ -90,7 +90,11 @@ typedef unsigned long power_t; // Power (Relay) type
|
|||
#ifdef USE_MQTT_TLS
|
||||
#define MAX_LOG_LINES 10 // Max number of lines in weblog
|
||||
#else
|
||||
#define MAX_LOG_LINES 20 // Max number of lines in weblog
|
||||
// #ifdef ARDUINO_ESP8266_RELEASE_2_3_0
|
||||
#define MAX_LOG_LINES 20 // Max number of lines in weblog
|
||||
// #else
|
||||
// #define MAX_LOG_LINES 13 // Max number of lines in weblog (less due to more memory usage which prohibits full webpage load)
|
||||
// #endif
|
||||
#endif
|
||||
#define MAX_BACKLOG 16 // Max number of commands in backlog (chk backlog_index and backlog_pointer code)
|
||||
#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds
|
||||
|
|
|
@ -25,9 +25,10 @@
|
|||
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x050B0105 // 5.11.1e
|
||||
#define VERSION 0x050B0107 // 5.11.1g
|
||||
|
||||
// Location specific includes
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
#include "sonoff.h" // Enumeration used in user_config.h
|
||||
#include "user_config.h" // Fixed user configurable options
|
||||
#include "user_config_override.h" // Configuration overrides for user_config.h
|
||||
|
@ -1026,6 +1027,7 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
|
|||
case 16: // ws_clock_reverse
|
||||
case 17: // decimal_text
|
||||
case 18: // light_signal
|
||||
case 20: // not_power_linked
|
||||
bitWrite(Settings.flag.data, index, payload);
|
||||
}
|
||||
if (12 == index) { // stop_flash_rotate
|
||||
|
|
|
@ -108,7 +108,7 @@ void WifiWpsStatusCallback(wps_cb_status status);
|
|||
#define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string (6 x DS18x20 sensors)
|
||||
#endif
|
||||
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
//#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
#ifndef ARDUINO_ESP8266_RELEASE
|
||||
#define ARDUINO_ESP8266_RELEASE "STAGED"
|
||||
#endif
|
||||
|
|
|
@ -216,6 +216,8 @@
|
|||
#define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1)
|
||||
#define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1)
|
||||
|
||||
#define USE_PMS5003 // Add support for PMS5003 particle concentration sensor (+1k3 code)
|
||||
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
|
||||
// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code)
|
||||
#define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram)
|
||||
|
|
|
@ -60,7 +60,7 @@ const char HTTP_HEAD[] PROGMEM =
|
|||
"x=new XMLHttpRequest();"
|
||||
"x.onreadystatechange=function(){"
|
||||
"if(x.readyState==4&&x.status==200){"
|
||||
"var s=x.responseText.replace(/{s}/g,\"<tr><th>\").replace(/{m}/g,\"</th><td>\").replace(/{e}/g,\"</td></tr>\").replace(/{t}/g,\"%'><div style='text-align:center;font-weight:\");"
|
||||
"var s=x.responseText.replace(/{t}/g,\"<table style='width:100%'>\").replace(/{s}/g,\"<tr><th>\").replace(/{m}/g,\"</th><td>\").replace(/{e}/g,\"</td></tr>\").replace(/{c}/g,\"%'><div style='text-align:center;font-weight:\");"
|
||||
"document.getElementById('l1').innerHTML=s;"
|
||||
"}"
|
||||
"};"
|
||||
|
@ -414,6 +414,8 @@ void PollDnsWebserver()
|
|||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void SetHeader()
|
||||
{
|
||||
WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"));
|
||||
|
@ -424,8 +426,6 @@ void SetHeader()
|
|||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void ShowPage(String &page, bool auth)
|
||||
{
|
||||
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
|
||||
|
@ -453,57 +453,6 @@ void ShowPage(String &page)
|
|||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void ShowPageStartChunk()
|
||||
{
|
||||
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), "");
|
||||
}
|
||||
|
||||
void ShowPageChunk(String &page)
|
||||
{
|
||||
page.replace(F("{ha"), my_module.name);
|
||||
page.replace(F("{h}"), Settings.friendlyname[0]);
|
||||
if (HTTP_MANAGER == webserver_state) {
|
||||
if (WifiConfigCounter()) {
|
||||
page.replace(F("<body>"), F("<body onload='u()'>"));
|
||||
page += FPSTR(HTTP_COUNTER);
|
||||
}
|
||||
}
|
||||
WebServer->sendContent(page);
|
||||
}
|
||||
|
||||
void ShowPageStart(String &page, bool auth)
|
||||
{
|
||||
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
|
||||
return WebServer->requestAuthentication();
|
||||
}
|
||||
SetHeader();
|
||||
ShowPageStartChunk();
|
||||
ShowPageChunk(page);
|
||||
}
|
||||
|
||||
void ShowPageStart(String &page)
|
||||
{
|
||||
ShowPageStart(page, true);
|
||||
}
|
||||
|
||||
void ShowPageStopChunk()
|
||||
{
|
||||
WebServer->sendContent("");
|
||||
WebServer->client().stop(); // Stop is needed because we sent no content length
|
||||
}
|
||||
|
||||
void ShowPageEnd(String &page)
|
||||
{
|
||||
ShowPageChunk(page);
|
||||
String endpart = FPSTR(HTTP_END);
|
||||
endpart.replace(F("{mv"), my_version);
|
||||
WebServer->sendContent(endpart);
|
||||
ShowPageStopChunk();
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void HandleWifiLogin()
|
||||
{
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
|
@ -534,7 +483,6 @@ void HandleRoot()
|
|||
}
|
||||
} else {
|
||||
char stemp[10];
|
||||
char line[160];
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
page.replace(F("{v}"), FPSTR(S_MAIN_MENU));
|
||||
page += FPSTR(HTTP_HEAD_STYLE);
|
||||
|
@ -544,19 +492,19 @@ void HandleRoot()
|
|||
if (devices_present) {
|
||||
if (light_type) {
|
||||
if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) {
|
||||
snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER1, LightGetColorTemp());
|
||||
page += line;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER1, LightGetColorTemp());
|
||||
page += mqtt_data;
|
||||
}
|
||||
snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER2, Settings.light_dimmer);
|
||||
page += line;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER2, Settings.light_dimmer);
|
||||
page += mqtt_data;
|
||||
}
|
||||
page += FPSTR(HTTP_TABLE100);
|
||||
page += F("<tr>");
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx);
|
||||
snprintf_P(line, sizeof(line), PSTR("<td style='width:%d%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>"),
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>"),
|
||||
100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : "");
|
||||
page += line;
|
||||
page += mqtt_data;
|
||||
}
|
||||
page += F("</tr></table>");
|
||||
}
|
||||
|
@ -570,8 +518,8 @@ void HandleRoot()
|
|||
}
|
||||
for (byte j = 0; j < 4; j++) {
|
||||
idx++;
|
||||
snprintf_P(line, sizeof(line), PSTR("<td style='width:25%'><button onclick='la(\"?k=%d\");'>%d</button></td>"), idx, idx);
|
||||
page += line;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:25%'><button onclick='la(\"?k=%d\");'>%d</button></td>"), idx, idx);
|
||||
page += mqtt_data;
|
||||
}
|
||||
}
|
||||
page += F("</tr></table>");
|
||||
|
@ -604,24 +552,74 @@ void HandleAjaxStatusRefresh()
|
|||
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), WebServer->arg("k").c_str());
|
||||
ExecuteCommand(svalue);
|
||||
}
|
||||
|
||||
ShowPageStartChunk();
|
||||
WebServer->sendContent(HTTP_TABLE100);
|
||||
/*
|
||||
String page = "";
|
||||
mqtt_data[0] = '\0';
|
||||
XsnsCall(FUNC_WEB_APPEND);
|
||||
WebServer->sendContent(PSTR("</table>"));
|
||||
if (strlen(mqtt_data)) {
|
||||
page += FPSTR(HTTP_TABLE100);
|
||||
page += mqtt_data;
|
||||
page.replace(F("."), F(D_DECIMAL_SEPARATOR));
|
||||
page += F("</table>");
|
||||
}
|
||||
if (devices_present) {
|
||||
WebServer->sendContent(HTTP_TABLE100);
|
||||
WebServer->sendContent(PSTR("<tr>"));
|
||||
page += FPSTR(HTTP_TABLE100);
|
||||
page += F("<tr>");
|
||||
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d{t}%s;font-size:%dpx'>%s</div></td>"), // {t} = %'><div style='text-align:center;font-weight:
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d{c}%s;font-size:%dpx'>%s</div></td>"), // {c} = %'><div style='text-align:center;font-weight:
|
||||
100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
|
||||
WebServer->sendContent(mqtt_data);
|
||||
page += mqtt_data;
|
||||
}
|
||||
WebServer->sendContent(PSTR("</tr></table>"));
|
||||
page += F("</tr></table>");
|
||||
}
|
||||
ShowPageStopChunk();
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page);
|
||||
*/
|
||||
/*
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<table style='width:100%%'>"));
|
||||
XsnsCall(FUNC_WEB_APPEND);
|
||||
if (D_DECIMAL_SEPARATOR[0] != '.') {
|
||||
for (int i = 0; i < strlen(mqtt_data); i++) {
|
||||
if ('.' == mqtt_data[i]) {
|
||||
mqtt_data[i] = D_DECIMAL_SEPARATOR[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s</table>"), mqtt_data);
|
||||
if (devices_present) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s<table style='width:100%%'><tr>"), mqtt_data);
|
||||
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s<td style='width:%d{c}%s;font-size:%dpx'>%s</div></td>"), // {c} = %'><div style='text-align:center;font-weight:
|
||||
mqtt_data, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s</tr></table>"), mqtt_data);
|
||||
}
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), mqtt_data);
|
||||
*/
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{t}"));
|
||||
XsnsCall(FUNC_WEB_APPEND);
|
||||
if (D_DECIMAL_SEPARATOR[0] != '.') {
|
||||
for (int i = 0; i < strlen(mqtt_data); i++) {
|
||||
if ('.' == mqtt_data[i]) {
|
||||
mqtt_data[i] = D_DECIMAL_SEPARATOR[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s</table>"), mqtt_data);
|
||||
if (devices_present) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{t}<tr>"), mqtt_data);
|
||||
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s<td style='width:%d{c}%s;font-size:%dpx'>%s</div></td>"), // {c} = %'><div style='text-align:center;font-weight:
|
||||
mqtt_data, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s</tr></table>"), mqtt_data);
|
||||
}
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), mqtt_data);
|
||||
}
|
||||
|
||||
boolean HttpUser()
|
||||
|
@ -714,67 +712,61 @@ void HandleModuleConfiguration()
|
|||
return;
|
||||
}
|
||||
char stemp[20];
|
||||
char line[160];
|
||||
uint8_t midx;
|
||||
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE);
|
||||
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE));
|
||||
ShowPageStart(page);
|
||||
|
||||
page = FPSTR(HTTP_SCRIPT_MODULE1);
|
||||
page += FPSTR(HTTP_SCRIPT_MODULE1);
|
||||
for (byte i = 0; i < MAXMODULE; i++) {
|
||||
midx = pgm_read_byte(kNiceList + i);
|
||||
snprintf_P(stemp, sizeof(stemp), kModules[midx].name);
|
||||
snprintf_P(line, sizeof(line), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp);
|
||||
page += line;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp);
|
||||
page += mqtt_data;
|
||||
}
|
||||
page += FPSTR(HTTP_SCRIPT_MODULE3);
|
||||
ShowPageChunk(page);
|
||||
|
||||
snprintf_P(line, sizeof(line), PSTR("sk(%d,99);o0=\""), Settings.module); // g99
|
||||
page = line;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,99);o0=\""), Settings.module); // g99
|
||||
page += mqtt_data;
|
||||
|
||||
mytmplt cmodule;
|
||||
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule));
|
||||
|
||||
for (byte j = 0; j < GPIO_SENSOR_END; j++) {
|
||||
if (!GetUsedInModule(j, cmodule.gp.io)) {
|
||||
snprintf_P(stemp, sizeof(stemp), kSensors[j]);
|
||||
snprintf_P(line, sizeof(line), HTTP_SCRIPT_MODULE2, j, j, stemp);
|
||||
page += line;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, j, j, stemp);
|
||||
page += mqtt_data;
|
||||
}
|
||||
}
|
||||
page += FPSTR(HTTP_SCRIPT_MODULE3);
|
||||
ShowPageChunk(page);
|
||||
|
||||
page = FPSTR(HTTP_HEAD_STYLE);
|
||||
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (GPIO_USER == cmodule.gp.io[i]) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16
|
||||
page += mqtt_data;
|
||||
}
|
||||
}
|
||||
page += F("}");
|
||||
|
||||
page += FPSTR(HTTP_HEAD_STYLE);
|
||||
page.replace(F("<body>"), F("<body onload='sl()'>"));
|
||||
page += FPSTR(HTTP_FORM_MODULE);
|
||||
snprintf_P(stemp, sizeof(stemp), kModules[MODULE].name);
|
||||
page.replace(F("{mt"), stemp);
|
||||
page += F("<br/><table>");
|
||||
|
||||
String func = "";
|
||||
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (GPIO_USER == cmodule.gp.io[i]) {
|
||||
snprintf_P(stemp, 3, PINS_WEMOS +i*2);
|
||||
snprintf_P(line, sizeof(line), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:126px'><select id='g%d' name='g%d'></select></td></tr>"),
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:126px'><select id='g%d' name='g%d'></select></td></tr>"),
|
||||
(WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i);
|
||||
page += line;
|
||||
snprintf_P(line, sizeof(line), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16
|
||||
func += line;
|
||||
page += mqtt_data;
|
||||
}
|
||||
}
|
||||
func += F("}");
|
||||
ShowPageChunk(func);
|
||||
|
||||
page.replace(F("<body>"), F("<body onload='sl()'>"));
|
||||
page += F("</table>");
|
||||
ShowPageChunk(page);
|
||||
|
||||
page = FPSTR(HTTP_FORM_END);
|
||||
page += FPSTR(HTTP_FORM_END);
|
||||
page += FPSTR(HTTP_BTN_CONF);
|
||||
ShowPageEnd(page);
|
||||
ShowPage(page);
|
||||
}
|
||||
|
||||
void HandleWifiConfigurationWithScan()
|
||||
|
@ -1472,7 +1464,6 @@ void HandleHttpCommand()
|
|||
}
|
||||
SetHeader();
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message);
|
||||
// WebServer->sendContent("");
|
||||
}
|
||||
|
||||
void HandleConsole()
|
||||
|
@ -1517,10 +1508,8 @@ void HandleAjaxConsoleRefresh()
|
|||
counter = atoi(WebServer->arg("c2").c_str());
|
||||
}
|
||||
|
||||
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_XML), "");
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<r><i>%d</i><j>%d</j><l>"), web_log_index, reset_web_log_flag);
|
||||
WebServer->sendContent(mqtt_data);
|
||||
String message = F("}9"); // Cannot load mqtt_data here as <> will be encoded by replacements below
|
||||
if (!reset_web_log_flag) {
|
||||
counter = 99;
|
||||
reset_web_log_flag = 1;
|
||||
|
@ -1533,23 +1522,24 @@ void HandleAjaxConsoleRefresh()
|
|||
do {
|
||||
if (web_log[counter].length()) {
|
||||
if (cflg) {
|
||||
WebServer->sendContent(PSTR("\n"));
|
||||
message += F("\n");
|
||||
} else {
|
||||
cflg = 1;
|
||||
}
|
||||
web_log[counter].replace(F("<"), F("%3C")); // XML encoding to fix blank console log in concert with javascript decodeURIComponent
|
||||
web_log[counter].replace(F(">"), F("%3E"));
|
||||
web_log[counter].replace(F("&"), F("%26"));
|
||||
WebServer->sendContent(web_log[counter]);
|
||||
message += web_log[counter];
|
||||
}
|
||||
counter++;
|
||||
if (counter > MAX_LOG_LINES -1) {
|
||||
counter = 0;
|
||||
}
|
||||
} while (counter != web_log_index);
|
||||
message.replace(F("<"), F("%3C")); // XML encoding to fix blank console log in concert with javascript decodeURIComponent
|
||||
message.replace(F(">"), F("%3E"));
|
||||
message.replace(F("&"), F("%26"));
|
||||
}
|
||||
WebServer->sendContent(PSTR("</l></r>"));
|
||||
ShowPageStopChunk();
|
||||
message.replace(F("}9"), mqtt_data); // Save to load here
|
||||
message += F("</l></r>");
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_XML), message);
|
||||
}
|
||||
|
||||
void HandleInformation()
|
||||
|
|
|
@ -568,7 +568,9 @@ void LightState(uint8_t append)
|
|||
void LightPreparePower()
|
||||
{
|
||||
if (Settings.light_dimmer && !(light_power)) {
|
||||
ExecuteCommandPower(light_device, POWER_ON_NO_STATE);
|
||||
if (!Settings.flag.not_power_linked) {
|
||||
ExecuteCommandPower(light_device, POWER_ON_NO_STATE);
|
||||
}
|
||||
}
|
||||
else if (!Settings.light_dimmer && light_power) {
|
||||
ExecuteCommandPower(light_device, POWER_OFF_NO_STATE);
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
xsns_18_pms5003.ino - PMS5003-7003 particle concentration sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_PMS5003
|
||||
/*********************************************************************************************\
|
||||
* PlanTower PMS5003 and PMS7003 particle concentration sensor
|
||||
* For background information see http://aqicn.org/sensor/pms5003-7003/
|
||||
\*********************************************************************************************/
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
TasmotaSerial *PmsSerial;
|
||||
|
||||
uint8_t pms_type = 1;
|
||||
uint8_t pms_valid = 0;
|
||||
|
||||
struct pms5003data {
|
||||
uint16_t framelen;
|
||||
uint16_t pm10_standard, pm25_standard, pm100_standard;
|
||||
uint16_t pm10_env, pm25_env, pm100_env;
|
||||
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
|
||||
uint16_t unused;
|
||||
uint16_t checksum;
|
||||
} pms_data;
|
||||
|
||||
boolean PmsReadData()
|
||||
{
|
||||
if (! PmsSerial->available()) {
|
||||
return false;
|
||||
}
|
||||
while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) {
|
||||
PmsSerial->read();
|
||||
}
|
||||
if (PmsSerial->available() < 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t buffer[32];
|
||||
uint16_t sum = 0;
|
||||
PmsSerial->readBytes(buffer, 32);
|
||||
PmsSerial->flush(); // Make room for another burst
|
||||
|
||||
// get checksum ready
|
||||
for (uint8_t i = 0; i < 30; i++) {
|
||||
sum += buffer[i];
|
||||
}
|
||||
// The data comes in endian'd, this solves it so it works on all platforms
|
||||
uint16_t buffer_u16[15];
|
||||
for (uint8_t i = 0; i < 15; i++) {
|
||||
buffer_u16[i] = buffer[2 + i*2 + 1];
|
||||
buffer_u16[i] += (buffer[2 + i*2] << 8);
|
||||
}
|
||||
if (sum != buffer_u16[14]) {
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE));
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy((void *)&pms_data, (void *)buffer_u16, 30);
|
||||
pms_valid = 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void PmsSecond() // Every second
|
||||
{
|
||||
if (PmsReadData()) {
|
||||
pms_valid = 10;
|
||||
} else {
|
||||
if (pms_valid) {
|
||||
pms_valid--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void PmsInit()
|
||||
{
|
||||
pms_type = 0;
|
||||
|
||||
if (pin[GPIO_PMS5003] < 99) {
|
||||
PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1);
|
||||
if (PmsSerial->begin()) {
|
||||
pms_type = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_PMS5003_SNS[] PROGMEM = "%s"
|
||||
// "{s}PMS5003 " D_STANDARD_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
|
||||
// "{s}PMS5003 " D_STANDARD_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
|
||||
// "{s}PMS5003 " D_STANDARD_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
|
||||
"{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
|
||||
"{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
|
||||
"{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
|
||||
"{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"
|
||||
"{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"
|
||||
"{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"
|
||||
"{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"
|
||||
"{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"
|
||||
"{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void PmsShow(boolean json)
|
||||
{
|
||||
if (pms_valid) {
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), mqtt_data,
|
||||
pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard,
|
||||
pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env,
|
||||
pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_PMS5003_SNS, mqtt_data,
|
||||
// pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard,
|
||||
pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env,
|
||||
pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_18
|
||||
|
||||
boolean Xsns18(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (pms_type) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
PmsInit();
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
PmsSecond();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
PmsShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_APPEND:
|
||||
PmsShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_PMS5003
|
|
@ -119,23 +119,10 @@ boolean XsnsCall(byte Function)
|
|||
boolean result = false;
|
||||
|
||||
for (byte x = 0; x < xsns_present; x++) {
|
||||
if (FUNC_WEB_APPEND == Function) {
|
||||
mqtt_data[0] = '\0';
|
||||
}
|
||||
result = xsns_func_ptr[x](Function);
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
if ((FUNC_WEB_APPEND == Function) && strlen(mqtt_data)) {
|
||||
if (D_DECIMAL_SEPARATOR[0] != '.') {
|
||||
for (int i = 0; i < strlen(mqtt_data); i++) {
|
||||
if ('.' == mqtt_data[i]) {
|
||||
mqtt_data[i] = D_DECIMAL_SEPARATOR[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
WebServer->sendContent(mqtt_data);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue