home-assistant / architecture Goto Github PK
View Code? Open in Web Editor NEWRepo to discuss Home Assistant architecture
Repo to discuss Home Assistant architecture
Allow for a method to change names of entities through the UI just like with unique_id
for MQTT Discovery component
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.
Configuration of devices names can be done either:
As xiaomi_aqara
already has Discovery through the gateway and unique_id
is allowed, would be nice to have the same for zigbee2mqtt
.
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)
Implement some sort of Automation Store in a git repo. This would allow users to pick up automations easier.
Users visit various sources for automation:
All of the above are manual tasks and also are not versioned to match the current Home Assistant version.
A user would be able to use the Automation Store to:
Integration with the current Automation Editor to allow changing of entities to match user's.
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.
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:
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
Adjust sensor to allow automation based on updates received not on to/from or create a completely new type of entity "controller"/"button"
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
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:
custom_ui_state_card
attributepartial-cards ha-cards[view-visible] .main ha-entities-card .name
/config
path, find ha-config-navigation
element and inject a new config page into it.LOGIC_STATE_ATTRIBUTES
to allow the user to hide additional attributes in 'more-info' and customize customUI attributes via the general UI customize editor.partialCards.mqls
to allow redefinition of column width and number.partialCards._defaultViewFilter
to allow hiding entities from view.haStateLabelBadge.stateChanged
to allow theming top-of-the-page badges.stateBadge.updateIconAppearance
to allow specifying icon_color
.localize
of state-card-scene
and state-card-script
to allow overriding the text on the button.And one ring to rule them all:
homeAssistant._updateHass
to pre-process state update and change entity values according to user-supplied JS templates.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:
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.
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.
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.
(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.
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.
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.
configuration.yaml
SCAN_INTERVAL
(if a polling integration)PlatformNotReady
if unable to connect during setup (if appropriate)PARALLEL_UPDATES
constantIntegrations that reach expert level will require the code owner approval for each PR.
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).
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).
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.
Currently Entity exposes supported_features
that has become overloaded to mean both:
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.
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?
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:
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:
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.
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.
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)
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.
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.
Implement device
to represent physical devices connected to Home Assistant.
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 sensor
s, some other binary_sensor
s, perhaps a light
, and maybe a switch
. Currently, these are all separate entities in Home Assistant, united only by the common underlying component
.
Create a new concept in Home Assistant: device
. A device
may have one or more entities ( binary_sensor
, light
, switch
) related to it.
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.
Depending on how this is represented in configuration files, this change is likely to break existing installs.
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 attributedevice_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 - ..
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.
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?
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.
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:
lawn_mower
component duplicating most of the vacuum
codevacuum
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!
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
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.
Entity
to include a manufacturer_name
and model_name
property (similar to unique_id
)# 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
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:
www
directory that contains code (Lovelace monster card in my case)custom_components
that contains code (ElkM1 in my case)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 purposeI have two proposals.
~/.config
for configuration. ~/.config is the default with fallback to .homeassistant; Use XDG_CONFIG_HOME as appropriate.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
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.
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
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.
Naming
I really struggle on this, which one is better? remote_address
, real_ip
, from
, where
, even location
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,
)
@balloob commented on Dec 13, 2017, 8:54 AM UTC:
#10732 started having 2 conversations in 1. This splits out the conversation about having attributes that contain measurements be represented as standalone sensors.
This issue was moved by @balloob from home-assistant/core/issues/11118.
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].
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?
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:
For abandoned libs:
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.
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.
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.
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
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.
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:
I'm not completely sure which states we should support, as different manufactures report different things.
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.
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
.
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.
Lovelace only shows status and unit_of_measurement, which makes no sense:
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.
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
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.
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:
I am seeking advise on the following:
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.opensky
, crimereports
or spotcrime
sensors that may fit into this category.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:
For the user, to integrate the events on the calendar with their home automation:
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'
Camera defined three states [STATE_RECORDING, STATE_STREAMING, STATE_IDLE]
, but don't have services to allow user change state.
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
Add generic turn_on
turn_off
service to Camera.
entity_id
and state
mode
as parameter (MODE_RECORDING
or MODE_STREAMING
)entity_id
supported_feature
support modeled after the light component. Limit to only turn_on/turn_off
as a feature.(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:
We will still have some generic guidelines for entity components like:
supported_features
to indicate which features are supporteddevice_class
to indicate different device types within a categoryBackground 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:
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:
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 👍
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.
dev
release-0-XX
0.XX
0.XX
into branch release-0-XX
, merge to master
and release as stableAt 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:
rc
unless specified by the user (pip3 install homeassistant==0.65.0.rc0
)rc
tag to get release candidates.The branches will look like this:
master
: always the latest stable releaserc
: 2nd equivalent to master
, end of 2nd week it will be a snapshot of dev
, 3rd week it will have fixes cherry pickeddev
: 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).
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)
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
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.
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?
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.
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?
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.
--- 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)
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.
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.
Add hass.async_add_executor_job
function.
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.
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
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.
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).
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?
I would like your comments/thoughts on this matter.
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.
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.
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.
STATE_*
to 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:
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.
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.
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.
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.
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.
Atmospheric pressure
hPa
, mbar
[, inHg
😶]
Other units: kPa
(move to hPa
?), mb
(move to mbar
?),
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
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:
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:
json([255, 0, 0])
json(200)
json({"hello": "world"})
Advantages from this approach is that it is opt-in and allows for slightly more advanced things in templated service calls.
Currently we support at least two different configuration patterns for platforms:
sensor:
- platform: yr
monitored_conditions:
- temperature
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.