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

RFC: Measurable attributes should be sensors #11118

Closed
balloob opened this issue Dec 13, 2017 · 9 comments
Closed

RFC: Measurable attributes should be sensors #11118

balloob opened this issue Dec 13, 2017 · 9 comments

Comments

@balloob
Copy link
Member

balloob commented Dec 13, 2017

#10732 started having 2 conversations in 1. This splits out the conversation about having attributes that contain measurements be represented as standalone sensors.

@balloob
Copy link
Member Author

balloob commented Dec 13, 2017

So one thing that I don't see mentioned in the discussion at all is our abstract base classes. We define how a thermostat works, the developer just fills in the properties and methods and you get a nice UI and, because all thermostats follow the same base class, a unified interface to control any thermostat of any brand. For people proposing we split all attributes as sensors, would you expect the components to figure out which sensors and entities are being maintained by an integration?

@tboyce021
Copy link
Contributor

I may be misunderstanding because I don't know much about the core code, but I think this is where the idea of a "device" level comes into play. The thermostat would be a "device" and all states related to it's operation would be stored under it. Most of these would be predefined (temperature, target temperature, battery level, etc.) but we may want to consider allowing additional states that could be accessed for automation or controlled by custom UI if we can't realistically handle special cases. Each device type would require certain states to be present on the device in order to operate (temperature, target temperature, etc. for thermostats).

Essentially, I think what I'm envisioning is basically making the state field a dict and moving any dynamic attributes into that dict along with the single state value that we currently have. Entity then become the same as "device". I'm not sure if we need a way to specify a primary state or not. I don't know what it would really be used for other than UI, which could be handled elsewhere.

@NovapaX
Copy link
Contributor

NovapaX commented Dec 13, 2017

Yes. That would be my way of modeling that data too.

The only problem is that currently every entity is a member of a singly domain (switch, light, sensor).
But wall plug can switch and measure. So what domain should that be put in?
The attribute could be part of a domain, or the entity could be part of multiple domains.

Say I have a power strip with 6 switchable outlets and power + total energy measurement on each outlet. It also has combined power+total energy measurement, and fancy controllable RGB light.
How should this be exposed?

  1. as 21 different entities and states (6 switches, 14 sensors and 1 light) with duplicate device info about model/manufacturer/connection state
  2. as 22 different entities: 1 parent state (with device info) + 21 child entities
  3. as 8 different entities: 6 switches (with additional attributes for power measurement in their state) + 1 sensor for the total power measurement + 1 light. (with duplicate device info in the state)
  4. as 8 different entities: 1 parent entity with device info and total power measurement attributes) + 7 child entities (6 switches and 1 light)
  5. as 1 device entity with 21 "entity attributes" in its state.

things to consider for the various options:

  • How many states are getting updated on a new readout of the power strip.
  • How easy would it be to use the different readouts as triggers for automations
  • How are the entities displayed by default in the UI
  • Which services should I be able to call on what entity
  • How to define the base classes (domains?) on the different entities.

This is not an easy problem imo.

@balloob
Copy link
Member Author

balloob commented Dec 13, 2017

Comment by @armills (he posted in the wrong issue)


Potentially less disruptive proposal that covers both issues:

We create a new domain device, for which each entity represents a single IoT device. (i.e. 1 multisensor, 1 thermostat, 1 smart bulb, 1 switch, etc.) The attributes on this entity can store all of the metadata. (firmware, brand, etc.) The existing entities can use an attribute device_id to associate themselves with this device.

  • Since the attributes on the device entity shouldn't change often, we won't have the problem of logging them on every state change.

  • The frontend could use the device_id to make decisions about how to order/group entities if we wanted to, and we could even display the device entity as its own card with a summary of the different entities.

  • Since entities are only linked to a device, we don't open the door to arbitrary nesting of entities.

  • It's a non-breaking change, and the implementation can be rolled out as platforms gain support. It's just a single new entity/attribute that doesn't break the existing way we do things.

@tboyce021
Copy link
Contributor

tboyce021 commented Dec 13, 2017

@NovapaX, my best attempt at the considerations:

  • How many states are getting updated on a new readout of the power strip

I think it would be nice if it was a single state change event for the "device" (i.e. the entire strip) mostly just for performance reasons, but obviously automations that trigger based on a single state (e.g. sensor.power_strip_outlet_1_power) need to trigger appropriately.

  • How easy would it be to use the different readouts as triggers for automations

