diff --git a/README.md b/README.md index 1b37950e8f9d..a04ded0e4a68 100644 --- a/README.md +++ b/README.md @@ -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 **4.0.2** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **4.0.3** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. - This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic. - Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```. diff --git a/api/arduino/sonoff-minimal.ino.bin b/api/arduino/sonoff-minimal.ino.bin index 323e05bc1816..b8e800cc45a6 100644 Binary files a/api/arduino/sonoff-minimal.ino.bin and b/api/arduino/sonoff-minimal.ino.bin differ diff --git a/api/arduino/sonoff.ino.bin b/api/arduino/sonoff.ino.bin index d88398cb1d8c..7a59ab28b259 100644 Binary files a/api/arduino/sonoff.ino.bin and b/api/arduino/sonoff.ino.bin differ diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index ca8e9e9b766f..6bd591c925d9 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,10 @@ -/* 4.0.2 20170308 +/* 4.0.3 20170309 + * Renamed Module NodeMCU to WeMos D1 mini + * Add GPIO1 as user option to some modules + * Add Buttons, Relays and Leds to user configurable options (#159) + * Add description on Module parameters web page to some well known GPIOs (#107, #171) + * + * 4.0.2 20170308 * Restore correct seriallog level after Serial logging was disabled * Add simple dimmer slider to Sonoff Led web page * Reduced root webpage size by 31% diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 01c1edfb62d3..ea150d8d3a92 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -12,9 +12,9 @@ //#define ALLOW_MIGRATE_TO_V3 #ifdef ALLOW_MIGRATE_TO_V3 - #define VERSION 0x03091900 // 3.9.25 + #define VERSION 0x03091A00 // 3.9.26 #else - #define VERSION 0x04000200 // 4.0.2 + #define VERSION 0x04000300 // 4.0.3 #endif // ALLOW_MIGRATE_TO_V3 enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; @@ -890,7 +890,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) else if (!strcmp(type,"MODULES")) { snprintf_P(svalue, sizeof(svalue), PSTR("{\"Modules1\":\""), svalue); byte jsflg = 0; - for (byte i = 0; i < 11; i++) { + for (byte i = 0; i < MAXMODULE /2; i++) { if (jsflg) snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue); jsflg = 1; snprintf_P(stemp1, sizeof(stemp1), modules[i].name); @@ -900,7 +900,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) mqtt_publish_topic_P(0, PSTR("RESULT"), svalue); snprintf_P(svalue, sizeof(svalue), PSTR("{\"Modules2\":\""), svalue); jsflg = 0; - for (byte i = 11; i < MAXMODULE; i++) { + for (byte i = MAXMODULE /2; i < MAXMODULE; i++) { if (jsflg) snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue); jsflg = 1; snprintf_P(stemp1, sizeof(stemp1), modules[i].name); @@ -935,9 +935,19 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } } else if (!strcmp(type,"GPIOS")) { - snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIOs\":\""), svalue); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIOs1\":\""), svalue); byte jsflg = 0; - for (byte i = 0; i < GPIO_SENSOR_END; i++) { + for (byte i = 0; i < GPIO_SENSOR_END /2; i++) { + if (jsflg) snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue); + jsflg = 1; + snprintf_P(stemp1, sizeof(stemp1), sensors[i]); + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s (%d)"), svalue, stemp1, i); + } + snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue); + mqtt_publish_topic_P(0, PSTR("RESULT"), svalue); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIOs2\":\""), svalue); + jsflg = 0; + for (byte i = GPIO_SENSOR_END /2; i < GPIO_SENSOR_END; i++) { if (jsflg) snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue); jsflg = 1; snprintf_P(stemp1, sizeof(stemp1), sensors[i]); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 960e0068231e..feda506e0362 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -17,27 +17,7 @@ enum upins_t { GPIO_SWT2, GPIO_SWT3, GPIO_SWT4, - GPIO_SENSOR_END }; - -// Text in webpage Module Parameters and commands GPIOS and GPIO -const char sensors[GPIO_SENSOR_END][9] PROGMEM = { - "None", - "DHT11", - "AM2301", - "DHT22", - "DS18x20", - "I2C SCL", - "I2C SDA", - "WS2812", - "IRremote", - "Switch1", - "Switch2", - "Switch3", - "Switch4" }; - -// Programmer selectable GPIO functionality offset by user selectable GPIOs -enum fpins_t { - GPIO_KEY1 = GPIO_SENSOR_END, // Button usually connected to GPIO0 + GPIO_KEY1, // Button usually connected to GPIO0 GPIO_KEY2, GPIO_KEY3, GPIO_KEY4, @@ -57,7 +37,48 @@ enum fpins_t { GPIO_LED2_INV, GPIO_LED3_INV, GPIO_LED4_INV, - GPIO_PWM0, // Cold + GPIO_SENSOR_END }; + +// Text in webpage Module Parameters and commands GPIOS and GPIO +const char sensors[GPIO_SENSOR_END][9] PROGMEM = { + "None", + "DHT11", + "AM2301", + "DHT22", + "DS18x20", + "I2C SCL", + "I2C SDA", + "WS2812", + "IRremote", + "Switch1", + "Switch2", + "Switch3", + "Switch4", + "Button1", + "Button2", + "Button3", + "Button4", + "Relay1", + "Relay2", + "Relay3", + "Relay4", + "Relay1I", + "Relay2I", + "Relay3I", + "Relay4I", + "Led1", + "Led2", + "Led3", + "Led4", + "Led1I", + "Led2I", + "Led3I", + "Led4I" + }; + +// Programmer selectable GPIO functionality offset by user selectable GPIOs +enum fpins_t { + GPIO_PWM0 = GPIO_SENSOR_END, // Cold GPIO_PWM1, // Warm GPIO_PWM2, // Red (swapped with Blue from original) GPIO_PWM3, // Green @@ -91,7 +112,7 @@ enum module_t { ELECTRODRAGON, EXS_RELAY, WION, - NODEMCU, + WEMOS, USER_TEST, MAXMODULE }; @@ -110,9 +131,9 @@ typedef struct MYTMPLT { // Default module settings const mytmplt modules[MAXMODULE] PROGMEM = { - { "Sonoff Basic", // Sonoff Basic + { "Sonoff Basic", // Sonoff Basic (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, // GPIO01 Serial RXD + GPIO_USER, // GPIO01 Serial RXD and Optional sensor 0, // GPIO02 GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor @@ -129,114 +150,126 @@ const mytmplt modules[MAXMODULE] PROGMEM = { 0, // GPIO15 0 // GPIO16 }, - { "Sonoff RF", // Sonoff RF + { "Sonoff RF", // Sonoff RF (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor - 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor 0, 0 }, - { "Sonoff SV", // Sonoff SV + { "Sonoff SV", // Sonoff SV (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor GPIO_USER, // GPIO05 Optional sensor - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor 0, 0 }, - { "Sonoff TH", // Sonoff TH10/16 + { "Sonoff TH", // Sonoff TH10/16 (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor - 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor 0, 0 }, - { "Sonoff Dual", // Sonoff Dual + { "Sonoff Dual", // Sonoff Dual (ESP8266) 0, GPIO_TXD, // GPIO01 Relay control 0, GPIO_RXD, // GPIO03 Relay control GPIO_USER, // GPIO04 Optional sensor - 0, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0, 0, 0, // Flash connection + 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0 }, - { "Sonoff Pow", // Sonoff Pow + { "Sonoff Pow", // Sonoff Pow (ESP8266) GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, GPIO_HLW_SEL, // GPIO05 HLW8012 Sel output - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_HLW_CF1, // GPIO13 HLW8012 CF1 voltage / current GPIO_HLW_CF, // GPIO14 HLW8012 CF power GPIO_LED1, // GPIO15 Green Led (0 = On, 1 = Off) 0 }, - { "Sonoff 4CH", // Sonoff 4CH + { "Sonoff 4CH", // Sonoff 4CH (ESP8285) GPIO_KEY1, // GPIO00 Button 1 - 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor GPIO_USER, // GPIO02 Optional sensor GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) - 0, 0, 0, + 0, 0, 0, // Flash connection GPIO_KEY2, // GPIO09 Button 2 GPIO_KEY3, // GPIO10 Button 3 0, GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_KEY4, // GPIO14 Button 4 GPIO_REL4, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) 0 }, - { "S20 Socket", // S20 Smart Socket + { "S20 Socket", // S20 Smart Socket (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0 }, - { "Slampher", // Slampher + { "Slampher", // Slampher (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0 }, - { "Sonoff Touch", // Sonoff Touch + { "Sonoff Touch", // Sonoff Touch (ESP8285) GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, // Flash connection + 0, 0, 0, GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0 }, - { "Sonoff LED", // Sonoff LED + { "Sonoff LED", // Sonoff LED (ESP8266) GPIO_KEY1, // GPIO00 Button 0, 0, 0, GPIO_USER, // GPIO04 Optional sensor (PWM3 Green) GPIO_USER, // GPIO05 Optional sensor (PWM2 Red) - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_PWM0, // GPIO12 Cold light GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_PWM1, // GPIO14 Warm light GPIO_USER, // GPIO15 Optional sensor (PWM4 Blue) 0 }, - { "1 Channel", // 1 Channel Inching/Latching Relay + { "1 Channel", // 1 Channel Inching/Latching Relay using (PSA-B01 - ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0 @@ -246,81 +279,83 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_TXD, // GPIO01 Relay control 0, GPIO_RXD, // GPIO03 Relay control - 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection + 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0 }, - { "Motor C/AC", // Motor Clockwise / Anti clockwise + { "Motor C/AC", // Motor Clockwise / Anti clockwise (PSA-B01 - ESP8266) GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0 }, - { "ElectroDragon", // ElectroDragon IoT Relay Board + { "ElectroDragon", // ElectroDragon IoT Relay Board (ESP8266) GPIO_KEY2, // GPIO00 Button 2 - 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor GPIO_KEY1, // GPIO02 Button 1 GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor - 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL2, // GPIO12 Red Led and Relay 2 (0 = Off, 1 = On) GPIO_REL1, // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On) GPIO_USER, // GPIO14 Optional sensor 0, GPIO_LED1 // GPIO16 Green/Blue Led (1 = On, 0 = Off) }, - { "EXS Relay", // Latching relay https://ex-store.de/ESP8266-WiFi-Relay-V31 + { "EXS Relay", // Latching relay https://ex-store.de/ESP8266-WiFi-Relay-V31 (ESP8266) // Module Pin 1 VCC 3V3, Module Pin 6 GND GPIO_KEY1, // GPIO00 Module Pin 8 - Button (firmware flash) - 0, // GPIO01 Module Pin 2 = UART0_TXD + GPIO_USER, // GPIO01 Module Pin 2 = UART0_TXD GPIO_USER, // GPIO02 Module Pin 7 GPIO_USER, // GPIO03 Module Pin 3 = UART0_RXD GPIO_USER, // GPIO04 Module Pin 10 GPIO_USER, // GPIO05 Module Pin 9 - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) GPIO_REL2, // GPIO13 Relay1 ( 1 = On) GPIO_USER, // GPIO14 Module Pin 5 0, GPIO_USER // GPIO16 Module Pin 4 }, - { "WiOn", // Indoor Tap https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w + { "WiOn", // Indoor Tap https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w (ESP8266) GPIO_USER, // GPIO00 Optional sensor (pm clock) 0, GPIO_LED1, // GPIO02 Green Led (1 = On, 0 = Off) - 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_USER, // GPIO12 Optional sensor (pm data) GPIO_KEY1, // GPIO13 Button 0, GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0 }, - { "NodeMCU", // NodeMCU and Wemos hardware - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD - GPIO_USER, // GPIO02 - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - GPIO_USER, // GPIO05 - 0, 0, 0, - GPIO_USER, // GPIO09 - GPIO_USER, // GPIO10 - 0, - GPIO_USER, // GPIO12 - GPIO_USER, // GPIO13 - GPIO_USER, // GPIO14 - GPIO_USER, // GPIO15 - 0 + { "WeMos D1 mini", // WeMos and NodeMCU hardware (ESP8266) + GPIO_USER, // GPIO00 D3 Wemos Button Shield + GPIO_USER, // GPIO01 TX Serial RXD + GPIO_USER, // GPIO02 D4 Wemos DHT Shield + GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor + GPIO_USER, // GPIO04 D2 Wemos I2C SDA + GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_USER, // GPIO12 D6 + GPIO_USER, // GPIO13 D7 + GPIO_USER, // GPIO14 D5 + GPIO_USER, // GPIO15 D8 + GPIO_USER // GPIO16 D0 Wemos Wake }, - { "User Test", // Sonoff Basic User Test + { "User Test", // Sonoff Basic User Test (ESP8266) GPIO_KEY1, // GPIO00 Button - 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor GPIO_USER, // GPIO02 Optional sensor GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor GPIO_USER, // GPIO05 Optional sensor - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 1b5f132ffd91..2eb368e9831b 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -508,6 +508,15 @@ void handleConfig() showPage(page); } +boolean inModule(byte val, uint8_t *arr) +{ + if (!val) return false; // None + for (byte i = 0; i < MAX_GPIO_PIN; i++) { + if (arr[i] == val) return true; + } + return false; +} + void handleModule() { if (httpUser()) return; @@ -524,28 +533,27 @@ void handleModule() for (byte i = 0; i < MAXMODULE; i++) { snprintf_P(stemp, sizeof(stemp), modules[i].name); - snprintf_P(line, sizeof(line), PSTR("%d %s"), + snprintf_P(line, sizeof(line), PSTR("%02d %s"), (i == sysCfg.module) ? " selected" : "", i, i +1, stemp); page += line; } page += F("
"); - mytmplt cmodule; memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule)); for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (cmodule.gp.io[i] == GPIO_USER) { - snprintf_P(line, sizeof(line), PSTR("
GPIO%d"), + i, (i==0)?"Button1":(i==1)?"Serial Out":(i==3)?"Serial In":(i==12)?"Relay1":(i==13)?"Led1I":(i==14)?"Sensor":"", i, i); page += line; for (byte j = 0; j < GPIO_SENSOR_END; j++) { snprintf_P(stemp, sizeof(stemp), sensors[j]); - snprintf_P(line, sizeof(line), PSTR("%d %s"), - (j == my_module.gp.io[i]) ? " selected" : "", j, j, stemp); + snprintf_P(line, sizeof(line), PSTR("%02d %s"), + (j == my_module.gp.io[i])?" selected":(inModule(j, cmodule.gp.io))?" disabled":"", j, j, stemp); page += line; } page += F("
"); } } - page += FPSTR(HTTP_FORM_END); page += FPSTR(HTTP_BTN_CONF); showPage(page);