Coder Social home page Coder Social logo

architecture's Introduction

Home Assistant Chat Status

Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server.

Check out home-assistant.io for a demo, installation instructions, tutorials and documentation.

This is a project of the Open Home Foundation.

screenshot-states

Featured integrations

screenshot-integrations

The system is built using a modular approach so support for other devices or actions can be implemented easily. See also the section on architecture and the section on creating your own components.

If you run into issues while using Home Assistant or during development of a component, check the Home Assistant help section of our website for further help and information.

architecture's People

Contributors

agners avatar bachya avatar balloob avatar cerebrate avatar colinfrei avatar ctalkington avatar emontnemery avatar frenck avatar ikifar2012 avatar imicknl avatar ludeeus avatar lukastribus avatar martinhjelmare avatar matthewflamm avatar pvizeli avatar scop avatar spacegaier avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

architecture's Issues

RFC: First-class entity like input_select

Background

I'm relatively new to HA and am integrating it with ZoneMinder. One of the main features that I wanted to control are ZoneMinder's Run States, effectively a named group of camera/monitor settings that can be switched between via the API.

Logically, this is an enumeration of string Run State names that's pulled from the ReST API (the list of options, and the currently-active option). The API also exposes an endpoint to set the desired run state.

I did some investigation on the forums and Google for what others have done, and the two threads I found both reference cobbling something together with a manually-curated input_select and then some automations or scripts.

Before I realized that input_select is a purely user input construct (thanks @balloob ) I did some non-zoneminder-specific investigation and found many references on the forums of this common pattern of integrations that expose a set of options and have one of that set as "current" - essentially the programmatic equivalent of input_select (I found a large number of the forum search results for "input_select" to be some combination of wanting to update the list of options, update the selected option, or take action on a user selection, via a component or other integration).

Proposal

For the use cases described above, I believe it would be of great benefit to have a first-class component that allows selection of a single option from a dynamic list of options (like input_select) but has the first-class update/polling/action capabilities of full Entities (i.e. a multi-valued switch).

Group platform definition

So interest has been shown in implementing "group" platforms for several PlatformComponents. To recap, group platforms are platforms that encapsulate and proxy the state of several "child" entities. (Just like Hue, ... light groups)

screen shot 2018-02-19 at 22 19 51

For example, if I have four lights along the corners of my room, I could now (using "light.group") let them show up as one in the front-end.

While I personally love this feature and can't wait for it be added, we definitely shouldn't rush this. We should first try to define what a "group" platform is, how the user expects it to behave, and how configuration should look like.

During this post I will mostly be referring to grouped lights, as that's the component I'm most familiar with. If there are other components that need different configs/behavior, please contribute.

I think our first concern should be abaut how a user expects the group to behave (maybe mimic the behavior of Hue, ... groups) and only then what features it should support.

Related: home-assistant/core#12229, home-assistant/core#11323, home-assistant/core#12303

Behavior

Features: Union / Intersection

So I think first we should define whether the functionality of a group is the union or the intersection of the features of its child components.

For example, if we're setting up several lights into a group, like all lights in the 1. floor, if one of the grouped lights doesn't support RGB colors and all others do, should we disable colors for the entire group? I think this would eventually happen quite often as light groups are potentially great for combining lights of different domains (for example Hue and MQTT lights). Maybe we could even add a configuration option to control this.

State reporting

Next, we should define what state should be reported to the front-end. For example, for a light it would IMHO make very little sense to report the average brightness of all child lights. So one option is to report the state of the first entity - another option would be to report the state of the first entity that is on. Maybe we could even have a "leader" option in the configuration to select this. If one light is on, should we display the whole group as on (as we do in the "normal" groups)? There are many different ways of doing this, and also one of the things we should really be consistent about.

As another example, in lights, should we report all possible effects you could set as effect_list? Should we use the minimum possible min_mireds value or the value of the leader. If we call light.toggle on a light group, should we use our reported state to sync all lights to be of the same state after the toggle, or should we toggle each light individually (probably not too good IMO). So another question: Should we always try to sync the state of all children?

Initial state

Also: What do we report when no child entity has a state yet? Personally I would advocate for STATE_UNAVAILABLE since that also visually shows in the front-end that you can't control it.

Configuration

Ideally, the configuration would look more or less exactly the same between different components. And I personally also think we should keep customization at a minimum and the default behavior "as dumb as it gets". Why? We have the template platforms to do more complicated stuff and lots of customizability will just scare off users IMHO.

So, do we want the configuration to look something like this: ?

light:
  - platform: group
    name: Cool Light Group
    entities:
      - light.amazing_light
      - light.foobar
      - light.sun

Are there any other features groups should definitely support? Anything we should consider concerning other components?

Front-end support

This is very much a hypothetical, but as @balloob said "We might even add frontend support for "group" platforms to show the child entities." I think we should at least think about how it should be done.

RFC: Add set_state service to Camera

Camera defined three states [STATE_RECORDING, STATE_STREAMING, STATE_IDLE], but don't have services to allow user change state.

Proposed Solution:

Add abstract set_state set_mode service to Camera, take entity_id and state mode as parameter. Using different mode const to clarify that shall not directly set state machine, [MODE_RECORDING, MODE_STREAMING, MODE_IDLE]. Each platform should have its own implementation

Alternative Solution:

Add generic turn_on turn_off service to Camera.

  • turn_on has entity_id and state mode as parameter (MODE_RECORDING or MODE_STREAMING)
  • turn_off only has entity_id

Approved Solution:

  • Adds supported_feature support modeled after the light component. Limit to only turn_on/turn_off as a feature.
  • Add service to turn on/off a camera entity (also modeled after how light component does services)
  • Update the demo component to support turn on/off. Do not include other platforms in this PR.

Configuration directory

This is a two-part issue.

The simpler to describe, and possibly solve part, is that many programs now use ~/.config to store their configuration files. In particular in OSX and Linux/Unix this is the trend. Google XDG_CONFIG_HOME environment variable for more.

The more complex piece of this discussion is that the configuration directory (.homeassistant) contains a mix of different purposed "stuff". For example a quick scan of my config dir show:

  • Edited YAML files that are part of my configuration
  • Generated YAML files (e.g.: Harmony)
  • www directory that contains code (Lovelace monster card in my case)
  • custom_components that contains code (ElkM1 in my case)
  • Log file(s)
  • deps directory, which looks like a virtualenv setup, not sure of its purpose (I actual run hass in my own virtualenv while developing)
  • tts directory, not sure of its purpose