Unless I'm missing something, I haven't found a way to use the current attributes as triggers without using a template trigger, so either way this should make that easier sensor.power_strip_outlet_1_power and sensor.power_strip.outlet_1_power are nearly identical in terms of writing the templates, but obviously the first one matches what we have currently.

  • How are the entities displayed by default in the UI

I would personally be alright with either displaying all entities within a group representing the device or just displaying them all individually. Displaying them individually by default may be easiest and I'm guessing as long as there's a way to link the entities together, custom UI or something could easily group them for you if you want.

  • Which services should I be able to call on what entity

For the most part, the services would match the entities (switch services for each switch, and light services for the light). If the strip supports anything beyond those, it could just have its own service (fancy_power_strip.do_something).

  • How to define the base classes (domains?) on the different entities.

This part I don't really know. But, look at something like the Nest component or any other hub component that creates entities in multiple domains. Could we use something along those lines?

@BioSehnsucht
Copy link
Contributor

If adding a new device domain as @balloob proposes, then regarding the issue of whether UI should group all members of the device or not, probably stick to the naive default behavior we have now (list all things by domain), then add an option for when creating a custom view that lets you do something like group.device.device_id to create a group of just the entities that are part of that device_id

@rytilahti
Copy link
Member

rytilahti commented Dec 14, 2017

Say I have a power strip with 6 switchable outlets and power + total energy measurement on each outlet. It also has combined power+total energy measurement, and fancy controllable RGB light.
How should this be exposed?

as 8 different entities: 1 parent entity with device info and total power measurement attributes) + 7 child entities (6 switches and 1 light)

This is the closest that I think how it should work. If each outlet has a energy measurement possibility, the sensors do belong under the switch entity, not under the power strip as is the case with the light.

One power strip entity (or device as discussed above), consisting of:
  * Switch[6]
    - turn_on()
    - turn_off()
    - switch_custom_service()
    - .. and_other_switch_domain_functionalities ..
    * Sensors:
          - temperature sensor
          - voltage sensor
          - ..
  * Children of Switch light entity
How many states are getting updated on a new readout of the power strip.

Each sensor has a state.

How easy would it be to use the different readouts as triggers for automations

Each sensor would still exists under the sensor domain, so they should be trackable by any automation. The strip itself would be a logical composition of its sub-entities.

How are the entities displayed by default in the UI

The platform developer of this "strip" device has to decide how the information is best exposed to the users. Although preferably the UI will have a tab containing access to all of its sub-entities. A summarized form however should be decided by the developer, and be kept concise and useful.

Which services should I be able to call on what entity

I think one should be commanding the specific entitity, but that the main platform could provide global services where feasible.

How to define the base classes (domains?) on the different entities.

The base classes / domains of sub-entities shall follow the structure of existing related domains. E.g. light of the strip should follow the API of light domain (where it also resides). The switch #1 is still a switch, implementing its interface.

So code-wise I would expect the following:

  1. Strip entity creates 1x light.<strips_id>_<some_random_uuid> and 6x switch.<strips_id>_<some_random_uuid> entities.
  2. All those entities are passed a reference to the strip entity, which is how they interface and get updated by the strip.
  3. Each switch and light provide the functionality those domains already do.
  4. The developer of this strip platform will implement turn_off as he sees fit. If the switches support separate switching on/off, the turn_off should be targeted on the wanted switch. If that is not the case, the switches themselves shall not implement turn_off, as it is a functionality of that strip.

edit: to add, I like @armills proposal for how this probably should work on the low-level. Although I'm unsure if it makes sense to add a new domain instead of choosing the most suitable and use it as a base? In case of this strip example it would be a switch.

edit2: on API level the strip developer should hold the ownership of those entities, if I create a switch.tplink I should be able to add sub-entities (and update them as needed) for those sensors without requiring to construct a full-blown component.

@c727
Copy link
Contributor

c727 commented Feb 15, 2018

I think this topic needs some more attention as we run into issues around this again and again:
Imo we should have separate entities for each state, here is a concept for a light domain:
un22benannt

some more notes: https://docs.google.com/presentation/d/12tu2G7lV4Ybph6_u7tz35WBI1pXQwcKsGF9SPj_ucPM/edit?usp=sharing

@ghost
Copy link

ghost commented Feb 15, 2018

This issue was moved by @balloob to home-assistant/architecture/issues/8.

@ghost ghost deleted a comment from balloob Feb 15, 2018
@ghost ghost closed this as completed Feb 15, 2018
@home-assistant home-assistant locked and limited conversation to collaborators May 29, 2018
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants