eclipse-archived / smarthome

Eclipse SmartHome™ project
https://www.eclipse.org/smarthome/
Eclipse Public License 2.0
862 stars 783 forks source link

Obtaining the ThingStatus from an item (e.g. within sitemaps or rules) #5149

Open pfink opened 6 years ago

pfink commented 6 years ago

There are different use cases that require obtaining the ThingStatus from an item within sitemaps or rules (e.g. here or here). I open this issue as a further base of discussing how we can extend ESH so that these use cases can be solved better in the future.

Josar commented 6 years ago

And here obtaining binding status of a Thing linked to an Item.

triller-telekom commented 6 years ago

First of all I think this is a nice feature to have!

Unfortunately we have the problem that we do not want to mix the physical layer (i.e. things) with the functional layer (i.e. items). So when introducing such a feature we have to be careful to not fully mix up the two layers.

The ThingStatus is available in our "admin user interface", i.e. Paper UI, so an admin user knows which things are reachable and which are not. In our user interfaces for "users of the system" we only show the functional layer, i.e. the items. In a lot of cases the ordinary user happens to be the admin user as well so we could argue that he could look into the admin interface and find out whether a Thing is online or offline. However in reality this is not necessarily the case!

I would therefore propose a sketch of a solution for this problem:

Right now we have two events: ThingStatusInfoChangedEvent and ThingUpdatedEvent, both carrying information about the state of a Thing. We could therefore create a service that subscribes itself to these events and creates a new ItemLinkStatusEventcontaining the information for a specific Item whether its linked Channels point to an online or offline Thing. The service will also cache all these calculated state information (to send it out only if something changes) and can be asked "what is the link status of item xyz?".

This new ItemLinkStatusEvent can be send out via SSE also to UIs like Basic UI, etc. For Basic UI we also need to take care of its SitemapWidgetEvents so they also contain this information.

In addition the REST interface should be extended so the ItemResource returns DTO objects containing the link information, i.e. whether the Item is linked to something that is online or offline.

If UIs have the information about the ThingStatus of the Thing which is behind the Channel of an Item it can render a hint saying "Careful when interacting with this control, it might not work" or something. Or they even could disable the controls of that particular ´Item` completely.

This also addresses #5122. If one defines a ´Thingvia a.thingsfile and theGenericItemProviderwants to create an ´Item which has a Channel pointing to a Thing whose ThingUID resides in a non-installed binding it delays the creating of such a Thing, so it creates the Item with a Channel that points to "nowhere". We could treat this the same way as if the Thing is offline.

Rules can ask the new service for the "link status" of an Item too.

Problems that need to be discussed:

What if the Item is linked to multiple Channels of different Things of possibly different bindings?

Users that wish to have more control over the default behavior above could create a GroupItem with Items that each have only one Channel, instead of multiple Channels on one Item. For these GroupItems in sitemaps we could have a configuration parameter that allows changing the behavior which we have defined for Items with multiple Channels, i.e. we can have a function that calculates the Group state based on the online/offline information.

Josar commented 6 years ago

Sounds like an good approach.

I would also suggests an error for

Thing whose ThingUID resides in a non-installed

There just has to be an option to choose how the ui behaves when the item is offline.

  1. Grayed out non functional, good for single channel or to restrict if neccessary that all channels have to be available.
  2. Change color to red or what ever, signalizing here is something wrong. Can be used if other channels schould be able to be triggered if one fails.

Item will be offline as soon as one channel is oflline, UI will will represent that.

meingraham commented 6 years ago

Any progress?

maggu2810 commented 6 years ago

Personally I don't think it make sense to mix the Thing's status and the items.

An item could be linked to 0, 1, ... (0..n) channels of a thing.

It could be wired to a things channel by rules and so not by a link.

The detection of online / offline of a thing depends on the binding and the connection to that things. Perhaps the offline / online detection can also be identified on interaction with the real device (e.g. only on sending a command and receive or not receiving a reply but no change to send something without user interaction because it will trigger a change on the device)...

IMHO the suggestion above will fit for some cases but not for others. I don't think it should be added to the framework that way.

@kaikreuzer, @sjka, @htreu WDYT?

htreu commented 6 years ago

I second @maggu2810's opinion. Especially the 0..n relationship between items and channels makes it impossible to provide a consistent solution. I suggest to work around this issue by using thing based tiggers as stated in the openHAB docs:

With

Thing <thingUID> received update [<status>]
Thing <thingUID> changed [from <status>] [to <status>]

it should be possible to modify synthetic items and react to thing status changes.

timcharper commented 5 years ago

The real thing that is wanted, for me, is an easy mechanism to access the things OFFLINE status. I'm working on the Homekit binding and I want to report if a LeakSensor is unreachable, so this notification can be surfaced appropriately, for example.

EDIT

It looks like ItemChannelLinkRegistry has the method I want: getBoundThings. Neat.

pfink commented 5 years ago

Other idea: Each thing provides a predefined online channel (type: Switch) without the need of any implementation by the binding developer. Easy to implement and less complicated for users compared to the other approaches as it does not require the knowledge of any new mechanisms or syntax. Many use cases could be covered very nicely with our existing features (e.g. Multi-Channel linking, Group functions, ...).

timcharper commented 5 years ago

That's an interesting idea. I was wondering if it'd be a bad idea to make online/offline an inherent property of channels.

Really, as one working on an addon, I'm mostly interested in an efficient way to get the thing(s) from which an item's status is derived. ItemChannelLinkRegistry is a way, but it's not efficient. If Items could just keep track of associated things and update their list as bindings are removed / added, that would be pretty helpful. Then there could be a method call on Item such as .getBoundThings().

EDIT

On second thought I over estimated the complexity of ItemChannelLinkRegistry.getBoundThings; I had the impression there was a scan or two involved in finding bound things, but it looks like it's a few Map lookups and a few Set instantiations. It's probably fine.

It'd still be convenient to have a getBoundThings method on Item, but still, this is fine.

EDITED AGAIN

Well, I'm feeling sheepish. I had assumed all along (I'm not sure what gave me this impression) that a Thing could be offline while the linked item state is defined (IE not UNDEF), but upon further experimentation I've realized that items values are automatically translated to UNDEF when their associated thing is offline.

Perhaps this can be called out better in the docs? It'd be nice to have a warm cozy assertion that we can rely on this behavior.

htreu commented 5 years ago

a warm cozy assertion that we can rely on this behavior

Sorry, but this can not be taken for granted. The state of an item can not be used to derive the status of a thing. Your approach using ItemChannelLinkRegistry.getBoundThings sounds okay to me though.

timcharper commented 5 years ago

Sorry, but this can not be taken for granted. The state of an item can not be used to derive the status of a thing.

And, corollary, the state of an item can not be derived from the state of a thing. IE the expire binding combined with MQTT generic items. :/