Skip to content

Commit c3400e2

Browse files
authored
Merge pull request #5207 from chromoxdor/openmeteo-events
[sendtohttp] Add Open-Meteo events + JSON event
2 parents 8ad8227 + 6ce68d2 commit c3400e2

File tree

9 files changed

+732
-101
lines changed

9 files changed

+732
-101
lines changed
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
.. _HTTPResponseParser:
2+
3+
####################
4+
HTTP Response Parser
5+
####################
6+
7+
Introduction
8+
============
9+
10+
The HTTP Response Parser are a set of parsers that can be used to parse the response of an HTTP request. They extract specific information from the response and use it in rules by generating specific events.
11+
12+
.. note:: These parsers are disabled by default and only available in max builds or custom builds where you have to enable them with either ``#define FEATURE_THINGSPEAK_EVENT 1``, ``#define FEATURE_OPENMETEO_EVENT 1`` or ``#define FEATURE_JSON_EVENT 1`` in the config.h file.
13+
14+
The Thingspeak Parser
15+
---------------------
16+
17+
* ``SendToHTTP`` generates an event with the response of a thingspeak request (https://www.mathworks.com/help/thingspeak/readlastfieldentry.html & https://www.mathworks.com/help/thingspeak/readdata.html)
18+
* There are two options:
19+
20+
1. Get the value of a single field:
21+
22+
- Example command:
23+
``SendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last.csv``
24+
- Example of the resulting event:
25+
``"EVENT: ThingspeakReply=143789,5,9.65"``
26+
27+
| channel number = ``%eventvalue1%``
28+
| field number = ``%eventvalue2%``
29+
| value = ``%eventvalue3%``
30+
31+
2. Get the values of all fields:
32+
33+
- Example command:
34+
``SendToHTTP,api.thingspeak.com,80,/channels/143789/feeds/last.csv``
35+
- Example of the resulting event:
36+
``"EVENT: ThingspeakReply=143789,11.12,9.46,9.55,16.32,9.65,8.81,-1.23,14.76"``
37+
38+
| channel number = ``%eventvalue1%``
39+
| values = ``%eventvalue2%`` to ``%eventvalue9%``
40+
41+
.. note::
42+
``last.csv`` is mandatory!
43+
44+
.. 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)
45+
46+
* Rules example:
47+
48+
.. code:: none
49+
50+
On Rules#Timer=1 Do
51+
SendToHTTP,api.thingspeak.com,80,/channels/143789/feeds/last.csv
52+
Endon
53+
54+
On ThinkspeakReply Do
55+
LogEntry,'The channel number is: %eventvalue1%'
56+
LogEntry,'%eventvalue6%°C in Berlin'
57+
LogEntry,'%eventvalue7%°C in Paris'
58+
Endon
59+
60+
Added 2024/02/05
61+
62+
* Added the option to get a single value of a field or all values of a channel at a certain time (not only the last entry)
63+
64+
* Examples:
65+
66+
Single channel: ``SendToHTTP,api.thingspeak.com,80,channels/143789/fields/1.csv?end=2024-01-01%2023:59:00&results=1``
67+
=> gets the value of field 1 at (or the last entry before) 23:59:00 of the channel 143789
68+
69+
All channels: ``SendToHTTP,api.thingspeak.com,80,channels/143789/feeds.csv?end=2024-01-01%2023:59:00&results=1``
70+
=> gets the value of each field of the channel 143789 at (or the last entry before) 23:59:00
71+
72+
.. note::
73+
``csv`` and ``results=1`` are mandatory!
74+
75+
76+
The Open Meteo Parser
77+
---------------------
78+
79+
* ``SendToHTTP`` generates an event with the response of an open-meteo.com request.
80+
81+
**Short description:**
82+
Generates an event with the response of an Open-Meteo request.
83+
No need for an API key and it is free (daily requests are limited to 10,000 in the free version).
84+
Visit the URL (https://open-meteo.com/en/docs) and build your personal URL by selecting the location and values you want to receive.
85+
Supported variable kinds are "current", "hourly", "daily"!
86+
In rules, you can grep the reply by the kind of weather variables with ``On OpenMeteo# Do``.
87+
88+
**Example:** ``On OpenMeteo#current Do``.
89+
90+
.. note:: **"hourly"** and **"daily"** results are arrays which can become very long.
91+
It is best to make separate calls, especially for hourly results.
92+
93+
**How-To:**
94+
95+
1. Visit https://open-meteo.com/en/docs
96+
2. Select in the side menu your topic (e.g., Weather Forecast, Marine Forecast, Air Quality)
97+
3. Click together what you need and scroll down to the API Response section where you find this:
98+
99+
.. image:: OpenMeteoAPILink.png
100+
:alt: Open Meteo API Link Example
101+
:width: 600px
102+
103+
1. Copy everything after "open-meteo.com"
104+
2. Use the copied part of the URL with SendToHTTP. Example: ``SendToHTTP,api.open-meteo.com,80,"/v1/forecast?..."`` (make sure to use the quotes!)
105+
106+
**Rules Example:**
107+
108+
.. code:: none
109+
110+
On Rules#Timer=1 Do
111+
SendToHTTP,api.open-meteo.com,80,"v1/forecast?latitude=52.52&longitude=13.41&current=temperature_2m&hourly=temperature_2m&daily=temperature_2m_max&forecast_days=3"
112+
Endon
113+
114+
On OpenMeteo#current Do
115+
TaskValueSet 1,Outdoor,Temp,%eventvalue1%
116+
TaskValueSet 1,Outdoor,Hum,%eventvalue2%
117+
TaskValueSet 1,Outdoor,Baro,%eventvalue3%
118+
TaskValueSet 1,Outdoor,UV,%eventvalue4%
119+
LogEntry,'Values : Temp=%eventvalue1% Hum=%eventvalue2% Baro=%eventvalue3% UV=%eventvalue4%'
120+
Endon
121+
122+
//this is a generic approach to grep all the different kinds of weather variables in one rules block
123+
On OpenMeteo* Do
124+
If {ord:%eventpar%} = 99 // the ordinal/integer value of the first character of "current" is 99
125+
LogEntry,'%eventpar% 1: %eventvalue1% 2: %eventvalue2% 3: %eventvalue3%'
126+
Elseif {ord:%eventpar%} = 104 // the ordinal/integer value of the first character of "hourly" is 104
127+
LogEntry,'%eventpar% 1: %eventvalue1% 2: %eventvalue2% 3: %eventvalue3%'
128+
Elseif {ord:%eventpar%} = 100 // the ordinal/integer value of the first character of "daily" is 100
129+
LogEntry,'%eventpar% 1: %eventvalue1% 2: %eventvalue2% 3: %eventvalue3%'
130+
Endif
131+
Endon
132+
133+
134+
135+
The gerneric JSON Parser
136+
------------------------
137+
138+
* ``SendToHTTP`` generates an event with the response of a JSON request.
139+
* The JSON parser is a generic parser that can be used to parse any JSON response.
140+
141+
**How-To:**
142+
143+
1. Add either #json or ?json to the end of the URL (either will always work) to tell ESPEasy that the response is in JSON format.
144+
145+
Example: ``SendToHTTP 192.168.1.199,80,"/solar_api/v1/GetInverterRealtimeData.cgi?Scope=System#json"``
146+
.. code-block:: json
147+
:caption: Example response:
148+
:class: collapsible
149+
150+
{
151+
"Head" : {
152+
"RequestArguments" : {
153+
"DataCollection" : "",
154+
"Scope" : "System"
155+
},
156+
"Status" : {
157+
"Code" : 0,
158+
"Reason" : "",
159+
"UserMessage" : ""
160+
},
161+
"Timestamp" : "2014-12-10T11:25:18+01:00"
162+
},
163+
"Body" : {
164+
"Data" : {
165+
"PAC" : {
166+
"Unit" : "W",
167+
"Values" : {
168+
"1" : 277
169+
}
170+
},
171+
"DAY_ENERGY" : {
172+
"Unit" : "Wh",
173+
"Values" : {
174+
"1" : 274
175+
}
176+
},
177+
"TOTAL_ENERGY" : {
178+
"Unit" : "Wh",
179+
"Values" : {
180+
"1" : 4173000
181+
}
182+
}
183+
}
184+
}
185+
}
186+
187+
2. Create a file called json.keys and add the keys you want the values from (each key in an extra line):
188+
189+
.. code-block:: none
190+
:caption: Example:
191+
192+
Body.Data.PAC.Values.1
193+
Body.Data.DAY_ENERGY.Values.1
194+
Body.Data.TOTAL_ENERGY.Values.1
195+
196+
3. Upload the file.
197+
198+
4. Grep the data with ``On JsonReply Do``.
199+
200+
**Extras:**
201+
202+
- Grouping or separate calls with different URLs.
203+
204+
1. Add a number to #json or ?json:
205+
206+
e.g.: ``SendToHTTP 192.168.1.199,80,"/solar_api/v1/GetInverterRealtimeData.cgi?Scope=System#json1"``
207+
208+
2. Add the number + ":" to the key you want to group:
209+
210+
.. code-block:: none
211+
:caption: Example:
212+
213+
1:Body.Data.DAY_ENERGY.Values.1
214+
2:Body.Data.PAC.Values.1
215+
216+
3. Grep the data with ``On JsonReply#<number> Do``.
217+
218+
e.g.: ``On JsonReply#1 Do``
219+
220+
This way you can call more than one URL or put an array in a separate response, as the amount of event values would probably be too long.
221+
222+
**Rule example using %eventpar% to only have one rules block:**
223+
224+
.. code:: none
225+
226+
On JsonReply* Do
227+
If %eventpar% = 1
228+
LogEntry,'Keygroup:%eventpar% DAY_ENERGY:%eventvalue1%'
229+
Elseif %eventpar% = 2
230+
LogEntry,'Keygroup:%eventpar% PAC:%eventvalue1%'
231+
Endif
232+
Endon
233+
234+
.. note:: When using groups in the key file but not adding a number at the end of the URL, ALL keys will be parsed!
235+
236+
237+
238+
239+
44.6 KB
Loading

docs/source/Rules/Rules.rst

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,65 +2146,14 @@ Added: 2022/07/23
21462146
* Host name can contain user credentials. For example: ``http://username:pass@hostname:portnr/foo.html``
21472147
* HTTP user credentials now can handle Basic Auth and Digest Auth.
21482148

2149-
Added: 2023/10/26
2149+
Added: 2025/01/15
21502150

2151-
* ``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)
2152-
* There are two options:
2153-
2154-
1. Get the value of a single field:
2155-
2156-
- Example command:
2157-
``SendToHTTP,api.thingspeak.com,80,/channels/143789/fields/5/last.csv``
2158-
- Example of the resulting event:
2159-
``"EVENT: ThingspeakReply=143789,5,9.65"``
2160-
2161-
| channel number = ``%eventvalue1%``
2162-
| field number = ``%eventvalue2%``
2163-
| value = ``%eventvalue3%``
2164-
2165-
2. Get the values of all fields:
2151+
* **HTTPResponseParser:** A Set of special parser for the response of a HTTP request.
21662152

