-
Notifications
You must be signed in to change notification settings - Fork 4
custom device _system
Since ver 2.2.0 'core' and 'trigger' are devices, with few DPs: this increases independence and test capabilities.
CORE properties:
-
_name GET only, returns
global.instance_name
-
_DBase PUSH and GET,
true
if all DBs connected - _heartbeat periodical timestamp, decoded as 'HH:MM;SS' (for easy test). PUSH and GET.
- _info SET(any) fills a structure with the enabled flows and all connected devices. GET returns last value.
TRIGGER extra properties:
- _tstPing Roundtrip tuya-cloud time. For details see the wiki, trigger info.
- _testPing24H For details see wiki, trigger info.
With version 2.0 the '_system' device has undergone refactoring and is now a device, in a separate flow. The goal of this SW-only custom device is to group some useful extra functionalities. Here is an overview of the _system
features, for details see the standard documentation.
This _system property (and the related start_DEAMON node) is SET only once, some seconds after a node-red restart. Used to do some delayed startup operations on custom devices or to check devices' status.
_This system property implements the message exchange between tuyaDAEMON instances on lan. It uses the REST interface to connect a remote tuyaDAEMON server. A map of the URLs for the existing tuyaDAEMON instances is in CORE, in the config 'global' node, named 'remotemap'.
The user doesn't use directly this property, enough to extend the tuyaDAEMON standard messages so:
{
"remote": "ANDROID",
"device": "switch module #1",
"property": "switch",
"value": "OFF"
}
The global.tuyastatus
variable is the storage of all last values got from devices, structured in device.property.value
, plus some pseudoDP (_t
, _connected
).
The tuyastatus
is automatically updated with any GET
and SET
. Some _system
functions allow more control over it.
-
_tuyastatus(std_cmd) Alternative and indirect access to the
global.tuyastatus
structure, regardless of dp capabilities. We can get:- the device list (if
std_cmd
is empty{}
) - the SCHEMA for a device, if
std_cmd.property
is undefined - to GET the last value of a property if
std_cmd.value
is undefined - an unconditioned SET (take care: potentially dangerous) if the
std_cmd
is full.
- the device list (if
-
_doSCHEMA(device) Does a SCHEMA simulation for any device (real, virtual, fake) sending ALL GETs available (from
alldevices
definitions), and update tuyastatus. Returns a list of all DPs tested + the output for any GET. -
_doUPDATE(NULL|real|virtual|fake) For all devices connected, does a 'doSCHEMA' command. That can fully update
tuyastatus
, e.g. after a startup. Returns a list of devices.This can be a good check for 'alldevices' definitions: it must run without 'warning messages.
-
_toGlobal(variable, value) To GET (if value === 'NULL') the
global.variable
, or SET aglobal.variable
, e.g. in remote. Take care: SET is potentially dangerous. Returns {variable, value}.
Runs a system command and returns its output.
Any used DB can be controlled via _system
, for DB maintenance and DB data access:
-
_sqlDBlocal(SQL) allows to send a sql-string to a DB and get the answer
- more _sqlDBxxxx properties can be user-defined for all DB used. See core.
The timer functions are built around the 'node-red-contrib-jsontimer'. This implementation allows to define a temporized start for any task (local or remote tuyaDAEMON standard command) using a standard command or a share. The timer itself is simple: it has only one function, to send a stored message at a specific time. The time can be defined in three ways: timeout
(in ms), time
(as 22:13:36.010), and datetime
(unixtimestamp).
The timer doesn't offer any kind of repetition. But it can handle many timers, identified by an 'id'. The running timers are maintained with the 'Deploy' and 'Restart Flows' operations.
-
_timerON ((id,) timeout:xx|time:yy|datetime:zz, alarmPayload:{<std_cmd>|<share>}) sets a new timer.
-
alarmPayload
can be a standard command (more simple) or a share (more powerful). -
id
is mandatory only if you use_timerOFF
elseid
is auto.
-
-
_timerOFF(id) deletes an existing timer selected by
id
, mandatory. - _timerList() gets the list of all active timers.
A timer can be used also inside a standard share, to have a delay effect on a task triggered by an event, see _system._beep_loop
implementation in global.alldevices
.
Use of _timerON: this command sets a timer to send a TRIGGER5000 to Tuya-cloud, 100 seconds later.
{
"device": "_system",
"property": "_timerON",
"value": {
"timeout": 100000, // or time|datetime
"alarmPayload": { // the delayed command
"device": "_system",
"property": "_doTrigger",
"value": 5000
}
}
}
Benchmarks can be done by repeatedly running a task in freerunning and counting the number of runs performed by tuyaDAEMON in a given time.
Some _system
properties simplify the benchmarks:
- _zeroTask: the fastest SW-only task, does nothing, and it is without any logging (no debug pad, no DB).
- _zeroLog: like _zeroTask, but with logging (debug pad and DB) and SET returns the coded 'value'.
- _benchmark: to SET/GET the task (default _zeroTask) and the benchmark duration (default 10000 ms).
- _doBenchmark: SET: trigger to execute a benchmark.
To do a benchmark, choose the task (device
and property
), then:
- To retrigger in free-run the chosen task, add to
global.alldevice.<device>.<property>
theshare
:
"share": [{
"action": [{
"device": "_system",
"property": "_benchmark_step"
}]}]
note: the _benchmark_step
does is retrigger action only inside a running benchmark, so this share
can be permanent (see global.alldevices._system._zeroTask
and global.alldevices._system._zeroLog
), or you can delete it after the benchmark.
- Use the
_benchmark
property to SET the task:
"payload":{
"device": "_system",
"property": "_benchmark",
"value" {
"device":"_system", // the chosen task GET _system._zeroTask
"property":"_zeroTask",
"value": if_required, // to do GET/SET test
"timeout": 20000 // optional, default 10000 ms
}}
- Use
_doBenchmark
(SET: trigger) to start the benchmark.
- In my old test server (i7-4777, 3.40 GHz, Win 10) and tuyaDAEMON 2.0 I get 15300/20s for
_zeroTask
, 11700/20s for_zeroLog
, and a good 480/20s for a GET from the tuya_bridge real device. - Using ver. tuyaDAEMON 2.2.0 (new server i9-11900, 2.50 GHz, win 11) zeroTask more than 2000 run/s and zeroLog more than 1400 run/s.
- On ANDROID 11 (H96 Max-V11, CPU RK3319 1.5 GHz 4core) I get 448/10s (zeroTask) and 309/10s (zeroLog).
Using MQTTExplorer, the benchmark results are visible in a chart (In the example zeroTask, min:12148/5s, max:12595/5s):
Nevertheless, I impose the very conservative limit of 30/10s to MQTT messages for all real devices, to keep low the Tuya-cloud stress.
note on _zeroLog
SET _zeroLog(value)
returns the user value
encoded (see alldevicesnote[8]) using the default
or _zeroLog.type
or _zeroLog.typefield
rules: this allows to do encoding tests changing the _zeroLog
definitions in alldevices
.
about tests
_Also _doUPDATE
, with all trace enabled, is a good stress test: if you get any warning, fine-tune global.alldevices
.
Some _system
features are about the UI:
-
_toDebug(string|obj)
The
string|obj
is printed on the debug pad by anode.debug()
call. To share results and info between tuyaDAEMON servers. -
_toWarn(string|obj)
The
string|obj
is printed on the debug pad by anode.warn()
call. To signals problems or share alarms between tuyaDAEMON servers. - _play(WAV|string) Play a sound (WAV) or does text-to-speech function (browser dependent: set language on interface)
-
_beep
Plays the short beep stored inglobals.beep64
as WAV code64. -
_beep_loop(count, interval)
Example of tuyaDAEMON-chain: repeats the 'beep'
count
times, with aninterval
in ms.
A group of properties is present to help the user to build robust and fault-tolerant applications. This is one strong motivation for the tuyaDAEMON project.
Random or malicious events can cause serious problems. Here are some accident scenarios:
- _DBase and DB_ALARM node control the MySQL connections (note: this is placed in the CORE flow).
- loss of remote connection: tuya-cloud is out. Also the user control from the remote. Only tuyaDAEMON works. _LANnet (and the related LAN_ALARM node) are triggered by this event.
- local WiFi down: all devices are offline. Only the cabled LAN and devices (a siren?) can work. _WiFinet, WiFi_ALARM node, and _WiFiunconnected (a list of unconnected devices, including 'disabled' devices) can handle this event.
- AC power off: blackout or external action? Only UPS devices are available. Good to provide for the WiFi router, one tuyaDEAMON server, the siren, and also the IP cams... _ACpower, AC_ALARM node and _ACunconnected are triggered by this event.
It is now common for apartment thieves to interrupt the AC power and to use a jammer to disrupt communications. If you build your own security alarm think carefully to choose a good solution.
These are some low-level properties that offer access to CORE functions via messages. This way allows meta-Programmation and can be useful for applications that use REST
or for remote control:
- _doTrigger(number) Offers an alternative way to send TRIGGERs to tuya-cloud. Useful used in 'share' structures (see timer example).
-
_toLowIN(toDev, dev-msg)
The
dev-msg
is sent directly to the tuya-smart-device node, selected bytoDev
(see 'core.low_level_IN' node). To test new device functions. -
_toFastIN(std_msg)
The
standard message
is sent to the 'core.fast_cmds' node to be executed. -
_toStdCmd(std_msg)
The
standard message
is sent to the 'core.std_cmd' node to be executed. -
_toShare(share)
The
share
structure is sent to the 'core.share_IN' node to be processed. -
_toLogging(out_msg)
The
out_msg
(see 'core.logging' node) is processed like any device event.
This _system v 2.0 is now a collection of heterogeneous and basic utilities. It can be extended to meet the user's application needs. Better, it can be split into many SW-only devices, by application fields, to become specialized user "task libraries".