Skip to content

Easywave integration#165895

Open
eldateas wants to merge 35 commits intohome-assistant:devfrom
eldateas:easywave-integration
Open

Easywave integration#165895
eldateas wants to merge 35 commits intohome-assistant:devfrom
eldateas:easywave-integration

Conversation

@eldateas
Copy link
Copy Markdown

Proposed change

Add the Easywave integration for the ELDAT RX11 USB transceiver module.

The Easywave system is a 868 MHz wireless protocol used in European home automation for controlling lights, blinds, and other devices. The RX11 is a USB transceiver that communicates with Easywave devices.

This integration provides:

USB auto-discovery — automatically detected via usb matcher (VID 155A, PID 1014)
Manual setup via config flow with serial port selection
Sensor platform — exposes device status, hardware/firmware versions, connection state, and regulatory information
Automatic reconnection — handles USB disconnect/reconnect gracefully with coordinator-based polling
Regulatory compliance — enforces 868 MHz frequency restrictions based on the configured Home Assistant country (EU/EEA region only)
Device registry — registers the RX11 gateway with full device information
The integration communicates locally via serial (pyserial) with no cloud dependency.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copilot AI review requested due to automatic review settings March 18, 2026 09:37
Copy link
Copy Markdown

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @eldateas,

When attempting to inspect the commits of your pull request for CLA signature status among all authors we encountered commit(s) which were not linked to a GitHub account, thus not allowing us to determine their status(es).

The commits that are missing a linked GitHub account are the following:

Unfortunately, we are unable to accept this pull request until this situation is corrected.

Here are your options:

  1. If you had an email address set for the commit that simply wasn't linked to your GitHub account you can link that email now and it will retroactively apply to your commits. The simplest way to do this is to click the link to one of the above commits and look for a blue question mark in a blue circle in the top left. Hovering over that bubble will show you what email address you used. Clicking on that button will take you to your email address settings on GitHub. Just add the email address on that page and you're all set. GitHub has more information about this option in their help center.

  2. If you didn't use an email address at all, it was an invalid email, or it's one you can't link to your GitHub, you will need to change the authorship information of the commit and your global Git settings so this doesn't happen again going forward. GitHub provides some great instructions on how to change your authorship information in their help center.

    • If you only made a single commit you should be able to run
      git commit --amend --author="Author Name <email@address.com>"
      
      (substituting "Author Name" and "email@address.com" for your actual information) to set the authorship information.
    • If you made more than one commit and the commit with the missing authorship information is not the most recent one you have two options:
      1. You can re-create all commits missing authorship information. This is going to be the easiest solution for developers that aren't extremely confident in their Git and command line skills.
      2. You can use this script that GitHub provides to rewrite history. Please note: this should be used only if you are very confident in your abilities and understand its impacts.
    • Whichever method you choose, I will come by to re-check the pull request once you push the fixes to this branch.

We apologize for this inconvenience, especially since it usually bites new contributors to Home Assistant. We hope you understand the need for us to protect ourselves and the great community we all have built legally. The best thing to come out of this is that you only need to fix this once and it benefits the entire Home Assistant and GitHub community.

Thanks, I look forward to checking this PR again soon! ❤️

@home-assistant
Copy link
Copy Markdown

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Home Assistant Core integration for the ELDAT RX11 USB transceiver (Easywave 868 MHz), including config flow, coordinator-based reconnect/polling, diagnostics sensor, USB discovery, and regulatory compliance enforcement.

Changes:

  • Introduce the easywave integration (config flow, coordinator, transceiver/protocol implementation, diagnostics sensor, translations).
  • Add USB matcher + generated registries updates (usb matchers, integrations list, config flows list).
  • Add a full test suite covering config flow, coordinator, init/setup behavior, sensors, and regulatory checks.

Reviewed changes

