diff --git a/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h index 2f27b846b..1d6c0f969 100644 --- a/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h +++ b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h @@ -32,7 +32,7 @@ extern String EscapeJSONString(const char *str); class JsonGeneratorArray { public: - JsonGeneratorArray(): val("[]") {} // start with empty array + JsonGeneratorArray(): val(F("[]")) {} // start with empty array void add(uint32_t uval32); void add(int32_t uval32); @@ -53,7 +53,7 @@ protected: class JsonGeneratorObject { public: - JsonGeneratorObject(): val("{}") {} // start with empty object + JsonGeneratorObject(): val(F("{}")) {} // start with empty object void add(const char* key, uint32_t uval32); void add(const char* key, int32_t uval32); diff --git a/tasmota/settings.ino b/tasmota/settings.ino index b2d438df6..0ebdac4c7 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -812,10 +812,10 @@ void SettingsDefaultSet2(void) flag3.use_wifi_rescan |= WIFI_SCAN_REGULARLY; Settings.wifi_output_power = 170; Settings.param[P_ARP_GRATUITOUS] = WIFI_ARP_INTERVAL; - ParseIp(&Settings.ip_address[0], WIFI_IP_ADDRESS); - ParseIp(&Settings.ip_address[1], WIFI_GATEWAY); - ParseIp(&Settings.ip_address[2], WIFI_SUBNETMASK); - ParseIp(&Settings.ip_address[3], WIFI_DNS); + ParseIp(&Settings.ip_address[0], PSTR(WIFI_IP_ADDRESS)); + ParseIp(&Settings.ip_address[1], PSTR(WIFI_GATEWAY)); + ParseIp(&Settings.ip_address[2], PSTR(WIFI_SUBNETMASK)); + ParseIp(&Settings.ip_address[3], PSTR(WIFI_DNS)); Settings.sta_config = WIFI_CONFIG_TOOL; // Settings.sta_active = 0; SettingsUpdateText(SET_STASSID1, PSTR(STA_SSID1)); @@ -865,22 +865,22 @@ void SettingsDefaultSet2(void) flag3.grouptopic_mode |= MQTT_GROUPTOPIC_FORMAT; SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); Settings.mqtt_port = MQTT_PORT; - SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); - SettingsUpdateText(SET_MQTT_USER, MQTT_USER); - SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); - SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); - SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); + SettingsUpdateText(SET_MQTT_CLIENT, PSTR(MQTT_CLIENT_ID)); + SettingsUpdateText(SET_MQTT_USER, PSTR(MQTT_USER)); + SettingsUpdateText(SET_MQTT_PWD, PSTR(MQTT_PASS)); + SettingsUpdateText(SET_MQTT_TOPIC, PSTR(MQTT_TOPIC)); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, PSTR(MQTT_BUTTON_TOPIC)); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, PSTR(MQTT_SWITCH_TOPIC)); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, PSTR(MQTT_GRPTOPIC)); + SettingsUpdateText(SET_MQTT_FULLTOPIC, PSTR(MQTT_FULLTOPIC)); Settings.mqtt_retry = MQTT_RETRY_SECS; - SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); - SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); - SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); - SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); - SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); + SettingsUpdateText(SET_MQTTPREFIX1, PSTR(SUB_PREFIX)); + SettingsUpdateText(SET_MQTTPREFIX2, PSTR(PUB_PREFIX)); + SettingsUpdateText(SET_MQTTPREFIX3, PSTR(PUB_PREFIX2)); + SettingsUpdateText(SET_STATE_TXT1, PSTR(MQTT_STATUS_OFF)); + SettingsUpdateText(SET_STATE_TXT2, PSTR(MQTT_STATUS_ON)); + SettingsUpdateText(SET_STATE_TXT3, PSTR(MQTT_CMND_TOGGLE)); + SettingsUpdateText(SET_STATE_TXT4, PSTR(MQTT_CMND_HOLD)); memcpy_P(Settings.mqtt_fingerprint[0], default_fingerprint1, sizeof(default_fingerprint1)); memcpy_P(Settings.mqtt_fingerprint[1], default_fingerprint2, sizeof(default_fingerprint2)); Settings.tele_period = TELE_PERIOD; diff --git a/tasmota/support.ino b/tasmota/support.ino index 0d5ce5b94..dace03c58 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -384,7 +384,7 @@ char* Uint64toHex(uint64_t value, char *str, uint16_t bits) char* dtostrfd(double number, unsigned char prec, char *s) { if ((isnan(number)) || (isinf(number))) { // Fix for JSON output (https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript) - strcpy(s, "null"); + strcpy_P(s, PSTR("null")); return s; } else { return dtostrf(number, 1, prec, s); @@ -661,10 +661,13 @@ bool ValidIpAddress(const char* str) return (*p == '\0'); } -bool ParseIp(uint32_t* addr, const char* str) +bool ParseIp(uint32_t* addr, const char* str_p) { uint8_t *part = (uint8_t*)addr; uint8_t i; + char str_r[strlen_P(str_p)+1]; + char * str = &str_r[0]; + strcpy_P(str, str_p); *addr = 0; for (i = 0; i < 4; i++) { @@ -861,7 +864,7 @@ float ConvertPressureForSeaLevel(float pressure) String PressureUnit(void) { - return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); + return (Settings.flag.pressure_conversion) ? String(F(D_UNIT_MILLIMETER_MERCURY)) : String(F(D_UNIT_PRESSURE)); } float ConvertSpeed(float s) @@ -1024,11 +1027,11 @@ String GetSerialConfig(void) { // b00000x00 - 1 or 2 stop bits // b000xx000 - None, Even or Odd parity - const char kParity[] = "NEOI"; + const static char kParity[] PROGMEM = "NEOI"; char config[4]; config[0] = '5' + (Settings.serial_config & 0x3); - config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; + config[1] = pgm_read_byte(&kParity[(Settings.serial_config >> 3) & 0x3]); config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); config[3] = '\0'; return String(config); diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 1c5e32474..145d86ef2 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -110,7 +110,7 @@ void ResponseCmndStateText(uint32_t value) void ResponseCmndDone(void) { - ResponseCmndChar(D_JSON_DONE); + ResponseCmndChar(PSTR(D_JSON_DONE)); } void ResponseCmndIdxChar(const char* value) @@ -352,7 +352,7 @@ void CmndBacklog(void) #else TasmotaGlobal.backlog_pointer = TasmotaGlobal.backlog_index; #endif - ResponseCmndChar(blflag ? D_JSON_EMPTY : D_JSON_ABORTED); + ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED)); } } @@ -1282,7 +1282,7 @@ void CmndTemplate(void) if (Settings.module != USER_MODULE) { ModuleDefault(Settings.module); } - SettingsUpdateText(SET_TEMPLATE_NAME, "Merged"); + SettingsUpdateText(SET_TEMPLATE_NAME, PSTR("Merged")); uint32_t j = 0; for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { if (6 == i) { j = 9; } diff --git a/tasmota/support_network.ino b/tasmota/support_network.ino index b2bb73bf0..e2b24d782 100644 --- a/tasmota/support_network.ino +++ b/tasmota/support_network.ino @@ -38,7 +38,7 @@ void StartMdns(void) { // mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; MDNS.end(); // close existing or MDNS.begin will fail Mdns.begun = (uint8_t)MDNS.begin(TasmotaGlobal.hostname); - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? D_INITIALIZED : D_FAILED); + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? PSTR(D_INITIALIZED) : PSTR(D_FAILED)); // } } } diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 08f7cfc3d..2f2403e7a 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -33,8 +33,8 @@ const uint32_t MINS_PER_HOUR = 60UL; Ticker TickerRtc; -static const uint8_t kDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // API starts months from 1, this array starts from 0 -static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; +static const uint8_t kDaysInMonth[] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // API starts months from 1, this array starts from 0 +static const char kMonthNamesEnglish[] PROGMEM = "JanFebMarAprMayJunJulAugSepOctNovDec"; struct RTC { uint32_t utc_time = 0; @@ -88,7 +88,9 @@ String GetBuildDateAndTime(void) // "2017-03-07T11:08:02" - ISO8601:2004 char bdt[21]; char *p; - char mdate[] = __DATE__; // "Mar 7 2017" + static const char mdate_P[] PROGMEM = __DATE__; // "Mar 7 2017" + char mdate[strlen_P(mdate_P)+1]; // copy on stack first + strcpy_P(mdate, mdate_P); char *smonth = mdate; int day = 0; int year = 0; @@ -107,8 +109,10 @@ String GetBuildDateAndTime(void) year = atoi(str); } } - int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /3 +1; - snprintf_P(bdt, sizeof(bdt), PSTR("%d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%s"), year, month, day, __TIME__); + char MonthNamesEnglish[sizeof(kMonthNamesEnglish)]; + strcpy_P(MonthNamesEnglish, kMonthNamesEnglish); + int month = (strstr(MonthNamesEnglish, smonth) -MonthNamesEnglish) /3 +1; + snprintf_P(bdt, sizeof(bdt), PSTR("%d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%s"), year, month, day, PSTR(__TIME__)); return String(bdt); // 2017-03-07T11:08:02 } @@ -290,7 +294,7 @@ void BreakTime(uint32_t time_input, TIME_T &tm) month_length = 28; } } else { - month_length = kDaysInMonth[month]; + month_length = pgm_read_byte(&kDaysInMonth[month]); } if (time >= month_length) { @@ -326,7 +330,7 @@ uint32_t MakeTime(TIME_T &tm) if ((2 == i) && LEAP_YEAR(tm.year)) { seconds += SECS_PER_DAY * 29; } else { - seconds += SECS_PER_DAY * kDaysInMonth[i-1]; // monthDay array starts from 0 + seconds += SECS_PER_DAY * pgm_read_byte(&kDaysInMonth[i-1]); // monthDay array starts from 0 } } seconds+= (tm.day_of_month - 1) * SECS_PER_DAY; diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 64bc6e09d..40d5836ad 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -20,10 +20,12 @@ const char kSleepMode[] PROGMEM = "Dynamic|Normal"; const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; -char* Format(char* output, const char* input, int size) +char* Format(char* output, const char* input_p, int size) { char *token; uint32_t digits = 0; + char input[strlen_P(input_p)+1]; // copy from PMEM to RAM + strcpy_P(input, input_p); if (strchr(input, '%') != nullptr) { strlcpy(output, input, size); @@ -102,7 +104,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi fulltopic += TasmotaGlobal.mqtt_client; fulltopic += F("_fb"); // cmnd/_fb } else { - fulltopic += topic; // cmnd/ + fulltopic += (const __FlashStringHelper *)topic; // cmnd/ } } else { fulltopic = SettingsText(SET_MQTT_FULLTOPIC); @@ -118,7 +120,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi } fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix)); - fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); + fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), (const __FlashStringHelper *)topic); fulltopic.replace(F("%hostname%"), TasmotaGlobal.hostname); String token_id = WiFi.macAddress(); token_id.replace(":", ""); @@ -486,7 +488,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) #endif // USE_DOMOTICZ result = !Settings.flag3.button_switch_force_local; // SetOption61 - Force local operation when button/switch topic is set } else { - Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); + Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? PSTR("Switch") : PSTR("Button"), device, state); result = XdrvRulesProcess(); } #ifdef USE_PWM_DIMMER @@ -742,7 +744,8 @@ void TempHumDewShow(bool json, bool pass_on, const char *types, float f_temperat String GetSwitchText(uint32_t i) { String switch_text = SettingsText(SET_SWITCH_TXT1 + i); if ('\0' == switch_text[0]) { - switch_text = D_JSON_SWITCH + String(i +1); + switch_text = F(D_JSON_SWITCH); + switch_text += String(i+1); } return switch_text; } diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 15f5e10c2..68208b941 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -176,7 +176,7 @@ void WiFiSetSleepMode(void) void WifiBegin(uint8_t flag, uint8_t channel) { - const char kWifiPhyMode[] = " bgnl"; + const static char kWifiPhyMode[] PROGMEM = " bgnl"; #ifdef USE_EMULATION UdpDisconnect(); @@ -218,7 +218,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); } AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], TasmotaGlobal.hostname); + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), TasmotaGlobal.hostname); #if LWIP_IPV6 for (bool configured = false; !configured;) { diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 2407e61b1..18995cd47 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -302,7 +302,7 @@ void setup(void) { snprintf_P(TasmotaGlobal.version, sizeof(TasmotaGlobal.version), PSTR("%s.%d"), TasmotaGlobal.version, VERSION & 0xff); } // Thehackbox inserts "release" or "commit number" before compiling using sed -i -e 's/PSTR("(%s)")/PSTR("(85cff52-%s)")/g' tasmota.ino - snprintf_P(TasmotaGlobal.image_name, sizeof(TasmotaGlobal.image_name), PSTR("(%s)"), CODE_IMAGE_STR); // Results in (85cff52-tasmota) or (release-tasmota) + snprintf_P(TasmotaGlobal.image_name, sizeof(TasmotaGlobal.image_name), PSTR("(%s)"), PSTR(CODE_IMAGE_STR)); // Results in (85cff52-tasmota) or (release-tasmota) Format(TasmotaGlobal.mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(TasmotaGlobal.mqtt_client)); Format(TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(TasmotaGlobal.mqtt_topic)); @@ -321,7 +321,7 @@ void setup(void) { SetPowerOnState(); AddLog_P(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_CORE_RELEASE "(%s)"), - PROJECT, SettingsText(SET_DEVICENAME), TasmotaGlobal.version, TasmotaGlobal.image_name, GetBuildDateAndTime().c_str()); + PSTR(PROJECT), SettingsText(SET_DEVICENAME), TasmotaGlobal.version, TasmotaGlobal.image_name, GetBuildDateAndTime().c_str()); #ifdef FIRMWARE_MINIMAL AddLog_P(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); #endif // FIRMWARE_MINIMAL diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 42cbf1af4..b43bc573f 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -376,9 +376,10 @@ struct WEB { } Web; // Helper function to avoid code duplication (saves 4k Flash) +// arg can be in PROGMEM static void WebGetArg(const char* arg, char* out, size_t max) { - String s = Webserver->arg(arg); + String s = Webserver->arg((const __FlashStringHelper *)arg); strlcpy(out, s.c_str(), max); // out[max-1] = '\0'; // Ensure terminating NUL } @@ -460,7 +461,7 @@ void StartWebserver(int type, IPAddress ipweb) WebServer_on(uri, line.handler, pgm_read_byte(&line.method)); } Webserver->onNotFound(HandleNotFound); - Webserver->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); // this call requires 2 functions so we keep a direct call + Webserver->on(F("/u2"), HTTP_POST, HandleUploadDone, HandleUploadLoop); // this call requires 2 functions so we keep a direct call #ifndef FIRMWARE_MINIMAL XdrvCall(FUNC_WEB_ADD_HANDLER); XsnsCall(FUNC_WEB_ADD_HANDLER); @@ -691,7 +692,7 @@ void WSContentStart_P(const char* title, bool auth) WSContentBegin(200, CT_HTML); if (title != nullptr) { - WSContentSend_P(HTTP_HEADER1, D_HTML_LANGUAGE, SettingsText(SET_DEVICENAME), title); + WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), title); } } @@ -767,7 +768,7 @@ void WSContentButton(uint32_t title_index) WSContentSend_P(PSTR("

"), GetTextIndexed(action, sizeof(action), title_index, kButtonAction), GetTextIndexed(confirm, sizeof(confirm), title_index, kButtonConfirm), - (!title_index) ? "rst" : "non", + (!title_index) ? PSTR("rst") : PSTR("non"), GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); } else { WSContentSend_P(PSTR("

"), @@ -866,8 +867,8 @@ void HandleWifiLogin(void) void WebSliderColdWarm(void) { WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Cold Warm - "a", // a - Unique HTML id - "#eff", "#f81", // 6500k in RGB (White) to 2500k in RGB (Warm Yellow) + PSTR("a"), // a - Unique HTML id + PSTR("#eff"), PSTR("#f81"), // 6500k in RGB (White) to 2500k in RGB (Warm Yellow) 1, // sl1 153, 500, // Range color temperature LightGetColorTemp(), @@ -879,17 +880,17 @@ void HandleRoot(void) { if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page. - if (Webserver->hasArg("rst")) { + if (Webserver->hasArg(F("rst"))) { WebRestart(0); return; } if (WifiIsInManagerMode()) { #ifndef FIRMWARE_MINIMAL - if (strlen(SettingsText(SET_WEBPWD)) && !(Webserver->hasArg("USER1")) && !(Webserver->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + if (strlen(SettingsText(SET_WEBPWD)) && !(Webserver->hasArg(F("USER1"))) && !(Webserver->hasArg(F("PASS1"))) && HTTP_MANAGER_RESET_ONLY != Web.state) { HandleWifiLogin(); } else { - if (!strlen(SettingsText(SET_WEBPWD)) || (((Webserver->arg("USER1") == WEB_USERNAME ) && (Webserver->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { + if (!strlen(SettingsText(SET_WEBPWD)) || (((Webserver->arg(F("USER1")) == WEB_USERNAME ) && (Webserver->arg(F("PASS1")) == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { HandleWifiConfiguration(); } else { // wrong user and pass @@ -936,8 +937,8 @@ void HandleRoot(void) LightGetHSB(&hue, &sat, nullptr); WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Hue - "b", // b - Unique HTML id - "#800", PSTR("#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800"), // Hue colors + PSTR("b"), // b - Unique HTML id + PSTR("#800"), PSTR("#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800"), // Hue colors 2, // sl2 - Unique range HTML id - Used as source for Saturation end color 1, 359, // Range valid Hue hue, @@ -951,7 +952,7 @@ void HandleRoot(void) snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); // Saturation end color WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Saturation - "s", // s - Unique HTML id related to eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))'; + PSTR("s"), // s - Unique HTML id related to eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))'; scolor, stemp, // Brightness to max current color 3, // sl3 - Unique range HTML id - Not used 0, 100, // Range 0 to 100% @@ -960,8 +961,8 @@ void HandleRoot(void) } WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Brightness - Black to White - "c", // c - Unique HTML id - "#000", "#fff", // Black to White + PSTR("c"), // c - Unique HTML id + PSTR("#000"), PSTR("#fff"), // Black to White 4, // sl4 - Unique range HTML id - Used as source for Saturation begin color Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% (SetOption77 - Do not power off if slider moved to far left) Settings.light_dimmer, @@ -972,8 +973,8 @@ void HandleRoot(void) WebSliderColdWarm(); } WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // White brightness - Black to White - "f", // f - Unique HTML id - "#000", "#fff", // Black to White + PSTR("f"), // f - Unique HTML id + PSTR("#000"), PSTR("#fff"), // Black to White 5, // sl5 - Unique range HTML id - Not used Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% (SetOption77 - Do not power off if slider moved to far left) LightGetDimmer(2), @@ -987,7 +988,7 @@ void HandleRoot(void) WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Channel brightness - Black to White stemp, // e1 to e5 - Unique HTML id - "#000", "#fff", // Black to White + PSTR("#000"), PSTR("#fff"), // Black to White i+1, // sl1 to sl5 - Unique range HTML id - Not used 1, 100, // Range 1 to 100% changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), @@ -1008,7 +1009,7 @@ void HandleRoot(void) #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, - (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : D_BUTTON_TOGGLE, + (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : PSTR(D_BUTTON_TOGGLE), ""); for (uint32_t i = 0; i < MaxFanspeed(); i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); @@ -1031,7 +1032,7 @@ void HandleRoot(void) #endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / TasmotaGlobal.devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (TasmotaGlobal.devices_present < 5) ? D_BUTTON_TOGGLE : "", + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (TasmotaGlobal.devices_present < 5) ? PSTR(D_BUTTON_TOGGLE) : "", (set_button) ? "" : (TasmotaGlobal.devices_present > 1) ? stemp : ""); } #ifdef USE_SONOFF_IFAN @@ -1107,7 +1108,7 @@ bool HandleRootStatusRefresh(void) char svalue[32]; // Command and number parameter char webindex[5]; // WebGetArg name - WebGetArg("o", tmp, sizeof(tmp)); // 1 - 16 Device number for button Toggle or Fanspeed + WebGetArg(PSTR("o"), tmp, sizeof(tmp)); // 1 - 16 Device number for button Toggle or Fanspeed if (strlen(tmp)) { ShowWebSource(SRC_WEBGUI); uint32_t device = atoi(tmp); @@ -1153,12 +1154,12 @@ bool HandleRootStatusRefresh(void) #endif // USE_TUYA_MCU } #ifdef USE_LIGHT - WebGetArg("d0", tmp, sizeof(tmp)); // 0 - 100 Dimmer value + WebGetArg(PSTR("d0"), tmp, sizeof(tmp)); // 0 - 100 Dimmer value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("w0", tmp, sizeof(tmp)); // 0 - 100 White value + WebGetArg(PSTR("w0"), tmp, sizeof(tmp)); // 0 - 100 White value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); @@ -1173,17 +1174,17 @@ bool HandleRootStatusRefresh(void) ExecuteWebCommand(svalue, SRC_WEBGUI); } } - WebGetArg("t0", tmp, sizeof(tmp)); // 153 - 500 Color temperature + WebGetArg(PSTR("t0"), tmp, sizeof(tmp)); // 153 - 500 Color temperature if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("h0", tmp, sizeof(tmp)); // 0 - 359 Hue value + WebGetArg(PSTR("h0"), tmp, sizeof(tmp)); // 0 - 359 Hue value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("n0", tmp, sizeof(tmp)); // 0 - 99 Saturation value + WebGetArg(PSTR("n0"), tmp, sizeof(tmp)); // 0 - 99 Saturation value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); @@ -1200,19 +1201,19 @@ bool HandleRootStatusRefresh(void) } #endif // USE_SHUTTER #ifdef USE_SONOFF_RF - WebGetArg("k", tmp, sizeof(tmp)); // 1 - 16 Pre defined RF keys + WebGetArg(PSTR("k"), tmp, sizeof(tmp)); // 1 - 16 Pre defined RF keys if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } #endif // USE_SONOFF_RF #ifdef USE_ZIGBEE - WebGetArg("zbj", tmp, sizeof(tmp)); + WebGetArg(PSTR("zbj"), tmp, sizeof(tmp)); if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR("ZbPermitJoin")); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("zbr", tmp, sizeof(tmp)); + WebGetArg(PSTR("zbr"), tmp, sizeof(tmp)); if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR("ZbMap")); ExecuteWebCommand(svalue, SRC_WEBGUI); @@ -1315,7 +1316,7 @@ void WSContentSendNiceLists(uint32_t option) { char stemp[30]; // Template number and Sensor name for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3... if (option && (1 == i)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); // }2'255'>User}3 + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), PSTR(D_SENSOR_USER)); // }2'255'>User}3 } uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0; uint32_t midx = BGPIO(ridx); @@ -1356,7 +1357,7 @@ void WSContentSendAdcNiceList(uint32_t option) { WSContentSend_P(PSTR("os=\"")); for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { // GPIO: }2'0'>None}3}2'17'>Analog}3... if (option && (1 == i)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); // }2'15'>User}3 + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), PSTR(D_SENSOR_USER)); // }2'15'>User}3 } uint32_t ridx = pgm_read_word(kAdcNiceList + i) & 0xFFE0; uint32_t midx = BGPIO(ridx); @@ -1372,7 +1373,7 @@ void HandleTemplateConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (Webserver->hasArg("save")) { + if (Webserver->hasArg(F("save"))) { TemplateSaveSettings(); WebRestart(1); return; @@ -1380,7 +1381,7 @@ void HandleTemplateConfiguration(void) char stemp[30]; // Template number and Sensor name - WebGetArg("t", stemp, sizeof(stemp)); // 0 - 69 Template number + WebGetArg(PSTR("t"), stemp, sizeof(stemp)); // 0 - 69 Template number if (strlen(stemp)) { uint32_t module = atoi(stemp); uint32_t module_save = Settings.module; @@ -1474,7 +1475,7 @@ void TemplateSaveSettings(void) char tmp[TOPSZ]; // WebGetArg NAME and GPIO/BASE/FLAG byte value char svalue[300]; // Template command string - WebGetArg("s1", tmp, sizeof(tmp)); // NAME + WebGetArg(PSTR("s1"), tmp, sizeof(tmp)); // NAME snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); uint32_t j = 0; @@ -1492,7 +1493,7 @@ void TemplateSaveSettings(void) uint32_t state = Webserver->hasArg(webindex) << i; // FLAG flag += state; } - WebGetArg("g99", tmp, sizeof(tmp)); // BASE + WebGetArg(PSTR("g99"), tmp, sizeof(tmp)); // BASE uint32_t base = atoi(tmp) +1; snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); @@ -1505,7 +1506,7 @@ void HandleModuleConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (Webserver->hasArg("save")) { + if (Webserver->hasArg(F("save"))) { ModuleSaveSettings(); WebRestart(1); return; @@ -1572,7 +1573,7 @@ void ModuleSaveSettings(void) { char tmp[8]; // WebGetArg numbers only - WebGetArg("g99", tmp, sizeof(tmp)); + WebGetArg(PSTR("g99"), tmp, sizeof(tmp)); uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); Settings.last_module = Settings.module; Settings.module = new_module; @@ -1624,7 +1625,7 @@ void HandleWifiConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_WIFI)); - if (Webserver->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { + if (Webserver->hasArg(F("save")) && HTTP_MANAGER_RESET_ONLY != Web.state) { WifiSaveSettings(); WebRestart(2); return; @@ -1639,7 +1640,7 @@ void HandleWifiConfiguration(void) #endif // USE_ENHANCED_GUI_WIFI_SCAN if (HTTP_MANAGER_RESET_ONLY != Web.state) { - if (Webserver->hasArg("scan")) { + if (Webserver->hasArg(F("scan"))) { #ifdef USE_EMULATION UdpDisconnect(); #endif // USE_EMULATION @@ -1776,20 +1777,20 @@ void WifiSaveSettings(void) { char tmp[TOPSZ]; // Max length is currently 150 - WebGetArg("h", tmp, sizeof(tmp)); + WebGetArg(PSTR("h"), tmp, sizeof(tmp)); SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); if (strchr(SettingsText(SET_HOSTNAME), '%') != nullptr) { SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); } - WebGetArg("c", tmp, sizeof(tmp)); + WebGetArg(PSTR("c"), tmp, sizeof(tmp)); SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); - WebGetArg("s1", tmp, sizeof(tmp)); + WebGetArg(PSTR("s1"), tmp, sizeof(tmp)); SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); - WebGetArg("s2", tmp, sizeof(tmp)); + WebGetArg(PSTR("s2"), tmp, sizeof(tmp)); SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); - WebGetArg("p1", tmp, sizeof(tmp)); + WebGetArg(PSTR("p1"), tmp, sizeof(tmp)); SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); - WebGetArg("p2", tmp, sizeof(tmp)); + WebGetArg(PSTR("p2"), tmp, sizeof(tmp)); SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); @@ -1839,19 +1840,19 @@ void LoggingSaveSettings(void) { char tmp[TOPSZ]; // Max length is currently 33 - WebGetArg("l0", tmp, sizeof(tmp)); + WebGetArg(PSTR("l0"), tmp, sizeof(tmp)); SetSeriallog((!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp)); - WebGetArg("l1", tmp, sizeof(tmp)); + WebGetArg(PSTR("l1"), tmp, sizeof(tmp)); Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); - WebGetArg("l2", tmp, sizeof(tmp)); + WebGetArg(PSTR("l2"), tmp, sizeof(tmp)); Settings.mqttlog_level = (!strlen(tmp)) ? MQTT_LOG_LEVEL : atoi(tmp); - WebGetArg("l3", tmp, sizeof(tmp)); + WebGetArg(PSTR("l3"), tmp, sizeof(tmp)); SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp)); - WebGetArg("lh", tmp, sizeof(tmp)); + WebGetArg(PSTR("lh"), tmp, sizeof(tmp)); SettingsUpdateText(SET_SYSLOG_HOST, (!strlen(tmp)) ? SYS_LOG_HOST : tmp); - WebGetArg("lp", tmp, sizeof(tmp)); + WebGetArg(PSTR("lp"), tmp, sizeof(tmp)); Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); - WebGetArg("lt", tmp, sizeof(tmp)); + WebGetArg(PSTR("lt"), tmp, sizeof(tmp)); Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { Settings.tele_period = 10; // Do not allow periods < 10 seconds @@ -1868,7 +1869,7 @@ void HandleOtherConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_OTHER)); - if (Webserver->hasArg("save")) { + if (Webserver->hasArg(F("save"))) { OtherSaveSettings(); WebRestart(1); return; @@ -1932,15 +1933,15 @@ void OtherSaveSettings(void) char friendlyname[TOPSZ]; char message[MAX_LOGSZ]; - WebGetArg("dn", tmp, sizeof(tmp)); + WebGetArg(PSTR("dn"), tmp, sizeof(tmp)); SettingsUpdateText(SET_DEVICENAME, (!strlen(tmp)) ? "" : (!strcmp(tmp,"1")) ? SettingsText(SET_FRIENDLYNAME1) : tmp); - WebGetArg("wp", tmp, sizeof(tmp)); + WebGetArg(PSTR("wp"), tmp, sizeof(tmp)); SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); - Settings.flag.mqtt_enabled = Webserver->hasArg("b1"); // SetOption3 - Enable MQTT + Settings.flag.mqtt_enabled = Webserver->hasArg(F("b1")); // SetOption3 - Enable MQTT #ifdef USE_EMULATION UdpDisconnect(); #if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) - WebGetArg("b2", tmp, sizeof(tmp)); + WebGetArg(PSTR("b2"), tmp, sizeof(tmp)); Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); #endif // USE_EMULATION_WEMO || USE_EMULATION_HUE #endif // USE_EMULATION @@ -1951,14 +1952,14 @@ void OtherSaveSettings(void) snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); WebGetArg(webindex, tmp, sizeof(tmp)); snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); - SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp); + SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : PSTR(FRIENDLY_NAME) : tmp); snprintf_P(message, sizeof(message), PSTR("%s%s %s"), message, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); } AddLogData(LOG_LEVEL_INFO, message); - WebGetArg("t1", tmp, sizeof(tmp)); + WebGetArg(PSTR("t1"), tmp, sizeof(tmp)); if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} - snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : ""); + snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg(F("t2"))) ? PSTR("; " D_CMND_MODULE " 0") : ""); ExecuteWebCommand(message, SRC_WEBGUI); } } @@ -2034,7 +2035,7 @@ void HandleRestoreConfiguration(void) WSContentStart_P(PSTR(D_RESTORE_CONFIGURATION)); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_RST); - WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); + WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_RESTORE)); if (WifiIsInManagerMode()) { WSContentSpaceButton(BUTTON_MAIN); } else { @@ -2249,7 +2250,7 @@ void HandleUpgradeFirmware(void) { WSContentStart_P(PSTR(D_FIRMWARE_UPGRADE)); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL)); - WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); + WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_UPGRADE)); WSContentSpaceButton(BUTTON_MAIN); WSContentStop(); @@ -2265,7 +2266,7 @@ void HandleUpgradeFirmwareStart(void) { WifiConfigCounter(); char otaurl[TOPSZ]; - WebGetArg("o", otaurl, sizeof(otaurl)); + WebGetArg(PSTR("o"), otaurl, sizeof(otaurl)); if (strlen(otaurl)) { snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl); ExecuteWebCommand(command, SRC_WEBGUI); @@ -2668,9 +2669,9 @@ void HandleHttpCommand(void) if (!WebAuthenticate()) { // Prefer authorization via HTTP header (Basic auth), if it fails, use legacy method via GET parameters char tmp1[33]; - WebGetArg("user", tmp1, sizeof(tmp1)); + WebGetArg(PSTR("user"), tmp1, sizeof(tmp1)); char tmp2[strlen(SettingsText(SET_WEBPWD)) + 1]; - WebGetArg("password", tmp2, sizeof(tmp2)); + WebGetArg(PSTR("password"), tmp2, sizeof(tmp2)); if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { WSContentBegin(401, CT_JSON); @@ -2681,7 +2682,7 @@ void HandleHttpCommand(void) } WSContentBegin(200, CT_JSON); - String svalue = Webserver->arg("cmnd"); + String svalue = Webserver->arg(F("cmnd")); if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { uint32_t curridx = TasmotaGlobal.log_buffer_pointer; TasmotaGlobal.templog_level = LOG_LEVEL_INFO; @@ -2717,7 +2718,7 @@ void HandleConsole(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (Webserver->hasArg("c2")) { // Console refresh requested + if (Webserver->hasArg(F("c2"))) { // Console refresh requested HandleConsoleRefresh(); return; } @@ -2734,14 +2735,14 @@ void HandleConsole(void) void HandleConsoleRefresh(void) { - String svalue = Webserver->arg("c1"); + String svalue = Webserver->arg(F("c1")); if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); } char stmp[8]; - WebGetArg("c2", stmp, sizeof(stmp)); + WebGetArg(PSTR("c2"), stmp, sizeof(stmp)); uint32_t index = 0; // Initial start, dump all if (strlen(stmp)) { index = atoi(stmp); } @@ -2758,7 +2759,7 @@ void HandleConsoleRefresh(void) if (len > sizeof(TasmotaGlobal.mqtt_data) -2) { len = sizeof(TasmotaGlobal.mqtt_data); } char stemp[len +1]; strlcpy(stemp, line, len); - WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp); + WSContentSend_P(PSTR("%s%s"), (cflg) ? PSTR("\n") : "", stemp); cflg = true; } WSContentSend_P(PSTR("}1")); @@ -2776,14 +2777,14 @@ void HandleNotFound(void) #ifdef USE_EMULATION #ifdef USE_EMULATION_HUE String path = Webserver->uri(); - if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) { + if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith(F("/api")))) { HandleHueApi(&path); } else #endif // USE_EMULATION_HUE #endif // USE_EMULATION { WSContentBegin(404, CT_PLAIN); - WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), Webserver->uri().c_str(), (Webserver->method() == HTTP_GET) ? "GET" : "POST", Webserver->args()); + WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), Webserver->uri().c_str(), (Webserver->method() == HTTP_GET) ? PSTR("GET") : PSTR("POST"), Webserver->args()); for (uint32_t i = 0; i < Webserver->args(); i++) { WSContentSend_P(PSTR(" %s: %s\n"), Webserver->argName(i).c_str(), Webserver->arg(i).c_str()); } @@ -2978,7 +2979,7 @@ void CmndWebServer(void) } if (Settings.webserver) { Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str()); + (2 == Settings.webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str()); } else { ResponseCmndStateText(0); } diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 6324a584b..bf4a9e6f9 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -156,7 +156,7 @@ void MqttInit(void) { // Detect AWS IoT and set default parameters String host = String(SettingsText(SET_MQTT_HOST)); - if (host.indexOf(".iot.") && host.endsWith(".amazonaws.com")) { // look for ".iot." and ".amazonaws.com" in the domain name + if (host.indexOf(F(".iot.")) && host.endsWith(F(".amazonaws.com"))) { // look for ".iot." and ".amazonaws.com" in the domain name Settings.flag4.mqtt_no_retain = true; } @@ -527,10 +527,10 @@ void MqttConnected(void) { if (Settings.webserver) { #if LWIP_IPV6 Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str()); + (2 == Settings.webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str()); #else Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str()); + (2 == Settings.webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str()); #endif // LWIP_IPV6 = 1 MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } @@ -787,7 +787,7 @@ void CmndMqttFingerprint(void) { void CmndMqttUser(void) { if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data); + SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? PSTR(MQTT_USER) : XdrvMailbox.data); TasmotaGlobal.restart_flag = 2; } ResponseCmndChar(SettingsText(SET_MQTT_USER)); @@ -795,7 +795,7 @@ void CmndMqttUser(void) { void CmndMqttPassword(void) { if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data); + SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? PSTR(MQTT_PASS) : XdrvMailbox.data); ResponseCmndChar(SettingsText(SET_MQTT_PWD)); TasmotaGlobal.restart_flag = 2; } else { @@ -852,7 +852,7 @@ void CmndStateText(void) { void CmndMqttClient(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data); + SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? PSTR(MQTT_CLIENT_ID) : XdrvMailbox.data); TasmotaGlobal.restart_flag = 2; } ResponseCmndChar(SettingsText(SET_MQTT_CLIENT)); @@ -882,7 +882,7 @@ void CmndPrefix(void) { if (XdrvMailbox.data_len > 0) { MakeValidMqtt(0, XdrvMailbox.data); SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, - (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); + (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? PSTR(SUB_PREFIX) : (2==XdrvMailbox.index) ? PSTR(PUB_PREFIX) : PSTR(PUB_PREFIX2) : XdrvMailbox.data); TasmotaGlobal.restart_flag = 2; } ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); @@ -918,7 +918,7 @@ void CmndGroupTopic(void) { uint32_t settings_text_index = (1 == XdrvMailbox.index) ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2; MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } - SettingsUpdateText(settings_text_index, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); + SettingsUpdateText(settings_text_index, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? PSTR(MQTT_GRPTOPIC) : XdrvMailbox.data); // Eliminate duplicates, have at least one and fill from index 1 char stemp[MAX_GROUP_TOPICS][TOPSZ]; @@ -940,7 +940,7 @@ void CmndGroupTopic(void) { } } if (0 == read_index) { - SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, PSTR(MQTT_GRPTOPIC)); } else { uint32_t write_index = 0; uint32_t real_index = SET_MQTT_GRP_TOPIC; @@ -998,7 +998,7 @@ void CmndSwitchTopic(void) { switch (Shortcut()) { case SC_CLEAR: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, ""); break; case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, TasmotaGlobal.mqtt_topic); break; - case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); break; + case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, PSTR(MQTT_SWITCH_TOPIC)); break; default: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, XdrvMailbox.data); } } @@ -1266,7 +1266,7 @@ void HandleMqttConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_MQTT)); - if (Webserver->hasArg("save")) { + if (Webserver->hasArg(F("save"))) { MqttSaveSettings(); WebRestart(1); return; @@ -1282,11 +1282,11 @@ void HandleMqttConfiguration(void) #ifdef USE_MQTT_TLS Mqtt.mqtt_tls ? PSTR(" checked") : "", // SetOption102 - Enable MQTT TLS #endif // USE_MQTT_TLS - Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); + Format(str, PSTR(MQTT_CLIENT_ID), sizeof(str)), PSTR(MQTT_CLIENT_ID), SettingsText(SET_MQTT_CLIENT)); WSContentSend_P(HTTP_FORM_MQTT2, (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), - Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), - MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); + Format(str, PSTR(MQTT_TOPIC), sizeof(str)), PSTR(MQTT_TOPIC), SettingsText(SET_MQTT_TOPIC), + PSTR(MQTT_FULLTOPIC), PSTR(MQTT_FULLTOPIC), SettingsText(SET_MQTT_FULLTOPIC)); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); @@ -1298,10 +1298,10 @@ void MqttSaveSettings(void) char stemp[TOPSZ]; char stemp2[TOPSZ]; - WebGetArg("mt", tmp, sizeof(tmp)); + WebGetArg(PSTR("mt"), tmp, sizeof(tmp)); strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); MakeValidMqtt(0, stemp); - WebGetArg("mf", tmp, sizeof(tmp)); + WebGetArg(PSTR("mf"), tmp, sizeof(tmp)); strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); MakeValidMqtt(1, stemp2); if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { @@ -1310,18 +1310,18 @@ void MqttSaveSettings(void) } SettingsUpdateText(SET_MQTT_TOPIC, stemp); SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); - WebGetArg("mh", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("ml", tmp, sizeof(tmp)); + WebGetArg(PSTR("mh"), tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? PSTR(MQTT_HOST) : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg(PSTR("ml"), tmp, sizeof(tmp)); Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); #ifdef USE_MQTT_TLS - Settings.flag4.mqtt_tls = Webserver->hasArg("b3"); // SetOption102 - Enable MQTT TLS + Settings.flag4.mqtt_tls = Webserver->hasArg(F("b3")); // SetOption102 - Enable MQTT TLS #endif - WebGetArg("mc", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); - WebGetArg("mu", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("mp", tmp, sizeof(tmp)); + WebGetArg(PSTR("mc"), tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? PSTR(MQTT_CLIENT_ID) : tmp); + WebGetArg(PSTR("mu"), tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? PSTR(MQTT_USER) : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg(PSTR("mp"), tmp, sizeof(tmp)); SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 90d94ffb7..7e0907dd1 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2625,7 +2625,7 @@ void CmndWakeup(void) Light.wakeup_active = 3; Settings.light_scheme = LS_WAKEUP; LightPowerOn(); - ResponseCmndChar(D_JSON_STARTED); + ResponseCmndChar(PSTR(D_JSON_STARTED)); } void CmndColorTemperature(void) diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index 82b769963..b982a58b1 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -546,7 +546,7 @@ void HandleDomoticzConfiguration(void) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_DOMOTICZ)); - if (Webserver->hasArg("save")) { + if (Webserver->hasArg(F("save"))) { DomoticzSaveSettings(); WebRestart(1); return; @@ -605,7 +605,7 @@ void DomoticzSaveSettings(void) { 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]); } - WebGetArg("ut", tmp, sizeof(tmp)); + WebGetArg(PSTR("ut"), tmp, sizeof(tmp)); Settings.domoticz_update_timer = (!strlen(tmp)) ? DOMOTICZ_UPDATE_TIMER : atoi(tmp); AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d,%d,%d,%d, " D_CMND_KEYIDX " %d,%d,%d,%d, " D_CMND_SWITCHIDX " %d,%d,%d,%d, " D_CMND_SENSORIDX " %s, " D_CMND_UPDATETIMER " %d"), diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index 0f6292e13..a33204906 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -841,7 +841,7 @@ void HandleTimerConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_TIMER)); - if (Webserver->hasArg("save")) { + if (Webserver->hasArg(F("save"))) { TimerSaveSettings(); HandleConfiguration(); return; @@ -883,8 +883,8 @@ void TimerSaveSettings(void) char message[32 + (MAX_TIMERS *11)]; // MQT: Timers 0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 Timer timer; - Settings.flag3.timers_enable = Webserver->hasArg("e0"); // CMND_TIMERS - WebGetArg("t0", tmp, sizeof(tmp)); + Settings.flag3.timers_enable = Webserver->hasArg(F("e0")); // CMND_TIMERS + WebGetArg(PSTR("t0"), tmp, sizeof(tmp)); char *p = tmp; snprintf_P(message, sizeof(message), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); // CMND_TIMERS for (uint32_t i = 0; i < MAX_TIMERS; i++) { diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 637a3b963..4a6d3c9c1 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -416,7 +416,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all // Step1: Analyse rule String rule_expr = rule; // "TELE-INA219#CURRENT>0.100" if (Rules.teleperiod) { - int ppos = rule_expr.indexOf("TELE-"); // "TELE-INA219#CURRENT>0.100" or "INA219#CURRENT>0.100" + int ppos = rule_expr.indexOf(F("TELE-")); // "TELE-INA219#CURRENT>0.100" or "INA219#CURRENT>0.100" if (ppos == -1) { return false; } // No pre-amble in rule rule_expr = rule.substring(5); // "INA219#CURRENT>0.100" or "SYSTEM#BOOT" } @@ -494,7 +494,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all // Step2: Search rule_name int pos; int rule_name_idx = 0; - if ((pos = rule_name.indexOf("[")) > 0) { // "SUBTYPE1#CURRENT[1]" + if ((pos = rule_name.indexOf(F("["))) > 0) { // "SUBTYPE1#CURRENT[1]" rule_name_idx = rule_name.substring(pos +1).toInt(); if ((rule_name_idx < 1) || (rule_name_idx > 6)) { // Allow indexes 1 to 6 rule_name_idx = 1; @@ -515,7 +515,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all } String subtype; uint32_t i = 0; - while ((pos = rule_name.indexOf("#")) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT" + while ((pos = rule_name.indexOf(F("#"))) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT" subtype = rule_name.substring(0, pos); obj = obj[subtype.c_str()].getObject(); if (!obj) { return false; } // not found @@ -686,14 +686,14 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) String rule = rules; rule.toUpperCase(); // "ON INA219#CURRENT>0.100 DO BACKLOG DIMMER 10;COLOR 100000 ENDON" - if (!rule.startsWith("ON ")) { return serviced; } // Bad syntax - Nothing to start on + if (!rule.startsWith(F("ON "))) { return serviced; } // Bad syntax - Nothing to start on - int pevt = rule.indexOf(" DO "); + int pevt = rule.indexOf(F(" DO ")); if (pevt == -1) { return serviced; } // Bad syntax - Nothing to do String event_trigger = rule.substring(3, pevt); // "INA219#CURRENT>0.100" - plen = rule.indexOf(" ENDON"); - plen2 = rule.indexOf(" BREAK"); + plen = rule.indexOf(F(" ENDON")); + plen2 = rule.indexOf(F(" BREAK")); if ((plen == -1) && (plen2 == -1)) { return serviced; } // Bad syntax - No ENDON neither BREAK if (plen == -1) { plen = 9999; } @@ -717,10 +717,10 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) // if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception // Use Backlog with event to prevent rule event loop exception unless IF is used which uses an implicit backlog - if ((ucommand.indexOf("IF ") == -1) && - (ucommand.indexOf("EVENT ") != -1) && - (ucommand.indexOf("BACKLOG ") == -1)) { - commands = "backlog " + commands; + if ((ucommand.indexOf(F("IF ")) == -1) && + (ucommand.indexOf(F("EVENT ")) != -1) && + (ucommand.indexOf(F("BACKLOG ")) == -1)) { + commands = String(F("backlog ")) + commands; } RulesVarReplace(commands, F("%VALUE%"), Rules.event_value); diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index bf4664886..0120615e0 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -294,7 +294,7 @@ void NewHAssDiscovery(void) for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { char fname[TOPSZ]; snprintf_P(fname, sizeof(fname), PSTR("\"%s\""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str()); - snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%s"), stemp2, (i > 0 ? "," : ""), (i < maxfn) ? fname : "null"); + snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%s"), stemp2, (i > 0 ? "," : ""), (i < maxfn) ? fname : PSTR("null")); } stemp3[0] = '\0'; @@ -304,7 +304,7 @@ void NewHAssDiscovery(void) char sname[TOPSZ]; snprintf_P(sname, sizeof(sname), PSTR("\"%s\""), GetSwitchText(i).c_str()); snprintf_P(stemp3, sizeof(stemp3), PSTR("%s%s%d"), stemp3, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? Settings.switchmode[i] : -1); - snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%s"), stemp4, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? sname : "null"); + snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%s"), stemp4, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? sname : PSTR("null")); } stemp5[0] = '\0'; @@ -338,7 +338,7 @@ void NewHAssDiscovery(void) if (!Settings.flag.hass_discovery) { // HassDiscoveryRelays(relays) Response_P(HASS_DISCOVER_DEVICE, WiFi.localIP().toString().c_str(), SettingsText(SET_DEVICENAME), stemp2, TasmotaGlobal.hostname, unique_id, ModuleName().c_str(), TuyaMod, iFanMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3), - TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, + TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), PSTR(SUB_PREFIX), PSTR(PUB_PREFIX), PSTR(PUB_PREFIX2), Hass.RelLst, stemp3, stemp4, stemp5, Settings.flag.mqtt_response, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag4.alexa_ct_range, Settings.flag5.mqtt_switches, Settings.flag5.fade_fixed_duration, light_controller.isCTRGBLinked(), Light.subtype, stemp6); diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index a291d2e11..7535d29c5 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -1295,7 +1295,7 @@ void TuyaSensorsShow(bool json) GetTextIndexed(sname, sizeof(sname), (sensor-71), kTuyaSensors); ResponseAppend_P(PSTR("\"%s\":%s"), sname, - (Tuya.SensorsValid[sensor-71] ? dtostrfd(Tuya.Sensors[sensor-71], res, tempval) : "null")); + (Tuya.SensorsValid[sensor-71] ? dtostrfd(Tuya.Sensors[sensor-71], res, tempval) : PSTR("null"))); added = true; } #ifdef USE_WEBSERVER diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 4da625847..013e22a98 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -429,9 +429,9 @@ void HandleUpnpSetupHue(void) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_HUE_BRIDGE_SETUP)); String description_xml = Decompress(HUE_DESCRIPTION_XML_COMPRESSED,HUE_DESCRIPTION_XML_SIZE); - description_xml.replace("{x1", WiFi.localIP().toString()); - description_xml.replace("{x2", HueUuid()); - description_xml.replace("{x3", HueSerialnumber()); + description_xml.replace(F("{x1"), WiFi.localIP().toString()); + description_xml.replace(F("{x2"), HueUuid()); + description_xml.replace(F("{x3"), HueSerialnumber()); WSSend(200, CT_XML, description_xml); } @@ -439,19 +439,19 @@ void HueNotImplemented(String *path) { AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); - WSSend(200, CT_JSON, "{}"); + WSSend(200, CT_JSON, PSTR("{}")); } void HueConfigResponse(String *response) { *response += Decompress(HueConfigResponse_JSON, HueConfigResponse_JSON_SIZE); - response->replace("{ma", WiFi.macAddress()); - response->replace("{ip", WiFi.localIP().toString()); - response->replace("{ms", WiFi.subnetMask().toString()); - response->replace("{gw", WiFi.gatewayIP().toString()); - response->replace("{br", HueBridgeId()); - response->replace("{dt", GetDateAndTime(DT_UTC)); - response->replace("{id", GetHueUserId()); + response->replace(F("{ma"), WiFi.macAddress()); + response->replace(F("{ip"), WiFi.localIP().toString()); + response->replace(F("{ms"), WiFi.subnetMask().toString()); + response->replace(F("{gw"), WiFi.gatewayIP().toString()); + response->replace(F("{br"), HueBridgeId()); + response->replace(F("{dt"), GetDateAndTime(DT_UTC)); + response->replace(F("{id"), GetHueUserId()); } void HueConfig(String *path) @@ -534,13 +534,13 @@ void HueLightStatus1(uint8_t device, String *response) char * buf = (char*) malloc(buf_size); // temp buffer for strings, avoid stack UnishoxStrings msg(HUE_LIGHTS); - snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (TasmotaGlobal.power & (1 << (device-1))) ? "true" : "false"); + snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (TasmotaGlobal.power & (1 << (device-1))) ? PSTR("true") : PSTR("false")); // Brightness for all devices with PWM if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { // force dimmer for 1st gen Echo snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); } if (LST_COLDWARM <= local_light_subtype) { - snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, g_gotct ? "ct" : "hs"); + snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, g_gotct ? PSTR("ct") : PSTR("hs")); } if (LST_RGB <= local_light_subtype) { // colors if (prev_x_str[0] && prev_y_str[0]) { @@ -680,7 +680,7 @@ void HueGlobalConfig(String *path) { #endif // USE_ZIGBEE response += F("},\"groups\":{},\"schedules\":{},\"config\":"); HueConfigResponse(&response); - response += "}"; + response += F("}"); WSSend(200, CT_JSON, response); } @@ -700,7 +700,7 @@ void CheckHue(String * response, bool &appending) { for (uint32_t i = 1; i <= maxhue; i++) { if (HueActive(i)) { if (appending) { *response += ","; } - *response += "\""; + *response += F("\""); *response += EncodeLightId(i); *response += F("\":{\"state\":"); HueLightStatus1(i, response); @@ -735,7 +735,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { on = hue_on.getBool(); snprintf_P(buf, buf_size, msg[HUE_RESP_ON], - device_id, on ? "true" : "false"); + device_id, on ? PSTR("true") : PSTR("false")); #ifdef USE_SHUTTER if (ShutterState(device)) { @@ -778,7 +778,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "bri", bri); + device_id, PSTR("bri"), bri); response += buf; if (LST_SINGLE <= Light.subtype) { // extend bri value if set to max @@ -824,7 +824,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "hue", hue); + device_id, PSTR("hue"), hue); response += buf; if (LST_RGB <= Light.subtype) { // change range from 0..65535 to 0..360 @@ -843,7 +843,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "sat", sat); + device_id, PSTR("sat"), sat); response += buf; if (LST_RGB <= Light.subtype) { // extend sat value if set to max @@ -862,7 +862,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "ct", ct); + device_id, PSTR("ct"), ct); response += buf; if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { g_gotct = true; @@ -923,7 +923,7 @@ void HueLights(String *path) path->remove(0,path->indexOf(F("/lights"))); // Remove until /lights if (path->endsWith(F("/lights"))) { // Got /lights - response = "{"; + response = F("{"); bool appending = false; #ifdef USE_LIGHT CheckHue(&response, appending); @@ -934,7 +934,7 @@ void HueLights(String *path) #ifdef USE_SCRIPT_HUE Script_Check_Hue(&response); #endif - response += "}"; + response += F("}"); } else if (path->endsWith(F("/state"))) { // Got ID/state path->remove(0,8); // Remove /lights/ @@ -992,7 +992,7 @@ void HueLights(String *path) #endif // USE_LIGHT } else { - response = "{}"; + response = F("{}"); code = 406; } exit: @@ -1005,24 +1005,24 @@ void HueGroups(String *path) /* * http://tasmota/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"}) */ - String response = "{}"; + String response(F("{}")); uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups (%s)"), path->c_str()); - if (path->endsWith("/0")) { + if (path->endsWith(F("/0"))) { UnishoxStrings msg(HUE_LIGHTS); response = msg[HUE_GROUP0_STATUS_JSON]; String lights = F("\"1\""); for (uint32_t i = 2; i <= maxhue; i++) { - lights += ",\""; + lights += F(",\""); lights += EncodeLightId(i); - lights += "\""; + lights += F("\""); } #ifdef USE_ZIGBEE ZigbeeHueGroups(&response); #endif // USE_ZIGBEE - response.replace("{l1", lights); + response.replace(F("{l1"), lights); #ifdef USE_LIGHT HueLightStatus1(1, &response); #endif // USE_LIGHT diff --git a/tasmota/xdrv_23_zigbee_1z_libs.ino b/tasmota/xdrv_23_zigbee_1z_libs.ino index 4e018a21e..a228798e2 100644 --- a/tasmota/xdrv_23_zigbee_1z_libs.ino +++ b/tasmota/xdrv_23_zigbee_1z_libs.ino @@ -579,7 +579,7 @@ String Z_attribute::toString(bool prefix_comma) const { // value part switch (type) { case Za_type::Za_none: - res += "null"; + res += F("null"); break; case Za_type::Za_bool: res += val.uval32 ? F("true") : F("false"); @@ -638,7 +638,9 @@ String Z_attribute::toString(bool prefix_comma) const { if (val.arrval) { res += val.arrval->toString(); } else { - res += "[]"; + // res += '['; + // res += ']'; + res += F("[]"); } break; } diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino index 7d850ef5a..55a98a748 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino @@ -556,7 +556,7 @@ void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_l if (Settings.flag5.zb_received_as_subtopic) GetTopic_P(stopic, TELE, subtopic, json_prefix); else - GetTopic_P(stopic, TELE, subtopic, D_RSLT_SENSOR); + GetTopic_P(stopic, TELE, subtopic, PSTR(D_RSLT_SENSOR)); MqttPublish(stopic, Settings.flag.mqtt_sensor_retain); } else { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index a77c8b67f..d71a8c3a9 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -62,13 +62,13 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri const size_t buf_size = 256; char * buf = (char*) malloc(buf_size); // temp buffer for strings, avoid stack - snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), power ? "true" : "false"); + snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), power ? PSTR("true") : PSTR("false")); // Brightness for all devices with PWM if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { // force dimmer for 1st gen Echo snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); } if (LST_COLDWARM <= local_light_subtype) { - snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, (0 == colormode) ? "hs" : (1 == colormode) ? "xy" : "ct"); + snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, (0 == colormode) ? PSTR("hs") : (1 == colormode) ? PSTR("xy") : PSTR("ct")); } if (LST_RGB <= local_light_subtype) { // colors if (prev_x_str[0] && prev_y_str[0]) { @@ -83,7 +83,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { // white temp snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); } - snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE, buf, reachable ? "true" : "false"); + snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE, buf, reachable ? PSTR("true") : PSTR("false")); *response += buf; free(buf); @@ -233,7 +233,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { on = hue_on.getBool(); snprintf_P(buf, buf_size, msg[HUE_RESP_ON], - device_id, on ? "true" : "false"); + device_id, on ? PSTR("true") : PSTR("false")); if (on) { ZigbeeHuePower(shortaddr, 0x01); @@ -252,7 +252,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "bri", bri); + device_id, PSTR("bri"), bri); response += buf; if (LST_SINGLE <= bulbtype) { // extend bri value if set to max @@ -293,7 +293,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "hue", hue); + device_id, PSTR("hue"), hue); response += buf; if (LST_RGB <= bulbtype) { // change range from 0..65535 to 0..360 @@ -311,7 +311,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "sat", sat); + device_id, PSTR("sat"), sat); response += buf; if (LST_RGB <= bulbtype) { // extend sat value if set to max @@ -332,7 +332,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { if (resp) { response += ","; } snprintf_P(buf, buf_size, msg[HUE_RESP_NUM], - device_id, "ct", ct); + device_id, PSTR("ct"), ct); response += buf; if ((LST_COLDWARM == bulbtype) || (LST_RGBW <= bulbtype)) { ZigbeeHueCT(shortaddr, ct); diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index ec9a454ac..673f1ff8d 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -2092,7 +2092,7 @@ void ZigbeeMapRefresh(void) { if ((!zigbee.init_phase) && (!zigbee.mapping_in_progress)) { ZigbeeMapAllDevices(); } - Webserver->sendHeader("Location","/zbm"); // Add a header to respond with a new location for the browser to go to the home page again + Webserver->sendHeader(F("Location"),F("/zbm")); // Add a header to respond with a new location for the browser to go to the home page again Webserver->send(302); } diff --git a/tasmota/xdrv_38_ping.ino b/tasmota/xdrv_38_ping.ino index 3f87a54bb..0974697fe 100644 --- a/tasmota/xdrv_38_ping.ino +++ b/tasmota/xdrv_38_ping.ino @@ -303,7 +303,7 @@ void PingResponsePoll(void) { ",\"AvgTime\":%d" "}}}"), ping->hostname.c_str(), - success ? "true" : "false", + success ? PSTR("true") : PSTR("false"), ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, success, ping->timeout_count, diff --git a/tasmota/xdrv_40_telegram.ino b/tasmota/xdrv_40_telegram.ino index ec230e792..0ceefa3a7 100644 --- a/tasmota/xdrv_40_telegram.ino +++ b/tasmota/xdrv_40_telegram.ino @@ -434,14 +434,14 @@ void CmndTmChatId(void) { void CmndTmSend(void) { if (!Telegram.send_enable || !strlen(SettingsText(SET_TELEGRAM_CHATID))) { - ResponseCmndChar(D_JSON_FAILED); + ResponseCmndChar(PSTR(D_JSON_FAILED)); return; } if (XdrvMailbox.data_len > 0) { String message = XdrvMailbox.data; String chat_id = SettingsText(SET_TELEGRAM_CHATID); if (!TelegramSendMessage(chat_id.toInt(), message)) { - ResponseCmndChar(D_JSON_FAILED); + ResponseCmndChar(PSTR(D_JSON_FAILED)); return; } } diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index fb12e3b9d..dfca83cef 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -391,7 +391,7 @@ void UFSDelete(void) { result = (ufs_type && ufsp->remove(XdrvMailbox.data)); } if (!result) { - ResponseCmndChar(D_JSON_FAILED); + ResponseCmndChar(PSTR(D_JSON_FAILED)); } else { ResponseCmndDone(); } @@ -454,8 +454,8 @@ void UfsDirectory(void) { strcpy(ufs_path, "/"); - if (Webserver->hasArg("download")) { - String stmp = Webserver->arg("download"); + if (Webserver->hasArg(F("download"))) { + String stmp = Webserver->arg(F("download")); char *cp = (char*)stmp.c_str(); if (UfsDownloadFile(cp)) { // is directory @@ -465,8 +465,8 @@ void UfsDirectory(void) { } } - if (Webserver->hasArg("dir")) { - String stmp = Webserver->arg("dir"); + if (Webserver->hasArg(F("dir"))) { + String stmp = Webserver->arg(F("dir")); ufs_dir = atoi(stmp.c_str()); if (ufs_dir == 1) { dfsp = ufsp; @@ -477,8 +477,8 @@ void UfsDirectory(void) { } } - if (Webserver->hasArg("delete")) { - String stmp = Webserver->arg("delete"); + if (Webserver->hasArg(F("delete"))) { + String stmp = Webserver->arg(F("delete")); char *cp = (char*)stmp.c_str(); dfsp->remove(cp); } @@ -498,7 +498,7 @@ void UfsDirectory(void) { } WSContentSend_P(UFS_FORM_FILE_UPGc2); - WSContentSend_P(UFS_FORM_FILE_UPG, D_SCRIPT_UPLOAD); + WSContentSend_P(UFS_FORM_FILE_UPG, PSTR(D_SCRIPT_UPLOAD)); WSContentSend_P(UFS_FORM_SDC_DIRa); if (ufs_type) { @@ -516,7 +516,7 @@ void UfsListDir(char *path, uint8_t depth) { char name[32]; char npath[128]; char format[12]; - sprintf(format, "%%-%ds", 24 - depth); + sprintf(format, PSTR("%%-%ds"), 24 - depth); File dir = dfsp->open(path, UFS_FILE_READ); if (dir) { @@ -533,7 +533,7 @@ void UfsListDir(char *path, uint8_t depth) { break; } } - WSContentSend_P(UFS_FORM_SDC_DIRd, npath, path, ".."); + WSContentSend_P(UFS_FORM_SDC_DIRd, npath, path, PSTR("..")); } char *ep; while (true) { @@ -764,13 +764,13 @@ bool Xdrv50(uint8_t function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_MANAGEMENT_BUTTON: if (ufs_type) { - WSContentSend_PD(UFS_WEB_DIR, D_MANAGE_FILE_SYSTEM); + WSContentSend_PD(UFS_WEB_DIR, PSTR(D_MANAGE_FILE_SYSTEM)); } break; case FUNC_WEB_ADD_HANDLER: - Webserver->on("/ufsd", UfsDirectory); - Webserver->on("/ufsu", HTTP_GET, UfsDirectory); - Webserver->on("/ufsu", HTTP_POST,[](){Webserver->sendHeader("Location","/ufsu");Webserver->send(303);}, HandleUploadLoop); + Webserver->on(F("/ufsd"), UfsDirectory); + Webserver->on(F("/ufsu"), HTTP_GET, UfsDirectory); + Webserver->on(F("/ufsu"), HTTP_POST,[](){Webserver->sendHeader(F("Location"),F("/ufsu"));Webserver->send(303);}, HandleUploadLoop); break; #endif // USE_WEBSERVER } diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index 4f22d7cca..7dc9da3d7 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -241,7 +241,7 @@ bool HxCommand(void) break; case 7: // WeightSave Settings.energy_frequency_calibration = Hx.weight; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, PSTR(D_JSON_DONE)); break; case 8: // Json on weight change if (strchr(XdrvMailbox.data, ',') != nullptr) {