From 4060dad689a1883368396c673bd619c146a1bb05 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Mon, 23 Oct 2023 19:18:53 +0200 Subject: [PATCH 01/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index f165cf40f2..ed109c32cf 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1544,6 +1544,11 @@ int http_authenticate(const String& logIdentifier, event += '='; event += httpCode; eventQueue.addMove(std::move(event)); + String revent = F("reply#"); + revent += host; + revent += '='; + revent += http.getString().substring(0, 21); + eventQueue.addMove(std::move(revent)); } #ifndef BUILD_NO_DEBUG log_http_result(http, logIdentifier, host + ':' + port, HttpMethod, httpCode, EMPTY_STRING); From bb5ac3e626ac86118960920ffe833b8116736f6e Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 12:52:21 +0200 Subject: [PATCH 02/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index ed109c32cf..9487dc1649 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1543,10 +1543,19 @@ int http_authenticate(const String& logIdentifier, event += host; event += '='; event += httpCode; + // Generate event with the response of a + // one value one channel tingspeak request + // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) + // where first eventvalue is the channel number, the second the field number + // and the third is the value received by the request eventQueue.addMove(std::move(event)); String revent = F("reply#"); revent += host; revent += '='; + revent += uri.substring(0, uri.length() - 14).substring(10, uri.length()); //get the channel number + revent += ','; + revent += uri.substring(uri.length() - 6, uri.length() - 5); //get the field number + revent += ','; revent += http.getString().substring(0, 21); eventQueue.addMove(std::move(revent)); } From 425aec46c5d8806d2276f8c6b10454f42fe135fb Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:02:07 +0200 Subject: [PATCH 03/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 9487dc1649..64eef54ca3 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1543,12 +1543,13 @@ int http_authenticate(const String& logIdentifier, event += host; event += '='; event += httpCode; - // Generate event with the response of a + eventQueue.addMove(std::move(event)); + // Generate event with the response of a // one value one channel tingspeak request // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) // where first eventvalue is the channel number, the second the field number // and the third is the value received by the request - eventQueue.addMove(std::move(event)); + if (equals(host, F("api.thingspeak.com"))) { String revent = F("reply#"); revent += host; revent += '='; @@ -1558,6 +1559,7 @@ int http_authenticate(const String& logIdentifier, revent += ','; revent += http.getString().substring(0, 21); eventQueue.addMove(std::move(revent)); + } } #ifndef BUILD_NO_DEBUG log_http_result(http, logIdentifier, host + ':' + port, HttpMethod, httpCode, EMPTY_STRING); From db1d7d9b15919a1a02084c0bb95a53588faeb4e9 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:36:02 +0200 Subject: [PATCH 04/22] make thinkspeak event optional --- src/Custom-sample.h | 1 + src/src/Helpers/Networking.cpp | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Custom-sample.h b/src/Custom-sample.h index f6ff28e00a..a1bbdbd247 100644 --- a/src/Custom-sample.h +++ b/src/Custom-sample.h @@ -25,6 +25,7 @@ #define FEATURE_RULES_EASY_COLOR_CODE 1 // Use code highlighting, autocompletion and command suggestions in Rules #define FEATURE_ESPEASY_P2P 1 // (1/0) enables the ESP Easy P2P protocol #define FEATURE_ARDUINO_OTA 1 //enables the Arduino OTA capabilities +#define FEATURE_THINGSPEAK_EVENT 1 // generate an event when requesting last value of a field in thingspeak via SendToHTTP(e.g. sendToHTTP,api.thingspeak.com,80,/channels/1667332/fields/5/last) // #define FEATURE_SD 1 // Enable SD card support // #define FEATURE_DOWNLOAD 1 // Enable downloading a file from an url diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 64eef54ca3..8e7733f112 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1549,18 +1549,21 @@ int http_authenticate(const String& logIdentifier, // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) // where first eventvalue is the channel number, the second the field number // and the third is the value received by the request - if (equals(host, F("api.thingspeak.com"))) { - String revent = F("reply#"); - revent += host; - revent += '='; - revent += uri.substring(0, uri.length() - 14).substring(10, uri.length()); //get the channel number - revent += ','; - revent += uri.substring(uri.length() - 6, uri.length() - 5); //get the field number - revent += ','; - revent += http.getString().substring(0, 21); - eventQueue.addMove(std::move(revent)); - } + #if FEATURE_THINGSPEAK_EVENT + if (equals(host, F("api.thingspeak.com"))) { + String revent = F("reply#"); + revent += host; + revent += '='; + revent += uri.substring(0, uri.length() - 14).substring(10, uri.length()); //get the channel number + revent += ','; + revent += uri.substring(uri.length() - 6, uri.length() - 5); //get the field number + revent += ','; + revent += http.getString().substring(0, 21); + eventQueue.addMove(std::move(revent)); + } + #endif } + #ifndef BUILD_NO_DEBUG log_http_result(http, logIdentifier, host + ':' + port, HttpMethod, httpCode, EMPTY_STRING); #endif From 6b5e24941e374b630850de09970ae32eb228f57b Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:50:09 +0200 Subject: [PATCH 05/22] compare also the last part of the uri to generate an event --- src/src/Helpers/Networking.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 8e7733f112..45dd320621 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1544,13 +1544,13 @@ int http_authenticate(const String& logIdentifier, event += '='; event += httpCode; eventQueue.addMove(std::move(event)); - // Generate event with the response of a - // one value one channel tingspeak request - // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) - // where first eventvalue is the channel number, the second the field number - // and the third is the value received by the request #if FEATURE_THINGSPEAK_EVENT - if (equals(host, F("api.thingspeak.com"))) { + // Generate event with the response of a + // one value one channel tingspeak request + // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) + // where first eventvalue is the channel number, the second the field number + // and the third is the value received by the request + if (equals(host, F("api.thingspeak.com")) && equals(uri.substring(uri.length() - 5, uri.length()), F("/last"))) { String revent = F("reply#"); revent += host; revent += '='; From fb0f8ed1bf2864555ca59c1fb8f151b930c0a3a2 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:42:04 +0200 Subject: [PATCH 06/22] add check if we got an answer otherwise we get -1 as a value --- src/src/Helpers/Networking.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 45dd320621..f40ff62799 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1550,7 +1550,7 @@ int http_authenticate(const String& logIdentifier, // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) // where first eventvalue is the channel number, the second the field number // and the third is the value received by the request - if (equals(host, F("api.thingspeak.com")) && equals(uri.substring(uri.length() - 5, uri.length()), F("/last"))) { + if (equals(host, F("api.thingspeak.com")) && equals(uri.substring(uri.length() - 5, uri.length()), F("/last")) && httpCode == 200) { String revent = F("reply#"); revent += host; revent += '='; From 197dc102c35c81a2eea9d0bed5000d5d1302efac Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:16:09 +0200 Subject: [PATCH 07/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index f40ff62799..1910b25cd7 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1546,20 +1546,25 @@ int http_authenticate(const String& logIdentifier, eventQueue.addMove(std::move(event)); #if FEATURE_THINGSPEAK_EVENT // Generate event with the response of a - // one value one channel tingspeak request + // "last-value-of-field" tingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html) // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) // where first eventvalue is the channel number, the second the field number // and the third is the value received by the request - if (equals(host, F("api.thingspeak.com")) && equals(uri.substring(uri.length() - 5, uri.length()), F("/last")) && httpCode == 200) { - String revent = F("reply#"); - revent += host; - revent += '='; - revent += uri.substring(0, uri.length() - 14).substring(10, uri.length()); //get the channel number - revent += ','; - revent += uri.substring(uri.length() - 6, uri.length() - 5); //get the field number - revent += ','; - revent += http.getString().substring(0, 21); - eventQueue.addMove(std::move(revent)); + // Example of received reply: "HTTP : SendToHTTP api.thingspeak.com GETHTTP code: 200 Received reply: 24.2" + // Example of the event: "EVENT: reply#thingspeak=1637928,5,24.2" + // ^ ^ ^ + // channel number ┘ | └ received value + // field number + if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last"))) { + String revent = F("reply#thingspeak"); + //revent += host; + revent += '='; + revent += uri.substring(10, uri.length() - 14);; //get the channel number + revent += ','; + revent += uri.substring(uri.length() - 6, uri.length() - 5); //get the field number + revent += ','; + revent += http.getString().substring(0, 21); + eventQueue.addMove(std::move(revent)); } #endif } From 4c934d4657406b762b3c44c78d629f3934074490 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:48:39 +0200 Subject: [PATCH 08/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 1910b25cd7..adf86dd67a 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1555,13 +1555,13 @@ int http_authenticate(const String& logIdentifier, // ^ ^ ^ // channel number ┘ | └ received value // field number + // In rules you can grep the reply by "On ThingspeakReply# Do ..." if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last"))) { - String revent = F("reply#thingspeak"); - //revent += host; + String revent = F("ThingspeakReply#"); revent += '='; - revent += uri.substring(10, uri.length() - 14);; //get the channel number + revent += parseString(uri.c_str(), 2, '/');; //get the channel number revent += ','; - revent += uri.substring(uri.length() - 6, uri.length() - 5); //get the field number + revent += parseString(uri.c_str(), 4, '/');; //get the field number revent += ','; revent += http.getString().substring(0, 21); eventQueue.addMove(std::move(revent)); From 4ad08ac11db7db177dbef88a28bc2003368cc173 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 17:18:31 +0200 Subject: [PATCH 09/22] Update define_plugin_sets.h --- src/src/CustomBuild/define_plugin_sets.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 8e5333fec7..94915a6305 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -181,6 +181,13 @@ To create/register a plugin, you have to : #define FEATURE_NO_HTTP_CLIENT 0 #endif +#ifndef FEATURE_THINGSPEAK_EVENT + #ifdef LIMIT_BUILD_SIZE + #define FEATURE_THINGSPEAK_EVENT 0 + #else + #define FEATURE_THINGSPEAK_EVENT 1 + #endif +#endif /******************************************************************************\ * BUILD Configs ************************************************************** From ad5e2eaaad2abb4c0e34b3ad53f71b97f0964ba8 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 17:24:21 +0200 Subject: [PATCH 10/22] Update define_plugin_sets.h --- src/src/CustomBuild/define_plugin_sets.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 94915a6305..aee9f7ba79 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -181,13 +181,6 @@ To create/register a plugin, you have to : #define FEATURE_NO_HTTP_CLIENT 0 #endif -#ifndef FEATURE_THINGSPEAK_EVENT - #ifdef LIMIT_BUILD_SIZE - #define FEATURE_THINGSPEAK_EVENT 0 - #else - #define FEATURE_THINGSPEAK_EVENT 1 - #endif -#endif /******************************************************************************\ * BUILD Configs ************************************************************** @@ -3185,7 +3178,12 @@ To create/register a plugin, you have to : #endif #endif - - + #ifndef FEATURE_THINGSPEAK_EVENT + #ifdef LIMIT_BUILD_SIZE + #define FEATURE_THINGSPEAK_EVENT 0 + #else + #define FEATURE_THINGSPEAK_EVENT 1 + #endif + #endif #endif // CUSTOMBUILD_DEFINE_PLUGIN_SETS_H From 1ef66a487a3e70b04eb3d470cf8400fe04987d0c Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 20:49:18 +0200 Subject: [PATCH 11/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index adf86dd67a..0dfdcb0ee5 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1551,13 +1551,13 @@ int http_authenticate(const String& logIdentifier, // where first eventvalue is the channel number, the second the field number // and the third is the value received by the request // Example of received reply: "HTTP : SendToHTTP api.thingspeak.com GETHTTP code: 200 Received reply: 24.2" - // Example of the event: "EVENT: reply#thingspeak=1637928,5,24.2" - // ^ ^ ^ - // channel number ┘ | └ received value - // field number - // In rules you can grep the reply by "On ThingspeakReply# Do ..." + // Example of the event: "EVENT: ThingspeakReply=1637928,5,24.2" + // ^ ^ ^ + // channel number ┘ | └ received value + // field number + // In rules you can grep the reply by "On ThingspeakReply Do ..." if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last"))) { - String revent = F("ThingspeakReply#"); + String revent = F("ThingspeakReply"); revent += '='; revent += parseString(uri.c_str(), 2, '/');; //get the channel number revent += ','; From 5a689b2a19bce5d7fe68094e4c5bcd20882d10f6 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 21:02:43 +0200 Subject: [PATCH 12/22] Add ThingspeakReply to wordlist --- static/espeasy.js | 2 +- static/espeasy.min.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/espeasy.js b/static/espeasy.js index 0484333552..41e7fc5340 100644 --- a/static/espeasy.js +++ b/static/espeasy.js @@ -8,7 +8,7 @@ var commonCommands = ["AccessInfo", "Background", "Build", "ClearAccessBlock", " "ControllerEnable", "DateTime", "Debug", "Dec", "DeepSleep", "DisablePriorityTask", "DNS", "DST", "EraseSDKWiFi", "ExecuteRules", "Gateway", "I2Cscanner", "Inc", "IP", "Let", "Load", "LogEntry", "LogPortStatus", "LoopTimerSet", "LoopTimerSet_ms", "MemInfo", "MemInfoDetail", "Name", "Password", "PostToHTTP", "Publish", "Reboot", "Reset", "Save", "SendTo", "SendToHTTP", "SendToUDP", "Settings", "Subnet", "Subscribe", "TaskClear", "TaskClearAll", - "TaskDisable", "TaskEnable", "TaskRun", "TaskValueSet", "TaskValueSetAndRun", "TimerPause", "TimerResume", "TimerSet", "TimerSet_ms", "TimeZone", + "TaskDisable", "TaskEnable", "TaskRun", "TaskValueSet", "TaskValueSetAndRun", "ThingspeakReply", "TimerPause", "TimerResume", "TimerSet", "TimerSet_ms", "TimeZone", "UdpPort", "UdpTest", "Unit", "UseNTP", "WdConfig", "WdRead", "WiFi", "WiFiAPkey", "WiFiAllowAP", "WiFiAPMode", "WiFiConnect", "WiFiDisconnect", "WiFiKey", "WiFiKey2", "WiFiScan", "WiFiSSID", "WiFiSSID2", "WiFiSTAMode", "WiFi#Disconnected", "Event", "AsyncEvent", diff --git a/static/espeasy.min.js b/static/espeasy.min.js index b625acaf21..015b3d9a76 100644 --- a/static/espeasy.min.js +++ b/static/espeasy.min.js @@ -1 +1 @@ -var rEdit,commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","Reboot","Reset","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAPkey","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","WiFi#Disconnected","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor",],commonString2=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup",],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544",],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn"],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","substring","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","var","int"];for(const element2 of pluginDispKind)commonPlugins=commonPlugins.concat(element2);for(const element2 of pluginDispKind)for(const element3 of pluginDispCmd){let e=element2+element3;commonPlugins=commonPlugins.concat(e)}var EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonString2,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab(e){"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",function(){rEdit.save()}),rEdit.on("inputRead",function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})})}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("espeasy",function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase());commonCommands=commonCommands.concat(n);var o=commonString2.map(e=>e.toLowerCase());commonString2=commonString2.concat(o);var i=commonPlugins.map(e=>e.toLowerCase());commonPlugins=commonPlugins.concat(i);var a=commonAtoms.map(e=>e.toLowerCase());commonAtoms=commonAtoms.concat(a);var r=commonKeywords.map(e=>e.toLowerCase());commonKeywords=commonKeywords.concat(r);var s=commonTag.map(e=>e.toLowerCase());commonTag=commonTag.concat(s);var c=commonNumber.map(e=>e.toLowerCase());commonNumber=commonNumber.concat(c);var m=commonMath.map(e=>e.toLowerCase());commonMath=commonMath.concat(m);var l=AnythingElse.map(e=>e.toLowerCase());AnythingElse=AnythingElse.concat(l);var d=taskSpecifics.map(e=>e.toLowerCase());function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(let i of EXTRAWORDS){let a=i.substring(1);(i.includes(":")||i.includes(",")||i.includes("."))&&t.match(a)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var r=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"string-2"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(r)?e[r]:null}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("string-2",commonString2),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){var n,o;return n=e,((o=t).tokens[0]||u)(n,o)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}(function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,function(t,n,r){r&&r!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(a(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))});var i={Backspace:function t(i){var a=s(i);if(!a||i.getOption("disableInput"))return e.Pass;for(var r=o(a,"pairs"),c=i.listSelections(),m=0;m=0;m--){var u=c[m].head;i.replaceRange("",n(u.line,u.ch-1),n(u.line,u.ch+1),"+delete")}},Enter:function t(n){var i=s(n),a=i&&o(i,"explode");if(!a||n.getOption("disableInput"))return e.Pass;for(var r=n.listSelections(),m=0;m=0&&i.getRange(y,n(y.line,y.ch+3))==a+a+a?"skipThree":"skip";else if(h&&y.ch>1&&p.indexOf(a)>=0&&i.getRange(n(y.line,y.ch-2),y)==a+a){if(y.ch>2&&/\bstring/.test(i.getTokenTypeAt(n(y.line,y.ch-2))))return e.Pass;P="addFour"}else if(h){var b=0==y.ch?" ":i.getRange(n(y.line,y.ch-1),y);if(e.isWordChar(M)||b==a||e.isWordChar(b))return e.Pass;P="both"}else{if(!(x&&(0===M.length||/\s/.test(M)||f.indexOf(M)>-1)))return e.Pass;P="both"}if(C){if(C!=P)return e.Pass}else C=P}var v=u%2?l.charAt(u-1):a,D=u%2?a:l.charAt(u+1);i.operation(function(){if("skip"==C)c(i,1);else if("skipThree"==C)c(i,3);else if("surround"==C){for(var e=i.getSelections(),t=0;t0?{line:r.head.line,ch:r.head.ch+t}:{line:r.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function m(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function l(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}a(t.pairs+"`")}); \ No newline at end of file +var commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","Reboot","Reset","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","ThingspeakReply","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAPkey","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","WiFi#Disconnected","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor"],commonString2=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup"],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544"],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn"],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","substring","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","var","int"];for(const e of pluginDispKind)commonPlugins=commonPlugins.concat(e);for(const e of pluginDispKind)for(const t of pluginDispCmd){let n=e+t;commonPlugins=commonPlugins.concat(n)}var rEdit,EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonString2,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab:e=>{"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",(function(){rEdit.save()})),rEdit.on("inputRead",(function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})}))}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}((function(e){"use strict";e.defineMode("espeasy",(function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase()));commonCommands=commonCommands.concat(n);var o=commonString2.map((e=>e.toLowerCase()));commonString2=commonString2.concat(o);var i=commonPlugins.map((e=>e.toLowerCase()));commonPlugins=commonPlugins.concat(i);var r=commonAtoms.map((e=>e.toLowerCase()));commonAtoms=commonAtoms.concat(r);var a=commonKeywords.map((e=>e.toLowerCase()));commonKeywords=commonKeywords.concat(a);var s=commonTag.map((e=>e.toLowerCase()));commonTag=commonTag.concat(s);var c=commonNumber.map((e=>e.toLowerCase()));commonNumber=commonNumber.concat(c);var m=commonMath.map((e=>e.toLowerCase()));commonMath=commonMath.concat(m);var l=AnythingElse.map((e=>e.toLowerCase()));AnythingElse=AnythingElse.concat(l);var d=taskSpecifics.map((e=>e.toLowerCase()));function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(const e of EXTRAWORDS){let n=e.substring(1);(e.includes(":")||e.includes(",")||e.includes("."))&&t.match(n)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var i=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"string-2"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(i)?e[i]:null}function f(e,t){return(t.tokens[0]||u)(e,t)}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("string-2",commonString2),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){return f(e,t)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}}))})),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}((function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,(function(t,n,a){a&&a!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(r(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))}));var i={Backspace:function(t){var i=s(t);if(!i||t.getOption("disableInput"))return e.Pass;for(var r=o(i,"pairs"),a=t.listSelections(),c=0;c=0;c--){var d=a[c].head;t.replaceRange("",n(d.line,d.ch-1),n(d.line,d.ch+1),"+delete")}},Enter:function(t){var n=s(t),i=n&&o(n,"explode");if(!i||t.getOption("disableInput"))return e.Pass;for(var r=t.listSelections(),a=0;a1&&p.indexOf(i)>=0&&t.getRange(n(M.line,M.ch-2),M)==i+i){if(M.ch>2&&/\bstring/.test(t.getTokenTypeAt(n(M.line,M.ch-2))))return e.Pass;S="addFour"}else if(h){var y=0==M.ch?" ":t.getRange(n(M.line,M.ch-1),M);if(e.isWordChar(T)||y==i||e.isWordChar(y))return e.Pass;S="both"}else{if(!x||!(0===T.length||/\s/.test(T)||f.indexOf(T)>-1))return e.Pass;S="both"}else S=h&&d(t,M)?"both":p.indexOf(i)>=0&&t.getRange(M,n(M.line,M.ch+3))==i+i+i?"skipThree":"skip";if(u){if(u!=S)return e.Pass}else u=S}var b=l%2?a.charAt(l-1):i,_=l%2?i:a.charAt(l+1);t.operation((function(){if("skip"==u)c(t,1);else if("skipThree"==u)c(t,3);else if("surround"==u){for(var e=t.getSelections(),n=0;n0?{line:a.head.line,ch:a.head.ch+t}:{line:a.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function m(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function l(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}r(t.pairs+"`")})); \ No newline at end of file From 89bf66c4003db1b1b9ccbf2765c1a0b53b97e6d8 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:08:10 +0200 Subject: [PATCH 13/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 0dfdcb0ee5..a33ac6031e 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1546,8 +1546,8 @@ int http_authenticate(const String& logIdentifier, eventQueue.addMove(std::move(event)); #if FEATURE_THINGSPEAK_EVENT // Generate event with the response of a - // "last-value-of-field" tingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html) - // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last) + // "last-value-of-field" thingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html) + // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last) // where first eventvalue is the channel number, the second the field number // and the third is the value received by the request // Example of received reply: "HTTP : SendToHTTP api.thingspeak.com GETHTTP code: 200 Received reply: 24.2" @@ -1557,14 +1557,10 @@ int http_authenticate(const String& logIdentifier, // field number // In rules you can grep the reply by "On ThingspeakReply Do ..." if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last"))) { - String revent = F("ThingspeakReply"); - revent += '='; - revent += parseString(uri.c_str(), 2, '/');; //get the channel number - revent += ','; - revent += parseString(uri.c_str(), 4, '/');; //get the field number - revent += ','; - revent += http.getString().substring(0, 21); - eventQueue.addMove(std::move(revent)); + eventQueue.add(strformat(F("ThingspeakReply=%s,%s,%s"), + parseStringKeepCase(uri, 2, '/').c_str(), + parseStringKeepCase(uri, 4, '/').c_str(), + http.getString().substring(0, 21).c_str())); } #endif } From 600367b3bb9986057b2e3863d28721bc66b11df6 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:31:26 +0200 Subject: [PATCH 14/22] Update Networking.cpp --- src/src/Helpers/Networking.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index a33ac6031e..f35e5abe9e 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1539,11 +1539,9 @@ int http_authenticate(const String& logIdentifier, if (Settings.UseRules) { // Generate event with the HTTP return code // e.g. http#hostname=401 - String event = F("http#"); - event += host; - event += '='; - event += httpCode; - eventQueue.addMove(std::move(event)); + eventQueue.add(strformat(F("http#%s=%s"), + host.c_str(), + httpCode)); #if FEATURE_THINGSPEAK_EVENT // Generate event with the response of a // "last-value-of-field" thingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html) From 99b8156ab3dd88c38783ff085ae2199cab9566c7 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 26 Oct 2023 10:08:01 +0200 Subject: [PATCH 15/22] added documentation --- docs/source/Rules/Rules.rst | 18 ++++++++++++++++++ src/src/Helpers/Networking.cpp | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/source/Rules/Rules.rst b/docs/source/Rules/Rules.rst index 6e5471b6a5..7276e8b84b 100644 --- a/docs/source/Rules/Rules.rst +++ b/docs/source/Rules/Rules.rst @@ -1958,6 +1958,24 @@ Added: 2022/07/23 * Host name can contain user credentials. For example: ``http://username:pass@hostname:portnr/foo.html`` * HTTP user credentials now can handle Basic Auth and Digest Auth. +Added: 2023/10/26 + +* ``SendToHTTP`` now generates an event with the response of a "last-value-of-field" thingspeak request (``https://de.mathworks.com/help/thingspeak/readlastfieldentry.html``) where the first eventvalue is the channel number, the second the field number and the third is the value received by the request. +* Example: ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` +* Example of the resulting event: ``"EVENT: ThingspeakReply=1637928,5,24.2"`` +* Example in Rules: + +.. code:: none + + on ThinkspeakReply do + LogEntry,'The channel number is: %eventvalue1%' + if %eventvalue2% = 5 //when the field number is 5 + LogEntry,'%eventvalue3%°C in Berlin' + elseif %eventvalue2% = 6 //when the field number is 6 + LogEntry,'%eventvalue3%°C in Paris' + endif + endon + Convert curl POST command to PostToHTTP --------------------------------------- diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index f35e5abe9e..e5b67d6208 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1539,7 +1539,7 @@ int http_authenticate(const String& logIdentifier, if (Settings.UseRules) { // Generate event with the HTTP return code // e.g. http#hostname=401 - eventQueue.add(strformat(F("http#%s=%s"), + eventQueue.add(strformat(F("http#%s=%d"), host.c_str(), httpCode)); #if FEATURE_THINGSPEAK_EVENT From 7d3763766857190c32342e848399560c77f8b776 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 26 Oct 2023 10:28:39 +0200 Subject: [PATCH 16/22] Update Rules.rst --- docs/source/Rules/Rules.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/Rules/Rules.rst b/docs/source/Rules/Rules.rst index 7276e8b84b..53e03f9a31 100644 --- a/docs/source/Rules/Rules.rst +++ b/docs/source/Rules/Rules.rst @@ -1961,7 +1961,7 @@ Added: 2022/07/23 Added: 2023/10/26 * ``SendToHTTP`` now generates an event with the response of a "last-value-of-field" thingspeak request (``https://de.mathworks.com/help/thingspeak/readlastfieldentry.html``) where the first eventvalue is the channel number, the second the field number and the third is the value received by the request. -* Example: ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` +* Example command: ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` * Example of the resulting event: ``"EVENT: ThingspeakReply=1637928,5,24.2"`` * Example in Rules: @@ -1969,7 +1969,7 @@ Added: 2023/10/26 on ThinkspeakReply do LogEntry,'The channel number is: %eventvalue1%' - if %eventvalue2% = 5 //when the field number is 5 + if %eventvalue2% = 5 //when the field number is 5 LogEntry,'%eventvalue3%°C in Berlin' elseif %eventvalue2% = 6 //when the field number is 6 LogEntry,'%eventvalue3%°C in Paris' From c9ef1514ea8d1d7c338ae65c2544c362276ef254 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 26 Oct 2023 20:41:49 +0200 Subject: [PATCH 17/22] single + multifield reply combined --- docs/source/Rules/Rules.rst | 35 +++++++++++++++++++++++++++---- src/src/Helpers/Networking.cpp | 38 +++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/docs/source/Rules/Rules.rst b/docs/source/Rules/Rules.rst index 53e03f9a31..947a2a50d6 100644 --- a/docs/source/Rules/Rules.rst +++ b/docs/source/Rules/Rules.rst @@ -1960,10 +1960,36 @@ Added: 2022/07/23 Added: 2023/10/26 -* ``SendToHTTP`` now generates an event with the response of a "last-value-of-field" thingspeak request (``https://de.mathworks.com/help/thingspeak/readlastfieldentry.html``) where the first eventvalue is the channel number, the second the field number and the third is the value received by the request. -* Example command: ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` -* Example of the resulting event: ``"EVENT: ThingspeakReply=1637928,5,24.2"`` -* Example in Rules: +* ``SendToHTTP`` now generates an event with the response of a thingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html & // https://de.mathworks.com/help/thingspeak/readdata.html) +* There are two options: + + 1. Get the value of a single field: + + - Example command: + ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` + - Example of the resulting event: + ``"EVENT: ThingspeakReply=1637928,5,24.2"`` + + channel number = ``%eventvalue1%`` + + field number = ``%eventvalue2%`` + + value = ``%eventvalue3%`` + + 2. Get the values of all fields: + + - Example command: + ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/feeds/last.csv`` + - Example of the resulting event: + ``"EVENT:ThingspeakReply=1637928,5929,353,42.0,177,19.1,995.6,,"`` + + channel number = ``%eventvalue1%`` + + values = ``%eventvalue3%`` to ``%eventvalue9%`` + +.. warning:: **Attention!** When using the command for all fields the reply can become extremely big and can lead to memory issues which results in instabilities of your device (especially when all eight fields a filled with very big numbers) + +* Example for two single field events in rules: .. code:: none @@ -1977,6 +2003,7 @@ Added: 2023/10/26 endon + Convert curl POST command to PostToHTTP --------------------------------------- diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index e5b67d6208..5ff6384fb6 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1544,21 +1544,31 @@ int http_authenticate(const String& logIdentifier, httpCode)); #if FEATURE_THINGSPEAK_EVENT // Generate event with the response of a - // "last-value-of-field" thingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html) - // e.g. (sendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last) - // where first eventvalue is the channel number, the second the field number - // and the third is the value received by the request - // Example of received reply: "HTTP : SendToHTTP api.thingspeak.com GETHTTP code: 200 Received reply: 24.2" - // Example of the event: "EVENT: ThingspeakReply=1637928,5,24.2" - // ^ ^ ^ - // channel number ┘ | └ received value - // field number + // thingspeak request (https://de.mathworks.com/help/thingspeak/readlastfieldentry.html & + // https://de.mathworks.com/help/thingspeak/readdata.html) + // e.g. command for a specific field: "sendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last.csv" + // command for all fields: "sendToHTTP,api.thingspeak.com,80,/channels/1637928/feeds/last.csv" + // where first eventvalue is the channel number and the second to the nineth event values + // are the field values + // Example of the event: "EVENT: ThingspeakReply=1637928,5,24.2,12,900,..." + // ^ ^ └------┬------┘ + // channel number ┘ | └ received values + // field number (only available for a "single-value-event") // In rules you can grep the reply by "On ThingspeakReply Do ..." - if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last"))) { - eventQueue.add(strformat(F("ThingspeakReply=%s,%s,%s"), - parseStringKeepCase(uri, 2, '/').c_str(), - parseStringKeepCase(uri, 4, '/').c_str(), - http.getString().substring(0, 21).c_str())); + + if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last.csv"))) { + String result = http.getString(); + const int posTimestamp = result.lastIndexOf(':'); + if (posTimestamp >= 0) { + result = parseStringToEndKeepCase(result.substring(posTimestamp), 3); + if (uri.indexOf(F("fields")) >= 0) { //when there is a single field call add the field number before the value + result = parseStringKeepCase(uri, 4, '/') + "," + result; + } + eventQueue.addMove(strformat( + F("ThingspeakReply=%s,%s"), + parseStringKeepCase(uri, 2, '/').c_str(), + result.c_str())); + } } #endif } From c6b96c5c74d2844431b2e858c5bf769edbf42e36 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 26 Oct 2023 21:07:48 +0200 Subject: [PATCH 18/22] Update Rules.rst --- docs/source/Rules/Rules.rst | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/docs/source/Rules/Rules.rst b/docs/source/Rules/Rules.rst index 947a2a50d6..fd3047a4d1 100644 --- a/docs/source/Rules/Rules.rst +++ b/docs/source/Rules/Rules.rst @@ -1968,13 +1968,11 @@ Added: 2023/10/26 - Example command: ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` - Example of the resulting event: - ``"EVENT: ThingspeakReply=1637928,5,24.2"`` - - channel number = ``%eventvalue1%`` - - field number = ``%eventvalue2%`` - - value = ``%eventvalue3%`` + ``"EVENT: ThingspeakReply=1637928,5,24.2"`` + + | channel number = ``%eventvalue1%`` + | field number = ``%eventvalue2%`` + | value = ``%eventvalue3%`` 2. Get the values of all fields: @@ -1983,9 +1981,8 @@ Added: 2023/10/26 - Example of the resulting event: ``"EVENT:ThingspeakReply=1637928,5929,353,42.0,177,19.1,995.6,,"`` - channel number = ``%eventvalue1%`` - - values = ``%eventvalue3%`` to ``%eventvalue9%`` + | channel number = ``%eventvalue1%`` + | values = ``%eventvalue3%`` to ``%eventvalue9%`` .. warning:: **Attention!** When using the command for all fields the reply can become extremely big and can lead to memory issues which results in instabilities of your device (especially when all eight fields a filled with very big numbers) From 065efcd8135886486fdebc6ea26c499d4c59e612 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 26 Oct 2023 21:09:27 +0200 Subject: [PATCH 19/22] Update Rules.rst --- docs/source/Rules/Rules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Rules/Rules.rst b/docs/source/Rules/Rules.rst index fd3047a4d1..cfff4306d0 100644 --- a/docs/source/Rules/Rules.rst +++ b/docs/source/Rules/Rules.rst @@ -1984,7 +1984,7 @@ Added: 2023/10/26 | channel number = ``%eventvalue1%`` | values = ``%eventvalue3%`` to ``%eventvalue9%`` -.. warning:: **Attention!** When using the command for all fields the reply can become extremely big and can lead to memory issues which results in instabilities of your device (especially when all eight fields a filled with very big numbers) +.. warning:: When using the command for all fields, the reply can become extremely big and can lead to memory issues which results in instabilities of your device (especially when all eight fields are filled with very big numbers) * Example for two single field events in rules: From ae3cbb98696db614d3454ffd52feb0923dde73d6 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Sun, 29 Oct 2023 19:30:42 +0100 Subject: [PATCH 20/22] a little formatting --- src/Custom-sample.h | 12 ++++++------ src/src/Helpers/Networking.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Custom-sample.h b/src/Custom-sample.h index a1bbdbd247..edf6ad156c 100644 --- a/src/Custom-sample.h +++ b/src/Custom-sample.h @@ -22,12 +22,12 @@ // --- Feature Flagging --------------------------------------------------------- // Can be set to 1 to enable, 0 to disable, or not set to use the default (usually via define_plugin_sets.h) -#define FEATURE_RULES_EASY_COLOR_CODE 1 // Use code highlighting, autocompletion and command suggestions in Rules -#define FEATURE_ESPEASY_P2P 1 // (1/0) enables the ESP Easy P2P protocol -#define FEATURE_ARDUINO_OTA 1 //enables the Arduino OTA capabilities -#define FEATURE_THINGSPEAK_EVENT 1 // generate an event when requesting last value of a field in thingspeak via SendToHTTP(e.g. sendToHTTP,api.thingspeak.com,80,/channels/1667332/fields/5/last) -// #define FEATURE_SD 1 // Enable SD card support -// #define FEATURE_DOWNLOAD 1 // Enable downloading a file from an url +#define FEATURE_RULES_EASY_COLOR_CODE 1 // Use code highlighting, autocompletion and command suggestions in Rules +#define FEATURE_ESPEASY_P2P 1 // (1/0) enables the ESP Easy P2P protocol +#define FEATURE_ARDUINO_OTA 1 // enables the Arduino OTA capabilities +#define FEATURE_THINGSPEAK_EVENT 1 // generate an event when requesting last value of a field in thingspeak via SendToHTTP(e.g. sendToHTTP,api.thingspeak.com,80,/channels/1667332/fields/5/last) +// #define FEATURE_SD 1 // Enable SD card support +// #define FEATURE_DOWNLOAD 1 // Enable downloading a file from an url #ifdef BUILD_GIT # undef BUILD_GIT diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index 5ff6384fb6..e5c91f2e5d 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -1556,7 +1556,7 @@ int http_authenticate(const String& logIdentifier, // field number (only available for a "single-value-event") // In rules you can grep the reply by "On ThingspeakReply Do ..." - if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last.csv"))) { + if (httpCode == 200 && equals(host, F("api.thingspeak.com")) && uri.endsWith(F("/last.csv"))) { String result = http.getString(); const int posTimestamp = result.lastIndexOf(':'); if (posTimestamp >= 0) { From 967f940895648aa0c3a9f9c8b89148c9f168b0a6 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:13:54 +0100 Subject: [PATCH 21/22] Update espeasy.min.js --- static/espeasy.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/espeasy.min.js b/static/espeasy.min.js index 04ce088c40..109e90920e 100644 --- a/static/espeasy.min.js +++ b/static/espeasy.min.js @@ -1 +1 @@ -var rEdit,commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","Reboot","Reset","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAPkey","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","WiFi#Disconnected","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor",],commonString2=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup","ld2410","ld2410,factoryreset","ld2410,logall",],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544",],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn"],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","substring","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","var","int"];for(const element2 of pluginDispKind)commonPlugins=commonPlugins.concat(element2);for(const element2 of pluginDispKind)for(const element3 of pluginDispCmd){let e=element2+element3;commonPlugins=commonPlugins.concat(e)}var EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonString2,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab(e){"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",function(){rEdit.save()}),rEdit.on("inputRead",function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})})}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("espeasy",function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase());commonCommands=commonCommands.concat(n);var o=commonString2.map(e=>e.toLowerCase());commonString2=commonString2.concat(o);var i=commonPlugins.map(e=>e.toLowerCase());commonPlugins=commonPlugins.concat(i);var a=commonAtoms.map(e=>e.toLowerCase());commonAtoms=commonAtoms.concat(a);var r=commonKeywords.map(e=>e.toLowerCase());commonKeywords=commonKeywords.concat(r);var s=commonTag.map(e=>e.toLowerCase());commonTag=commonTag.concat(s);var c=commonNumber.map(e=>e.toLowerCase());commonNumber=commonNumber.concat(c);var l=commonMath.map(e=>e.toLowerCase());commonMath=commonMath.concat(l);var m=AnythingElse.map(e=>e.toLowerCase());AnythingElse=AnythingElse.concat(m);var d=taskSpecifics.map(e=>e.toLowerCase());function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(let i of EXTRAWORDS){let a=i.substring(1);(i.includes(":")||i.includes(",")||i.includes("."))&&t.match(a)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var r=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"string-2"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(r)?e[r]:null}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("string-2",commonString2),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){var n,o;return n=e,((o=t).tokens[0]||u)(n,o)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}(function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,function(t,n,r){r&&r!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(a(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))});var i={Backspace:function t(i){var a=s(i);if(!a||i.getOption("disableInput"))return e.Pass;for(var r=o(a,"pairs"),c=i.listSelections(),l=0;l=0;l--){var u=c[l].head;i.replaceRange("",n(u.line,u.ch-1),n(u.line,u.ch+1),"+delete")}},Enter:function t(n){var i=s(n),a=i&&o(i,"explode");if(!a||n.getOption("disableInput"))return e.Pass;for(var r=n.listSelections(),l=0;l=0&&i.getRange(y,n(y.line,y.ch+3))==a+a+a?"skipThree":"skip";else if(h&&y.ch>1&&p.indexOf(a)>=0&&i.getRange(n(y.line,y.ch-2),y)==a+a){if(y.ch>2&&/\bstring/.test(i.getTokenTypeAt(n(y.line,y.ch-2))))return e.Pass;P="addFour"}else if(h){var b=0==y.ch?" ":i.getRange(n(y.line,y.ch-1),y);if(e.isWordChar(M)||b==a||e.isWordChar(b))return e.Pass;P="both"}else{if(!(x&&(0===M.length||/\s/.test(M)||f.indexOf(M)>-1)))return e.Pass;P="both"}if(C){if(C!=P)return e.Pass}else C=P}var v=u%2?m.charAt(u-1):a,D=u%2?a:m.charAt(u+1);i.operation(function(){if("skip"==C)c(i,1);else if("skipThree"==C)c(i,3);else if("surround"==C){for(var e=i.getSelections(),t=0;t0?{line:r.head.line,ch:r.head.ch+t}:{line:r.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function l(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function m(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}a(t.pairs+"`")}); \ No newline at end of file +var rEdit,commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","Reboot","Reset","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun", "ThingspeakReply","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAPkey","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","WiFi#Disconnected","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor",],commonString2=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup","ld2410","ld2410,factoryreset","ld2410,logall",],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544",],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn"],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","substring","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","var","int"];for(const element2 of pluginDispKind)commonPlugins=commonPlugins.concat(element2);for(const element2 of pluginDispKind)for(const element3 of pluginDispCmd){let e=element2+element3;commonPlugins=commonPlugins.concat(e)}var EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonString2,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab(e){"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",function(){rEdit.save()}),rEdit.on("inputRead",function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})})}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("espeasy",function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase());commonCommands=commonCommands.concat(n);var o=commonString2.map(e=>e.toLowerCase());commonString2=commonString2.concat(o);var i=commonPlugins.map(e=>e.toLowerCase());commonPlugins=commonPlugins.concat(i);var a=commonAtoms.map(e=>e.toLowerCase());commonAtoms=commonAtoms.concat(a);var r=commonKeywords.map(e=>e.toLowerCase());commonKeywords=commonKeywords.concat(r);var s=commonTag.map(e=>e.toLowerCase());commonTag=commonTag.concat(s);var c=commonNumber.map(e=>e.toLowerCase());commonNumber=commonNumber.concat(c);var l=commonMath.map(e=>e.toLowerCase());commonMath=commonMath.concat(l);var m=AnythingElse.map(e=>e.toLowerCase());AnythingElse=AnythingElse.concat(m);var d=taskSpecifics.map(e=>e.toLowerCase());function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(let i of EXTRAWORDS){let a=i.substring(1);(i.includes(":")||i.includes(",")||i.includes("."))&&t.match(a)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var r=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"string-2"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(r)?e[r]:null}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("string-2",commonString2),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){var n,o;return n=e,((o=t).tokens[0]||u)(n,o)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}(function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,function(t,n,r){r&&r!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(a(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))});var i={Backspace:function t(i){var a=s(i);if(!a||i.getOption("disableInput"))return e.Pass;for(var r=o(a,"pairs"),c=i.listSelections(),l=0;l=0;l--){var u=c[l].head;i.replaceRange("",n(u.line,u.ch-1),n(u.line,u.ch+1),"+delete")}},Enter:function t(n){var i=s(n),a=i&&o(i,"explode");if(!a||n.getOption("disableInput"))return e.Pass;for(var r=n.listSelections(),l=0;l=0&&i.getRange(y,n(y.line,y.ch+3))==a+a+a?"skipThree":"skip";else if(h&&y.ch>1&&p.indexOf(a)>=0&&i.getRange(n(y.line,y.ch-2),y)==a+a){if(y.ch>2&&/\bstring/.test(i.getTokenTypeAt(n(y.line,y.ch-2))))return e.Pass;P="addFour"}else if(h){var b=0==y.ch?" ":i.getRange(n(y.line,y.ch-1),y);if(e.isWordChar(M)||b==a||e.isWordChar(b))return e.Pass;P="both"}else{if(!(x&&(0===M.length||/\s/.test(M)||f.indexOf(M)>-1)))return e.Pass;P="both"}if(C){if(C!=P)return e.Pass}else C=P}var v=u%2?m.charAt(u-1):a,D=u%2?a:m.charAt(u+1);i.operation(function(){if("skip"==C)c(i,1);else if("skipThree"==C)c(i,3);else if("surround"==C){for(var e=i.getSelections(),t=0;t0?{line:r.head.line,ch:r.head.ch+t}:{line:r.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function l(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function m(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}a(t.pairs+"`")}); \ No newline at end of file From 7f2a4eddc6d4e8db90ec21eef0e22cbe2e52face Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:39:59 +0100 Subject: [PATCH 22/22] Update Rules.rst --- docs/source/Rules/Rules.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/Rules/Rules.rst b/docs/source/Rules/Rules.rst index 5065e3a66d..14d288c387 100644 --- a/docs/source/Rules/Rules.rst +++ b/docs/source/Rules/Rules.rst @@ -1966,7 +1966,7 @@ Added: 2023/10/26 1. Get the value of a single field: - Example command: - ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last`` + ``SendToHTTP,api.thingspeak.com,80,/channels/1637928/fields/5/last.csv`` - Example of the resulting event: ``"EVENT: ThingspeakReply=1637928,5,24.2"`` @@ -1982,7 +1982,7 @@ Added: 2023/10/26 ``"EVENT:ThingspeakReply=1637928,5929,353,42.0,177,19.1,995.6,,"`` | channel number = ``%eventvalue1%`` - | values = ``%eventvalue3%`` to ``%eventvalue9%`` + | values = ``%eventvalue2%`` to ``%eventvalue9%`` .. warning:: When using the command for all fields, the reply can become extremely big and can lead to memory issues which results in instabilities of your device (especially when all eight fields are filled with very big numbers)