Copilot reviewed 21 out of 24 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
homeassistant/components/easywave/__init__.py Integration setup/unload, runtime data, regulatory compliance enforcement, device removal guard
homeassistant/components/easywave/config_flow.py User + USB discovery config flow with serial port scanning and confirmation
homeassistant/components/easywave/const.py Domain constants, USB ID registry, polling interval, regulatory allow-list + helpers, gateway events
homeassistant/components/easywave/coordinator.py DataUpdateCoordinator handling connect/reconnect/offline transitions
homeassistant/components/easywave/sensor.py Diagnostic ENUM sensor for gateway connection status + device info/attributes
homeassistant/components/easywave/transceiver.py RX11 transceiver abstraction using RxModule, health checks, reconnect logic, USB discovery
homeassistant/components/easywave/rx_module.py Serial protocol implementation (request/response handling, stuffing, version queries, thread-based RX loop)
homeassistant/components/easywave/manifest.json Integration manifest (requirements, USB matcher, metadata)
homeassistant/components/easywave/strings.json Config flow strings, entity strings, exceptions, repair issue strings
homeassistant/components/easywave/quality_scale.yaml Quality scale declaration and exemptions/done markers
homeassistant/generated/usb.py Generated USB matcher entry for Easywave RX11
homeassistant/generated/integrations.json Generated integrations registry entry for easywave
homeassistant/generated/config_flows.py Generated list updated to include easywave
requirements_all.txt Generated requirements comment updated for easywave
requirements_test_all.txt Generated test requirements comment updated for easywave
CODEOWNERS Add code ownership for the new integration + tests
tests/components/easywave/__init__.py Test package marker for the integration
tests/components/easywave/conftest.py Shared fixtures for Easywave tests
tests/components/easywave/test_config_flow.py Config flow tests (user + USB discovery + unique_id behaviors)
tests/components/easywave/test_const.py Constants/helper function tests
tests/components/easywave/test_coordinator.py Coordinator connection/reconnect/disconnect behavior tests
tests/components/easywave/test_init.py Integration setup/unload/device-removal behavior tests
tests/components/easywave/test_regulatory_compliance.py Country/frequency allow-list + setup enforcement tests
tests/components/easywave/test_sensor.py Gateway sensor state/icon/events/device-info update tests

@eldateas eldateas force-pushed the easywave-integration branch from b601c65 to 60c10c6 Compare March 18, 2026 09:48
Copy link
Copy Markdown

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @eldateas,

When attempting to inspect the commits of your pull request for CLA signature status among all authors we encountered commit(s) which were not linked to a GitHub account, thus not allowing us to determine their status(es).

The commits that are missing a linked GitHub account are the following:

Unfortunately, we are unable to accept this pull request until this situation is corrected.

Here are your options:

  1. If you had an email address set for the commit that simply wasn't linked to your GitHub account you can link that email now and it will retroactively apply to your commits. The simplest way to do this is to click the link to one of the above commits and look for a blue question mark in a blue circle in the top left. Hovering over that bubble will show you what email address you used. Clicking on that button will take you to your email address settings on GitHub. Just add the email address on that page and you're all set. GitHub has more information about this option in their help center.

  2. If you didn't use an email address at all, it was an invalid email, or it's one you can't link to your GitHub, you will need to change the authorship information of the commit and your global Git settings so this doesn't happen again going forward. GitHub provides some great instructions on how to change your authorship information in their help center.

    • If you only made a single commit you should be able to run
      git commit --amend --author="Author Name <email@address.com>"
      
      (substituting "Author Name" and "email@address.com" for your actual information) to set the authorship information.
    • If you made more than one commit and the commit with the missing authorship information is not the most recent one you have two options:
      1. You can re-create all commits missing authorship information. This is going to be the easiest solution for developers that aren't extremely confident in their Git and command line skills.
      2. You can use this script that GitHub provides to rewrite history. Please note: this should be used only if you are very confident in your abilities and understand its impacts.
    • Whichever method you choose, I will come by to re-check the pull request once you push the fixes to this branch.

We apologize for this inconvenience, especially since it usually bites new contributors to Home Assistant. We hope you understand the need for us to protect ourselves and the great community we all have built legally. The best thing to come out of this is that you only need to fix this once and it benefits the entire Home Assistant and GitHub community.

Thanks, I look forward to checking this PR again soon! ❤️

Copilot AI review requested due to automatic review settings March 18, 2026 10:11
@eldateas eldateas force-pushed the easywave-integration branch from 60c10c6 to 1edcf30 Compare March 18, 2026 10:11
Copy link
Copy Markdown

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eldateas

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Home Assistant Core integration (easywave) for the ELDAT RX11 USB transceiver (Easywave 868 MHz), including config flow + USB discovery, a diagnostic sensor for gateway status, a coordinator/transceiver stack for reconnect handling, and regulatory compliance checks based on the configured HA country.

