Skip to content
Open
Show file tree
Hide file tree
Changes from 77 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
e89eee4
Add Wibeee integration with full quality scale and tests
fquinto Apr 17, 2026
c633461
Update manifest.json: point documentation to official HA docs
fquinto Apr 17, 2026
11a0a06
Add Wibeee energy monitor component
fquinto Apr 17, 2026
500e050
Fix pylint warnings: AddConfigEntryEntitiesCallback and move EntityDe…
fquinto Apr 17, 2026
b72296d
Fix manifest.json: remove invalid fields, add network dependency
fquinto Apr 17, 2026
683d672
Fix type errors and type annotations
fquinto Apr 17, 2026
82a062e
Merge branch 'dev' into dev
fquinto Apr 17, 2026
20ad7b9
Update homeassistant/components/wibeee/sensor.py
fquinto Apr 17, 2026
d190c8a
Update homeassistant/components/wibeee/__init__.py
fquinto Apr 17, 2026
09ed254
Update homeassistant/components/wibeee/__init__.py
fquinto Apr 17, 2026
e02601a
Update homeassistant/components/wibeee/__init__.py
fquinto Apr 17, 2026
ae975a7
Update tests/components/wibeee/test_button.py
fquinto Apr 17, 2026
6133c75
Update tests/components/wibeee/test_init.py
fquinto Apr 17, 2026
a8edf92
Merge branch 'dev' into dev
fquinto Apr 17, 2026
14a448b
Refactor: use external pywibeee library instead of internal api.py
fquinto Apr 17, 2026
211d9c9
Remove .qwen directory from tracking
fquinto Apr 17, 2026
042660c
Use UnitOfReactiveEnergy constants instead of raw 'varh' strings
fquinto Apr 17, 2026
e1d7e99
Fix lint errors: DeviceInfo imports, lazy imports, PERF401, unused va…
fquinto Apr 17, 2026
d12073a
Update manifest.json: add quality_scale platinum and pin pywibeee ver…
fquinto Apr 17, 2026
570c6fd
Fix lint errors: DeviceInfo, strict-typing, C7461, options flow typing
fquinto Apr 17, 2026
6b00186
Add wibeee to .strict-typing for quality scale compliance
fquinto Apr 17, 2026
5323c3d
Move WibeeeSensorEntityDescription to sensor.py per C7461
fquinto Apr 17, 2026
8b88cc1
Fix type errors: change SENSOR_TYPES to use SensorEntityDescription
fquinto Apr 17, 2026
c1eaa5e
Add pywibeee dependency
fquinto Apr 17, 2026
8c4d140
Update pywibeee to 0.1.3 for PEP 561 compliance
fquinto Apr 17, 2026
9d74d4b
Re-run CI to pick up pywibeee 0.1.3
fquinto Apr 17, 2026
beb4d58
Fix WibeeeSensorEntityDescription usage and Python 2 exception syntax
fquinto Apr 17, 2026
61e6eec
Move WibeeeSensorEntityDescription back to const.py with pylint disable
fquinto Apr 17, 2026
3eeb385
Remove duplicate WibeeeSensorEntityDescription from sensor.py
fquinto Apr 18, 2026
f3194dd
Merge branch 'dev' into dev
fquinto Apr 18, 2026
cfc02ff
Merge branch 'dev' into dev
fquinto Apr 18, 2026
58bc6df
Regenerate requirements to place pywibeee in correct alphabetical pos…
fquinto Apr 18, 2026
5995efe
Run hassfest to update generated files for Wibeee integration
fquinto Apr 18, 2026
a0b36f2
Fix Python 3.14 compatibility and mypy type errors
fquinto Apr 18, 2026
13abc52
Fix mypy unreachable statements in sensor.py
fquinto Apr 18, 2026
00dcc3d
Fix mypy unreachable statements in sensor.py
fquinto Apr 19, 2026
687b01f
Validate MAC in push receiver to prevent spoofing
fquinto Apr 19, 2026
effed37
Normalize MAC address for unique_id consistency
fquinto Apr 19, 2026
70e30a2
Fix CONF_HOST import from homeassistant.const
fquinto Apr 19, 2026
65be1d3
Merge branch 'dev' into dev
fquinto Apr 19, 2026
e935d73
Add unit tests for push receiver
fquinto Apr 19, 2026
ed378f8
Merge branch 'dev' into dev
fquinto Apr 19, 2026
cc16f05
Fix review comments and improve robustness
fquinto Apr 19, 2026
32862e1
Fix unused imports in test_push_receiver.py
fquinto Apr 19, 2026
88e883e
Fix review comments
fquinto Apr 20, 2026
12644ca
Merge branch 'dev' into dev
fquinto Apr 20, 2026
1dd0bef
Merge branch 'dev' into dev
fquinto Apr 20, 2026
0cd4457
Merge branch 'dev' into dev
fquinto Apr 21, 2026
608fa8f
Re-run CI to pick up pywibeee 0.1.3
fquinto Apr 17, 2026
63c2b26
Fix Python 3.14 exception syntax in wibeee component
fquinto Apr 20, 2026
0872a3e
Fix review comments: consistent WiBeee capitalization, validate local…
fquinto Apr 21, 2026
b7aa02a
Format WiBeee strings and icons with Prettier
fquinto Apr 22, 2026
ba45f83
Merge branch 'dev' into dev
fquinto Apr 22, 2026
adf39b7
Address review comments: Fix diagnostics type hints, IP validation fo…
fquinto Apr 22, 2026
1ff85ba
Fix CI failures: Add missing translations and mock async_configure_pu…
fquinto Apr 22, 2026
65b4280
Trigger CI: retry after infrastructure timeout
fquinto Apr 22, 2026
bc48239
Address review comments: Simplify docstring, lower quality_scale to b…
fquinto Apr 24, 2026
d54e23b
Fix quality scale issues: remove manual scan_interval and fix unused …
fquinto Apr 24, 2026
62d3a56
Final cleanup for Python 3.14.2: remove unused imports
fquinto Apr 24, 2026
209df15
Address remaining Copilot review comments: resolve hostname for IP va…
fquinto Apr 24, 2026
dc21e5f
Fix ruff formatting and use resolved_ip for push receiver registration
fquinto Apr 26, 2026
4b6ef46
Fix CI test failures, improve IP security and reduce log spam
fquinto Apr 26, 2026
d69385d
Style: reorder imports according to Home Assistant standards (isort/r…
fquinto Apr 26, 2026
7c4401a
Fix sensor creation in push mode and DHCP abort translation
fquinto Apr 27, 2026
d6282af
Fix sensor tests, resolve via_device warning and update coordinator t…
fquinto Apr 27, 2026
bf13e93
Test: reach 100% coverage by adding error paths, diagnostics and coor…
fquinto Apr 27, 2026
689aeca
Fix tests: mock local IP to avoid socket errors, fix DHCP flow expect…
fquinto Apr 27, 2026
0bddaf6
Architectural improvements: shared auto-config helper, improved senso…
fquinto Apr 27, 2026
ecbb3af
Fix imports and typing: use helpers for DhcpServiceInfo and typed Con…
fquinto Apr 27, 2026
6d560b0
Fix final CI issues: correct AbortFlow import, fix DhcpServiceInfo pa…
fquinto Apr 27, 2026
c3afef3
Fix test mocks: unwrap overlapping patches and ensure consistent API …
fquinto Apr 28, 2026
73f6638
Fix Copilot review comments: reuse DEFAULT_HA_PORT, validate dict typ…
fquinto Apr 29, 2026
2609965
Format conftest.py multi-line with statement
fquinto Apr 29, 2026
5aae960
Final polish: ensure perfect ruff formatting and repository sync
fquinto Apr 29, 2026
14e3db7
Fix tests: unblock socket by mocking pywibeee.WibeeeAPI globally and …
fquinto Apr 30, 2026
9f2caee
Final technical polish: robust IP resolution, unique_id normalization…
fquinto Apr 30, 2026
ed20679
Fix wibeee tests: resolve fixture name shadowing and add missing tran…
fquinto May 1, 2026
e269140
Address Copilot AI review: align icons/strings with sensor-only platf…
fquinto May 1, 2026
9613bbf
Increase wibeee test coverage to 96% to satisfy codecov
fquinto May 2, 2026
24f1e87
Address Copilot review: harden push mode and tighten sensor setup
fquinto May 2, 2026
c1b443e
Add wibeee tests to reach 100% patch coverage
fquinto May 2, 2026
db262df
Retrigger CI: prior run hit unrelated flaky zwave_js test
fquinto May 3, 2026
e381e63
Address @erwindouna review: simplify imports and tighten code
fquinto May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .strict-typing
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ homeassistant.components.webostv.*
homeassistant.components.websocket_api.*
homeassistant.components.wemo.*
homeassistant.components.whois.*
homeassistant.components.wibeee.*
homeassistant.components.withings.*
homeassistant.components.wiz.*
homeassistant.components.wled.*
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

156 changes: 156 additions & 0 deletions homeassistant/components/wibeee/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
"""The Wibeee integration."""

from __future__ import annotations

from dataclasses import dataclass
import ipaddress
import logging
import socket

import aiohttp
from pywibeee import WibeeeAPI, WibeeeDeviceInfo

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession

from .const import (
CONF_MAC_ADDRESS,
CONF_UPDATE_MODE,
CONF_WIBEEE_ID,
DEFAULT_SCAN_INTERVAL,
MODE_LOCAL_PUSH,
MODE_POLLING,
)
from .coordinator import WibeeeCoordinator
from .push_receiver import async_setup_push_receiver

_LOGGER = logging.getLogger(__name__)

PLATFORMS = [Platform.SENSOR]

Comment on lines +34 to +35
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

Align the PR description with the implementation (or add the missing platform): the integration currently only forwards the sensor platform (no button platform/entities are set up).

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +35
Copy link

Copilot AI May 1, 2026

Choose a reason for hiding this comment

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

Align the implementation with the PR description by either adding the button platform (and including Platform.BUTTON in PLATFORMS) or updating the PR description/translations/icons to match the current sensor-only integration.

Copilot uses AI. Check for mistakes.

@dataclass
class WibeeeRuntimeData:
"""Runtime data stored in entry.runtime_data."""

api: WibeeeAPI
device_info: WibeeeDeviceInfo
coordinator: WibeeeCoordinator


WibeeeConfigEntry = ConfigEntry[WibeeeRuntimeData]


async def async_setup_entry(hass: HomeAssistant, entry: WibeeeConfigEntry) -> bool:
"""Set up Wibeee from a config entry."""
mode = entry.options.get(CONF_UPDATE_MODE, MODE_LOCAL_PUSH)
host = entry.data[CONF_HOST]
mac_addr = entry.data[CONF_MAC_ADDRESS]
wibeee_id = entry.data.get(CONF_WIBEEE_ID, "WIBEEE")

_LOGGER.debug(
"Setting up Wibeee entry %s (mode=%s, host=%s)",
entry.entry_id,
mode,
host,
)

session = async_get_clientsession(hass)
api = WibeeeAPI(session, host)

# Fetch device info
try:
device_info = await api.async_fetch_device_info(retries=3)
except (TimeoutError, aiohttp.ClientError) as err:
raise ConfigEntryNotReady(f"Could not connect to Wibeee at {host}") from err

if device_info is None:
_LOGGER.warning("Could not get device info from %s, using fallback", host)
device_info = WibeeeDeviceInfo(
wibeee_id=wibeee_id,
mac_addr=mac_addr,
model="Unknown",
firmware_version="Unknown",
ip_addr=host,
)

# Create coordinator based on mode
if mode == MODE_POLLING:
coordinator = WibeeeCoordinator(
hass,
api,
config_entry=entry,
name=f"Wibeee {device_info.mac_addr_short}",
Comment on lines +83 to +88
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

Use the configured scan interval option (if present) when creating the polling coordinator instead of always using DEFAULT_SCAN_INTERVAL.

Copilot uses AI. Check for mistakes.
update_interval=DEFAULT_SCAN_INTERVAL,
)
await coordinator.async_config_entry_first_refresh()
Comment on lines +84 to +91
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

Use the config entry’s configured scan interval option (if present) when constructing the polling-mode coordinator instead of always using the default interval.

Copilot uses AI. Check for mistakes.
else:
# Push mode: no polling, data arrives via async_set_updated_data()
coordinator = WibeeeCoordinator(
hass,
api,
config_entry=entry,
name=f"Wibeee {device_info.mac_addr_short}",
update_interval=None,
Comment on lines +94 to +99
)
# Do one initial poll to discover available sensors
try:
initial_data = await api.async_fetch_sensors_data(retries=3)
except (TimeoutError, aiohttp.ClientError) as err:
raise ConfigEntryNotReady(f"Error connecting to Wibeee at {host}") from err
Comment on lines +102 to +106
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

Initialize the coordinator with the initial sensor payload in push mode so sensor setup can discover phases and create entities.

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +106

if not initial_data:
raise ConfigEntryNotReady(
f"Could not fetch initial sensor data from Wibeee at {host}"
Comment on lines +102 to +110
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

Fail setup (e.g., raise ConfigEntryNotReady) or otherwise ensure sensors are still created when the initial data fetch returns no data, since in push mode coordinator.data stays None and sensor.async_setup_entry will create zero entities permanently.

Copilot uses AI. Check for mistakes.
)
Comment on lines +102 to +111
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

Catch network/parsing errors when doing the initial sensor fetch in push mode and raise ConfigEntryNotReady so setup is retried.

await api.async_fetch_sensors_data(...) can raise (e.g., timeout / client errors / XML parse errors); currently these will bubble out of async_setup_entry as an unhandled exception, preventing the normal retry behavior used in polling mode via the coordinator.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +111
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

Wrap the initial async_fetch_sensors_data call in push mode with exception handling and raise ConfigEntryNotReady on expected connection errors.

Copilot uses AI. Check for mistakes.

Comment on lines +102 to +112
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

Wrap the initial async_fetch_sensors_data call in push mode in a try/except and raise ConfigEntryNotReady on connection/parsing errors, so transient network/device issues cause a retry instead of failing the config entry setup with an unhandled exception.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

Set the initial sensor payload on the coordinator in push mode so sensor setup can discover phases and create entities.

Suggested change
coordinator.async_set_updated_data(initial_data)

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

Validate that the initial sensor payload fetched in push mode is a dict before storing it in the coordinator to avoid runtime errors in sensor entities when the library returns an unexpected type.

Suggested change
if not isinstance(initial_data, dict):
raise ConfigEntryNotReady(
f"Invalid initial sensor data received from Wibeee at {host}"
)

Copilot uses AI. Check for mistakes.
coordinator.async_set_updated_data(initial_data)

# Register with push receiver
# Ensure we use a concrete IP even if host is a hostname for validation
try:
resolved_ip = str(ipaddress.ip_address(host))
except ValueError:
try:
resolved_ip = await hass.async_add_executor_job(
socket.gethostbyname, host
)
resolved_ip = str(ipaddress.ip_address(resolved_ip))
except (OSError, ValueError) as err:
raise ConfigEntryNotReady(
f"Could not resolve Wibeee host {host} to an IP address for push mode"
) from err

receiver = async_setup_push_receiver(hass)
receiver.register_device(mac_addr, resolved_ip, coordinator.async_push_update)

entry.async_on_unload(lambda: receiver.unregister_device(mac_addr))

Comment on lines +132 to +136
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

Register the push receiver with a concrete device IP (or resolve hostnames) so IP validation doesn’t reject legitimate push requests when the user configured the device via hostname.

Copilot uses AI. Check for mistakes.
entry.runtime_data = WibeeeRuntimeData(
api=api, device_info=device_info, coordinator=coordinator
)

# Reload on options change
entry.async_on_unload(entry.add_update_listener(async_update_options))

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True


async def async_unload_entry(hass: HomeAssistant, entry: WibeeeConfigEntry) -> bool:
"""Unload a config entry."""
_LOGGER.debug("Unloading Wibeee entry %s", entry.entry_id)

unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

Comment thread
fquinto marked this conversation as resolved.
if unload_ok:
del entry.runtime_data
return unload_ok


Comment thread
fquinto marked this conversation as resolved.
async def async_update_options(hass: HomeAssistant, entry: WibeeeConfigEntry) -> None:
"""Handle options update - reload the entry."""
await hass.config_entries.async_reload(entry.entry_id)
Loading
Loading