Giter Site home page Giter Site logo

integration-home-assistant's Introduction

Rust

Home-Assistant Integration for Remote Two

This service application connects Home Assistant with the Remote Two and allows to interact with most entities on the remote.

The integration is included in the Remote Two firmware and no external service must be run to connect Home Assistant with Remote Two. The standalone service can be used for development or connecting multiple Home Assistant servers.

The integration implements the Remote Two Integration-API which communicates with JSON messages over WebSocket.

The WebSocket server and client uses Actix Web with the Actix actor system for internal service communication.

Container Image

See Docker image for more information.

Configuration

  • Optional read-only configuration file to override defaults: configuration.yaml
  • User provided Home Integration server settings are written to $UC_CONFIG_HOME/$UC_USER_CFG_FILENAME once the driver setup flow is run.

Configuration file handling uses the Rust Crate config which allows loading configuration values from multiple sources and overwrite default values.

The configuration values can be overwritten with ENV variables.

  • Keys containing _ cannot be overridden. E.g. websocket.heartbeat.interval_sec.
  • ENV prefix: UC_
    • Example: integration.interface configuration setting: UC_INTEGRATION_INTERFACE=127.0.0.1

Environment Variables

The following environment variables exist in addition to the configuration file:

Variable Values Description
UC_CONFIG_HOME directory path Configuration directory to save the user configuration from the driver setup.
Default: current directory
UC_DISABLE_MDNS_PUBLISH true / false Disables mDNS service advertisement.
Default: false
UC_USER_CFG_FILENAME filename JSON configuration filename for the user settings.
Default: home-assistant.json
UC_DISABLE_CERT_VERIFICATION true / false Disables certificate verification for the Home Assistant WS connection.
Default: false
UC_API_MSG_TRACING all / in / out Enables incoming and outgoing WS Core-API message tracing
Default: no tracing
UC_HASS_MSG_TRACING all / in / out Enables incoming and outgoing Home Assistant WS message tracing
Default: no tracing

On the Remote Two device, the integration is configured for the embedded runtime environment with several environment variables. Mainly UC_DISABLE_MDNS_PUBLISH=true, UC_CONFIG_HOME and some UC_INTEGRATION_* to listen on the local interface only.

How to Build and Run

If you don't have Rust installed yet: https://www.rust-lang.org/tools/install

Build

Without mDNS advertisement support:

cargo build

With zeroconf library, wrapping underlying ZeroConf/mDNS implementations such as Bonjour on macOS or Avahi on Linux:

cargo build --features zeroconf

With pure Rust mdns-sd library:

⚠️ Use at own risk, this library can cause package flooding with Apple devices in the same network!

cargo build --features mdns-sd

This will run on any platform, but with limited functionality (no IPv6 support) and potential incompatibilities.

Run

To start the integration driver:

cargo run

Home Assistant WebSocket API test tool

The bin/ha_test.rs tool is a simple CLI tool to test the Home Assistant WebSocket API connectivity with the exact same code & logic as the HA integration for Remote Two.

The main purpose of this tool is to troubleshoot connectivity issues from a PC. Linux, macOS and Windows x86 binaries are automatically built with a GitHub action and attached to GitHub releases.

Functionality

  1. Connect to the HA server and authenticate with the token
  2. Subscribe to entity state events: subscribe_events
  3. Request the entity states: get_states
  4. Disconnect

The debug log including HA message communication is printed to the console.

Required parameters

  • HA long-lived access token.
  • HA WebSocket URL. Default if not provided: ws://homeassistant.local:8123/api/websocket

The configuration can either be provided in a home-assistant.json file in the current directory (see ./resources/home-assistant.json template), or through command line parameters.

Usage

./ha-test --help
Home Assistant server communication test

Usage: ha-test [OPTIONS]