Changes:

  • Introduces the Easywave integration (config flow, coordinator, transceiver/protocol implementation, diagnostic sensor, translations, manifest/quality scale).
  • Adds comprehensive test coverage for config flow, coordinator, init/setup, sensor behavior, constants, and regulatory compliance logic.
  • Updates generated/registry files and requirements comment maps to include the new integration and USB matcher.

Reviewed changes

Copilot reviewed 21 out of 24 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
homeassistant/components/easywave/init.py Integration setup/unload + regulatory compliance enforcement + device removal guard
homeassistant/components/easywave/config_flow.py User + USB discovery flows with serial port detection/selection
homeassistant/components/easywave/const.py Domain constants, USB IDs, scan interval, regulatory allow-list helpers, events
homeassistant/components/easywave/coordinator.py DataUpdateCoordinator handling offline mode + reconnect polling + disconnect callback
homeassistant/components/easywave/transceiver.py RX11 transceiver abstraction using RxModule, with connect/reconnect + health checking
homeassistant/components/easywave/rx_module.py Low-level serial/protocol implementation and serial handler thread
homeassistant/components/easywave/sensor.py Diagnostic enum sensor for gateway connection state + device registry updates
homeassistant/components/easywave/strings.json Config flow text, sensor states, exceptions, and repair issue strings
homeassistant/components/easywave/manifest.json Declares integration metadata, dependency, USB matcher, and requirement
homeassistant/components/easywave/quality_scale.yaml Bronze quality scale declaration for the new integration
homeassistant/generated/usb.py Adds USB matcher entry for RX11 auto-discovery
homeassistant/generated/integrations.json Registers new integration metadata in generated registry
homeassistant/generated/config_flows.py Adds easywave to generated config flow list
CODEOWNERS Adds code ownership for the new integration and tests
requirements_all.txt Adds integration comment mapping for requirements inventory
requirements_test_all.txt Adds integration comment mapping for test requirements inventory
tests/components/easywave/conftest.py Fixtures for config entries, USB discovery, coordinator/transceiver mocks
tests/components/easywave/test_config_flow.py Tests for user/USB flows and unique-id fallback behavior
tests/components/easywave/test_const.py Tests for constants and helper functions
tests/components/easywave/test_coordinator.py Tests for coordinator lifecycle, offline mode, reconnect, shutdown
tests/components/easywave/test_init.py Tests for setup/unload and device removal constraints
tests/components/easywave/test_regulatory_compliance.py Tests for country allow-list + setup compliance behavior/repair issue creation
tests/components/easywave/test_sensor.py Tests for sensor attributes, lifecycle, events, and device registry updates
tests/components/easywave/init.py Test package marker for the integration

@home-assistant home-assistant bot marked this pull request as draft March 19, 2026 21:58
Remove the in-tree RX11 serial protocol implementation (rx_module.py,
~1 200 lines) and replace it with the published PyPI package
easywave-home-control==0.1.1, which provides the same functionality as
RX11Device and RX11ErrorCode.

Changes:
- Delete rx_module.py (custom RX11 serial driver)
- Rewrite transceiver.py to use RX11Device / RX11ErrorCode from the
  library; keep existing connect/disconnect/health-check/dispose
  lifecycle and USB identity refresh logic
- Update manifest.json: add easywave-home-control==0.1.1 to requirements
- Adjust coordinator.py import (RX11ErrorCode moved to top-level export)
- Add test_transceiver.py with 46 tests covering 100 % of transceiver.py
- Update test_coordinator.py to use RX11ErrorCode instead of
  RX11Device.ErrorCode
- Update requirements_all.txt and requirements_test_all.txt
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Home Assistant Core integration (easywave) for the ELDAT RX11 USB transceiver, including config flow + USB discovery, a coordinator/transceiver connection layer with reconnection handling, and a diagnostic sensor with device-registry metadata and regulatory compliance gating.

Changes:

  • Introduces the Easywave integration (config flow, transceiver, coordinator, sensor, constants, translations, manifest/quality scale).
  • Registers USB discovery matcher + generated integration metadata, and adds the new dependency to requirements.
  • Adds a comprehensive test suite covering config flow, coordinator/transceiver behavior, sensors, and regulatory compliance.