2167-
- Example command:
2168-
``SendToHTTP,api.thingspeak.com,80,/channels/143789/feeds/last.csv``
2169-
- Example of the resulting event:
2170-
``"EVENT: ThingspeakReply=143789,11.12,9.46,9.55,16.32,9.65,8.81,-1.23,14.76"``
2171-
2172-
| channel number = ``%eventvalue1%``
2173-
| values = ``%eventvalue2%`` to ``%eventvalue9%``
2174-
2175-
.. note::
2176-
``last.csv`` is mandatory!
2177-
2178-
.. 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)
2179-
2180-
* Rules example:
2181-
2182-
.. code:: none
2183-
2184-
On System#Boot Do
2185-
SendToHTTP,api.thingspeak.com,80,/channels/143789/feeds/last.csv
2186-
Endon
2187-
2188-
On ThinkspeakReply Do
2189-
LogEntry,'The channel number is: %eventvalue1%'
2190-
LogEntry,'%eventvalue6%°C in Berlin'
2191-
LogEntry,'%eventvalue7%°C in Paris'
2192-
Endon
2193-
2194-
Added 2024/02/05
2195-
2196-
* Added the option to get a single value of a field or all values of a channel at a certain time (not only the last entry)
2153+
See :ref:`HTTPResponseParser`
2154+
21972155