I have two proposals.

  1. On appropriate OSs use the ~/.config for configuration. ~/.config is the default with fallback to .homeassistant; Use XDG_CONFIG_HOME as appropriate.
  2. For more discussion but general goal is editable configuration exists alone in a directory (tree). Code, logs, generated configuration is not mixed in with edited configuration.

A starting proposal for directory structure:

.config/home-assistant
โ”œโ”€โ”€ config
โ”‚ย ย  โ”œโ”€โ”€ automations.yaml
โ”‚ย ย  โ”œโ”€โ”€ configuration.yaml
โ”‚ย ย  โ”œโ”€โ”€ secrets.yaml
โ”‚ย ย  โ””โ”€โ”€ ui-lovelace.yaml
โ”œโ”€โ”€ custom-components
โ”‚ย ย  โ””โ”€โ”€ elkm1
โ”‚ย ย      โ”œโ”€โ”€ alarm_control_panel
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ elkm1.py
โ”‚ย ย      โ”œโ”€โ”€ climate
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ elkm1.py
โ”‚ย ย      โ”œโ”€โ”€ elkm1.py
โ”‚ย ย      โ”œโ”€โ”€ light
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ elkm1.py
โ”‚ย ย      โ”œโ”€โ”€ sensor
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ elkm1.py
โ”‚ย ย      โ””โ”€โ”€ switch
โ”‚ย ย          โ””โ”€โ”€ elkm1.py
โ”œโ”€โ”€ logs
โ””โ”€โ”€ www
    โ””โ”€โ”€ monster-card.js

Invalid characters in entity id are silently accepted, breaks service calls to that entity

Home Assistant release with the issue:
0.68 (likely older releases too)

Last working Home Assistant release (if known):
Unknown

Operating environment (Hass.io/Docker/Windows/etc.):
Docker

Component/platform:
New component/platform under development for Elk M1 automation / security system panel - but issue likely would affect any entity making the same mistake I did

Description of problem:
If you use invalid characters for entity_id such as uppercase letters, HASS may silently accept it without error, but service calls to the entity will never find it. I had forgotten to .lower() the entity id before assigning it and couldn't figure out why service calls wouldn't work - when I looked in HASS developer tools / entity states it appeared lower, so I didn't realize I had goofed right away.

Attempting to toggle switches / lights stopped working (originally was working, but made changes to how entity ids were created which lead to the problem of accidental uppercase), and as far as I can tell due to the entity id mismatch (lowercase in the frontend but truly mixed case in the backend) those service calls never found the entity. Once I finally realized I forgot to .lower() that solved the problem, but it really had me scratching my head for a while. While debugging this I even commented out my turn_on method expecting a NotImplementedException but that didn't happen... because the service call wasn't hitting the entity at all, not just failing to call my methods.

I would have expected some kind of error to be thrown, either an Exception regarding invalid entity id or at least something logged to warn you that invalid characters were used. Obviously this is the responsibility of the developer (in this case, myself) creating the component / platform to get this right, but if we don't, it would be nice if HASS would remind us. :)

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):
N/A

Traceback (if applicable):
None

Additional information:
None

RFC: Backend translations

Description

As of yet, we haven't tackled the problem of how to manage translations that are platform specific. I started a WIP PR with one approach, but I wanted to take a moment to get some more opinions.

Right now I see two approaches, detailed above. I started briefly with approach 1, but I'm starting to suspect that 2 will be easier to maintain in the long run. I think in reality, we're never going to need the flexibility that approach 1 would give us, and we could always revisit it later if it really came down to it.

1. Serve translations from the backend

This is the approach I started with the #12453. In this world, platforms will register their strings with the frontend component, which can then serve these translations to clients via an API endpoint. We will have two projects in Lokalise, the current polymer project, and a new project for backend translations.

Pros

  • Extremely flexible. The server could potentially add/remove translations at runtime, using any logic that makes sense.
  • Separation of interests. The polymer project remains unaware of all our platforms. Strings specific to any one component/platform stay in the same codebase, and we don't have to coordinate PRs across multiple projects.
  • Custom components are supported as well.

2. Merge platform-specific translations into the polymer project

In this approach, we would merge platform-specific translations into our current translation source, under their own component/platform namespace. We would then use the existing translation fragment logic to fetch the strings for each platform that is loaded in hass.

Pros

  • Utilizes existing infrastructure. This is pretty much it, but it's a big one. All of the translation syncing, compiling, caching, and serving is already written. It isn't really desirable to duplicate this infrastructure on the backend in Python, or hack in js to reuse our gulp tasks.
  • Display concerns stay in the frontend. This is really just the reverse interpretation of the second bullet point from 1, but it also isn't the worst thing to keep these translation sets out of the backend project.

Use Cases to consider

Configuration prompts:
https://github.com/home-assistant/home-assistant/blob/c7c0df53aab8e5cd22e7d5973e406e8d0a34b152/homeassistant/components/light/hue.py#L72-L84
Custom sensor states:
https://github.com/home-assistant/home-assistant/blob/c7c0df53aab8e5cd22e7d5973e406e8d0a34b152/homeassistant/components/sensor/season.py#L24-L27

RFC: Wildcard support for entity_id lists

After reading about the wildcard support for customize and zwave/device_config, I thought about if something similar is possible with entity ID lists, eg. for groups, history, recorder, logbook, service_data/entity_id, and many other components that use them.

As an example:

group:
  group_1:
    entities:
      - input_number.*

Instead of

group:
  group_1:
    entities:
      - input_number.slider_1
      - input_number.slider_2

A few forum links to feature requests regarding this:
https://community.home-assistant.io/t/wildcard-operators-for-groups/4643
https://community.home-assistant.io/t/allow-wildcard-for-entity-selection-in-config-files/9029
https://community.home-assistant.io/t/wildcard-entities-in-groups/10021

As a starting point: home-assistant/core/pull/12380
Before I spend more time on it, is this something we should implement?

supported_features Vs current_supported_features

Currently Entity exposes supported_features that has become overloaded to mean both:

  • all of the entities supported features
  • the current set of supported features based on the entities state

The second use case breaks Alexa Discovery which relies on supported_features to discover all of the capabilities of an entity not just the ones that are available in it's current state.

One proposal from @balloob is to use supported_features as the list of all features and introduce a new current_supported_features that will reflect the features available at the current time base on the players state.

Users & Authentication

We have HTTP api support in HA, but currently only has password auth supported.

If password leaked accidently, we have to change the API password on HA and every device that using the API with password.

I think we should have more authentication method, like public key and HMAC, to prevent use same password everywhere. Also, we can also support multiple user pass pair.

RFC: Templates that generate non-strings

In #general people were talking about how to generate a list from a template. That is currently not possible because all templates generate strings.