Reviewed changes

Copilot reviewed 21 out of 24 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
homeassistant/components/easywave/init.py Integration setup/unload, runtime data, and regulatory compliance enforcement.
homeassistant/components/easywave/config_flow.py User + USB discovery flows with port selection and confirmation.
homeassistant/components/easywave/const.py Domain constants, USB ID registry, polling interval, and regulatory country lists/helpers.
homeassistant/components/easywave/coordinator.py DataUpdateCoordinator managing offline/online state and reconnect polling.
homeassistant/components/easywave/transceiver.py RX11 device abstraction: connect/disconnect/reconnect, health-check loop, version queries, and callbacks.
homeassistant/components/easywave/sensor.py Diagnostic gateway-status sensor + device registry updates and HA event emission.
homeassistant/components/easywave/manifest.json Integration metadata + requirements + USB matcher.
homeassistant/components/easywave/strings.json User-facing strings for flow, sensor enum states, exceptions, and issues.
homeassistant/components/easywave/quality_scale.yaml Declares bronze quality-scale status and exemptions.
homeassistant/generated/usb.py Adds generated USB discovery entry for RX11 → easywave.
homeassistant/generated/config_flows.py Registers easywave as a config flow handler.
homeassistant/generated/integrations.json Adds generated metadata entry for the new integration.
requirements_all.txt Adds easywave-home-control==0.1.1 to the pinned dependency list.
requirements_test_all.txt Adds easywave-home-control==0.1.1 to the test dependency list.
tests/components/easywave/init.py Initializes the test package for the new integration.
tests/components/easywave/conftest.py Provides fixtures for config entries, USB discovery info, and coordinator mocks.
tests/components/easywave/test_config_flow.py Tests user + USB discovery config flows and device enumeration helper.
tests/components/easywave/test_const.py Tests constants + helper functions (USB IDs, frequencies, country checks).
tests/components/easywave/test_coordinator.py Tests coordinator setup, offline/online transitions, and update logic.
tests/components/easywave/test_init.py Tests integration setup/unload and gateway device removal rules.
tests/components/easywave/test_regulatory_compliance.py Tests country/frequency allow-list logic and issue registry behavior.
tests/components/easywave/test_sensor.py Tests gateway-status sensor behavior, events, and device registry updates.
CODEOWNERS Adds ownership for the new integration and its tests.

- _health_check_loop: capture self._device into local var before the
  null-check to avoid a race with concurrent disconnect() setting it to
  None (AttributeError would have silently killed the background task)
- _on_device_disconnect: use hass.loop.call_soon_threadsafe() instead of
  hass.async_create_task() — the RX11Device callback can be invoked from
  the library's serial handler thread, not the HA event loop thread
- connect(): catch _SERIAL_OR_OS_ERRORS (not just _SERIAL_ERRORS) so an
  OSError during port enumeration returns False instead of propagating
- connect(): move _reconnect_attempts = 0 to after a successful
  _try_connect_to_path() call so warning-log gating works correctly
- _find_usb_device(): wrap comports() in try/except _SERIAL_OR_OS_ERRORS
  and return None on failure instead of propagating to the executor
Copilot AI review requested due to automatic review settings March 24, 2026 08:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 24 changed files in this pull request and generated 2 comments.

Comment on lines +293 to +295
task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await task
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prevent cancelling the health-check task from inside the health-check loop by avoiding task.cancel() when the current task is the health-check task (or by shielding the disconnect path), otherwise a health-check-triggered disconnect can cancel _handle_device_disconnect() mid-flight and skip cleanup/notifications.

Suggested change
task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await task
# Avoid cancelling the health check task from within itself
if task is not asyncio.current_task():
task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await task

Copilot uses AI. Check for mistakes.
@eldateas eldateas marked this pull request as ready for review March 24, 2026 08:42
@home-assistant home-assistant bot requested a review from joostlek March 24, 2026 08:42
Copilot AI review requested due to automatic review settings March 25, 2026 08:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 24 changed files in this pull request and generated 2 comments.

