From 7c71c3bdd87482968f57803db89ea76a12cc1660 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 24 Sep 2021 11:34:44 +0200 Subject: [PATCH] Add command ``WebQuery GET|POST|PUT|PATCH [] `` Add command ``WebQuery GET|POST|PUT|PATCH [] `` to extent HTTP requests (#13209) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/i18n.h | 1 + tasmota/xdrv_01_webserver.ino | 86 ++++++++++++++++++++++++++++++----- 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5fcf2f94..904543dc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - Berry support for Serial - Support for Sensirion SCD40/SCD41 CO2 sensor (#13139) - Support for BL0939 energy monitor as used in ESP32 based Sonoff Dual R3 V2 Pow (#13195) +- Command ``WebQuery GET|POST|PUT|PATCH [] `` to extent HTTP requests (#13209) ### Changed - M5 Stack Core2 uses UNIVERSAL_DISPLAY with enabled LVGL as default now diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6909a665d..2f78e5dca 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -107,6 +107,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Command ``SetSensor1..127 0|1`` to globally disable individual sensor driver - Command ``Subscribe2 ...`` to subscribe to a MQTT topic without appended "/#" [#12858](https://github.com/arendst/Tasmota/issues/12858) - Command ``WebGetConfig `` if ``#define USE_WEBGETCONFIG`` is enabled to restore/init configuration from external webserver [#13034](https://github.com/arendst/Tasmota/issues/13034) +- Command ``WebQuery GET|POST|PUT|PATCH [] `` to extent HTTP requests [#13209](https://github.com/arendst/Tasmota/issues/13209) - Optional IP filter to command ``TCPStart`` [#12806](https://github.com/arendst/Tasmota/issues/12806) - Neopool commands ``NPPHRes``, ``NPCLRes`` and ``NPIonRes`` [#12813](https://github.com/arendst/Tasmota/issues/12813) - Support for second DNS server diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 507e856f8..41c52f10b 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -415,6 +415,7 @@ #define D_CMND_WEBLOG "WebLog" #define D_CMND_WEBREFRESH "WebRefresh" #define D_CMND_WEBSEND "WebSend" +#define D_CMND_WEBQUERY "WebQuery" #define D_CMND_WEBCOLOR "WebColor" #define D_CMND_WEBBUTTON "WebButton" #define D_CMND_WEBSENSOR "WebSensor" diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 9d7feaf9f..58baf3a53 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -3098,14 +3098,67 @@ int WebSend(char *buffer) } url += F("cmnd="); // url = |http://192.168.178.86/cm?cmnd=| or |http://192.168.178.86/cm?user=admin&password=joker&cmnd=| } - url += command; // url = |http://192.168.178.86/cm?cmnd=POWER1 ON| + url += UrlEncode(command); // url = |http://192.168.178.86/cm?cmnd=POWER1%20ON| + url += F(" GET"); // url = |http://192.168.178.86/cm?cmnd=POWER1%20ON GET| - DEBUG_CORE_LOG(PSTR("WEB: Uri |%s|"), url.c_str()); + DEBUG_CORE_LOG(PSTR("WEB: Uri '%s'"), url.c_str()); + status = WebQuery(const_cast(url.c_str())); + } + return status; +} + +int WebQuery(char *buffer) +{ + // http://192.168.1.1/path GET -> Sends HTTP GET http://192.168.1.1/path + // http://192.168.1.1/path POST {"some":"message"} -> Sends HTTP POST to http://192.168.1.1/path with body {"some":"message"} + // http://192.168.1.1/path PUT [Autorization: Bearer abcdxyz] potato -> Sends HTTP PUT to http://192.168.1.1/path with authorization header and body "potato" + // http://192.168.1.1/path PATCH patchInfo -> Sends HTTP PATCH to http://192.168.1.1/path with body "potato" + + // Valid HTTP Commands: GET, POST, PUT, and PATCH + // An unlimited number of headers can be sent per request, and a body can be sent for all command types + // The body will be ignored if sending a GET command + + WiFiClient http_client; + HTTPClient http; + + int status = WEBCMND_WRONG_PARAMETERS; + + char *temp; + char *url = strtok_r(buffer, " ", &temp); + char *method = strtok_r(temp, " ", &temp); + + if (url && method) { + if (http.begin(http_client, UrlEncode(url))) { + char empty_body[1] = { 0 }; + char *body = empty_body; + if (temp) { // There is a body and/or header + if (temp[0] == '[') { // Header information was sent; decode it + temp += 1; + temp = strtok_r(temp, "]", &body); + bool headerFound = true; + while (headerFound) { + char *header = strtok_r(temp, ":", &temp); + if (header) { + char *headerBody = strtok_r(temp, "|", &temp); + if (headerBody) { + http.addHeader(header, headerBody); + } + else headerFound = false; + } + else headerFound = false; + } + } else { // No header information was sent, but there was a body + body = temp; + } + } + + int http_code; + if (0 == strcasecmp_P(method, PSTR("GET"))) { http_code = http.GET(); } + else if (0 == strcasecmp_P(method, PSTR("POST"))) { http_code = http.POST(body); } + else if (0 == strcasecmp_P(method, PSTR("PUT"))) { http_code = http.PUT(body); } + else if (0 == strcasecmp_P(method, PSTR("PATCH"))) { http_code = http.PATCH(body); } + else return status; - WiFiClient http_client; - HTTPClient http; - if (http.begin(http_client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| - int http_code = http.GET(); // Start connection and send HTTP header if (http_code > 0) { // http_code will be negative on error if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { #ifdef USE_WEBSEND_RESPONSE @@ -3125,7 +3178,7 @@ int WebSend(char *buffer) // recursive call must be possible in this case tasm_cmd_activ = 0; #endif // USE_SCRIPT - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_WEBQUERY)); #endif // USE_WEBSEND_RESPONSE } status = WEBCMND_DONE; @@ -3240,8 +3293,8 @@ const char kWebCommands[] PROGMEM = "|" // No prefix #if defined(USE_SENDMAIL) || defined(USE_ESP32MAIL) D_CMND_SENDMAIL "|" #endif - D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" - D_CMND_WEBSENSOR "|" D_CMND_WEBBUTTON + D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBQUERY "|" + D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR "|" D_CMND_WEBBUTTON #ifdef USE_WEBGETCONFIG "|" D_CMND_WEBGETCONFIG #endif @@ -3257,8 +3310,8 @@ void (* const WebCommand[])(void) PROGMEM = { #if defined(USE_SENDMAIL) || defined(USE_ESP32MAIL) &CmndSendmail, #endif - &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, - &CmndWebSensor, &CmndWebButton + &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebQuery, + &CmndWebColor, &CmndWebSensor, &CmndWebButton #ifdef USE_WEBGETCONFIG , &CmndWebGetConfig #endif @@ -3359,6 +3412,15 @@ void CmndWebSend(void) } } +void CmndWebQuery(void) +{ + if (XdrvMailbox.data_len > 0) { + uint32_t result = WebQuery(XdrvMailbox.data); + char stemp1[20]; + ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebCmndStatus)); + } +} + #ifdef USE_WEBGETCONFIG void CmndWebGetConfig(void) { @@ -3519,4 +3581,4 @@ bool Xdrv01(uint8_t function) } return result; } -#endif // USE_WEBSERVER +#endif // USE_WEBSERVER \ No newline at end of file