We once had an open PR to run all templates through YAML but that's a gigantic can of worms. The PR got rejected.

Today I was thinking how we might be able to solve this anyway, and I came up with something:

If a template result starts with json( and ends with ), the template result will be parsed as JSON before being returned to the caller.

Examples:

  • Returning a list: json([255, 0, 0])
  • Returning a number json(200)
  • Returning an object json({"hello": "world"})

Advantages from this approach is that it is opt-in and allows for slightly more advanced things in templated service calls.

Pressure Sensor device_class

Simple proposal: a pressure device class for sensors. From Wikipedia:

Pressure (symbol: p or P) is the force applied perpendicular to the surface of an object per unit area over which that force is distributed.

Potential uses

Atmospheric pressure

Units

hPa, mbar [, inHg ๐Ÿ˜ถ]

Other units: kPa (move to hPa?), mb (move to mbar?),

Icon

mdi:gauge

gauge 1

Past uses

WUnderground, Dark Sky, Yahoo Weather, One Wire, enviro pHAT, Android IP Webcam Sensor, Buienradar, Netatmo Sensor, Telldus Live Sensor, Xiaomi Aqara, OpenWeatherMap, ARWN, BME680, ZAMG, Sense HAT Sensor, BloomSky Sensor

Approach for Geo RSS sensor extensions/refactoring

I am working on an enhancement of the Geo RSS sensor:
At the moment this is a sensor that fetches an RSS feed, extracts entries, and filters by distance to HA; the sensor value represents the number of events in vicinity of HA, and the attributes show key-value-pairs with title of event and distance in km.
The use-cases for this Geo RSS sensor are things like bushfires, earthquakes or severe weather-related events.

Planned changes:

  • Add Geo RSS as a component that extends feedreader and automatically generates sensors based on its configuration.
  • Re-use functionality from the feedreader component because that already handles fetching data and filtering. The pre-work has already been merged into the code base.
  • Add a binary sensor that turns on if there is any event in vicinity of HA and off if not. In the above-mentioned use-cases one event occurring is already enough to action something in HA, e.g. automatically close windows, send notification to users. etc. Like the current sensor though it would be useful to display more details about the external event somewhere though.
  • Add ability to push data from external event to HA event bus so that an automation can pick this up and for example notify users.

I am seeking advise on the following:

  • Currently the Geo RSS sensor uses device_sensor_attributes to display information about the external events but this is very limiting. The more-info dialogue does not really suit me because I can only override the behaviour for all sensors or all binary sensors, not for sensors of this particular platform.
  • I think it would be useful to display external events on a map - either as a state card or inside the more-info dialogue. But again, state cards are tied to a domain.
  • Is it time for a geo-location domain? There are possibly a few other candidates like the opensky , crimereports or spotcrime sensors that may fit into this category.

Clean up calendar component

The calendar component is a mess. It has entities, events with weird offsets and is very confusing to implement a new platform for.

We should restructure it like this:

  • Each platform for the calendar component will expose 1 or more calendars.
  • Each calendar has a method to get events for a specific range.
  • Optional: Each calendar has a method to create event
  • Recurring events are handled inside the platform implementation. We just want the event objects to show on a calendar.

For the user, to integrate the events on the calendar with their home automation:

  • A new calendar trigger for the automation component. Ability to filter by calendar, event name, event location, start/end. This trigger will query the calendar data directly to find the next time that something will occur.
  • A new calendar condition for the automation component to check if some event is currently going on.
  • A frontend calendar card that will show an agenda of events. Config options will be calendars to include, number of events. Not sure how to make the card get rendered right now, with new UI it will be easy as we can have cards that are not powered by an entity.
  • A new service "calendar.create_event" so that users could store things in the calendar. For example, create event when I am at location X.

Sound mode support media_player general and denonavr

see this PR for the already implemented code.

I would like to add general support for "sound mode" to the media player component. I already implemented the general code and the specific code for the denonavr media players (see PR above).
It is just based on the source_input and source_input_list architecture and bassically just a coppy of that.

I will upload some pictures of how the working fronted looks like for the denonavr component:

Group platforms - mixed domains

Since we originally started the discussion about group platforms in #13 the question came up how to handle mixed domains. An example would be some sort of group.switch platform. turn_on and turn_off are supported by many other components as well (light, input_boolean, remote, ...) , so it could make sense to allow grouping them together.

@OttoWinter did a nice summary of the possible options we have moving forward home-assistant/core#13052 (comment)

Proposal: Automation store

Proposal

Implement some sort of Automation Store in a git repo. This would allow users to pick up automations easier.

Current state

Users visit various sources for automation:

  • Examples on git from other users
  • Examples in the webpages of various components on home-assistant.io documentation
  • Examples in community forums

All of the above are manual tasks and also are not versioned to match the current Home Assistant version.

User journey

A user would be able to use the Automation Store to:

  • Find automations that would be usable with available components in Home Assistant
  • Find new automations published - Maybe allow "installed X times" types of meta to get popular automations on top
  • Make sure they have tested automations for basic things

Integration with the current Automation Editor to allow changing of entities to match user's.

Benefits

  • Easier for users to start with automation through the UI
  • Better automation categories - Maybe find a way to link automations to components as examples on the website
  • Surface easier popular automations

RFC: Default Platform Schema

Currently we support at least two different configuration patterns for platforms:

  1. Just platform (e.g. YR, Version Sensor, Min/Max Sensor)
sensor:
  - platform: yr
    monitored_conditions:
      - temperature
  1. Mostly template platforms (e.g. Template Sensor, Template Cover)
sensor:
  - platform: template
    sensors:
      sensor_entity_id:
        value_template: "{{0}}"

Since it came up in the discussion regarding my PR: home-assistant/core#12500, is one schema better than other? If so should we try to harmonize the other components?

New entity for lawn mowing robots

Last year, I've written a component for Husqvarna lawn mowing robots and from the forum responses it seems there's quite some interest in it.

71eead8b7e647343d3c5bcdee2a463185909e158_1_690x464

The code can be inspected on my repo fork.

For my purpose, I have used the existing vacuum entity. It fits nicely as lawn mowing robots behave pretty much the same way as vacuum robots.

