Merge branch 'dev-chunks' into development

This commit is contained in:
Theo Arends 2019-03-07 18:34:51 +01:00
commit ae50f663fe
9 changed files with 698 additions and 720 deletions

View File

@ -1,4 +1,7 @@
/* 6.4.1.19 20190222
/* 6.4.1.20 20190304
* Changed webserver content handling from single String to small Chunks increasing RAM
*
* 6.4.1.19 20190222
* Add command SetOption37 for RGBCW color mapping (#5326)
* Add Korean language translations (#5344)
* Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373)

View File

@ -20,7 +20,7 @@
#ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_
#define VERSION 0x06040113
#define VERSION 0x06040114
#define D_PROGRAMNAME "Sonoff-Tasmota"
#define D_AUTHOR "Theo Arends"

View File

@ -1279,6 +1279,17 @@ void AddLog_P(uint8_t loglevel, const char *formatP, const char *formatP2)
AddLog(loglevel);
}
void AddLog_P2(uint8_t loglevel, PGM_P formatP, ...)
{
// This uses char strings. Be aware of sending %% if % is needed
va_list arg;
va_start(arg, formatP);
int len = vsnprintf_P(log_data, sizeof(log_data), formatP, arg);
va_end(arg);
AddLog(loglevel);
}
void AddLogBuffer(uint8_t loglevel, uint8_t *buffer, int count)
{
snprintf_P(log_data, sizeof(log_data), PSTR("DMP:"));

File diff suppressed because it is too large Load Diff

View File

@ -900,16 +900,17 @@ const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT;
const char HTTP_BTN_MENU_MQTT[] PROGMEM =
"<p><form action='" WEB_HANDLE_MQTT "' method='get'><button>" D_CONFIGURE_MQTT "</button></form></p>";
const char HTTP_FORM_MQTT[] PROGMEM =
const char HTTP_FORM_MQTT1[] PROGMEM =
"<fieldset><legend><b>&nbsp;" D_MQTT_PARAMETERS "&nbsp;</b></legend>"
"<form method='get' action='" WEB_HANDLE_MQTT "'>"
"<p><b>" D_HOST "</b> (" MQTT_HOST ")<br/><input id='mh' name='mh' placeholder='" MQTT_HOST" ' value='{m1'></p>"
"<p><b>" D_PORT "</b> (" STR(MQTT_PORT) ")<br/><input id='ml' name='ml' placeholder='" STR(MQTT_PORT) "' value='{m2'></p>"
"<p><b>" D_CLIENT "</b> ({m0)<br/><input id='mc' name='mc' placeholder='" MQTT_CLIENT_ID "' value='{m3'></p>"
"<p><b>" D_USER "</b> (" MQTT_USER ")<br/><input id='mu' name='mu' placeholder='" MQTT_USER "' value='{m4'></p>"
"<p><b>" D_HOST "</b> (" MQTT_HOST ")<br/><input id='mh' name='mh' placeholder='" MQTT_HOST" ' value='%s'></p>"
"<p><b>" D_PORT "</b> (" STR(MQTT_PORT) ")<br/><input id='ml' name='ml' placeholder='" STR(MQTT_PORT) "' value='%d'></p>"
"<p><b>" D_CLIENT "</b> (%s)<br/><input id='mc' name='mc' placeholder='%s' value='%s'></p>";
const char HTTP_FORM_MQTT2[] PROGMEM =
"<p><b>" D_USER "</b> (" MQTT_USER ")<br/><input id='mu' name='mu' placeholder='" MQTT_USER "' value='%s'></p>"
"<p><b>" D_PASSWORD "</b><br/><input id='mp' name='mp' type='password' placeholder='" D_PASSWORD "' value='" D_ASTERISK_PWD "'></p>"
"<p><b>" D_TOPIC "</b> = %topic% (" MQTT_TOPIC ")<br/><input id='mt' name='mt' placeholder='" MQTT_TOPIC" ' value='{m6'></p>"
"<p><b>" D_FULL_TOPIC "</b> (" MQTT_FULLTOPIC ")<br/><input id='mf' name='mf' placeholder='" MQTT_FULLTOPIC" ' value='{m7'></p>";
"<p><b>" D_TOPIC "</b> = %%topic%% (" MQTT_TOPIC ")<br/><input id='mt' name='mt' placeholder='" MQTT_TOPIC "' value='%s'></p>"
"<p><b>" D_FULL_TOPIC "</b> (%s)<br/><input id='mf' name='mf' placeholder='%s' value='%s'></p>";
void HandleMqttConfiguration(void)
{
@ -923,23 +924,24 @@ void HandleMqttConfiguration(void)
return;
}
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_MQTT);
char str[sizeof(Settings.mqtt_client)];
page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)));
page.replace(F("{m1"), Settings.mqtt_host);
page.replace(F("{m2"), String(Settings.mqtt_port));
page.replace(F("{m3"), Settings.mqtt_client);
page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user);
page.replace(F("{m6"), Settings.mqtt_topic);
page.replace(F("{m7"), Settings.mqtt_fulltopic);
page += FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF);
ShowPage(page);
WSContentStart(FPSTR(S_CONFIGURE_MQTT));
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_MQTT1,
Settings.mqtt_host,
Settings.mqtt_port,
Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)),
MQTT_CLIENT_ID,
Settings.mqtt_client);
WSContentSend_P(HTTP_FORM_MQTT2,
(Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user,
Settings.mqtt_topic,
MQTT_FULLTOPIC, MQTT_FULLTOPIC,
Settings.mqtt_fulltopic);
WSContentSend(FPSTR(HTTP_FORM_END));
WSContentSend(FPSTR(HTTP_BTN_CONF));
WSContentEnd();
}
void MqttSaveSettings(void)
@ -988,7 +990,7 @@ bool Xdrv02(uint8_t function)
switch (function) {
#ifdef USE_WEBSERVER
case FUNC_WEB_ADD_BUTTON:
strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data) - strlen(mqtt_data) -1);
WSContentSend(FPSTR(HTTP_BTN_MENU_MQTT));
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration);

View File

@ -439,14 +439,14 @@ const char HTTP_FORM_DOMOTICZ[] PROGMEM =
"<br/>"
"<table>";
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " {1</b></td><td style='width:70px'><input id='r{1' name='r{1' placeholder='0' value='{2'></td></tr>"
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " {1</b></td><td style='width:70px'><input id='k{1' name='k{1' placeholder='0' value='{3'></td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " %d</b></td><td style='width:70px'><input id='r%d' name='r%d' placeholder='0' value='%d'></td></tr>"
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " %d</b></td><td style='width:70px'><input id='k%d' name='k%d' placeholder='0' value='%d'></td></tr>";
const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM =
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SWITCH_IDX " {1</b></td><td style='width:70px'><input id='s{1' name='s{1' placeholder='0' value='{4'></td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SWITCH_IDX " %d</b></td><td style='width:70px'><input id='s%d' name='s%d' placeholder='0' value='%d'></td></tr>";
const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM =
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SENSOR_IDX " {1</b> {2</td><td style='width:70px'><input id='l{1' name='l{1' placeholder='0' value='{5'></td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SENSOR_IDX " %d</b> %s</td><td style='width:70px'><input id='l%d' name='l%d' placeholder='0' value='%d'></td></tr>";
const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
"<tr><td style='width:260px'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td style='width:70px'><input id='ut' name='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='{6'</td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td style='width:70px'><input id='ut' name='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='%d'</td></tr>";
void HandleDomoticzConfiguration(void)
{
@ -462,35 +462,30 @@ void HandleDomoticzConfiguration(void)
char stemp[32];
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_DOMOTICZ));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_DOMOTICZ);
WSContentStart(FPSTR(S_CONFIGURE_DOMOTICZ));
WSContentSendStyle();
WSContentSend(FPSTR(HTTP_FORM_DOMOTICZ));
for (int i = 0; i < MAX_DOMOTICZ_IDX; i++) {
if (i < devices_present) {
page += FPSTR(HTTP_FORM_DOMOTICZ_RELAY);
page.replace("{2", String((int)Settings.domoticz_relay_idx[i]));
page.replace("{3", String((int)Settings.domoticz_key_idx[i]));
WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY,
i +1, i, i, Settings.domoticz_relay_idx[i],
i +1, i, i, Settings.domoticz_key_idx[i]);
}
if (pin[GPIO_SWT1 +i] < 99) {
page += FPSTR(HTTP_FORM_DOMOTICZ_SWITCH);
page.replace("{4", String((int)Settings.domoticz_switch_idx[i]));
WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH,
i +1, i, i, Settings.domoticz_switch_idx[i]);
}
page.replace("{1", String(i +1));
if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { break; }
}
for (int i = 0; i < DZ_MAX_SENSORS; i++) {
page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR);
page.replace("{1", String(i +1));
page.replace("{2", GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors));
page.replace("{5", String((int)Settings.domoticz_sensor_idx[i]));
WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR,
i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, i, Settings.domoticz_sensor_idx[i]);
}
page += FPSTR(HTTP_FORM_DOMOTICZ_TIMER);
page.replace("{6", String((int)Settings.domoticz_update_timer));
page += F("</table>");
page += FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF);
ShowPage(page);
WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer);
WSContentSend(F("</table>"));
WSContentSend(FPSTR(HTTP_FORM_END));
WSContentSend(FPSTR(HTTP_BTN_CONF));
WSContentEnd();
}
void DomoticzSaveSettings(void)
@ -500,19 +495,19 @@ void DomoticzSaveSettings(void)
char tmp[100];
for (uint8_t i = 0; i < MAX_DOMOTICZ_IDX; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i +1);
snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i);
WebGetArg(stemp, tmp, sizeof(tmp));
Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i +1);
snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i);
WebGetArg(stemp, tmp, sizeof(tmp));
Settings.domoticz_key_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i +1);
snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i);
WebGetArg(stemp, tmp, sizeof(tmp));
Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
}
ssensor_indices[0] = '\0';
for (uint8_t i = 0; i < DZ_MAX_SENSORS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i +1);
snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i);
WebGetArg(stemp, tmp, sizeof(tmp));
Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
snprintf_P(ssensor_indices, sizeof(ssensor_indices), PSTR("%s%s%d"), ssensor_indices, (strlen(ssensor_indices)) ? "," : "", Settings.domoticz_sensor_idx[i]);
@ -541,7 +536,7 @@ bool Xdrv07(uint8_t function)
switch (function) {
#ifdef USE_WEBSERVER
case FUNC_WEB_ADD_BUTTON:
strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data) - strlen(mqtt_data) -1);
WSContentSend(FPSTR(HTTP_BTN_MENU_DOMOTICZ));
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration);

View File

@ -519,7 +519,7 @@ const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER;
const char HTTP_BTN_MENU_TIMER[] PROGMEM =
"<p><form action='" WEB_HANDLE_TIMER "' method='get'><button>" D_CONFIGURE_TIMER "</button></form></p>";
const char HTTP_TIMER_SCRIPT[] PROGMEM =
const char HTTP_TIMER_SCRIPT1[] PROGMEM =
"var pt=[],ct=99;"
"function qs(s){" // Alias to save code space
"return document.querySelector(s);"
@ -528,8 +528,9 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
"var o=document.createElement('option');"
"o.textContent=i;"
"q.appendChild(o);"
"}"
"}";
#ifdef USE_SUNRISE
const char HTTP_TIMER_SCRIPT2[] PROGMEM =
"function gt(){" // Set hours and minutes according to mode
"var m,p,q;"
"m=qs('input[name=\"rd\"]:checked').value;" // Get mode
@ -558,8 +559,9 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
"qs('#dr').disabled='disabled';"
"if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" // Create hours select options
"}"
"}"
"}";
#endif
const char HTTP_TIMER_SCRIPT3[] PROGMEM =
"function st(){" // Save parameters to hidden area
"var i,l,m,n,p,s;"
"m=0;s=0;"
@ -570,7 +572,7 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
"m=qs('input[name=\"rd\"]:checked').value;" // Check mode
"s|=(qs('input[name=\"rd\"]:checked').value<<29);" // Get mode
#endif
"if(}1>0){"
"if(%d>0){"
"i=qs('#d1').selectedIndex;if(i>=0){s|=(i<<23);}" // Get output
"s|=(qs('#p1').selectedIndex<<27);" // Get action
"}else{"
@ -587,7 +589,8 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
"s|=((qs('#mw').selectedIndex)&0x0F)<<11;" // Get window minutes
"pt[ct]=s;"
"eb('t0').value=pt.join();" // Save parameters from array to hidden area
"}"
"}";
const char HTTP_TIMER_SCRIPT4[] PROGMEM =
"function ot(t,e){" // Select tab and update elements
"var i,n,o,p,q,s;"
"if(ct<99){st();}" // Save changes
@ -602,23 +605,24 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
#else
"p=s&0x7FF;" // Get time
"q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" // Set hours
"q=p%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes
"q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes
#endif
"q=(s>>11)&0xF;if(q<10){q='0'+q;}qs('#mw').value=q;" // Set window minutes
"for(i=0;i<7;i++){p=(s>>(16+i))&1;eb('w'+i).checked=p;}" // Set weekdays
"if(}1>0){"
"if(%d>0){"
"p=(s>>23)&0xF;qs('#d1').value=p+1;" // Set output
"p=(s>>27)&3;qs('#p1').selectedIndex=p;" // Set action
"}"
"p=(s>>15)&1;eb('r0').checked=p;" // Set repeat
"p=(s>>31)&1;eb('a0').checked=p;" // Set arm
"}"
"}";
const char HTTP_TIMER_SCRIPT5[] PROGMEM =
"function it(){" // Initialize elements and select first tab
"var b,i,o,s;"
"pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array
"s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"<button type='button' class='tl' onclick='ot(\"+i+\",this)'\"+b+\">\"+(i+1)+\"</button>\"}"
"eb('bt').innerHTML=s;" // Create tabs
"if(}1>0){" // Create Output and Action drop down boxes
"if(%d>0){" // Create Output and Action drop down boxes
"eb('oa').innerHTML=\"<b>" D_TIMER_OUTPUT "</b>&nbsp;<span><select style='width:60px;' id='d1' name='d1'></select></span>&emsp;<b>" D_TIMER_ACTION "</b>&nbsp;<select style='width:99px;' id='p1' name='p1'></select>\";"
"o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" // Create offset direction select options
#ifdef USE_RULES
@ -628,48 +632,52 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
#endif
"}else{"
"eb('oa').innerHTML=\"<b>" D_TIMER_ACTION "</b> " D_RULE "\";" // No outputs but rule is allowed
"}"
"}";
const char HTTP_TIMER_SCRIPT6[] PROGMEM =
#ifdef USE_SUNRISE
"o=qs('#dr');ce('+',o);ce('-',o);" // Create offset direction select options
#endif
"o=qs('#ho');for(i=0;i<=23;i++){ce((i<10)?('0'+i):i,o);}" // Create hours select options
"o=qs('#mi');for(i=0;i<=59;i++){ce((i<10)?('0'+i):i,o);}" // Create minutes select options
"o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" // Create window minutes select options
"o=qs('#d1');for(i=0;i<}1;i++){ce(i+1,o);}" // Create outputs
"o=qs('#d1');for(i=0;i<%d;i++){ce(i+1,o);}" // Create outputs
"var a='" D_DAY3LIST "';"
"s='';for(i=0;i<7;i++){s+=\"<input id='w\"+i+\"' name='w\"+i+\"' type='checkbox'><b>\"+a.substring(i*3,(i*3)+3)+\"</b> \"}"
"eb('ds').innerHTML=s;" // Create weekdays
"eb('dP').click();" // Get the element with id='dP' and click on it
"}";
"}"
"window.onload=it;";
const char HTTP_TIMER_STYLE[] PROGMEM =
".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}" // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE (transparent won't work)
"</style>";
const char HTTP_FORM_TIMER[] PROGMEM =
".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}"; // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE1 (transparent won't work)
const char HTTP_FORM_TIMER1[] PROGMEM =
"<fieldset style='min-width:470px;text-align:center;'>"
"<legend style='text-align:left;'><b>&nbsp;" D_TIMER_PARAMETERS "&nbsp;</b></legend>"
"<form method='post' action='" WEB_HANDLE_TIMER "' onsubmit='return st();'>"
"<br/><input id='e0' name='e0' type='checkbox'{e0><b>" D_TIMER_ENABLE "</b><br/><br/><hr/>"
"<br/><input id='e0' name='e0' type='checkbox'%s><b>" D_TIMER_ENABLE "</b><br/><br/><hr/>"
"<input id='t0' name='t0' value='";
const char HTTP_FORM_TIMER1[] PROGMEM =
const char HTTP_FORM_TIMER2[] PROGMEM =
"' hidden><div id='bt' name='bt'></div><br/><br/><br/>"
"<div id='oa' name='oa'></div><br/>"
"<div>"
"<input id='a0' name='a0' type='checkbox'><b>" D_TIMER_ARM "</b>&emsp;"
"<input id='r0' name='r0' type='checkbox'><b>" D_TIMER_REPEAT "</b>"
"</div><br/>"
"<div>"
"<div>";
#ifdef USE_SUNRISE
"<fieldset style='width:299px;margin:auto;text-align:left;border:0;'>" // 299 used in page.replace(F("299")
const char HTTP_FORM_TIMER3[] PROGMEM =
"<fieldset style='width:%dpx;margin:auto;text-align:left;border:0;'>"
"<input id='b0' name='rd' type='radio' value='0' onclick='gt();'><b>" D_TIMER_TIME "</b><br/>"
"<input id='b1' name='rd' type='radio' value='1' onclick='gt();'><b>" D_SUNRISE "</b> (}8)<br/>"
"<input id='b2' name='rd' type='radio' value='2' onclick='gt();'><b>" D_SUNSET "</b> (}9)<br/>"
"<input id='b1' name='rd' type='radio' value='1' onclick='gt();'><b>" D_SUNRISE "</b> (%s)<br/>"
"<input id='b2' name='rd' type='radio' value='2' onclick='gt();'><b>" D_SUNSET "</b> (%s)<br/>"
"</fieldset>"
"<p></p>"
"<span><select style='width:46px;' id='dr' name='dr'></select></span>"
"&nbsp;"
"&nbsp;";
#else
"<b>" D_TIMER_TIME "</b>&nbsp;"
const char HTTP_FORM_TIMER3[] PROGMEM =
"<b>" D_TIMER_TIME "</b>&nbsp;";
#endif // USE_SUNRISE
const char HTTP_FORM_TIMER4[] PROGMEM =
"<span><select style='width:60px;' id='ho' name='ho'></select></span>"
"&nbsp;" D_HOUR_MINUTE_SEPARATOR "&nbsp;"
"<span><select style='width:60px;' id='mi' name='mi'></select></span>"
@ -690,28 +698,30 @@ void HandleTimerConfiguration(void)
return;
}
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_TIMER));
page += FPSTR(HTTP_TIMER_SCRIPT);
page += FPSTR(HTTP_HEAD_STYLE);
page.replace(F("</style>"), FPSTR(HTTP_TIMER_STYLE));
page += FPSTR(HTTP_FORM_TIMER);
page.replace(F("{e0"), (Settings.flag3.timers_enable) ? F(" checked") : F(""));
for (uint8_t i = 0; i < MAX_TIMERS; i++) {
if (i > 0) { page += F(","); }
page += String(Settings.timer[i].data);
}
page += FPSTR(HTTP_FORM_TIMER1);
page.replace(F("}1"), String(devices_present));
WSContentStart(FPSTR(S_CONFIGURE_TIMER));
WSContentSend(FPSTR(HTTP_TIMER_SCRIPT1));
#ifdef USE_SUNRISE
page.replace(F("}8"), GetSun(0)); // Add Sunrise
page.replace(F("}9"), GetSun(1)); // Add Sunset
page.replace(F("299"), String(100 + (strlen(D_SUNSET) *12))); // Fix string length to keep radios centered
WSContentSend(FPSTR(HTTP_TIMER_SCRIPT2));
#endif // USE_SUNRISE
page += FPSTR(HTTP_FORM_END);
page += F("<script>it();</script>"); // Init elements and select first tab/button
page += FPSTR(HTTP_BTN_CONF);
ShowPage(page);
WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present);
WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present);
WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present);
WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present);
WSContentSendStyle(FPSTR(HTTP_TIMER_STYLE));
WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : "");
for (uint8_t i = 0; i < MAX_TIMERS; i++) {
WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data);
}
WSContentSend(FPSTR(HTTP_FORM_TIMER2));
#ifdef USE_SUNRISE
WSContentSend_P(HTTP_FORM_TIMER3, 100 + (strlen(D_SUNSET) *12), GetSun(0).c_str(), GetSun(1).c_str());
#else
WSContentSend(FPSTR(HTTP_FORM_TIMER3));
#endif // USE_SUNRISE
WSContentSend(FPSTR(HTTP_FORM_TIMER4));
WSContentSend(FPSTR(HTTP_FORM_END));
WSContentSend(FPSTR(HTTP_BTN_CONF));
WSContentEnd();
}
void TimerSaveSettings(void)
@ -754,9 +764,9 @@ bool Xdrv09(uint8_t function)
#ifdef USE_TIMERS_WEB
case FUNC_WEB_ADD_BUTTON:
#ifdef USE_RULES
strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1);
WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER));
#else
if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); }
if (devices_present) { WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); }
#endif // USE_RULES
break;
case FUNC_WEB_ADD_HANDLER:

View File

@ -755,13 +755,14 @@ const char HTTP_BTN_MENU_KNX[] PROGMEM =
"<p><form action='kn' method='get'><button>" D_CONFIGURE_KNX "</button></form></p>";
const char HTTP_FORM_KNX[] PROGMEM =
"<fieldset><legend style='text-align:left;'><b>&nbsp;" D_KNX_PARAMETERS "&nbsp;</b>"
"</legend><form method='post' action='kn'>"
"<fieldset style='min-width:530px;'>"
"<legend style='text-align:left;'><b>&nbsp;" D_KNX_PARAMETERS "&nbsp;</b></legend>"
"<form method='post' action='kn'>"
"<br/><center>"
"<b>" D_KNX_PHYSICAL_ADDRESS " </b>"
"<input style='width:12%;' type='number' name='area' min='0' max='15' value='{kna'> . "
"<input style='width:12%;' type='number' name='line' min='0' max='15' value='{knl'> . "
"<input style='width:12%;' type='number' name='member' min='0' max='255' value='{knm'>"
"<input style='width:12%%;' type='number' name='area' min='0' max='15' value='%d'> . "
"<input style='width:12%%;' type='number' name='line' min='0' max='15' value='%d'> . "
"<input style='width:12%%;' type='number' name='member' min='0' max='255' value='%d'>"
"<br/><br/>" D_KNX_PHYSICAL_ADDRESS_NOTE "<br/><br/>"
"<input id='b1' name='b1' type='checkbox'";
@ -777,20 +778,20 @@ const char HTTP_FORM_KNX2[] PROGMEM =
"<select name='GAop' style='width:25%;'>";
const char HTTP_FORM_KNX_OPT[] PROGMEM =
"<option value='{vop}'>{nop}</option>";
"<option value='%d'>%s</option>";
const char HTTP_FORM_KNX_GA[] PROGMEM =
"<input style='width:12%;' type='number' id='GAfnum' name='GAfnum' min='0' max='31' value='0'> / "
"<input style='width:12%;' type='number' id='GAarea' name='GAarea' min='0' max='7' value='0'> / "
"<input style='width:12%;' type='number' id='GAfdef' name='GAfdef' min='0' max='255' value='0'> ";
"<input style='width:12%%;' type='number' id='%s' name='%s' min='0' max='31' value='0'> / "
"<input style='width:12%%;' type='number' id='%s' name='%s' min='0' max='7' value='0'> / "
"<input style='width:12%%;' type='number' id='%s' name='%s' min='0' max='255' value='0'> ";
const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM =
"<button type='submit' onclick='fncbtnadd()' btndis name='btn_add' value='{btnval}' style='width:18%;'>" D_ADD "</button><br/><br/>"
"<table style='width:80%; font-size: 14px;'><col width='250'><col width='30'>";
"<button type='submit' onclick='%s()' %s name='btn_add' value='%d' style='width:18%%;'>" D_ADD "</button><br/><br/>"
"<table style='width:80%%; font-size: 14px;'><col width='250'><col width='30'>";
const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM =
"<tr><td><b>{optex} -> GAfnum / GAarea / GAfdef </b></td>"
"<td><button type='submit' name='btn_del_ga' value='{opval}' class='button bred'> " D_DELETE " </button></td></tr>";
"<tr><td><b>%s -> %d / %d / %d </b></td>"
"<td><button type='submit' name='btn_del_ga' value='%d' class='button bred'> " D_DELETE " </button></td></tr>";
const char HTTP_FORM_KNX3[] PROGMEM =
"</table></center></fieldset><br/>"
@ -801,8 +802,8 @@ const char HTTP_FORM_KNX4[] PROGMEM =
"-> <select name='CBop' style='width:25%;'>";
const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM =
"<tr><td><b>GAfnum / GAarea / GAfdef -> {optex}</b></td>"
"<td><button type='submit' name='btn_del_cb' value='{opval}' class='button bred'> " D_DELETE " </button></td></tr>";
"<tr><td><b>%d / %d / %d -> %s</b></td>"
"<td><button type='submit' name='btn_del_cb' value='%d' class='button bred'> " D_DELETE " </button></td></tr>";
void HandleKNXConfiguration(void)
{
@ -871,113 +872,8 @@ void HandleKNXConfiguration(void)
}
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_KNX));
page += FPSTR(HTTP_HEAD_STYLE);
page.replace(F("340px"), F("530px"));
page += FPSTR(HTTP_FORM_KNX);
KNX_physs_addr.value = Settings.knx_physsical_addr;
page.replace(F("{kna"), String(KNX_physs_addr.pa.area));
page.replace(F("{knl"), String(KNX_physs_addr.pa.line));
page.replace(F("{knm"), String(KNX_physs_addr.pa.member));
if ( Settings.flag.knx_enabled ) { page += F(" checked"); }
page += FPSTR(HTTP_FORM_KNX1);
if ( Settings.flag.knx_enable_enhancement ) { page += F(" checked"); }
page += FPSTR(HTTP_FORM_KNX2);
for (uint8_t i = 0; i < KNX_MAX_device_param ; i++)
{
if ( device_param[i].show )
{
page += FPSTR(HTTP_FORM_KNX_OPT);
page.replace(F("{vop}"), String(device_param[i].type));
page.replace(F("{nop}"), String(device_param_ga[i]));
}
}
page += F("</select> -> ");
page += FPSTR(HTTP_FORM_KNX_GA);
page.replace(F("GAfnum"), F("GA_FNUM"));
page.replace(F("GAarea"), F("GA_AREA"));
page.replace(F("GAfdef"), F("GA_FDEF"));
page.replace(F("GAfnum"), F("GA_FNUM"));
page.replace(F("GAarea"), F("GA_AREA"));
page.replace(F("GAfdef"), F("GA_FDEF"));
page += FPSTR(HTTP_FORM_KNX_ADD_BTN);
page.replace(F("{btnval}"), String(1));
if (Settings.knx_GA_registered < MAX_KNX_GA) {
page.replace(F("btndis"), F(" "));
}
else
{
page.replace(F("btndis"), F("disabled"));
}
page.replace(F("fncbtnadd"), F("GAwarning"));
for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i)
{
if ( Settings.knx_GA_param[i] )
{
page += FPSTR(HTTP_FORM_KNX_ADD_TABLE_ROW);
page.replace(F("{opval}"), String(i+1));
page.replace(F("{optex}"), String(device_param_ga[Settings.knx_GA_param[i]-1]));
KNX_addr.value = Settings.knx_GA_addr[i];
page.replace(F("GAfnum"), String(KNX_addr.ga.area));
page.replace(F("GAarea"), String(KNX_addr.ga.line));
page.replace(F("GAfdef"), String(KNX_addr.ga.member));
}
}
page += FPSTR(HTTP_FORM_KNX3);
page += FPSTR(HTTP_FORM_KNX_GA);
page.replace(F("GAfnum"), F("CB_FNUM"));
page.replace(F("GAarea"), F("CB_AREA"));
page.replace(F("GAfdef"), F("CB_FDEF"));
page.replace(F("GAfnum"), F("CB_FNUM"));
page.replace(F("GAarea"), F("CB_AREA"));
page.replace(F("GAfdef"), F("CB_FDEF"));
page += FPSTR(HTTP_FORM_KNX4);
uint8_t j;
for (uint8_t i = 0; i < KNX_MAX_device_param ; i++)
{
// Check How many Relays are available and add: RelayX and TogleRelayX
if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; }
if ( i == 8 ) { j = 0; }
if ( device_param[j].show )
{
page += FPSTR(HTTP_FORM_KNX_OPT);
page.replace(F("{vop}"), String(device_param[i].type));
page.replace(F("{nop}"), String(device_param_cb[i]));
}
}
page += F("</select> ");
page += FPSTR(HTTP_FORM_KNX_ADD_BTN);
page.replace(F("{btnval}"), String(2));
if (Settings.knx_CB_registered < MAX_KNX_CB) {
page.replace(F("btndis"), F(" "));
}
else
{
page.replace(F("btndis"), F("disabled"));
}
page.replace(F("fncbtnadd"), F("CBwarning"));
for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i)
{
if ( Settings.knx_CB_param[i] )
{
page += FPSTR(HTTP_FORM_KNX_ADD_TABLE_ROW2);
page.replace(F("{opval}"), String(i+1));
page.replace(F("{optex}"), String(device_param_cb[Settings.knx_CB_param[i]-1]));
KNX_addr.value = Settings.knx_CB_addr[i];
page.replace(F("GAfnum"), String(KNX_addr.ga.area));
page.replace(F("GAarea"), String(KNX_addr.ga.line));
page.replace(F("GAfdef"), String(KNX_addr.ga.member));
}
}
page += F("</table></center></fieldset>");
page += F("<br/><button name='save' type='submit' class='button bgrn'>" D_SAVE "</button></form></fieldset>");
page += FPSTR(HTTP_BTN_CONF);
page.replace( F("</script>"),
WSContentStart(FPSTR(S_CONFIGURE_KNX));
WSContentSend(
F("function GAwarning()"
"{"
"var GA_FNUM = eb('GA_FNUM');"
@ -995,9 +891,63 @@ void HandleKNXConfiguration(void)
"if ( CB_FNUM != null && CB_FNUM.value == '0' && CB_AREA.value == '0' && CB_FDEF.value == '0' ) {"
"alert('" D_KNX_WARNING "');"
"}"
"}"
"</script>") );
ShowPage(page);
"}"));
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member);
if ( Settings.flag.knx_enabled ) { WSContentSend(F(" checked")); }
WSContentSend(FPSTR(HTTP_FORM_KNX1));
if ( Settings.flag.knx_enable_enhancement ) { WSContentSend(F(" checked")); }
WSContentSend(FPSTR(HTTP_FORM_KNX2));
for (uint8_t i = 0; i < KNX_MAX_device_param ; i++)
{
if ( device_param[i].show )
{
WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_ga[i]);
}
}
WSContentSend(F("</select> -> "));
WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_FNUM", "GA_AREA", "GA_AREA", "GA_FDEF", "GA_FDEF");
WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1);
for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i)
{
if ( Settings.knx_GA_param[i] )
{
KNX_addr.value = Settings.knx_GA_addr[i];
WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1);
}
}
WSContentSend(FPSTR(HTTP_FORM_KNX3));
WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_FNUM", "CB_AREA", "CB_AREA", "CB_FDEF", "CB_FDEF");
WSContentSend(FPSTR(HTTP_FORM_KNX4));
uint8_t j;
for (uint8_t i = 0; i < KNX_MAX_device_param ; i++)
{
// Check How many Relays are available and add: RelayX and TogleRelayX
if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; }
if ( i == 8 ) { j = 0; }
if ( device_param[j].show )
{
WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]);
}
}
WSContentSend(F("</select> "));
WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2);
for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i)
{
if ( Settings.knx_CB_param[i] )
{
KNX_addr.value = Settings.knx_CB_addr[i];
WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1);
}
}
WSContentSend(F("</table></center></fieldset>"));
WSContentSend(FPSTR(HTTP_FORM_END));
WSContentSend(FPSTR(HTTP_BTN_CONF));
WSContentEnd();
}
}
@ -1299,7 +1249,7 @@ bool Xdrv11(uint8_t function)
#ifdef USE_WEBSERVER
#ifdef USE_KNX_WEB_MENU
case FUNC_WEB_ADD_BUTTON:
strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data) - strlen(mqtt_data) -1);
WSContentSend(FPSTR(HTTP_BTN_MENU_KNX));
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/kn", HandleKNXConfiguration);

View File

@ -382,14 +382,14 @@ const char HTTP_BTN_MENU_HX711[] PROGMEM =
const char HTTP_FORM_HX711[] PROGMEM =
"<fieldset><legend><b>&nbsp;" D_CALIBRATION "&nbsp;</b></legend>"
"<form method='post' action='" WEB_HANDLE_HX711 "'>"
"<p><b>" D_REFERENCE_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' step='0.001' id='p1' name='p1' placeholder='0' value='{1'></p>"
"<p><b>" D_REFERENCE_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' step='0.001' id='p1' name='p1' placeholder='0' value='%s'></p>"
"<br/><button name='calibrate' type='submit'>" D_CALIBRATE "</button>"
"</form>"
"</fieldset><br/><br/>"
"<fieldset><legend><b>&nbsp;" D_HX711_PARAMETERS "&nbsp;</b></legend>"
"<form method='post' action='" WEB_HANDLE_HX711 "'>"
"<p><b>" D_ITEM_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' max='6.5535' step='0.0001' id='p2' name='p2' placeholder='0.0' value='{2'></p>";
"<p><b>" D_ITEM_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' max='6.5535' step='0.0001' id='p2' name='p2' placeholder='0.0' value='%s'></p>";
void HandleHxAction(void)
{
@ -403,41 +403,38 @@ void HandleHxAction(void)
return;
}
char tmp[100];
char stemp1[20];
if (WebServer->hasArg("reset")) {
snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 1")); // Reset
ExecuteWebCommand(tmp, SRC_WEBGUI);
snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); // Reset
ExecuteWebCommand(stemp1, SRC_WEBGUI);
HandleRoot(); // Return to main screen
return;
}
if (WebServer->hasArg("calibrate")) {
WebGetArg("p1", tmp, sizeof(tmp));
Settings.weight_reference = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 1000);
WebGetArg("p1", stemp1, sizeof(stemp1));
Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToDouble(stemp1) * 1000);
HxLogUpdates();
snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 2")); // Start calibration
ExecuteWebCommand(tmp, SRC_WEBGUI);
snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); // Start calibration
ExecuteWebCommand(stemp1, SRC_WEBGUI);
HandleRoot(); // Return to main screen
return;
}
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(D_CONFIGURE_HX711));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_HX711);
dtostrfd((float)Settings.weight_reference / 1000, 3, tmp);
page.replace("{1", String(tmp));
dtostrfd((float)Settings.weight_item / 10000, 4, tmp);
page.replace("{2", String(tmp));
page += FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF);
ShowPage(page);
WSContentStart(FPSTR(D_CONFIGURE_HX711));
WSContentSendStyle();
dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1);
char stemp2[20];
dtostrfd((float)Settings.weight_item / 10000, 4, stemp2);
WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2);
WSContentSend(FPSTR(HTTP_FORM_END));
WSContentSend(FPSTR(HTTP_BTN_CONF));
WSContentEnd();
}
void HxSaveSettings(void)
@ -495,10 +492,10 @@ bool Xsns34(uint8_t function)
break;
#ifdef USE_HX711_GUI
case FUNC_WEB_ADD_MAIN_BUTTON:
strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1);
WSContentSend(FPSTR(HTTP_BTN_MENU_MAIN_HX711));
break;
case FUNC_WEB_ADD_BUTTON:
strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1);
WSContentSend(FPSTR(HTTP_BTN_MENU_HX711));
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction);