I've temporarily ruled out open source. Figured I needed to do things the hard way to learn enough to know if one of the open source packages made sense or not. So... in thinking out loud...
Definition of Automation: When
this do
that
Do That
The
do that part seems pretty easy so let's tackle that first. Every
device has a set of
actions, e.g., fan1 off, fan2 speed1; where the devices are
fan1 and
fan2, and the actions are
off,
speed1. Every RF device needs a transmitter to send the action to the device, but we'll call the transmitters
controllers since these probably won't
all be transmitters. So, that can easily be setup in json like structure as:
Code:
[{name, controller, actions: [{name, data}]}]
That is a list of devices, each of which have a unique name, a controller, and a set of actions and their associated data. For example fan1 and hotWaterTankmight look like:
Code:
[...
{name:fan1, controller: bond, actions: [
{name: off, freq: 303.85, bps:1000, bits: 0001100001211, repetition: 5},
{name: speed1, freq: 303.85, bps:1000, bits: 0001100001310, repetition: 5}, ...]},
{name: hotWaterTank, controller: aeotec, actions: [
{name: off, ip: 192.168.0.44, body: off},
{name: on, ip: 192.168.0.44, body: on}],...]
The action parameters would be unique to the controller, and what the controller needs to perform the action.
When This
While polling isn't great, it's probably the most universally guaranteed way to get the state of something. For what we're doing the controllers for this are probably things like:
Code:
[
{device: envoy, actions: [gridActive, BatteryPower]},
{device: weather, actions: [solarRadiance, temperature, humidity]},
{device: clock, actions: [time]}]
You don't want to preserve state as humans can (and will) change state. You also can't get state for a lot of devices (e.g., fans). What we want is to be able to do things like:
- when envoy gridActive *true hotWaterTank on
- when clock time ~22:30 fan1, fan2 off
- when envoy gridActive false && weather solarRadiance < 700 hotWaterTank off else hotWaterTank on
The first one has a problem because most times you poll envoy for the grid state it's going to come back active, which means you'd be sending a lot of ON commands. It's also dangerous... if it was a WiFi circuit breaker and you flipped it off manually to replace the element...imagine your surprise when automation turns it on again.
It seems like physical devices will need some sort of virtual representation. For example, what we really want on the Envoy is to know the one time when the grid goes from inactive to active. Since we're polling, we can use the poll time to determine new occurrences from old occurrences, and then only take action on new occurrences when desired. So, for example, the
envoy.gridActive would only return true if the grid was active and has only been active for less then the polling cycle. But that's not always desirable, for example the gridActive false should always return false in the example above. So, how to tell the difference? I used the asterisk (*) in the examples above to indicate
first occurrence only. Similarly, on
clock time, there's a tilde (~) to indicate a +/- time around the polling cycle since it would be rare the polling occurred at exactly the matching time.
So the BNF is:
Code:
<when> ::= <condition> [ &&,|| <condition>] device [, device] action
<condition> ::= [device] [action] [~ | *] [test]
<test> ::= [< | > | <= | >= ] <value>
<value> ::= <number> | <string> | true | false
So, that's a start anyway....