WebThingsIO / gateway

WebThings Gateway
http://webthings.io/gateway
Mozilla Public License 2.0
2.61k stars 333 forks source link

Rules Engine: Property-Property rule #805

Open hobinjk opened 6 years ago

hobinjk commented 6 years ago

Select something like Property "level" as trigger, Property "on" as effect, the rule now maps from level to on as necessary. Note that this also works from level to level and is distinct from the current numerical level trigger "when {numerical property} is greater than {value}"

hobinjk commented 6 years ago

This might be difficult to represent in the current UI and will need to fall back to a LevelTrigger centered around (min + max) / 2 in some cases

hobinjk commented 6 years ago

The current idea I have is to have a FollowEffect which while active causes the property to follow another specified property. This would look like

const followEffect = {
  property: {
    name: 'temp',
    type: 'number',
    href: '/things/thermostat/properties/temp',
    unit: 'celsius',
    description: 'thermostat setpoint',
  },
  leaderProperty: {
    name: 'level',
    type: 'number',
    href: '/things/dimmable-bulb/properties/level',
  },
  type: 'FollowEffect',
};

This would also require a bit of changes to the existing UI to have enough space to select two properties at once. It also is a little confusing since it would only follow when the trigger of the rule is active so there would be a need for the kludge of an if $property > -100000 trigger if you want the following to always happen (or a special always trigger)

benfrancis commented 6 years ago

For the use case of having one property follow another, wouldn't it be better to have a property change trigger (triggered whenever a propertyStatus message is sent, with an output value) and a set property effect (which accepts an input value, like the setProperty message)?

This would require a slightly different UI to what's currently implemented. It would require you to pick a property and then select whether you want a particular condition to trigger the rule (e.g. greater than, less than or equals), or for any change in the property to trigger the rule. Then for the output side you'd need to select the property you want to set and somehow pick the input property as the input value rather than a constant. It gets particularly tricky if the scale of the input and the scale of the output don't match (e.g. a temperature mapping onto a brightness level rather than a percentage mapping onto a percentage).

rzr commented 6 years ago

May I suggest to add a refresh rate to the "follow" feature.

rzr commented 5 years ago

Let me crosslink to: https://discourse.mozilla.org/t/using-a-multilevelswitch-thing-level-property-to-control-brightness-of-lights/31951

dhylands commented 5 years ago

The Zigbee OSRAM 2 button switch implements level and on/off. The level has a rate, and the adapter starts a timer which updates the level at the prescribed rate as long as the button is pressed.

This will generate propertyChanged notifications each time the level changes.

2018-10-11 13:00:38.537 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 13 min: 0 max: 100
2018-10-11 13:00:38.786 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 26 min: 0 max: 100
2018-10-11 13:00:39.037 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 39 min: 0 max: 100
2018-10-11 13:00:39.288 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 52 min: 0 max: 100
2018-10-11 13:00:39.539 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 65 min: 0 max: 100
2018-10-11 13:00:39.789 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 78 min: 0 max: 100
2018-10-11 13:00:40.040 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 91 min: 0 max: 100
2018-10-11 13:00:40.291 debug: Got: propertyChanged notification for: zb-8418260000e8f328-button property: level value: 100 min: 0 max: 100
hobinjk commented 5 years ago

Concept of one way to implement the UI for this. @benfrancis thoughts? Base display: screen shot 2019-01-03 at 1 59 00 pm Editing as a dropdown:

screen shot 2019-01-03 at 1 59 05 pm

Alternatively, editing as the "flip side" of the rule part:

screen shot 2019-01-03 at 1 59 10 pm
hobinjk commented 5 years ago

I think I favor the dropdown style since it can scale more freely: dropdown_action

benfrancis commented 5 years ago

This is a tricky one, none of these feel particularly intuitive. Would be great to get a UX designer on this one.

rzr commented 5 years ago

I see 2 problems here,

1st we miss a feature to propagate a value from one property to an other (assuming prop are in same type and range), so we need to identify compatible input/outputs (in schemas?).

2d. In case properties are mismatching we need a way to transpose from one context to an other. to do that we could eventually add "generic functions" things that could adjust a property.

Examples:

Then function blocks could be viewable/editable from UI and routed using the rule tool... I think this could be done using add-ons.

Or maybe there are different approaches ? may this relate to W3C WoT's scriptlets ? https://www.w3.org/TR/wot-scripting-api/

My 2c

hobinjk commented 5 years ago

For the first, I would plan for Thing and Property to be dropdowns populated only with compatible properties (and things with compatible properties).

The second one is something I think would be better handled by a scripting subsection. I imagine this as similar to scriptlets but without the expectation that they'll be in a generic language that can be run on individual WoT implementations. Instead, the idea would be to provide a simple environment to author scripts like https://github.com/twobraids/pywot/blob/master/demo/rule_system/example_if_rule.py

flatsiedatsie commented 5 years ago

To add some use cases:

I've actually built that last one.

rzr commented 5 years ago

As I suggested above, maybe this ticket is depending on: https://github.com/mozilla-iot/gateway/issues/1863 (that should be reopen) that would propagate properties of same type (and range)

and keep this one: https://github.com/mozilla-iot/gateway/issues/805 for other cases ?

jamesmf commented 4 years ago

A use case that seems really powerful is a rule like:

When property X changes on input Thing, perform action A on output Thing with the value of property X passed to its input.

Seems like this property-property functionality would require at least tackling the "rule when property X changes at all" concept. Any idea if the second half (and pass it to action input) is doable?

rzr commented 4 years ago

If we want to pass properties, first then they should be named in expressions, It should be easy to use JS template strings but I suppose users are expecting a nice UI too but if it only rely on UI actions it can become boring.

Note that "Scale" operation is only one among others, if we want to generalize "transfer functions" maybe a matrix would me more flexible.

I would be also in favour to support some kind of "scriplets blocks" in UI, or eventually a way to extends possible operations (through add ons).

This issue is not specific to IoT, maybe it would make sense to inspire to other "block programming" editors (ie: scratch, lego, or other "smart toys" etc).

It would be awesome if there was a JS framework addressing this specific problem, any suggestion ?

flatsiedatsie commented 4 years ago

Perhaps rules could be some standardised programming code, and add-ons could generate it?

For example,

In Domoticz, the blockly feature generates LUA code. Alternatively users can also just create code directly if they want.

It might simplify development for Mozilla, since only a rules API would have to be created and maintained. The UI on top of that could be completely separate and interchangeable.

rzr commented 4 years ago

I just noticed this, may some parts be factorized between node-red and wt gw:

https://github.com/mozilla-iot/gateway/issues/690

flatsiedatsie commented 4 years ago

I always imagined something like:

gateway_rule_inverted_follow

"For the range of values from the fine dust sensor below 15, invert them to a range of 100 to 0 for the lamp's brightness"

Or something along those lines. But I understand the limitations of this approach.

flatsiedatsie commented 4 years ago

Another experiment:

gateway_reverse_follow_experiment

In this case values between 0 and 15 from the dust sensor are translated to value from 100 to 0 on the lamp. Values below and 0 and above 15 are clamped.

This makes it easy to do reverse follow or normal follow, and it solves the issue that a lot of properties don't have a pre-set range. Or they might have a pre-set range that is never practical in real life (if my CO2 sensor ever measures it's maximum possible value of 5000, we'd all be dead).

What's more, something like this would allow for handy things like setting the output between 50 and 100: "the light should always be at least 50%, and only the intensity should fluctuate based on the sensor value". That way the light is always on.

It could, oddly, even act as a normal threshold toggle: "Dust sensor values between 50 and 51 are mapped to 0 and 1 of the binary switch" means that the switch is off at 50 or lower, and on at an input of 51 and higher.

If people wanted a non-linear response, they could string a few of these rules together. For example: 0 to 10 -> 0% to 20% brightness 10 to 20 -> 20% to 80% brightness 20 to 30 -> 80% to 100% brightness

Freewheeling some more: it would be interesting to react to the progress of time. Users could create complex overlapping patterns. Imagine a smart alarm clock add-on. Based on a motion sensor that's pointed at the best, the add-on determines it's a good moment in the sleep cycle to start the wake up procedure. Over the next 5 minutes the add-on only does one thing: it will gradually increase a property on an alarm thing from 0 to 300 (seconds). Through rules, other devices can then be hooked into that "timeline":

Between 0 and 60 (the first minute) a small night light increases its brightness between 40 and 200 a second more powerful ceiling light joins in, and also starts increasing in brightness. between 120 and 300 the radio volume increases from 0 to 100% at 121 the radio is switched on If at 300 the user still hasn't toggled the snooze or "we're awake" button, the add-on sounds a harsh alarm.

And so forth. The user can use the rules engine to make a symphony to their liking. They essentially get a free smart alarm clock / wake-up light by using the smart devices they already own.

flatsiedatsie commented 4 years ago

Another experiment:

If a user could set a rule as a special "follow type", then they might do something that stays close to the current design:

gateway_follow_type_rule

Although this example shows how having more than one 'source' would create trouble. But that could just be a limitation of the "follow type": it only has one slot on the left, and if you drag another item to the left side, it will replace the thing that was already there.

arist0v commented 4 years ago

Maybe we could just use some kind of environnement variable linked to the value of a sensor and then also link it as the value of an input(ex outdoor temperature shown on some thermostat)

madb1lly commented 4 years ago

Hi all,

I also need this. It would be great if this could be achieved in the gateway, but that appears to be too difficult to agree/make work. So what are the alternative ways to make complex (or not even complex, just different) rules like this?

The easiest way for me to do this is to create a new native WebThing that takes the properties from the other Things I'm interested in, runs the algorithms and generates the results as its own properties, which I can then use as triggers for rules in the Gateway.

