Merge branch 'arendst/development' into development

This commit is contained in:
Nils Sdun 2018-01-30 10:35:39 +01:00
commit 1c7d475d0a
21 changed files with 2978 additions and 1578 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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);

173
sonoff/xsns_18_pms5003.ino Normal file
View File

@ -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

View File

@ -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;