-
Notifications
You must be signed in to change notification settings - Fork 4
custom device: 433 MHz weather station
For some time I have wanted to include meteorological probes in the tuyaDAEMON project: in particular, the rain gauge data can be integrated with the irrigation system, and the anemometer is useful for wind turbine testing (next project).
The problem is the probes. There are (yet) no weather probes in the Tuya system. The best solution I have found is not to select separate, very expensive probes, but to use a medium-quality standalone wireless (433 MHz) weather station: the "Auriol IAN-114435"(https://www.manua.ls/auriol/ian-114435/manual) offered some time ago by Lidl for € 50. (https://fandilidl.it/volantino/2019.01.21.caldo.inverno/17080,Stazione-meteorologica). Good quality/price factor.
The weather station consists of the main interface (H13716a), of a probe (H13716b) which transmits on two channels: one for temperature and humidity, the other for wind and direction, and we also have the rain gauge (H13716c). Googling for comments, it is considered an excellent entry level product, though some criticisms has been leveled at the position of the temperature probe: alternative DIY solutions can be found.
With this choice, the problem is generalized: finding a valid connection with tuyaDEAMON for devices using the ISM bands: 433.92 MHz, 868 MHz, 315 MHz, 345 MHz and 915 MHz. Examples of such devices include weather stations, sensors alarm, utility monitor, tire pressure monitor and more.
I am not an RF expert, so my first step is to investigate the problem, before starting with RX circuits and Arduino microprocessor to decode the signals and transmit them via WIFI (example: https://www.instructables.com/Decoding-and-sending-433MHz-RF-codes-with-Arduino-/).
Here my experience:
As HW, I used the RTL-SDR
, a very cheap USB dongle, around $ 30 with an antenna, that can be used as a computer-based radio scanner to receive live radio signals on Pc, Raspberry, and Android. more...
As software there is the brink of choice, see list. I chose SDRsharp (SDR#)
due to the presence of a specialized 433 plugin.
- I downloaded "
SRD# with Community Plugins
" from https://airspy.com/download/ for its easy installation. - After installing
SRD#
(see instructions at https://www.rtl-sdr.com/rtl-sdr-quick-start-guide) I also installed NET 5.0 SDK. - Then I followed these instructions https://www.rtl-sdr.com/rtl433-plugin-for-sdr-now-available/ to install in
SRD#
theRTL_433 plugin
from https://github.com/marco402/Rtl_433_dll-for-plugin-SdrSharp. - Finally I installed the driver as indicated in https//www.rtl-sdr.com/getting-the-rtl-sdr-to-work-on-windows-10/. The
Zadig.exe
file is present in thebin
dir ofSRD#
.
For the analysis of signals, you can refer to: https://www.sigidwiki.com/wiki/SignalIdentificationGuide.
This is a signal:
To my surprise the plugin has decoded all the weather devices providing this output in clear text.
All three channels of the weather station use the same protocol #16, called 'Alecto V1': see here for protocol details.
The good result obtained made me change plans: instead of building a DIY gateway, I decided to permanently use the RLT_SDR as receiver and RTL_433 as converter. Moreover: "One comment about the cc1101 transceiver module, I have found that the receiver is not as sensitive as a rtl_sdr and I get about 1/2 the range (by NorthernMan54) ".
I need now the rtl_433.exe
standalone from https://github.com/merbanan/rtl_433
The following operations were necessary:
- I downloaded the
rtl_433-win-msvc-x64-21.12.zip
file from https://github.com/merbanan/rtl_433/releases - I created a directory (
d:\usrbin
) and added it to the windows PATH (pop-upsystem properties
thenenvironment variables
) and unzipped herertl_433-win-msvc-x64- 21.12.zip
. - Using the RTL_SDR, we can't use the default
rtl_433.exe
. So I renamed the file "D:\userbin\rtl_433.exe
" to "D:\userbin\rtl_433_base.exe
" and I make a copy of the file "D:\userbin\rtl_433-rtlsdr.exe
" as "D:\userbin\rtl_433.exe
". - note: you can test all
exe
ind:\usrbin
simply using acommand line
terminal (cmd.exe
): the dir is in the PATH, so it works from anywhere.
Time now to use node-red.
- I installed the node-red-contrib-rtl_433 then I build a minimal test flow:
Just with the default settings, it worked the first time: as you can see in the debug pad, it returns all data in an object. Perfect!.
So this is a fast and easy solution for all 433 MHz (and 868 MHz, 315 MHz, 345 MHz and 915 MHz) RF devices. There are currently over 200 protocols available: it is likely (as in my case) that you will find the one required.
At this point it is possible to continue either by creating your own standalone weather application (example: https://www.rtl-sdr.com/tag/weather-station/, or by integrating the data in 'tuyaDAEMON', creating a 'fake weather station device'. Note: the original interface (Auriol H13716a) continues to function as before.
note (04/04/2023): If you get 'error -12' in the console, re-install the driver using Zadig as in 1.3 up. (see https://www.rtl-sdr.com/forum/viewtopic.php?f=7&t=1797).
Time to make some design choices:
- The new flow will be a general purpose 433 gateway, which manages (for now) two devices:
_Auriol_IAN_114435
for the meteo data and_extra_temperature
for other temperature probes, using device nodes.
-
General characteristics
-
Random ID
user configuration for all handled devices (when changing the battery). - Uses the
RT/AVG filter
subflow to average device data (optional, e.g. every 5 min). note: the user can select whichdp
to record in thetoyathome
DB for subsequent processing (seehide
). - Send any extra data captured as a warning message.
- As usual, user runtime configuration data are grouped for easy access in a
Global 433 gateway config
node. - Some useful meteorological functions are implemented in a singleton object
context.global.meteoUtils
to allow easy reuse in any flow/node.
-
-
the custom device "_Auriol_IAN_114435" groups three probes (temperature, wind, rain) and follows the rules:
- Unit of measurement in SI (°C, m/s, etc...)
- Uses a meteorological day with user-defined rollover time (default 09:00:00), compensated for DST (see here).
- Wind direction calibration feature (when changing the battery)
- In output we get all the values received by the sensors, plus the following values, calculated from the '
data process
' node:- Meteorological 'Day of year' ( _day )
- Daily rainfall (_rain_day_mm)
- Daily gust (_wind_daymax_m_s the max wind speed, 2 min avg)
- Heat index (_heat_index Celsius, see https://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml)
- Dew point (_dew_point Celsius, see https://en.wikipedia.org/wiki/Dew_point)
- Wind chill (_wind_chill Celsius, see https://en.wikipedia.org/wiki/Wind_chill)
This device simply groups 2 spare temperature probes, from old time+temperature clocks.
The last version of 433 gateway can be downloaded from https://github.com/msillano/tuyaDAEMON/tree/main/extra/433_gateway.
Code includes also the devices:
- weather_station
- extra_temperature
If you are receiving signals from other probes in a stable way, you can add a custom tuyaDAEMON device to the '433 gateway'. Here's how to proceed:
- Define a new fake device in alldevices: with the device id (e.g. _newDevice) and all the dps received plus other optional dps calculated by the device driver (you can use tuyaDAEMON-toolkit for this phase).
- In the 'global 433 gateway config' node add
- flow.RND_XXX the probe random ID (if used by probe)
- flow._newDevice_AVERAGE = true to use the average feature (optional)
- Add a new output to the 'RX data selector' node, and update the code to select only the new device data objects.
- Add a new function node 'newDevice process' to
- map probe data to defined tuyaDAEMON dps.
- calculate the added 'dps' (optional).
- If required, add also an 'AVG _newDevice' input node with average definitions.
In production, you can reduce the computational load by selecting only the useful protocols in the 'rtl_a33' node.
To extract weather data from the 'messages' table in a more useful format you can create a 'view' with a record every 5 minutes:
using this MYSQL query:
SELECT `timestamp`,
MAX(CASE WHEN messages.dps ="_day" THEN messages.value END) "day",
MAX(CASE WHEN messages.dps ="_temperature" THEN messages.value END) "temp",
MAX(CASE WHEN messages.dps ="_humidity" THEN messages.value END) "hum",
MAX(CASE WHEN messages.dps ="_rain_day_mm" THEN messages.value END) "rain",
MAX(CASE WHEN messages.dps ="_wind_avg_m_s" THEN messages.value END) "wind",
MAX(CASE WHEN messages.dps ="_heat_index" THEN messages.value END) "HI",
MAX(CASE WHEN messages.dps ="_dew_point" THEN messages.value END) "DP",
MAX(CASE WHEN messages.dps ="_wind_chill" THEN messages.value END) "WC",
MAX(CASE WHEN messages.dps ="_wind_max_m_s" THEN messages.value END) "WM",
MAX(CASE WHEN messages.dps ="_wind_dir_deg" THEN messages.value END) "dir"
FROM messages
WHERE `device-id`='_Auriol_IAN_114435'
GROUP BY `timestamp`
ORDER BY `timestamp` ASC
Update (2023): For an in-depth analysis and alternative options for using the data in the DB, see the application notes:
This subflow filter for tuyaDAEMON allows the processing of individual messages in real time, or the creation of an averaged sampling. This subflow is a generic node that can be used with data messages from any tuyaDAEMON device.
For devices in 'RT' mode
, all messages go directly to the output (no filter action).
For devices in 'AVG' mode
, all input messages are stored. A special "trigger" message in input provokes the output.
This message fires the output message with averaged data and causes the reset of the internal storage.
msg:{
topic = 'average' ' (mandatory)
}
The simplest way to generate trigger messages at fixed time intervals is to use a standard 'input' node, setting interval
to the required value.
This subflow can handle messages from one device, with a user-defined strategy, and it is designed to allow for a simple upgrade of any existing tuyaDAEMON module or device.
Condition to enable the AVG mode
for a device:
This global variable is used as flag:
global.<deviceid>_AVERAGE = true|false (mandatory)
The simplest and user-convenient way to set this value is to add it to the Global MODULE config
node, present in all tuyaDEAMON modules: it acts as a switch to enable or disable the 'average' function.
Processing dps
rules in AVG mode
- The
dps
full list is taken, for any device, from theglobal.alldevices
object (see theCORE.Global CORE config
node). - Only
dps
with at least one value in stored inputs are in the output. - If the
dp
value 'isNaN()
' (i.e. not numeric) automatically the last value is used in output. - If the
dp
value isnumeric
, we get theaverage
of all stored input values as output (default). - The
average
is rounded to an integer if 'dp' is in thedp_round
trigger list, else it is with user-defineddecimal digits
. - If a 'dp' is in
dp_max
ordp_min
trigger lists, we get themaximum
or theminimum
stored value instead of theaverage
.
Limits
This node only works with atomic values. In the case of dp
whose value is a data structure, the user can:
- default: the last value is used in triggered output.
- put the
dp
in thedp_exclude
list, it is sent as-is immediately. - add an
explode
node in input to generate atomic values from the structure.
Using the RT/AVG filter subflow alone does not get the expected result in the case of Objects (structures). Example: see BreakerDIN where a dP
(6) uses a structure to send 4 RT values.
The subflow Explode early decodes (using a decode user function) one data structure and adds the atomic values to the payload.
It is recursive, and, of course, the new values must be defined also in alldevices, as _<dp>.<path>
(e.g. _6.V
or _6.Leack
), as PUSH
(user can't GET/SET them).
Not all JSON structures are handled as expected by 'explode'. It does not work with arrays.
The following structures will not be exploded correctly (from TRV device):
dp 110 = [18,18,18,18,0,0,0] // fixed size, week data
dp 123 = {"count":4,
"changes": [ // variable size
{"time":"06:00","temp":16},
{"time":"10:00","temp":21},
{"time":"13:00","temp":21},
{"time":"23:00","temp":16} ] }
Workaround: If it is required an 'explode' for such data, make a custom version of 'explode', or change the DECODE/ENCODE functions to avoid the arrays. Example:
dp 110 = {
"Mon":18,
"Tue":18,
"Wed":18,
"Thu":18,
"Fri":0,
"Sat":0,
"Sun":0 }
This collection of functions is general enough to be useful in other weather projects as well.
In node-red, in order to use it in every flow/node, it is implemented as a global singleton, built by the code 'On Start' in the 433 gateway startup
node, see details.
In your function nodes, you can use it like so (from weather station process
function node):
...
if (context.global.meteoUtils.isDayChanged(RAINDAY)){
...
method | parameters | description |
---|---|---|
getDOY |
(aDate = null) |
returns the meteorological day-of-year. If aDate is missed or null, use now |
isDayChanged |
(nowDay ) |
returns true the first time and if the meteorological day is changed, else false ; param (flow.)nowDay : a local unique name where it stores DOY |
toFahrenheit |
(tc) | converts a temperature from [°Celsius] to [°Fahrenheit] |
toCelsius |
(tf ) |
converts a temperature from [°Fahrenheit] to [°Celsius] |
toKmHr |
(v ) |
converts a speed from [m/s] to [Km/h] |
evalHeatIndex |
(tc , RH ) |
Returns the NOAA Heat Index [°C] (see here) |
evalDewPoint |
(tc , RH ) |
Returns the Dew Point [°C] (see here) |
evalWindChill |
(tc , v , hi ) |
Returns the Wind Chill [°C] (see here) |