# If specific device path provided, try it first
if self.device_path:
if await self._try_connect_to_path(self.device_path):
await self._refresh_usb_identity()
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reset the reconnect-attempt counter after a successful connection via an explicit device_path as well, so subsequent logging/connection logic isn’t affected by stale _reconnect_attempts values.

Suggested change
await self._refresh_usb_identity()
await self._refresh_usb_identity()
# Reset reconnect attempts after a successful connection
self._reconnect_attempts = 0

Copilot uses AI. Check for mistakes.
@eldateas
Copy link
Copy Markdown
Author

eldateas commented Apr 9, 2026

Hi @joostlek,

thank you for the feedback provided in your earlier review. As requested, I have moved all device-specific code into a dedicated PyPI library (easywave-home-control) and refactored the integration accordingly to depend on that library instead of containing any custom hardware communication logic.

The PR has been ready for review for some time now. I would really appreciate it if you or another reviewer could take a look when time permits, so we can continue moving this forward.

Thank you for your time and the great work you all do maintaining Home Assistant!

Copy link
Copy Markdown
Member

@joostlek joostlek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so when I continued with the coordinator and sensor, I am now wondering a few things

  1. If you allow the library to add and remove listeners for connection status, you can subscribe on entity level.
  2. The coordinator itself doesn't seem to do any polling, so with 1, I am wondering if we really need the coordinator. From what I understand we only need reconnection logic.
  3. The current functionality of the integration returning if the USB is connected or not, so I am kinda wondering what the value will be. Wouldn't it make more sense to actually start with a feature that makes more sense for the user to use? What will your next steps be?

@home-assistant home-assistant bot marked this pull request as draft April 9, 2026 14:50
Changes based on code review (home-assistant#165895):

- Use None instead of 'unknown' for frequency/country
- Remove hasattr guard on runtime_data
- Remove async_remove_config_entry_device (single gateway device)
- Remove _find_easywave_devices; list all serial ports via comports()
- Merge async_step_user and async_step_detect into single step
- Use EasywaveConfigEntry type in coordinator
- Replace async_setup with _async_setup raising UpdateFailed
- Clean up unused imports, fixtures and tests
@eldateas
Copy link
Copy Markdown
Author

Thanks for the thorough review, @joostlek! We've addressed all your feedback:

Changes made:

  1. None instead of "unknown"frequency and country in __init__.py now use None when the value is unavailable. The EasywaveRuntimeData types were updated to str | None accordingly.

  2. Removed hasattr guard — The hasattr(entry, "runtime_data") check is gone; entry.runtime_data is accessed directly as guaranteed by the framework.

  3. Removed async_remove_config_entry_device — Since this integration only has a single gateway device tied to the config entry, the custom device removal logic was unnecessary and has been removed.

  4. Removed _find_easywave_devices — The custom VID/PID pre-filtering was redundant with HA's USB auto-discovery (manifest.json usb matchers). The manual async_step_user now lists all serial ports via comports() (following the Velbus pattern) and lets the user pick from a dropdown. USB metadata is extracted from the selected port object.

  5. Merged async_step_user and async_step_detect — These were collapsed into a single async_step_user step. The intermediate step was unnecessary since the user always needs to pick a port.

  6. EasywaveConfigEntry type in coordinator — The coordinator constructor now uses EasywaveConfigEntry instead of the generic ConfigEntry.

  7. _async_setup with UpdateFailed — Replaced the custom async_setup() with _async_setup() raising UpdateFailed, so we can use async_config_entry_first_refresh() instead of manual setup + ConfigEntryNotReady handling.

Intentionally kept:

  • DataUpdateCoordinator — While this PR only sets up the gateway connection, the coordinator is the foundation for the next PRs, which will integrate Easywave senders (e.g., remotes, wall switches, motion detectors) and receivers (e.g., actuators) as HA entities. The coordinator will manage their state updates and provide the central communication hub for all device types. Removing it now would mean reintroducing it immediately in the follow-up.

  • USB_DEVICE_NAMES / SUPPORTED_USB_IDS in const.py — These are still used by the transceiver module and the USB discovery step. SUPPORTED_USB_IDS will also be relevant when supporting additional Easywave hardware variants.

@eldateas eldateas marked this pull request as ready for review April 10, 2026 10:08
@home-assistant home-assistant bot requested a review from joostlek April 10, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants