Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rules Engine: Property-Property rule #805

Open
hobinjk opened this issue Mar 26, 2018 · 35 comments
Open

Rules Engine: Property-Property rule #805

hobinjk opened this issue Mar 26, 2018 · 35 comments

Comments

@hobinjk
Copy link
Contributor

hobinjk commented Mar 26, 2018

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
Copy link
Contributor Author

hobinjk commented Mar 26, 2018

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 hobinjk self-assigned this Mar 26, 2018
@hobinjk
Copy link
Contributor Author

hobinjk commented Jun 8, 2018

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
Copy link
Member

benfrancis commented Jun 18, 2018

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
Copy link
Contributor

rzr commented Jul 10, 2018

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

@rzr
Copy link
Contributor

rzr commented Oct 9, 2018

@dhylands
Copy link
Contributor

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
Copy link
Contributor Author

hobinjk commented Jan 3, 2019

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

@mrstegeman mrstegeman modified the milestone: 0.3 Jan 9, 2019
@hobinjk
Copy link
Contributor Author

hobinjk commented Jan 14, 2019

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

@benfrancis
Copy link
Member

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

@rzr
Copy link
Contributor

rzr commented Jan 25, 2019

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:

  • function toLevel(color)
  • function toColor(temperature);
  • function toLevel(value, min, val);
  • etc

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
Copy link
Contributor Author

hobinjk commented Jan 25, 2019

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
Copy link
Contributor

To add some use cases:

  • A rotating knob on device A decides the intensity of lamp B.
  • A humidity value on device A rotates a servo on device B.
  • The dirtier the air, the harder an air filter should run.
  • The dirtier the air, the less hard a smoke machine should run (interverted follow).
  • A smart alarm clock without its own internal lamp outputs a percentage value. Other lamps in the room follow this percentage to create a cheap wake-up light effect.

I've actually built that last one.

@rzr
Copy link
Contributor

rzr commented May 8, 2019

As I suggested above, maybe this ticket is depending on:
#1863
(that should be reopen)
that would propagate properties of same type (and range)

and keep this one:
#805
for other cases ?

@jamesmf
Copy link

jamesmf commented Dec 30, 2019

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
Copy link
Contributor

rzr commented Dec 31, 2019

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
Copy link
Contributor

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

For example,

  • Someone could build a blockly add-on that allows for the creation of complex rules.
  • Someone could create a text-editor add-on that allows very advanced users to script directly.
  • The current basic rules interface could be a default add-on that generates very simple programming code.
  • Service add-ons could generate rules. For example, a voice control add-on could allow users to say "every day turn on the livingroom lights at 6 'o clock in the evening", and this would then be turned into a rule through the rule API.

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
Copy link
Contributor

rzr commented Jan 30, 2020

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

#690

@flatsiedatsie
Copy link
Contributor

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
Copy link
Contributor

flatsiedatsie commented Feb 5, 2020

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
Copy link
Contributor

flatsiedatsie commented Feb 5, 2020

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
Copy link

arist0v commented May 6, 2020

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
Copy link

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
Copy link
Member

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 added a commit to flatsiedatsie/addon-list that referenced this issue Jul 20, 2020
This addon allows one property to respond to a changing value of another. For example, as one value rises, another value could also be made to rise. Or it could be made to slowly decrease instead. 

It adds funtionality that cannot currently be easily created through the rules system.

If the rules system every gains this functionality, then this addon could be removed.

See also the "property to property" issue: WebThingsIO/gateway#805
@flatsiedatsie
Copy link
Contributor

flatsiedatsie commented Jul 20, 2020

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.

  • It already has some sanity checking. The minimum and maximum boundaries need to be different, for example.
  • Currently it ignores 'out of bounds' values. I thought it might give more flexibility.
  • I wonder what will happen if you enter negative values. Decimal values also haven't been thoroughly tested.
  • It does not check if a property is already used up by another follower. Currently the later followers in the list would override the actions of earlier ones. Adding some kind of ordering/hierarchy could be useful. Another option is to forbid using an 'output' property in more than one rule.

Possible future improvements:

  • If a property has minimum and maximum values set, it could drop those in place when a new Follower is created. This could also benefit from a 'swap values' button.
  • The delete icon could be placed in the top-right, similarly to that of a rule. I tried to, but more thought needs to go into the mobile/touch use case.
  • On small screens the the toggle and delete button could shift below the follower to make better use of space.

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.

mrstegeman added a commit to WebThingsIO/addon-list that referenced this issue Jul 20, 2020
* Initial release of Followers


This addon allows one property to respond to a changing value of another. For example, as one value rises, another value could also be made to rise. Or it could be made to slowly decrease instead. 

It adds funtionality that cannot currently be easily created through the rules system.

If the rules system every gains this functionality, then this addon could be removed.

See also the "property to property" issue: WebThingsIO/gateway#805

* Removed api block

* 0.0.2

* Update followers.json

Co-authored-by: Michael Stegeman <[email protected]>
@madb1lly
Copy link

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
Copy link
Contributor

@madb1lly aren't you describing the Rules system?

@madb1lly
Copy link

Hi @flatsiedatsie,

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

Cheers 🙂

@flatsiedatsie
Copy link
Contributor

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

RULE 1
left column:

  • Property 1 == on
  • Property 2 == 100
    right column:
  • do something

RULE 2
left column:

  • Property 1 == off
  • Property 2 == 100
    right column:
  • do something else

@madb1lly
Copy link

madb1lly commented Jul 23, 2020

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

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

@rzr
Copy link
Contributor

rzr commented Sep 21, 2020

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

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 ?

#805 (comment)

@flatsiedatsie
Copy link
Contributor

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

What have you patched exactly?

@rzr
Copy link
Contributor

rzr commented Sep 21, 2020

See linked patch at:
flatsiedatsie/followers-addon#7

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

@bewee
Copy link
Member

bewee commented Sep 29, 2020

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
Copy link

Is there any plan on implementing this feature?

@rzr
Copy link
Contributor

rzr commented Nov 15, 2021

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

CrossStream/followers-addon@5b3e55a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
WebThings Gateway (Old)
  
Product Backlog
Development

No branches or pull requests