2198-
* Examples:
2199-
2200-
Single channel: ``SendToHTTP,api.thingspeak.com,80,channels/143789/fields/1.csv?end=2024-01-01%2023:59:00&results=1``
2201-
=> gets the value of field 1 at (or the last entry before) 23:59:00 of the channel 143789
2202-
2203-
All channels: ``SendToHTTP,api.thingspeak.com,80,channels/143789/feeds.csv?end=2024-01-01%2023:59:00&results=1``
2204-
=> gets the value of each field of the channel 143789 at (or the last entry before) 23:59:00
22052156

2206-
.. note::
2207-
``csv`` and ``results=1`` are mandatory!
22082157

22092158
Convert curl POST command to PostToHTTP
22102159
---------------------------------------

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Welcome to ESP Easy's documentation!
5454
Controller/C*
5555
Notify/N*
5656
Plugin/P*
57+
Rules/HTTPResponseParser.rst
5758

5859

5960
Indices and tables

src/Custom-sample.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
#define FEATURE_RULES_EASY_COLOR_CODE 1 // Use code highlighting, autocompletion and command suggestions in Rules
2626
#define FEATURE_ESPEASY_P2P 1 // (1/0) enables the ESP Easy P2P protocol
2727
#define FEATURE_ARDUINO_OTA 1 // enables the Arduino OTA capabilities
28-
#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)
28+
#define FEATURE_THINGSPEAK_EVENT 0 // Generates 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)
29+
#define FEATURE_OPENMETEO_EVENT 0 // Generates an event with the response of a open-meteo request (https://open-meteo.com/en/docs)
30+
#define FEATURE_JSON_EVENT 0 // Generates an event with the values of a JSON repsonse of an HTTP call. Keys are stored in json.keys one key per line (e.g.: Body.Data.DAY_ENERGY.Values.1)
2931
// #define FEATURE_SD 1 // Enable SD card support
3032
// #define FEATURE_DOWNLOAD 1 // Enable downloading a file from an url
3133