Then I thought, would it have to be a separate, physical, WebThing? No, I presume not. Why not a virtual WebThing running on the Gateway machine? Then how would I add this to the gateway? Same IP address and with the thing-url-adapter? This would probably be easiest for me.

But it's not a very elegant solution is it. What about an add-on that allows the creation of virtual things which implement these more complex rules?

What about accessing the properties of other Things in order to implement these algorithms? For an addon I presume it is straightforward to access these from within the gateway, but what about if I implement a separate WebThing? Can an external WebThing access properties of other Things in the gateway?

Please excuse the "thinking out loud", brain dump, and questions to which the answers are I'm sure readily available, I'll go looking for them tomorrow, I just wanted to get my thoughts down whilst they were arriving!

Cheers 🙂

benfrancis commented 4 years ago

Yes, an external web thing could access other things via the gateway's Web Thing API. Ideally it shouldn't require creating and dummy web things that don't represent physical devices though. Theoretically I think this could be implemented as a (service or extension?) add-on or external web application which reads and writes properties via the Web Thing API. E.g. a web application (running on the gateway or elsewhere) could listen for propertyStatus messages on a WebSocket and send corresponding setProperty messages to another web thing.

flatsiedatsie commented 3 years ago

I've created an addon for this functionality. It's called "Followers". A picture says more than a thousand words, so:

Followers

An easy way to test it is to create a countdown for 100 seconds using Voco, and then using the Snips > countdown property as the 'source' property. For example, as the countdown decreases from 100 to 0, the brightness of a lamp will also slowly decrease.

It also implements the 'reverse' option. Simply input reverse values (see the bottom example in the picture). In that case the lamp will slowly get brighter.

Possible future improvements:

I know @mrstegeman would prefer this functionality be incorporated in the Rules functionality. This addon could be retired when that arrives. Until then, this works. I wonder if separating it out could actually be a positive thing. For one thing, it might keep things simple.

madb1lly commented 3 years ago

Hi @benfrancis, Thanks for the pointers, I need to 1) learn JS 😉 and 2) work out how to make the addon to do that. For 2) it looks like @flatsiedatsie already did something I can work fom 😄

@flatsiedatsie that looks great, good work. It's more than I need, which is just a simple comparator (if thingx.propertyy [comparison operator] thinga.propertyb then do this else do that), but I'll try and understand what you did and see if I can make something that does what I need.

Cheers 🙂

flatsiedatsie commented 3 years ago

@madb1lly aren't you describing the Rules system?

madb1lly commented 3 years ago

Hi @flatsiedatsie,

As far as I can tell there's no way to compared two properties in the rules system, is there?

Cheers 🙂

flatsiedatsie commented 3 years ago

I was thinking you could perhaps split it into multiple rules. Something like:

RULE 1 left column:

RULE 2 left column:

madb1lly commented 3 years ago

Hi @flatsiedatsie, Thanks for trying to help me understand, let's continue our conversation here: https://github.com/flatsiedatsie/followers-addon/issues/4. Cheers 🙂

EDIT: Misunderstanding, it was a suggestion to use the rules engine but on reflection this won't work.

rzr commented 3 years ago

Hi some updates I've patched @flatsiedatsie's in an ugly way to provide this copy mecanism:

Watch video at:

https://github.com/rzr/mastodon-lite

[mozilla-iot-activitypub-adapter-apconf2020-rzr]( https://peertube.mastodon.host/videos/watch/b0357106-2c8a-42b0-aeb3-efe4a6b0e127#mozilla-iot-activitypub-adapter-apconf2020-rzr# "Watch on peertube" )

After looking into this adapter I had the feeling it was over engineered but it works!

What about @hobinjk UI suggestions ? Any plans to implements this ?

https://github.com/WebThingsIO/gateway/issues/805#issuecomment-451242864

flatsiedatsie commented 3 years ago

I've patched @flatsiedatsie's in an ugly way

What have you patched exactly?

rzr commented 3 years ago

See linked patch at: https://github.com/flatsiedatsie/followers-addon/issues/7

Are you in matrix room at: https://chat.mozilla.org/#/room/#iot:mozilla.org ?

bewee commented 3 years ago

Select something like Property "level" as trigger, Property "on" as effect, the rule now maps from level to on as necessary

This can as well be achieved using Macrozilla, which is now available via the add-on list. image Using a graphical editor, this add-on allows you to define macros which consist of one or more triggers, conditions and actions. Whenever one of the triggers (thing property changed / thing event was raised / surise ends / ...) gets triggered and all the conditions (thing property has a certain value / it is after sunset / variable has a certain value / ...) are fullfilled, all the actions (set thing property to a certain value / increment a variable / wait a second / ...) will be executed consecutively.

bsunderhus commented 2 years ago

Is there any plan on implementing this feature?

rzr commented 2 years ago

None I know meanwhile you could reuse this change I made for an other use:

https://github.com/astrolabe-coop/followers-addon/commit/5b3e55a58f9b13735b37740f7f89d818f384c6aa