From f65d87f4fbe74219028da9213f07eb6d7f82c20b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bro=C5=BE?= Date: Tue, 18 Aug 2026 23:26:49 +0200 Subject: [PATCH 1/3] Fix Signal Messenger self notifications (#179351) --- homeassistant/components/signal_messenger/notify.py | 1 + tests/components/signal_messenger/test_notify.py | 1 + 2 files changed, 2 insertions(+) diff --git a/homeassistant/components/signal_messenger/notify.py b/homeassistant/components/signal_messenger/notify.py index 58532339f48214..ee8543a822a622 100644 --- a/homeassistant/components/signal_messenger/notify.py +++ b/homeassistant/components/signal_messenger/notify.py @@ -120,6 +120,7 @@ def send_message(self, message: str = "", **kwargs: Any) -> None: self._signal_cli_rest_api.send_message( message, recipients, + notify_self=True, filenames=filenames, attachments_as_bytes=attachments_as_bytes, text_mode="normal" if data is None else data.get(ATTR_TEXTMODE), diff --git a/tests/components/signal_messenger/test_notify.py b/tests/components/signal_messenger/test_notify.py index e9946978302e79..c2b0b61eff310c 100644 --- a/tests/components/signal_messenger/test_notify.py +++ b/tests/components/signal_messenger/test_notify.py @@ -452,6 +452,7 @@ def assert_sending_requests( assert body_request["message"] == MESSAGE assert body_request["number"] == NUMBER_FROM assert body_request["recipients"] == (recipients or NUMBERS_TO) + assert body_request["notify_self"] is True assert len(body_request.get("base64_attachments", [])) == attachments_num for attachment in body_request.get("base64_attachments", []): From a4cc936d86c80f730e76541ed69d0bf8dbe396dc Mon Sep 17 00:00:00 2001 From: Tom Schneider <1506970+vigonotion@users.noreply.github.com> Date: Tue, 18 Aug 2026 23:48:34 +0200 Subject: [PATCH 2/3] Initialize quality scale in hvv_departures (#172867) --- .../hvv_departures/quality_scale.yaml | 171 ++++++++++++++++++ script/hassfest/quality_scale.py | 1 - 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/hvv_departures/quality_scale.yaml diff --git a/homeassistant/components/hvv_departures/quality_scale.yaml b/homeassistant/components/hvv_departures/quality_scale.yaml new file mode 100644 index 00000000000000..09133a728aae71 --- /dev/null +++ b/homeassistant/components/hvv_departures/quality_scale.yaml @@ -0,0 +1,171 @@ +rules: + # Bronze + action-setup: + status: exempt + comment: The integration does not register any custom actions or services. + appropriate-polling: done + brands: done + common-modules: + status: todo + comment: >- + The DataUpdateCoordinator is defined inline inside async_setup_entry in + binary_sensor.py rather than in a dedicated coordinator.py. + The sensor.py should also use the dedicated coordinator. + + Nice to have: a shared base entity in entity.py. + config-flow-test-coverage: + status: todo + comment: >- + A test verifying that the config flow prevents duplicate entries is + missing. This is related to the missing unique-config-entry + implementation. + All tests should end in CREATE_ENTRY or ABORT to test that the flow is + able to recover. + config-flow: + status: todo + comment: >- + The config flow is functional but does not use data_description in + strings.json to give users context for the input fields (host, + username, password). + + Todos that are not blocking `done`: + - Move to a sub entry flow for adding stations (single config flow + for auth, sub entry for every station) + - Remove `host` as there is no expected use case for + other-than-default hosts + dependency-transparency: done + docs-actions: + status: exempt + comment: The integration does not provide any custom actions. + docs-high-level-description: done + docs-installation-instructions: done + docs-removal-instructions: + status: todo + comment: The integration documentation does not include a removal instructions section. + entity-event-setup: + status: exempt + comment: The integration entities do not subscribe to any events. + entity-unique-id: done + has-entity-name: done + runtime-data: done + test-before-configure: done + test-before-setup: + status: todo + comment: >- + async_setup_entry in __init__.py forwards to platforms without verifying + connectivity first. No ConfigEntryNotReady or ConfigEntryAuthFailed is + raised on connection failure. + unique-config-entry: + status: todo + comment: >- + The config flow does not call async_set_unique_id() or + _abort_if_unique_id_configured(). The "already_configured" abort string + exists in strings.json but is never triggered. + + # Silver + action-exceptions: + status: exempt + comment: The integration does not provide any custom actions. + config-entry-unloading: done + docs-configuration-parameters: done + docs-installation-parameters: done + entity-unavailable: done + integration-owner: done + log-when-unavailable: done + parallel-updates: + status: todo + comment: >- + sensor.py defines PARALLEL_UPDATES = 0, but binary_sensor.py is missing + the PARALLEL_UPDATES constant entirely. + reauthentication-flow: + status: todo + comment: >- + The integration requires username and password credentials but does not + implement async_step_reauth. + test-coverage: + status: todo + comment: >- + Only the config flow is tested (test_config_flow.py). There are no tests + for sensor.py or binary_sensor.py, so coverage is well below 95%. + + # Gold + devices: done + diagnostics: + status: todo + comment: No diagnostics.py module exists. + discovery-update-info: + status: exempt + comment: >- + The integration connects to a cloud API (HVV GTI) that has no network + discovery mechanism. + discovery: + status: exempt + comment: >- + The HVV GTI API requires user-supplied credentials and cannot be + auto-discovered. + docs-data-update: + status: todo + comment: >- + The documentation does not describe polling intervals (1 minute for + departures, 1 hour for elevator status). + docs-examples: + status: todo + comment: The documentation does not include blueprints or usage examples. + docs-known-limitations: + status: todo + comment: The documentation does not include a Known Limitations section. + docs-supported-devices: + status: exempt + comment: >- + The integration connects to a cloud transit data service and does not + integrate physical devices. + docs-supported-functions: done + docs-troubleshooting: + status: todo + comment: The documentation does not include a troubleshooting section. + docs-use-cases: + status: todo + comment: The documentation does not include use-case examples. + dynamic-devices: + status: todo + comment: >- + binary_sensor.py only adds elevator entities at initial setup. There is + no coordinator listener to dynamically add entities for elevators that + appear in subsequent coordinator refreshes. + entity-category: done + entity-device-class: done + entity-disabled-by-default: done + entity-translations: + status: todo + comment: >- + binary_sensor.py sets _attr_name to a hardcoded English string + ("Elevator {label}", "Unknown elevator") constructed in + get_elevator_entities_from_station_information, rather than using a + translation key. The sensor entity correctly uses _attr_translation_key. + exception-translations: + status: todo + comment: >- + No exceptions use translation_domain or translation_key. There is no + "exceptions" section in strings.json. + icon-translations: done + reconfiguration-flow: + status: todo + comment: No async_step_reconfigure is implemented in config_flow.py. + repair-issues: + status: todo + comment: >- + If a configured station no longer exists in the GTI API, or if the + saved line filters reference lines that have been removed, the + integration should surface a repair issue to guide the user to + reconfigure. + stale-devices: + status: todo + comment: >- + There is no async_remove_config_entry_device implementation. Elevator + entities persist in the registry even if the station's elevator + configuration changes. + + # Platinum + async-dependency: done + inject-websession: done + strict-typing: done diff --git a/script/hassfest/quality_scale.py b/script/hassfest/quality_scale.py index 6e4c43b500c2e6..019e382a84a279 100644 --- a/script/hassfest/quality_scale.py +++ b/script/hassfest/quality_scale.py @@ -445,7 +445,6 @@ class Rule: "huisbaasje", "hunterdouglas_powerview", "husqvarna_automower_ble", - "hvv_departures", "hydrawise", "hyperion", "ialarm", From 66748babe4184b01f16548675c53654bbdca961d Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Tue, 18 Aug 2026 23:50:49 +0200 Subject: [PATCH 3/3] Add motion sensor for Shelly Camera (#179065) --- .../components/shelly/binary_sensor.py | 5 ++++ tests/components/shelly/test_binary_sensor.py | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/homeassistant/components/shelly/binary_sensor.py b/homeassistant/components/shelly/binary_sensor.py index 2aae645c3cf415..197587ef684c17 100644 --- a/homeassistant/components/shelly/binary_sensor.py +++ b/homeassistant/components/shelly/binary_sensor.py @@ -397,6 +397,11 @@ def __init__( ), supported=lambda status: status.get("slots") is not None, ), + "camera_motion": RpcBinarySensorDescription( + key="camera", + sub_key="motion", + device_class=BinarySensorDeviceClass.MOTION, + ), } diff --git a/tests/components/shelly/test_binary_sensor.py b/tests/components/shelly/test_binary_sensor.py index 096a7560e2cca6..40e16f0f6d72ff 100644 --- a/tests/components/shelly/test_binary_sensor.py +++ b/tests/components/shelly/test_binary_sensor.py @@ -924,3 +924,31 @@ async def test_rpc_cb_binary_sensors( assert (state := hass.states.get(safety_entity_id)) assert state.state == STATE_OFF + + +async def test_rpc_camera_motion( + hass: HomeAssistant, + mock_rpc_device: Mock, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test RPC motion binary sensor for Shelly Camera.""" + status = { + "camera:0": { + "id": 0, + "motion": False, + } + } + monkeypatch.setattr(mock_rpc_device, "status", status) + await init_integration(hass, 3) + + entity_id = f"{BINARY_SENSOR_DOMAIN}.test_name_motion" + + assert (state := hass.states.get(entity_id)) + assert state.state == STATE_OFF + + status["camera:0"]["motion"] = True + monkeypatch.setattr(mock_rpc_device, "status", status) + mock_rpc_device.mock_update() + + assert (state := hass.states.get(entity_id)) + assert state.state == STATE_ON