However, the naming doesn't fit, so I'd like to spark a discussing about what should be done. Two options come to mind:

  1. Create a new lawn_mower component duplicating most of the vacuum code
  2. Rename vacuum to something more generic like something along the lines of robot or roaming_bot (could be included in existing discussion in #29)

I'm happy to try implementing either after we have a consensus about the approach to take. It will probably make sense to wait for the outcome of #29 as well if we're going with option 1.

Thanks for your feedback!

RFC: Entity Component owners

(for now, let's focus on entity components)

I would love for people to step up and take ownership of certain entity components (light, switch, climate, media player). Right now random PRs will make changes to the entity base classes without a grand vision keeping it sane. Which color scheme do we support in the light component? What is operation mode supposed to contain in the climate component? etc etc.

The owner of an entity component would be responsible for:

  • Defining the entity component: what is a light? What is a light supposed to do, what methods does it support and what service data would we need?
  • Final say on PRs that touch that entity component

We will still have some generic guidelines for entity components like:

  • Use supported_features to indicate which features are supported
  • Use device_class to indicate different device types within a category
  • Unique services should be added to the platform and not the base class

RFC: Device manufacturer / model reporting

Goal

Report device manufacturer and model in a standardized way, accessible to other components and the frontend. For example, allow showing whether a Sonos player is a Play:1 vs Playbar. Many components/platforms already have this info, but either report it in state_attributes, or not at all.

Proposal

  1. homeassistant/helpers/entity.py: Extend Entity to include a manufacturer_name and model_name property (similar to unique_id)
  2. homeassistant/helpers/entity_platform.py: Pass the manufacturer/model information to the Entity Registry
  3. entity registry: Store the mfg / model info, so that other components may access it
  4. Platforms are extended to expose this information, for example in Hue:
# HueLight class
# https://github.com/home-assistant/home-assistant/blob/0.69.1/homeassistant/components/light/hue.py#L201
+    @property
+    def manufacturer_name(self):
+        """Return the manufacturer of the Hue light."""
+        return self.light.manufacturername
+
+    @property
+    def model_name(self):
+        """Return the model of the Hue light."""
+        return self.light.productname

Architectural review of vacuum entity

NOTE: My current proposal can be found here: #29 (comment)

I am in the process of implementing vacuum cleaners in the Google Assistant component, however this is currently not possible as the different vacuum components use different ways of reporting state and supported fan speeds (mode).

I think we should start a discussion of which states and modes the vacuums should be able to use.

I only own the Roborock vacuum which uses the Xiaomi Miio platform, so that is the platform I'm most familiar with.

State

As an example of different ways of state reporting, we can take a look at the Xiaomi miio platform and the dyson platform:

The xiaomi miio platform uses an attribute called status, while the dyson platform uses the actual state of the entity.

I propose that we add the supported states to the base vacuum component, these are the states I have been able to observe:

  • Cleaning
  • Paused
  • Stopped (off)
  • Charger disconnected (Stopped)
  • Charging (Docked)
  • Idle (off)

I'm not completely sure which states we should support, as different manufactures report different things.

Modes

Currently different vacuums seems to be able to be set in different modes depending on supported features. The Roborock only supports setting different fan modes, but some vacuums may support setting a thoroughness state.
Some of these modes may also be better served as toggles, at least if we look at how to present a vacuum device according to Google such as the quiet mode of the Xiaomi Miio platform.

Start/Paused

Currently the implementation of Start/Paused is a single service call (vacuum.SERVICE_START_PAUSE), however if we want to support the StartStop trait of Google Assistant, I think that we should split this in to two different service calls: vacuum.SERVICE_START and vacuum.SERVICE_PAUSE.

Improved releases plan

This last release has been a little rough because of our conversion to Python 3.5 and the async/await syntax. The syntax is a lot stricter. It also made us realize that most integrations are not covered by either tests or people running the dev version of Home Assistant. What if we can get more people to test the latest changes without exposing them to experimental features?

So people have been talking in the dev chat and we came up with the following idea.

Current release schedule (numbers are days)

  • T0: Release starts. Features and bug fixes are merged into dev
  • T9: Cut release branch release-0-XX
  • T9-T11: Bug fixes will be tagged with milestone 0.XX
  • T11: Cherry pick fixes from milestone 0.XX into branch release-0-XX, merge to master and release as stable
  • Hotfix 1, 2, 3 etc (overlapping with work on new release)

Proposed change

At T11, instead of releasing to master and release it as stable, we're going to merge it to branch rc and release it as 0.XX.rc0. Instead of making all hotfixes stable releases, they will now become rc releases.

The release candidates will be published to PyPi, Hass.io and Docker hub:

  • Hass.io needs to be switched to the dev channel to start running release candidates.
  • Pip will ignore any package tagged as rc unless specified by the user (pip3 install homeassistant==0.65.0.rc0)
  • Docker users will need to specify to pull from the rc tag to get release candidates.

The branches will look like this:

  • master: always the latest stable release
  • rc: 2nd equivalent to master, end of 2nd week it will be a snapshot of dev, 3rd week it will have fixes cherry picked
  • dev: latest, greatest (and buggiest)

Fixes for bugs found in rc will go into dev and will have to be tagged with the correct milestone (0.XX) to be (automatically?) merged into rc.

After a week, the latest RC will be promoted to stable (by just updating version number).

RPC: Unit systems conversion

As we know, there are different unit systems around. We have the temperature covered but there are more unit of measurement. Ok, my screen 14" but our car drives not faster than 145 km/h. Weather data units, speed, length, pressure, etc. are exposed in different unit of measurements around the world.

In #11166 (was triggered by #11136) the idea was to an additional helper (util/speed.py) to do the conversion of different wind speeds and their unit of measurements.

The question is: Do we want to start writing our own helper to convert various unit of measurements into the needed output format (if one is required) or use something like pint to do it?

Writing it as needed wouldn't require a lot of changes but is a bit of reinventing the wheel and introduce a solution to a problem which was already solved.

Using a third-party module would require changes to the core but in the long run it would add flexibility if we are pushing further in the direction of more localization (not only language) of the user interface.

RFC for dependencies policy

home-assistant/core#7069 was started long ago as an effort to reduce non-pypi dependencies.
In home-assistant/core#12126 there was a discussion on (temporary) adding such dependency.

I propose the following:

  • All existing non-pypi dependencies are grandfathered, though we might consider some abandoned (see below)
  • If author of a new integration adds a dependency on their lib - it must be in pypi
  • If author of a new integration adds a dependency on someone else's lib - ask the maintainer to create a pypi package. Wait time. If maintainer is not responsive - see abandoned.
  • For a dependency on a patched version - try to get the patch upstream.

For abandoned libs:

  1. I think it is OK to create a pypi package like homeassistant-my-integration-abandoned. It clearly indicates the purpose of the package. Since the upstream lib is abandoned - we won't need to update this package.
  2. If the lib development continues but HA needs a patch that is not accepted upstream: The non-pypi alternative is a either a hosted blob or a commit-point in a fork. If there is a dedicated maintainer of such integration - I think we should create a pypi package of the fork homeassistant-my-integration
  3. If the lib development continues and all changes (if any) are committed upstream and there is a reasonable pypi release schedule (as an example ozw-cpp is not) then just wait for the release.
  4. If the lib development continues, all changes (if any) are committed upstream, but no release is planned: I don't know what should we do in such case.

Need a name for sensor device class to show relative time

Background is this PR: home-assistant/core#14983 about the HA uptime sensor. Currently it's updating its state every 30 sec and flooding the state machine.

The state of the new sensor class will be an ISO formatted datetime (that you set once) and on the frontend we will show it as relative time like 3 days ago and keep it updated there. (balloobs's idea)

Class name suggestions:

  • period

Reverse Proxy Compatibility

This has been a bit of annoyance of mine (and from what I've read, many others) for a while now and it seemed like this was a good place to raise it for discussion and consideration. I imagine this is in no-way a small change which is why it hasn't happened already.

I run a few applications at home and have everything come through my NGINX reverse proxy (although this applies to any reverse proxy). It's good having a simple, single point of entry to my network and I can apply additional security at that level which is also nice. Every application I'm running has a reverse proxy allowance, in that all URLs for the service fall behind a set page; for example [IP/port]/appName/[UI/API/doesn't matter].

Home Assistant does not allow this, which means in my reverse proxy I have ALL traffic going to my Home Assistant instance with the exception of those that are picked up with rules that look for 'appName'. This works for me, because (so far) Home Assistant is the only app I run that doesn't support reverse proxies and requires external access, but others won't be so lucky.

It would be great to see all Home Assistant URLs sit behind an optional subpage (i.e. [IP/port]/HomeAssistant/[API/etc].

Proposal: Allow changing names through UI for MQTT Discovery

Proposal

Allow for a method to change names of entities through the UI just like with unique_id for MQTT Discovery component

Use Case

There is development for a drop in replacement of xiaomi_aqara using CC2531 stick to save some round trips and avoid the proprietary gateway. Currently there is https://github.com/Koenkk/zigbee2mqtt for the actual functionality using Home Assistant discovery setup, coupled with https://github.com/danielwelch/hassio-zigbee2mqtt hassio addon.

Current state

  • Installation of addon is done through UI
  • Pairing of devices can be done through MQTT or with some settings UI (input_boolean + automations)

Configuration of devices names can be done either:

  • Manually if you avoid MQTT discovery in Home Assistant configuration yaml
  • Manually inside zigbee2mqtt configuration yaml

As xiaomi_aqara already has Discovery through the gateway and unique_id is allowed, would be nice to have the same for zigbee2mqtt.

Hook points into the UI

Hook points into the UI can allow advanced customization. Those hook points could be marked "unsafe" and changed - this would still be better that hooking in without hooks.

Below is the example of hooks cutomUI uses:

  • The official custom_ui_state_card attribute
  • Find un update group names via partial-cards ha-cards[view-visible] .main ha-entities-card .name
  • When the user is on /config path, find ha-config-navigation element and inject a new config page into it.
  • Change LOGIC_STATE_ATTRIBUTES to allow the user to hide additional attributes in 'more-info' and customize customUI attributes via the general UI customize editor.
  • Change partialCards.mqls to allow redefinition of column width and number.
  • Change partialCards._defaultViewFilter to allow hiding entities from view.
  • Change haStateLabelBadge.stateChanged to allow theming top-of-the-page badges.
  • Change stateBadge.updateIconAppearance to allow specifying icon_color.
  • Change localize of state-card-scene and state-card-script to allow overriding the text on the button.

And one ring to rule them all:

  • Change homeAssistant._updateHass to pre-process state update and change entity values according to user-supplied JS templates.

Handling of dynamically provided backend strings

According to this comment
home-assistant/core#15083 (comment) all backend strings must be lower snake case. The frontend and the translation components are in charge of displaying the correct string in the UI.

This works if we know in advance all the possible backend strings used by a component. However in the case of dynamically provided strings, an exhaustive translation cannot be provided.

For instance the input sources of a media player component can be provided by the device/service itself.

How can we handle such cases?

Versioned "extra_html_url"

Currently custom UI loaded via extra_html_url has caching problem when a new versions is released.

Bellow I propose a few approaches how to solve that:

  1. Make HA detect "local" files, fingerprint them on each call and inject url like my-element-<hash>.html instead of my-element.html. This will slow the page load.

  2. Like (1), but fingerprint in the background and use the result next time. Latency now not affected, but still spends CPU and requires 2nd reload to get the updated file.

On Linux pynotify can be used to only FP if there were changes.

  1. Allow refreshing the extra_html_url value from yaml via a service call. So when a new version of custom UI is released it should be uniquely named, the user should edit the config and call "refresh" service.

  2. (1) + (3) fingerprint upon service call. Now user needs to call "refresh", but author doesn't need to name files uniquely and no config edit is required.

  3. No fingerprinting, but maintain a random number added to the url: my-element-random.html. This number is changed upon service call, so a user can initiate a cache miss regardless of whether the file actually changed.

Buttons as binary_sensors problem

Background

Currently buttons like Xiaomi that don't have anything physical to control directly are discovered as binary_sensors (either xiaomi_aqara platform or mqtt). This is fine, as you'd want to link all your automation into one unit.

Problem

Because these are buttons ideally you'd want the button to send key press and key release so you can take actions based on those states, however there are multiple types of buttons:

  1. Some send key press / key release
  2. Some send click and type (single, double)
  3. There are some that have even more states (like the cube)

The problems appear in case 2. where if you press a button multiple times, the binary_sensor state doesn't change as you always get "single" so writing automations based on this is impossible. For MQTT you can do workarounds by registering directly to the topic.

xiaomi_aqara seem to use some sort of manual "bus fire": https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/binary_sensor/xiaomi_aqara.py#L337 to get around this

Suggestion

Adjust sensor to allow automation based on updates received not on to/from or create a completely new type of entity "controller"/"button"

Rethinking the States panel in the frontend

The current States panel has a major flaw: it tries to do things magically at runtime. It takes all the available states and will organize all the things according to groups, hidden attributes and by domain (for ungrouped entities).

By doing things magically and at runtime, we've opened a can of worms:

  • All entities will be shown on the first tab unless a user defines a default view.
  • With a default view defined, new entities will not be shown anywhere unless explicitly added by the user to a view
  • All configuration for the runtime layout engine ended up in the state machine: views, groups, hidden attributes, custom UI overrides. By adding it to the state machine, you ended up having to pick 1 way for entities to be shown in every view where you wanted them to be.
  • The domain of an entity defines how it will be displayed.
  • Groups can show a toggle for entities. However, this is not always desirable so a config option was added to the group component to control this. This config option is stored in the state machine.

We can do better. Let's stop conflating concerns. Let the frontend be the frontend. The backend be the backend. The backend should provide the minimal information to the frontend: the entity id, name, state and attributes of an entity. No groups, no views.

For the frontend to figure it out, it should get its own configuration. This configuration will be loaded from the frontend component when the page is loaded and will be used to layout the entities.

So let's talk about the building blocks for a frontend configuration:

Views

A view's purpose is the same as today: view a subset of the states in Home Assistant. It would however no longer be "hacked" into the group component. It would only live inside the frontend component. It will not have a state in the state machine.

  • A user will need to have a minimum of 1 view
  • One of the views will need to be marked as "default".
  • Views can be ordered.
  • Views can either show an icon or a name for the tab.

Whenever a new state is added to Home Assistant, the frontend will check if it has seen this entity ID before. If not, it will add it to the default view. This will only happen once for each entity. The user can just choose to remove the entity from the view if he doesn't want to see it.

Cards & Badges

A view will consist of cards and badges, just like today. The biggest difference is that this will no longer be based on the group component. Instead, the user can configure cards to show things and this will be stored inside the frontend config.

The most important card is the entities card. It will, just like today, show a bunch of entities in a card. If a user doesn't like the climate, camera or media player card, they can now decide to add that entity to the entities card and remove the other card for an entity. A user can also pick to show the same entity 3 times if they feel like.

Other examples of cards: (all already exist today)

  • Group card: show the entities of a group as an entities card
  • Camera
  • Media Player
  • Climate
  • Plant
  • Weather
  • Persistent Notification (I probably will kill this and make notifications it's own section in frontend)

This will also allow us to make custom UI cards first class citizens and have their config be stored as part of the config for the view.

Pretty much all problems that users are facing today are solved by doing the auto layouting of entities when they are added to the default view instead of at runtime. At runtime we will just render the stored config for the view.

Conclusion

The biggest difference is that this setup will allow the user to take control of what is shown on each view without any surprises. It knows what is happening on each view ahead of time and can add new entities to a view of choice.

By still adding new entities to the default view, we will still have a great experience for users that are new to Home Assistant and don't want to dig into configuring views just yet.

It also allows us to relieve the state machine of configuration and will make custom UI first class citizens of our ecosystem.

Frontend Right-to-left support

Currently hass frontend defaults to left to right. Hebrew and Arabic use Right to left alignment and reading order. This requires style updates and possibly some script updates (for calculations dependent on GUI properties (such as sliders positions).

I need advice on the best method of implementation since it seems that many small changes are required in many places.

Need to decide on:

  • The level of RTL flag - is it at the frontend: level or each individual group or component. My vote is to keep it simple now and we gradually setup RTL support for more and more components

  • How will styles and scripts render the updated code? Conditional code in each component or a global style/script override file?

Just to understand the scope - getting the basics to look good is simply a direction:rtl in home-assistant-main but that immediately causes scroll bars not to work as well as sliders to produce the wrong value. I am working on a list of things to fix and how but I will need your guidance on how to incorporate it in a way that keeps the code clean.

I also want to set all panels other than the main states panel to use "direction: ltr" since they are perfectly fine to stay as-is and not be right-to-left friendly. Therefore the direction:ltr should probably not be placed in home-assistant-main but I'm not sure how to make it apply only to the states panel (haven't tried yet).

Thanks.

Web Things

Mozilla has been working on a new IoT spec called Web Things API. It's a spec meant to provide a common language between devices and gateways (blog post) (we already implement a few specs with similar goals like ZigBee, Z-Wave, HomeKit). This spec is slightly different in that it is a lot more web-native: it's based on JSON sent over websockets or REST APIs. Devices consist of attributes, actions and trigger events that one can listen to (example).

Standardizations of IoT is important. It allows Home Assistant to stop chasing proprietary APIs to integrate and instead focusing on building cool stuff on top of standardized APIs like UI, automations, visualizations and machine learning.

Here are a few things that make the Web Things API a great candidate for us to integrate with:

  • It is based on JSON which is human readable. This makes it easy for our developers, which are mainly hobbyists, to learn, interact and build on top of it.
  • It uses REST and WebSockets to communicate the JSON, two well established methods of communication within Home Assistant.
  • It is easily extensible via JSON schemas.
  • The spec is still in draft, meaning we can get involved and make sure our use cases are covered.

I've had a talk with the team at Mozilla that is working on this and they are excited to see Home Assistant get involved.

So this is not so much an RFC as to what to do for Home Assistant but instead a call to see who is interested to get involved help shape the future of the open home ๐Ÿ‘

Adopting IndieAuth extension

While developing the auth system, it always felt weird that we would have users create client IDs and then authenticate before being able to use their instance with third party apps. It should be able to just redirect user, authenticate and it should work.

Using client id as extra layer for security was also not realistic because the frontend would expose their client id. Hence, an attacker could just scrape the index to get a client ID to use.

All these things I kind of ignored while working on the meat of the problem: users itself. Then last night I read this article on HackerNews about the IndieAuth extension for the OAuth2 spec: https://aaronparecki.com/2018/07/07/7/oauth-for-the-open-web

It's perfect suited for our decentralized setup. Instead of client ID and redirect URI being preconfigured, it will be based on urls and a set of rules. No creation of clients necessary.

Cc @awarecan

FR: Allow camera scan_interval to be user configurable

Camera previews before and after Lovelace are updated at a hard coded default of every 10 seconds. Please provide a user configurable setting (ex. scan_interval: 2) for each individual camera and or all cameras collectively

Thanks

Add async_add_executor_job function to improve performance and avoid cpython bug

Proposed Changes

--- a/homeassistant/core.py
+++ b/homeassistant/core.py
@@ -205,7 +205,7 @@ class HomeAssistant(object):
     def async_add_job(
             self,
             target: Callable[..., Any],
-            *args: Any) -> Optional[asyncio.tasks.Task]:
+            *args: Any, run_in_executor=False) -> Optional[asyncio.tasks.Task]:
         """Add a job from within the eventloop.
 
         This method must be run in the event loop.
@@ -215,7 +215,9 @@ class HomeAssistant(object):
         """
         task = None
 
-        if asyncio.iscoroutine(target):
+        if run_in_executor:
+            task = self.loop.run_in_executor(None, target, *args)
+        elif asyncio.iscoroutine(target):
             task = self.loop.create_task(target)
         elif is_callback(target):
             self.loop.call_soon(target, *args)

Explain

1. Performance

When we pass in a "sync" function to async_add_job, it has to pass three type check to get conclusion it is not an "async" function, has to put it into an executor. So if we know it is a "sync" function, as developer we should know, we can pass in a parameter to help short cut the decision tree. That should improve performance a little bit.

2. CPython bug

In a corner case, asyncio.iscoroutinefunction will throw exception instead return false, if you have time, you can read more detail information here. So by provide a parameter to bypass iscoroutine check will be a not-bad workaround in my opinion.

By the way, it is real world scenario, my code just hit this bug. Here is stack trace

  File "/home/jason/ha/home-assistant/homeassistant/core.py", line 223, in async_add_job
    elif asyncio.iscoroutinefunction(target):
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 258, in iscoroutinefunction
    _inspect_iscoroutinefunction(func))
  File "/usr/lib/python3.6/inspect.py", line 186, in iscoroutinefunction
    object.__code__.co_flags & CO_COROUTINE)
AttributeError: 'ProxyMethod' object has no attribute '__code__'

I have to write my own version of _async_add_job to avoid that.

Approved Solution

Add hass.async_add_executor_job function.

Start using attrs instead of namedtuple

attrs is a Python package that allows you to write simple classes without any boilerplate. It's like a namedtuple, but better.

It makes it a lot easier to write small classes to pass data around. We use namedtuple 41 times currently in our codebase.

Normally I am not the person to propose adding dependencies to core, however I noticed that aiohttp started using attrs 2 weeks ago (aio-libs/aiohttp#2690) and thus it is already installed for a base install of Home Assistant.

Python 3.7 includes something similar to attrs called "Data Classes". However, it depends on PEP 526 which was only included in Python 3.6.

I think that using attrs can make our code easier to use. It also does not add any runtime costs since it does the work when the class is declared, not when a property is requested.

Extend Context to include remote address

Context is a new concept we just added into core (home-assistant/core#15674).

Now I want to extend it to include the remote address. I am going to get remote address from request.get('ha_real_ip'), which has been set by real_ip middleware. I have few design issue want get some input.

  1. Naming
    I really struggle on this, which one is better? remote_address, real_ip, from, where, even location

  2. Typing
    request['ha_real_ip'] is a IPAddressV4 or IPAddressV6 type, can I use object in the Context def, or use str?

@attr.s(slots=True, frozen=True)
class Context:
    """The context that triggered something."""

    id = attr.ib(
        type=str,
        default=attr.Factory(lambda: uuid.uuid4().hex),
    )
    remote_address = attr.ib(
        type=str,  # type=object ?
        default=None,
    )
    user_id = attr.ib(
        type=str,
        default=None,
    )

States with forecasts

In some cases it is useful to add some data array as an attribute. That will make the data available for the frontend and for automations. But this mean the data array are stored in the database, and easily may take a lot of disk space.

Currently we are adding the forecast data array as an attribute in the weather components.
In home-assistant/frontend#868 I wanted to add a data array as an attribute for visualization and automations. But it was not accepted since it easily may tak a lot of disk space. (But not more than the weather component already does)

One way to solve this, is to filter out all attributes starting with _ from the database. Then we can rename forecast in the weather component to _forecast. This will allow to add useful data to the state for automations, but without having to store it in the database.

@balloob did not like that solution (home-assistant/frontend#868 (comment)):

The recorder is going to record everything. It is not going to pick and choose attributes. It's opening a can of worms. We need to fetch that data via an API.

I understand his concerns, but I do not have any better idea.
I am hoping for some ideas of how we can solve this.

This issue might be relevante #11
Here a way of filtering out some sensors from being stored in the database might be useful.

Image Blackboard (was Image Processing refactoring)

Image Processing component allows the processing of images supplied by the camera component.

Basically it snapshots an image from a given camera, processes the image to extract information (eg. license plate, face) and triggers an event that most commonly is used in an automation (eg. send a notification)

In this process the image that was processed gets lost. Even if an automation triggers a new snapshot from the camera, the image will not be the same one captured before.

As image_processing components evolve, some will take longer time to process (using CV/ML/DL techniques) and eventually, whatever they detect in the image, will get lost in the "numbers" produced and without an option to use the image.

So what can be done?

  • Make the image_processing component behave like a camera (we can even recycle the camera UI) and therefore expose the image as an attribute of the component.
  • Have the image_processing component send the image together with the event (might be resource wasteful ?) and make possible for other entities to process such image or display (thinking about extending generic_camera to receive an image, or creating image_processing pipelines)

I would like your comments/thoughts on this matter.

Remove unit_of_measurement from climate object state

As requested in Lovelace UI home-assistant/ui-schema#137

The entity climate includes the status (on/off/cool/heat) and the unit_of_measurement attribute. In the current UI, the entity is displayed with current_temperature, and target_temperature, presumably why unit_of_measurement is available.
image

Lovelace only shows status and unit_of_measurement, which makes no sense:
image

Fan entity speed settings

This issue was triggerd by home-assistant/core#14351 which was / is adding HomeKit support for fan entites.

During the work on the PR @schmittx and I noticed that the current way we assign fan speeds is overly complicated and not really practical for things like HomeKit, Alexa or Google Home.

Current state

Each fan platform creates a list of supported speed settings, the speed_list, and setting the speed value requires to pass a string that exists in the list.

The most popular entries to speed_list are:

  • STATE_OFF or SPEED_OFF
  • SPEED_LOW
  • SPEED_MEDIUM (sometimes)
  • SPEED_HIGH

Others include: auto and smart
The dyson platform taking a special case with: 0001, 0002, ... , 0010 and AUTO

Problem

Secondary platforms expect a) consistent values and b) most often percent instead of a string. In addition (c) the speed setting is mixed up with the current operation mode.

Solution?

  • The speed attribute should change to an int value between [0, 100]. The conversion should be handled by each platform individually.
  • auto, smart, off, (maybe manual) should get their own attribute: mode / operation_mode?

Their might be things that I've missed, especially how to cover this change in the fronted, but since the current way is somewhat all over the place we decided (at least for the homekit component) not to support the speed setting (for now).

RFC: Battery Charging attribute

I'm working on an addition for HomeKit component to add battery tracking (home-assistant/core#14288). The HomeKit framework accommodates charging status in addition to battery level, therefore I'd like to propose a unified charging attribute.

My image is that attribute would be a boolean, and if charging is not supported for the entity then the attribute would not be generated.

I believe that we'd need to update at least one component to use this new attribute before it can be added, correct?

Any advice on how to proceed would be appreciated.

ATTR_BATTERY_CHARGING = 'battery_charging'

Introducing the home-assistant/architecture repo

From time to time we have architectural discussions in the chat. However, these conversations are easily lost nor are any followed up. This repo will help with organizing these discussions. Feel free to start new topics or join existing discussions.

CC @home-assistant/developers

Implement "Device" concept

Implement device to represent physical devices connected to Home Assistant.

Background

IoT devices with varied attributes must currently be represented as several different entities in Home Assistant. An atmospheric monitoring unit may have humidity and temperature sensors, some other binary_sensors, perhaps a light, and maybe a switch. Currently, these are all separate entities in Home Assistant, united only by the common underlying component.

Proposal

Create a new concept in Home Assistant: device. A device may have one or more entities ( binary_sensor, light, switch) related to it.

Justification

This would improve alignment between Home Assistant code/configuration and the physical devices being represented. This would benefit new users trying to understand Home Assistant.

Drawbacks

Depending on how this is represented in configuration files, this change is likely to break existing installs.

Related discussion

Related discussion has occurred in issue #8. Some excerpts:

balloob commented on 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.

rytilahti commented on Dec 14, 2017

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
          - ..

cgarwood commented on Feb 23

This would be a major architecture change, but what about creating a single entity per device that contains all of the sensor values/states/attributes, instead of a bunch of separate sensor entities.

Take a zwave multisensor for example. Currently you get separate sensors for motion, temperature, humidity, luminance, alarm_level, alarm_type, burglar, etc. What if, instead, you just had a single entity that contained all of this detail like such:

{
  "temperature" : {
    "value" : 71.6
    "unit_of_measurement" : "F"
  },
  "humidity" : {
    "value" : 52
    "unit_of_measurement" : "%"
  }
  "luminance" : {
    "value" : 123
    "unit_of_measurement" : "lux"
  }
  "motion" : false
  "alarm_type" : 22
  "alarm_level" : 0
  "burglar" : 8
  "sourcenodeid" : 0
  "battery_level" : {
    "value" : 98
    "unit_of_measurement" : "%"
  }
}

You could then access any of those values using dot-notation in automations or elsewhere in the config. For example, living_room_multisensor.motion or living_room_multisensor.battery_level.value

Everything would be treated the same as a state, no more template sensors to pull out attributes. You would add the different bits to the frontend using the same dot notation, so instead of the current setup of sensor.living_room_multisensor_temperature you'd just include living_room_multisensor.temperature in the group/view.

I'm not sure how the current domain structure of sensor,binary_sensor,etc would fit in with this architecture.

Integration quality scale

I want to introduce a scale to judge the quality of each integration. An integration is a combination of component/platform for a service or device.

This scale will guide developers in how to improve their integrations and will guide users in how "good" an integration is. (I don't like the word quality but can't come up with a better name atm)

Each section extends the requirements from the previous one.

Basic

Medium

  • Discoverable (if available)
  • Set an appropriate SCAN_INTERVAL (if a polling integration)
  • Tests
  • Set unavailable=False if connection lost or unable to connect
  • Raise PlatformNotReady if unable to connect during setup (if appropriate)
  • Has a code owner
  • Handles expiration of auth credentials
  • Handles internet unavailable
  • Handles device/service unavailable

Expert

  • Integration + dependency are async
  • Uses aiohttp and allows passing in websession (if making HTTP requests)
  • Configurable via config entries including removing it during run time.
  • Set appropriate PARALLEL_UPDATES constant

Integrations that reach expert level will require the code owner approval for each PR.

How to deal with history sensors

Definition: 2nd order components are components that take raw data available in Home Assistant and process it into new data.

We are getting more and more 2nd order components that show a statistic over a period in the history of an entity (example: history_average which allows calculating average value during last 2 hours)

The problem with these sensors is that their state is time based and thus they update the value on every update, which spams the state machine.

How can we solve this? One thing we can do is to set a minimal update interval to limit state updates.

But what else?

Architectural review of climate entity

This issue was triggered by home-assistant/core#13340 which was adding Alexa controls for our thermostats. I also just did a rewrite of Google Assistant and made it so it only supports our official operation modes.

I think that it's time to do a review of our climate entity. Clean it up and then be better in code reviews in enforcing the rules of the climate component.

Supported features

We have individual support flags for setting a temperature, setting the upper bound of a temp range and setting the lower bound of a temp range. This is still an artifact from when supported features was used to show/hide frontend controls.

  • Action: merge temp lower and temp higher
  • Action: merge humidithy lower and temp higher

Cleanup of made up values

The goal of our abstract base class is to specify which values can be used. That way we can build things on top like frontend, Alexa integration, Google Assistant integration or compare the usage history of two thermostats from different brands with machine learning.

However, there are a bunch of platforms that return their own values for properties. Especially operation mode suffers a lot here. Instead of using the STATE_* constants, these platforms return their own made up values. It works with our frontend because we also allow returning an operation list. It does not, however, work with Google Assistant or Alexa. Both have been coded now to be very strict and ignore any non standard operation.

  • Action: rename constants from STATE_* to OPERATION_MODE_*
  • Action: list violating platforms and open issues to get them fixed

Operation mode

Operation mode describes in what kind of operation the thermostat currently is. This is what we have right now:

STATE_HEAT = 'heat'
STATE_COOL = 'cool'
STATE_IDLE = 'idle'
STATE_AUTO = 'auto'
STATE_DRY = 'dry'
STATE_FAN_ONLY = 'fan_only'
STATE_ECO = 'eco'
STATE_ELECTRIC = 'electric'
STATE_PERFORMANCE = 'performance'
STATE_HIGH_DEMAND = 'high_demand'
STATE_HEAT_PUMP = 'heat_pump'
STATE_GAS = 'gas'

Here are just some initial observations:

  • Fan only means the current operation is idle. The fan state should show if fan is on. Can we remove this one?
  • eco, performance, high demand: these sound like performance profiles. Should be represented differently? (also performance and high demand are the same?)
  • heat pump: this needs to be merged with heat

Actually: I noticed that we have a platform called econet that is not a climate device but is a water heater. It's the only one that uses STATE_GAS, STATE_HEAT_PUMP and STATE_HIGH_DEMAND (they are also used by Wink, but that's because Wink represents econet via their API). I think that econet should not be a climate device.

State property

This should be just operation_mode. Right now it's a combination of is_on and operation_mode. By trying to blend two attributes, we've made the value pretty much useless.

is_on property

Do we need this? Can we blend this in with operation mode? For example, if something is an on/off device, it could just have operation mode be heat/idle or cool/idle. Idle and off are obviously the same kind of action: nothing is happening.

References

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.