Options:
  -u <url>                     Home Assistant WebSocket API URL (overrides home-assistant.json)
                               [default: ws://homeassistant.local:8123/api/websocket]
  -t <token>                   Home Assistant long lived access token (overrides home-assistant.json)
  -c <connection_timeout>      TCP connection timeout in seconds (overrides home-assistant.json)
  -r <request_timeout>         Request timeout in seconds (overrides home-assistant.json)
      --trace <MESSAGES>       Message tracing for HA server communication
                               [default: all] [possible values: in, out, all, none]
  -h, --help                   Print help
  -V, --version                Print version

Contributing

Please read CONTRIBUTING.md for details on how to contribute and submit pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags and releases on this repository.

The major changes found in each new release are listed in the changelog and under the GitHub releases.

License

This project is licensed under the Mozilla Public License 2.0. See the LICENSE file for details.

Project dependencies

A license report of the projects dependencies can be generated with the cargo-about tool:

cargo install cargo-about
cargo about generate about.hbs > integration-hass_licenses.html

integration-home-assistant's People

Contributors

zehnm avatar splattner avatar dependabot[bot] avatar

Stargazers

Wojciech Bederski avatar Andrew Jackson avatar Jason Chen avatar  avatar Quirin Lippl avatar Elvio avatar Andrew J Freyer avatar Markus Goy avatar  avatar  avatar Marc Boudreau avatar James Callaghan avatar Sander de Wildt avatar Jindrich Gavenda avatar Tony Stipanic avatar  avatar Rich Ahrens avatar  avatar Sandalots avatar Piotr Machowski avatar  avatar bnclt avatar

Watchers

rudgr avatar Paddy avatar Markus Goy avatar  avatar Marton avatar Jeroen van de Erve avatar

integration-home-assistant's Issues

I can't find devices.

why can I no longer take over devices from home assistant and only entities? 2 updates ago this was still possible.

After initial setup on remote integration remains in disconnected state

A fresh setup on the remote (e.g. after a factory reset) leaves the integration in DISCONNECTED state. At least from the remote's view.
However, the integration is not showing any connection issue and is communicating with HA.
Sending connect events (either through web-configurator, or manually with the Core-API) has no effect, since the internal state is already CONNECTED. There's also no device_state event sent back:

R2Event::Connect => {
if self.device_state != DeviceState::Connected {
ctx.notify(ConnectMsg::default());
}
}

After sleep & wakeup, the state is synchronized and the integration is working. Same happens after a reboot.

Discovered while testing unfoldedcircle/feature-and-bug-tracker/issues/237 after user reports of having to reboot the remote.

Required fixes:

  • Always send the device_state event back after receiving the connect event.
  • Make sure the device state is sent back after setup (might be already the case with the above fix).

Improve temperature unit handling for generic thermostat climate entity

The climate entity in Home Assistant defines the temperature_unit for °C or °F. According to the documentation this should be a required property.
In Remote Two, the correct unit handling is prepared, but not yet verified (#10).
However, the generic thermostat does not support custom temperature units, and simply takes the configured HA system unit:

This can be verified with the Remote Two Core-simulator and the prepared thermostat entities.

The temperature unit works as long as the HA unit system matches the Remote Two localization. For mixed environments or special use cases, this doesn't work correctly.

Proposed enhancements:

  • To use the same unit system, the HA configuration needs to be read and set into all climate entities, which don't specify a temperature_unit option.
    This will force the temperature values of all entities to the configured HA unit system and display the same value as in the HA dashboard. Switching the Remote Two units, won't change the temperature label anymore.
  • Add a configuration option in the HA integration setup to choose the temperature unit behaviour:
    • Use Remote Two setting if entity is missing temperature_unit (current behaviour)
    • Use Home Assistant setting if entity is missing temperature_unit
    • Force Celsius if missing
    • Force Fahrenheit if missing

How to get the HA configuration:

Note: the °C / °F handling is not yet fully working in firmware 1.3.x. This is currently being worked on.

Cannot connect to HASS "Protocol error: I/O error: unexpected end of file"

When I attempt to configure the HASS integration it spins for quite a while at the "Select entities" page (with nothing to select) before eventually failing with error.ECONNABORTED. After that at the integration config page both the "Configured Entities" and "Available Entities" columns say "Not Available". The left hand column has a disconnected toggle which I cannot change.

I've been seeing this behaviour for several updates.

Screenshot from 2024-01-20 17-07-36
Screenshot from 2024-01-20 17-07-47

After restarting the remote its a bit different but still no entities:

Screenshot from 2024-01-20 17-17-55
(after a bit the red "error.ECONNABORTED" appeared at the bottom of the "Available Entities" column here too)

I'm using wss://«my internal domain»/api/websocket as the endpoint and with tcpdump on the server I can see traffic on the websocket: auth_ok, subscribe_events and get_states with success results and a big list of entity states. TLS certs are from letsencrypt and lighttpd is providing the forwarding -- there are no errors in the lighttpd logs or the packet capture.

Firmware is v1.6.4 and HASS integration says it is v0.6.1-dirty. HASS itself is 2024.01.4.

Logs:
UCR2_logs_core_scrubbed.txt
UCR2_logs_hass_scrubbed.txt

Implement setup flow

Implement the new setup flow and use it to dynamically configure the Home Assistant server settings:

  • implement setup flow
  • add setup schema flow for Home Assistant server: url, wss, token
  • create a new read-write configuration file which will be used for user settings.
  • remove HA settings from old system configuration file

Remove reconnection limit to HA server

As reported in the Discord chat:

My WiFi is stopped during the night. In the morning, the remote doesn’t reconnect to homeassistant. Homeassistant is also stopped during the night. I have to reconnect homeassistant manually in the web-configurator. Does the remote stop trying to reconnect after e certain time?

The HA reconnect setting has a default of 100, which should be unlimited by default, as the other integrations:
https://github.com/unfoldedcircle/integration-home-assistant/blob/v0.5.0/src/configuration.rs#L146-L155

At the moment it can't even disabled, minimum is 1, maximum 65535:
https://github.com/unfoldedcircle/integration-home-assistant/blob/v0.5.0/src/controller/handler/setup.rs#L212-L224

Android TV integration stops working randomly

Hi,
my android (shield) TV integration stops working randomly

From the logs I have this repetitive warning :

2024-03-08 13:34:47.903602 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.820193 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.737474 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.645467 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.562410 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.479548 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.387415 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.304166 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.221269 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.128610 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:47.045612 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:46.962951 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:46.870786 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format

then key pressed but nothing happens on AndroidTV's side :

2024-03-08 13:34:33.758752 +00:00	ui	INFO	uc.ui.input: Key released: "DPAD_DOWN" "Activity_QMLTYPE_247(0x55a9e1ece0)"
2024-03-08 13:34:33.758242 +00:00	ui	INFO	qml: OVERRIDE RELEASED: DPAD_DOWN Activity_QMLTYPE_247(0x55a9e1ece0)
2024-03-08 13:34:33.725597 +00:00	ui	WARN	qrc:/components/entities/media_player/ImageLoader.qml:61:5: QML Image: Error decoding: data:image/png;base64,: Unsupported image format
2024-03-08 13:34:33.646885 +00:00	intg-androidtv	INFO	DEBUG:ucapi.api:[('127.0.0.1', 60446)] ->: {"kind": "resp", "req_id": 2256, "code": 200, "msg": "result", "msg_data": {}}
2024-03-08 13:34:33.646617 +00:00	intg-androidtv	INFO	INFO:driver:Got 00044BE87F74 command request: cursor_down None
2024-03-08 13:34:33.645345 +00:00	intg-androidtv	INFO	DEBUG:ucapi.api:[('127.0.0.1', 60446)] <-: {"kind":"req","id":2256,"msg":"entity_command","msg_data":{"cmd_id":"cursor_down","entity_id":"00044BE87F74","entity_type":"media_player"}}
2024-03-08 13:34:33.643512 +00:00	ui	INFO	uc.ui.input: Key pressed: "DPAD_DOWN" "Activity_QMLTYPE_247(0x55a9e1ece0)"
2024-03-08 13:34:33.643152 +00:00	ui	INFO	qml: OVERRIDE PRESSED: DPAD_DOWN Activity_QMLTYPE_247(0x55a9e1ece0)

Here are the logs :
UCR2_logs_2024-03-08.zip

Connection timeout configuration is used as request timeout

While testing the HA server communication I've noticed that the Home Assistant WebSocket connection timeout configuration is used as request timeout. The TCP connection timeout is always using the default 5s. (This is the max time allowed to connect to remote host, including DNS name resolution).

For certain setups this could be an issue and not enough time to successfully connect. It might even be a reason for the reported TLS connection issues.

Tasks:

  • enhance configuration with a request timeout
  • the awc::Client setup in new_websocket_client requires an awc::Connector setup for the TCP connection timeout:
        awc::ClientBuilder::new()
            .timeout(request_timeout)
            .connector(awc::Connector::new().timeout(connection_timeout))
            .finish()

Is it possible to call a service?

I have written a custom integration for Home Assistant that allows me to control the Virgin Media TiVo set top box. The integration exposes a service that allows me to send IR codes or keypresses to the box over the network.

It would be great if I could call the service and provide the appropriate data to the service and then link this to buttons in the remote UI. This would greatly reduce the entity sprawl I'm envisaging. As an example, to press the number 1, currently I would need to create a button helper in Home Assistant and an associated automation that would call the service to send the relevant code via the Home Assistant integration.

However, if I could call the service from the remote I could have an entity in the remote UI for the service that allows me to populate the data and do all the work from the remote...

Obviously, this would probably be easier if I created an integration for the Virgin Media TiVo set top box for the remote but I don't have the time at the moment for that, but may look to do so in the future.

X-Plattform Docker Image + Build Error on ARM

Is it possible to provide an X-platform Docker image so that the ARM platform can also be used?

The whole thing would be best as an addon for Home Assistant.

I still tried to build it for ARM and now have the following error message:

error[E0061]: this function takes 4 arguments but 5 arguments were supplied
   --> src/main.rs:187:21
    |
187 |       if let Err(e) = publish_service(
    |                       ^^^^^^^^^^^^^^^
...
191 |           "uc-integration",
    |  _________________________-
192 | |         "tcp",
    | |         -----
    | |_________|___|
    |           |   help: remove the extra argument
    |           unexpected argument of type `&'static str`
    |
note: function defined here
   --> src/server/mod.rs:24:8
    |
24  | pub fn publish_service(
    |        ^^^^^^^^^^^^^^^
25  |     _instance_name: impl AsRef<str>,
    |     -------------------------------
26  |     _reg_type: impl Into<String>,
    |     ----------------------------
27  |     _port: u16,
    |     ----------
28  |     _txt: Vec<String>,
    |     -----------------

For more information about this error, try `rustc --explain E0061`.
error: could not compile `uc-intg-hass` (bin "uc-intg-hass") due to previous error

Improve reconnection handling with a state machine

The current reconnection handling to the HA server is more of a quick and dirty implementation than a proper solution.
With the new reconfiguration options there's a chance of a race condition, where suddenly two client connections are active. This interferes with heartbeat timeouts and can lead to constant reconnections. This has been seen in unfoldedcircle/feature-and-bug-tracker#243

The core already uses a state machine implementation for the WebSocket integration driver connections. This could probably be used as a starting point with some modifications (e.g. no authentication_error transition from the transient Connecting state, because of no header-based authentication):

image

Tasks:

  • analyze if we just need an additional "(re)-connection state-machine" (as shown above), or an overall state-machine which includes the current setup-flow state machine
  • design state machine(s)
  • replace current flag based reconnect with state machine implementation

Provide mute_toggle feature if device only supports mute & unmute

I'm controlling my Denon network receiver with HA. Unfortunately it only provides mute and unmute commands, so toggling mute with the mute button on the remote is not possible.

Media-player entity tasks:

  • verify if this old source comment in the integration is still true: // HASS media player doesn't support mute toggle!

It this is still true:

  • handle mute_toggle in the integration, based on the current mute state
  • provide mute toggle feature to the remote

Update rustls to v0.22

Rustls 0.22 has been released a month ago. We should upgrade.
Maybe this fixes the connection issue to Traefik, reported in:

However, 0.22 has major breaking changes and it won't be a simple crate update.
Furthermore, we can't upgrade yet because actix-web, awc and actix-tls only support rustls 0.21 as of now.

This already happened when upgrading to 0.21 - maybe we should consider switching to rust-openssl?
Even though I really like the full Rust approach, those breaking changes are becoming a hassle.

Support custom certificate for HA wss connection

If someone secures the HA WebSocket connection, it's most likely done with a self signed certificate.

Support adding a self signed certificate. At the moment we use an embedded Mozilla cert store.

Option to disconnect from HA when device enters standby

When running on the Remote Two device, the WebSocket connection to the HA server is currently kept open when the device enters suspend mode.

The Remote Two sends the enter_standby and exit_standby events, but they aren't being used yet in the integration besides setting a flag:

R2Event::EnterStandby => {
session.standby = true;
}
R2Event::ExitStandby => {
session.standby = false;
// TODO send updates #5
}

In certain environments this works quite well and the HA connection is immediately available after WiFi is connected. However, this can also cause connectivity issues after the device wakes up and take longer to detect a no longer working WebSocket connection.

With the upcoming, renewed connection logic in the core (unfoldedcircle/feature-and-bug-tracker#320) the integration should disconnect from HA when entering standby, and immediatly reconnect when receiving the exit_standby event.

This might also help with the following HA server log entries: Client unable to keep up with pending messages (unfoldedcircle/feature-and-bug-tracker#301). Assumption: remote is in standby and HA tries to send entity change events over the still open WebSocket connection.

Improve reconfiguration in web-configuration

With the Integration-API v0.8.0-beta there's now a reconfigure flag in the setup_driver message for setting up the integration.
This is used in the web-configurator in the "edit integration" screen.

When reconfiguring the HA integration:

  • Access token should be optional, to make it easier for the user to change other options:
    • If left empty: use existing one
    • Only overwrite existing token if a new token is provided

climate, temperature +/- does not work

hello,
I have added two "climate" entities, one heating (thermostat) and another air conditioning, turning it on and off works, but raising or lowering the temperature does not work, an error message appears with a red background.

"invalid_comand_id: climate.target_temperature. valid commands:
on,off,hvac_mode.target_temperature"

Someone gives me a hand?

Thank you so much

Possibility to control the remote via home assistant

Since there is little to none documentation (or since I can't find it at least) and not many people seem to have a remote two yet, I was wondering if it's possible to control the remote via Home Assistant. Especially controlling the dock would be very handy.

Cache entity changes while Remote is in standby

⚠️ This feature requires more testing!

Cache entity changes from HA and send them once remote comes out of standby.

Depends on:

  • If the integration runs externally or on the device:
    • Only relevant if it runs externally.
    • On-device requires a refresh from HA after wakeup.
  • WebSocket connection needs to be tested, when or if it gets dropped when Remote enters standby.
    --> if there's no reliable way to keep the WebSocket connection open, we can close this issue and just send all states when a new WS connection is established.

Use of self-signed certificate

How can I use self signed certificates for my Home Assistant instance? I see that I can add some environement vars, but can I set them on the remote?

Support "remote"-entities

The "Remotes" section in the web configurator currently supports only IR-remotes.

This is a request for it to also support the HA "remote" enitity exposed by some integrations (e.g. remote.philips_tv).

Currently, it is necessary to create a script for each button in order to use the remote via HA. This is not only tedious to create but also problematic since an activity only allows 50 active entities and each press is an entity.

With remote entity support, you would just add the remote entity and thus expose all commands to Remote Two like with IR remotes.

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.