src/src/CustomBuild/define_plugin_sets.h

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3734,13 +3734,37 @@ To create/register a plugin, you have to :
37343734
#endif
37353735
#endif // if FEATURE_TASKVALUE_ATTRIBUTES
37363736

3737-
#ifndef FEATURE_THINGSPEAK_EVENT
3738-
#ifdef LIMIT_BUILD_SIZE
3739-
#define FEATURE_THINGSPEAK_EVENT 0
3740-
#else
3741-
#define FEATURE_THINGSPEAK_EVENT 1
3742-
#endif
3737+
//-------------------HTTPResponseParser Section----------------
3738+
#ifndef FEATURE_THINGSPEAK_EVENT
3739+
#if defined(PLUGIN_BUILD_MAX_ESP32)
3740+
#define FEATURE_THINGSPEAK_EVENT 1
3741+
#else
3742+
#define FEATURE_THINGSPEAK_EVENT 0
3743+
#endif
3744+
#endif
3745+
3746+
#ifndef FEATURE_OPENMETEO_EVENT
3747+
#if defined(PLUGIN_BUILD_MAX_ESP32)
3748+
#define FEATURE_OPENMETEO_EVENT 1
3749+
#else
3750+
#define FEATURE_OPENMETEO_EVENT 0
37433751
#endif
3752+
#endif
3753+
3754+
#ifndef FEATURE_JSON_EVENT
3755+
#if defined(PLUGIN_BUILD_MAX_ESP32)
3756+
#define FEATURE_JSON_EVENT 1
3757+
#else
3758+
#define FEATURE_JSON_EVENT 0
3759+
#endif
3760+
#endif
3761+
3762+
#if FEATURE_THINGSPEAK_EVENT || FEATURE_OPENMETEO_EVENT || FEATURE_JSON_EVENT
3763+
#define RESPONSE_PARSER_SUPPORT 1
3764+
#else
3765+
#define RESPONSE_PARSER_SUPPORT 0
3766+
#endif
3767+
//-------------------End of HTTPResponseParser Section----------
37443768

37453769
#if !(defined(SOC_DAC_SUPPORTED) && SOC_DAC_SUPPORTED)
37463770
#ifdef USES_P152

0 commit comments

Comments
 (0)