-
Notifications
You must be signed in to change notification settings - Fork 2
Scan updates #314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scan updates #314
Conversation
WalkthroughAdds a Select platform and two buttons, two diagnostic binary sensors; removes two services and their schemas/translations; adjusts several async_add_entities calls to default update behavior; changes number limits and set behavior; updates coordinator message; awaits coordinator.unsubscribe_all_nodefeatures() on unload; bumps dependency and versions. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant HA as Home Assistant
participant Integration as Plugwise USB (Select)
participant Coord as Coordinator
participant Node as Plugwise Node
rect rgb(240,245,250)
Note over HA,Integration: Config entry setup / preload
HA->>Integration: async_setup_entry()
Integration->>Coord: subscribe(NodeEvent.LOADED)
loop preload loaded nodes
Coord-->>Integration: node (with MOTION_CONFIG)
Integration->>HA: async_add_entities(SelectEntity)
end
end
rect rgb(245,255,245)
Note over User,HA: User selects motion sensitivity
User->>HA: select option
HA->>Integration: async_select_option(option)
Integration->>Node: set_motion_sensitivity_level(...)
Node-->>Coord: MOTION_CONFIG updated
Coord-->>Integration: data update
Integration->>HA: state update (current_option)
end
sequenceDiagram
autonumber
participant HA as Home Assistant
participant Init as __init__.py
participant Coord as Coordinator
Note over HA,Init: Config entry unload
HA->>Init: async_unload_entry()
Init->>Coord: await unsubscribe_all_nodefeatures()
Init->>HA: unload platforms
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (1)
custom_components/plugwise_usb/coordinator.py (1)
85-91: Ensure robust AVAILABLE check, fix f-string typo, and avoid private node attributeThe current logic still directly indexes
states[NodeFeature.AVAILABLE], uses the private_mac_in_str, and misses a space in the f-string. Please update as follows:- if ( - not self.node.node_info.is_battery_powered - and self.node.initialized - and not states[NodeFeature.AVAILABLE].state - ): - raise UpdateFailed(f"Device '{self.node._mac_in_str}'is (temporarily) not available") + if ( + not self.node.node_info.is_battery_powered + and self.node.initialized + ): + available = states.get(NodeFeature.AVAILABLE) + if available is not None and not available.state: + raise UpdateFailed( + f"Device '{self.node.mac}' is (temporarily) not available" + )
- Replaced private
_mac_in_strwith publicmac- Fixed missing space in the message
- Guarded against a missing
AVAILABLEentry usingstates.getNo other
self.node._…references were found incustom_components/plugwise_usb.
🧹 Nitpick comments (6)
custom_components/plugwise_usb/translations/nl.json (1)
52-57: Minor Dutch grammar improvements for new binary_sensor namesCompound nouns in Dutch prefer hyphenation. Suggested tweaks for better readability.
- "motion_config_dirty": { - "name": "Instellingen bewegingsdetectie aangepast" - }, + "motion_config_dirty": { + "name": "Bewegingsdetectie-instellingen aangepast" + }, - "battery_config_dirty": { - "name": "Batterij instellingen aangepast" - } + "battery_config_dirty": { + "name": "Batterij-instellingen aangepast" + }custom_components/plugwise_usb/__init__.py (1)
166-171: Optional: unsubscribe all nodefeatures concurrently to speed up unloadIf many nodes are present, running unsubscriptions concurrently can reduce unload time.
Apply this diff:
- for coordinator in config_entry.runtime_data[NODES].values(): - await coordinator.unsubscribe_all_nodefeatures() + await asyncio.gather( + *( + coordinator.unsubscribe_all_nodefeatures() + for coordinator in config_entry.runtime_data[NODES].values() + ) + )custom_components/plugwise_usb/number.py (1)
182-187: Avoid stale UI state after set; refresh or optimistically updateAfter
await self.async_number_fn(int(value))you only callself.async_write_ha_state()without updating_attr_native_valueor triggering a refresh. If the device doesn’t push a state update immediately, the UI can momentarily show the old value.Two options:
- Preferred: trigger a coordinator refresh and let
_handle_coordinator_updateset the value.- Alternative: optimistically update
_attr_native_valueto the requested value, then write state.Preferred (refresh-based) approach:
- await self.async_number_fn(int(value)) - self.async_write_ha_state() + await self.async_number_fn(int(value)) + # Refresh to pick up the authoritative value from the device + await self.coordinator.async_request_refresh()Alternative (optimistic update):
- await self.async_number_fn(int(value)) - self.async_write_ha_state() + await self.async_number_fn(int(value)) + self._attr_native_value = int(value) + self.async_write_ha_state() + # Optionally also refresh to reconcile if the device adjusts the value + await self.coordinator.async_request_refresh()custom_components/plugwise_usb/binary_sensor.py (1)
46-63: Verify battery node_feature and prefer PROBLEM device class for “config dirty”.
- Semantics: A “config changed/dirty” flag isn’t a safety condition. BinarySensorDeviceClass.PROBLEM is a closer fit than SAFETY for both new entities.
- Correctness: Please confirm that NodeFeature.BATTERY exposes a dirty attribute. If not, this will always resolve to AttributeError or False. The corresponding “config” feature (e.g., the one used by your API for battery configuration) should be referenced here instead of NodeFeature.BATTERY.
Proposed device_class adjustment:
PlugwiseBinarySensorEntityDescription( key="motion_config_dirty", translation_key="motion_config_dirty", node_feature=NodeFeature.MOTION_CONFIG, - device_class=BinarySensorDeviceClass.SAFETY, + device_class=BinarySensorDeviceClass.PROBLEM, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, api_attribute="dirty", ), PlugwiseBinarySensorEntityDescription( key="battery_config_dirty", translation_key="battery_config_dirty", - node_feature=NodeFeature.BATTERY, - device_class=BinarySensorDeviceClass.SAFETY, + node_feature=NodeFeature.BATTERY, + device_class=BinarySensorDeviceClass.PROBLEM, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, api_attribute="dirty", ),If your API exposes a distinct “battery config” feature with a dirty flag, point this entity’s node_feature to that specific feature instead of BATTERY. I can adjust the patch once you confirm the correct feature name.
custom_components/plugwise_usb/select.py (2)
131-131: Strip trailing whitespace (ruff W291).Remove the trailing spaces to satisfy linters.
- self._attr_current_option = current_option.name + self._attr_current_option = current_option.name @@ - self.async_write_ha_state() + self.async_write_ha_state()Also applies to: 148-148
53-53: Typo in docstring: “selectes”.Small grammar fix.
- """Set up the USB selectes from a config entry.""" + """Set up the USB selects from a config entry."""
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (13)
custom_components/plugwise_usb/__init__.py(1 hunks)custom_components/plugwise_usb/binary_sensor.py(3 hunks)custom_components/plugwise_usb/const.py(1 hunks)custom_components/plugwise_usb/coordinator.py(1 hunks)custom_components/plugwise_usb/event.py(1 hunks)custom_components/plugwise_usb/number.py(4 hunks)custom_components/plugwise_usb/select.py(1 hunks)custom_components/plugwise_usb/sensor.py(1 hunks)custom_components/plugwise_usb/services.yaml(0 hunks)custom_components/plugwise_usb/strings.json(1 hunks)custom_components/plugwise_usb/switch.py(1 hunks)custom_components/plugwise_usb/translations/en.json(1 hunks)custom_components/plugwise_usb/translations/nl.json(1 hunks)
💤 Files with no reviewable changes (1)
- custom_components/plugwise_usb/services.yaml
🧰 Additional context used
🧬 Code Graph Analysis (2)
custom_components/plugwise_usb/__init__.py (1)
custom_components/plugwise_usb/coordinator.py (1)
unsubscribe_all_nodefeatures(117-123)
custom_components/plugwise_usb/select.py (2)
custom_components/plugwise_usb/coordinator.py (1)
PlugwiseUSBDataUpdateCoordinator(27-123)custom_components/plugwise_usb/entity.py (2)
PlugwiseUSBEntity(27-75)PlugwiseUSBEntityDescription(21-24)
🪛 Ruff (0.12.2)
custom_components/plugwise_usb/coordinator.py
90-90: Private member accessed: _mac_in_str
(SLF001)
custom_components/plugwise_usb/select.py
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
148-148: Trailing whitespace
Remove trailing whitespace
(W291)
🔇 Additional comments (11)
custom_components/plugwise_usb/const.py (1)
28-28: SELECT platform inclusion looks goodAdding Platform.SELECT to PLUGWISE_USB_PLATFORMS aligns with the new select implementation.
custom_components/plugwise_usb/strings.json (1)
52-57: LGTM on new diagnostic binary sensorsKeys and names for motion_config_dirty and battery_config_dirty look consistent with the new diagnostics.
custom_components/plugwise_usb/sensor.py (1)
191-193: Dropping update_before_add is fine for coordinator-driven entitiesGiven entities are added only on NodeEvent.LOADED and are coordinator-backed, omitting update_before_add should not regress initial state handling. Entities may show unknown until the first coordinator refresh, which is standard.
If you notice initial states lingering as unknown unexpectedly, consider confirming the coordinator has data at add time or triggering an immediate refresh after subscription.
custom_components/plugwise_usb/event.py (1)
94-96: Consistent removal of update_before_addMatches the pattern used elsewhere in the PR; appropriate for coordinator-based event entities.
Please confirm there’s no dependency on a pre-add update for initial button state logic in downstream automations.
custom_components/plugwise_usb/__init__.py (1)
166-168: Good fix: await the async unsubscriptionAwaiting
unsubscribe_all_nodefeatures()ensures cleanup completes before unloading platforms.custom_components/plugwise_usb/switch.py (1)
97-99: Confirmupdate_before_addBehavior
EntityPlatform.async_add_entities defaults toupdate_before_add=Falseacross supported Home Assistant versions¹. That means entities won’t fetch their initial state before being added unless you explicitly passupdate_before_add=True. Please review whether default=False matches your intended behavior or if you need to add the flag to your calls in:
- custom_components/plugwise_usb/switch.py (line 98)
- custom_components/plugwise_usb/sensor.py (line 192)
- custom_components/plugwise_usb/select.py (line 70)
- custom_components/plugwise_usb/number.py (line 125)
- custom_components/plugwise_usb/event.py (line 95)
- custom_components/plugwise_usb/binary_sensor.py (line 91)
- custom_components/plugwise_usb/button.py (line 74)
If you do need entities to update before add, update the calls accordingly:
- async_add_entities(entities) + async_add_entities(entities, update_before_add=True)¹https://developers.home-assistant.io/docs/integration_fetching_data
custom_components/plugwise_usb/number.py (3)
72-75: Confirm sleep_duration upper bound (1440 minutes) against device firmware limitsI inspected the implementation in
• custom_components/plugwise_usb/number.py (lines 65–75)
and related translation strings but found no alternate bounds or validation logic. Please verify against the device’s official specification or firmware to ensure 1440 minutes is supported and won’t be rejected or silently clamped at runtime.
84-87: Verify awake_duration upper bound (60 seconds)Lowering the maximum from its previous value to 60 s is a behavioral change. Please confirm that all supported Plugwise devices enforce an awake_duration ≤ 60 s and that your frontend UIs and documentation have been updated to reflect this new limit.
Key locations to review:
- custom_components/plugwise_usb/number.py (lines 84–87):
native_max_value=60, native_min_value=1, api_attribute="awake_duration"- Translation keys in:
- custom_components/plugwise_usb/strings.json (
"sed_awake_duration")- custom_components/plugwise_usb/translations/en.json
- custom_components/plugwise_usb/translations/nl.json
Ensure:
- Hardware rejects values > 60 s (or handles them gracefully).
- UI controls (sliders/inputs) cap at 60 s.
- Documentation and user-facing schemas/docs call out 60 s as the maximum.
125-126: Verify default update_before_add behavior for async_add_entitiesIn
custom_components/plugwise_usb/number.py(lines 123–127), you’re calling:async_add_entities(entities)By default,
update_before_addisFalse, so newly added entities won’t fetch their initial state before being registered. Please confirm that this default aligns with all Home Assistant versions you support. If you need each entity to refresh immediately, explicitly pass:async_add_entities(entities, update_before_add=True)This check applies to every
async_add_entities(entities)invocation in:
event.pysensor.pyselect.pynumber.pybinary_sensor.pybutton.pyswitch.pycustom_components/plugwise_usb/binary_sensor.py (2)
16-16: LGTM: Importing EntityCategory and Platform is appropriate.Needed for DIAGNOSTIC entities and storing unsubscribes in runtime_data.
91-91: LGTM: Dropping update_before_add is fine.The default behavior suffices; avoids unnecessary pre-update calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
custom_components/plugwise_usb/select.py (1)
26-34: Critical: Description ‘options’ is undeclared and wrong type; use an Enum field and update usageThe dataclass doesn’t declare options, yet it’s passed at construction and used later. Also, SelectEntityDescription already has an options field with a different type (list[str] | None). Passing an Enum there will raise TypeError and/or cause runtime errors.
Fix by declaring an explicit Enum type field (options_enum) and using it for option mapping. This also resolves Ruff’s unused Enum import once used in typing.
@@ @dataclass(kw_only=True) class PlugwiseSelectEntityDescription( PlugwiseUSBEntityDescription, SelectEntityDescription ): """Describes Plugwise select entity.""" api_attribute: str = "" async_select_fn: str = "" + # Enum class holding available options (e.g., MotionSensitivity) + options_enum: type[Enum] @@ SELECT_TYPES: tuple[PlugwiseSelectEntityDescription, ...] = ( PlugwiseSelectEntityDescription( key="sensitivity_level", translation_key="motion_sensitivity_level", async_select_fn="set_motion_sensitivity_level", entity_category=EntityCategory.CONFIG, node_feature=NodeFeature.MOTION_CONFIG, api_attribute="sensitivity_level", - options = MotionSensitivity, + options_enum=MotionSensitivity, ), ) @@ """Initialize a select entity.""" super().__init__(node_duc, entity_description) - self._options: list[str] = [o.name for o in entity_description.options] + self._options: list[str] = [o.name for o in entity_description.options_enum] self._current_option = "MEDIUM" self.async_select_fn = getattr( node_duc.node, entity_description.async_select_fn ) self._node_duc = node_duc @@ async def async_select_option(self, option: str) -> None: """Change to the selected entity option.""" - value = self.entity_description.options[option] + # Lookup Enum by member name (e.g., "HIGH", "MEDIUM", "OFF") + value = self.entity_description.options_enum[option] await self.async_select_fn(value) self._current_option = option self._attr_current_option = option - self.async_write_ha_state() + self.async_write_ha_state()Also applies to: 36-46, 101-114, 145-151
🧹 Nitpick comments (3)
custom_components/plugwise_usb/select.py (2)
54-56: Nit: Typo in setup docstring“selectes” → “selects”.
- """Set up the USB selectes from a config entry.""" + """Set up the USB selects from a config entry."""
131-133: Nit: Remove trailing whitespaceTrailing whitespace violates linters (Ruff W291) and CI style checks.
- self._attr_current_option = current_option.name + self._attr_current_option = current_option.namecustom_components/plugwise_usb/strings.json (1)
151-156: Align entity name casing with existing style (nitpick)Elsewhere in this file names tend toward sentence case (e.g., “Reset energy collection”, “Motion reset timer”). Consider making these consistent.
Apply:
- "ping":{ - "name": "Ping Device" - }, - "calibrate_light":{ - "name": "Schedule Light Sensor Calibration" - } + "ping":{ + "name": "Ping device" + }, + "calibrate_light":{ + "name": "Schedule light sensor calibration" + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
custom_components/plugwise_usb/button.py(1 hunks)custom_components/plugwise_usb/entity.py(1 hunks)custom_components/plugwise_usb/select.py(1 hunks)custom_components/plugwise_usb/strings.json(2 hunks)custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
custom_components/plugwise_usb/select.py (2)
custom_components/plugwise_usb/coordinator.py (1)
PlugwiseUSBDataUpdateCoordinator(27-123)custom_components/plugwise_usb/entity.py (2)
PlugwiseUSBEntity(27-78)PlugwiseUSBEntityDescription(21-24)
🪛 Ruff (0.12.2)
custom_components/plugwise_usb/select.py
6-6: enum.Enum imported but unused
Remove unused import: enum.Enum
(F401)
132-132: Trailing whitespace
Remove trailing whitespace
(W291)
151-151: Trailing whitespace
Remove trailing whitespace
(W291)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Prepare
🔇 Additional comments (2)
custom_components/plugwise_usb/strings.json (2)
51-57: All translation keys properly wired up and localizedTranslation keys for
motion_config_dirtyandbattery_config_dirtyare correctly referenced in code and present in both English and Dutch translations.
- binary_sensor.py
– Lines 47–48:translation_key="motion_config_dirty"
– Lines 56–57:translation_key="battery_config_dirty"- custom_components/plugwise_usb/strings.json, en.json, nl.json
– Bothmotion_config_dirtyandbattery_config_dirtyentries exist
60-66: Motion sensitivity select translation key verifiedThe
translation_key="motion_sensitivity_level"in select.py (line 39) matches the entry in custom_components/plugwise_usb/strings.json (line 60), and all option labels (High,Medium,Off) are defined. No additional localization files are required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (1)
custom_components/plugwise_usb/translations/nl.json (1)
60-62: Dutch phrasing nit: consider more natural labelOptional: “Bewegingsdetectie Gevoeligheid” reads a bit clunky. Consider “Gevoeligheid bewegingsdetectie” or “Gevoeligheid voor bewegingsdetectie”.
If you prefer, I can update all locales consistently once you choose the phrasing.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)
🧰 Additional context used
🪛 GitHub Actions: Validate with hassfest
custom_components/plugwise_usb/translations/en.json
[error] 1-1: Command 'docker run --rm -v /home/runner/work/plugwise_usb-beta/plugwise_usb-beta://github/workspace ghcr.io/home-assistant/hassfest' failed: Invalid translations/en.json: Invalid translation key 'HIGH', need to be [a-z0-9-_]+ and cannot start or end with a hyphen or underscore. for dictionary value @ data['entity']['select']['motion_sensitivity_level']['state']. Got {'HIGH': 'High', 'MEDIUM': 'Medium', 'OFF': 'Off'}
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Setup for HA-core (release/master)
🔇 Additional comments (4)
custom_components/plugwise_usb/translations/nl.json (2)
52-57: Good addition: diagnostic binary_sensors for config changesThe new motion/battery config-dirty sensors are clear and align with the PR’s goals.
151-156: New buttons look good“Ping Node” and “Licht Sensor Calibratie Inplannen” fit the new functionality.
custom_components/plugwise_usb/translations/en.json (2)
52-57: Good addition: diagnostic binary_sensors for config changesClear naming and matches the new entities added by the PR.
151-156: Buttons translations look consistent“Ping Device” and “Schedule Light Sensor Calibration” are clear and concise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
custom_components/plugwise_usb/translations/en.json (2)
60-66: Fix hassfest failure: state keys must be lowercasePipeline fails because translation keys must match
[a-z0-9-_]+. Use lowercase keys and align emitted options in select.py accordingly.Apply this diff:
"motion_sensitivity_level": { "name": "Motion Sensitivity Level", "state": { - "HIGH": "High", - "MEDIUM": "Medium", - "OFF": "Off" + "high": "High", + "medium": "Medium", + "off": "Off" } }Additionally, ensure custom_components/plugwise_usb/select.py emits and expects lowercase values:
- Build options with
[o.name.lower() for o in entity_description.options]- Current option via
current_option.name.lower()- Map user selection back with
option.upper()when looking up enum members.
60-66: Implement lowercase normalization for select options in select.pyThe translation files are now using lowercase state keys, but
select.pystill emits and looks up options using uppercase names. This will prevent translations from resolving correctly formotion_sensitivity_level. Please update both the options list and the lookup:• File: custom_components/plugwise_usb/select.py
– Around line 108, change:
```diff
self._options: list[str] = [o.name for o in entity_description.options]
self._options: list[str] = [o.name.lower() for o in entity_description.options]– Around line 147, change: ```diff
value = self.entity_description.options[option]
value = self.entity_description.options[option.upper()]These two changes ensure that UI options are presented lowercase (matching your translations) and that lookups against the Enum (which uses uppercase names) still succeed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
custom_components/plugwise_usb/button.py(1 hunks)custom_components/plugwise_usb/strings.json(2 hunks)custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- custom_components/plugwise_usb/button.py
- custom_components/plugwise_usb/translations/nl.json
🧰 Additional context used
🪛 GitHub Actions: Validate with hassfest
custom_components/plugwise_usb/translations/en.json
[error] 1-1: Invalid translations/en.json: Invalid translation key 'HIGH', need to be [a-z0-9-_]+ and cannot start or end with a hyphen or underscore. for dictionary value @ data['entity']['select']['motion_sensitivity_level']['state']. Got {'HIGH': 'High', 'MEDIUM': 'Medium', 'OFF': 'Off'}
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Setup for HA-core (release/master)
🔇 Additional comments (4)
custom_components/plugwise_usb/translations/en.json (2)
52-57: New diagnostic binary_sensors look goodNaming is clear and consistent with the new diagnostic entities. No issues spotted.
150-156: Buttons translations added correctlyKeys and naming follow the existing style. Good addition.
custom_components/plugwise_usb/strings.json (2)
52-57: New diagnostic binary_sensors look goodNaming aligns with en.json and intended diagnostics behavior.
151-156: Buttons translations added correctlyConsistent with en.json and existing naming conventions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (4)
custom_components/plugwise_usb/translations/en.json (1)
60-66: Ensure select.py emits and handles lowercase option keysThe JSON translations are now fully lowercase, but
select.pystill uses uppercase enum names and does not normalize to lowercase. Updatecustom_components/plugwise_usb/select.pyas follows:• In
__init__, emit lowercase option names:- self._options: list[str] = [o.name for o in entity_description.options] + self._options: list[str] = [o.name.lower() for o in entity_description.options] - self._current_option = "MEDIUM" + # Default to first option in lowercase + self._current_option = entity_description.options[0].name.lower()• In the coordinator update handler, set the current option to lowercase:
- self._current_option = current_option.name - self._attr_current_option = current_option.name + self._current_option = current_option.name.lower() + self._attr_current_option = current_option.name.lower()• In
async_select_option, accept a lowercaseoptionstring and map back to the enum by uppercasing the key:- async def async_select_option(self, option: str) -> None: + async def async_select_option(self, option: str) -> None: """Change to the selected entity option.""" - value = self.entity_description.options[option] + # Map lowercase option back to enum member + value = self.entity_description.options[option.upper()] await self.async_select_fn(value) self._current_option = option self._attr_current_option = option self.async_write_ha_state()With these changes, both the displayed options and state updates will use lowercase keys matching
en.json, and selections will correctly map to the API enums.custom_components/plugwise_usb/select.py (2)
36-46: Use the newoptions_enumfield and keep naming consistentReplace
options=withoptions_enum=to match the dataclass and avoid runtime errors.SELECT_TYPES: tuple[PlugwiseSelectEntityDescription, ...] = ( PlugwiseSelectEntityDescription( key="sensitivity_level", translation_key="motion_sensitivity_level", async_select_fn="set_motion_sensitivity_level", entity_category=EntityCategory.CONFIG, node_feature=NodeFeature.MOTION_CONFIG, api_attribute="sensitivity_level", - options = MotionSensitivity, + options_enum=MotionSensitivity, ), )
26-35: Critical:optionsfield missing from description; construction will fail
SELECT_TYPESpassesoptions = MotionSensitivity, but the dataclass has nooptions(or similar) field. This raisesTypeError: __init__() got an unexpected keyword argument 'options'.Introduce a field (e.g.,
options_enum) and type it to the enum class:@dataclass(kw_only=True) class PlugwiseSelectEntityDescription( PlugwiseUSBEntityDescription, SelectEntityDescription ): """Describes Plugwise select entity.""" api_attribute: str = "" async_select_fn: str = "" + # Enum class that defines available options (iterable and name-addressable) + options_enum: type[MotionSensitivity]custom_components/plugwise_usb/strings.json (1)
60-66: Motion Sensitivity select key and state keys are correctly namedGood catch on using motion_sensitivity_level with lowercase state keys (high/medium/off). This addresses earlier feedback about the typo and hassfest’s lowercase requirement for option keys.
Run to verify translations are consistent across files and JSON stays valid:
#!/bin/bash set -euo pipefail echo "Validate JSON syntax with jq:" jq . custom_components/plugwise_usb/strings.json >/dev/null echo "Check select key and state keys across files:" for f in custom_components/plugwise_usb/strings.json \ custom_components/plugwise_usb/translations/en.json \ custom_components/plugwise_usb/translations/nl.json; do echo "-- $f --" rg -nC2 '"motion_sensitivity_level"' "$f" rg -nC1 '"state"\s*:\s*{\s*"high".*"medium".*"off"' "$f" || true done
🧹 Nitpick comments (5)
custom_components/plugwise_usb/binary_sensor.py (1)
46-63: ConsiderPROBLEMdevice class for “config changed”Using
SAFETYsuggests a hazard. These diagnostics represent a pending configuration change;BinarySensorDeviceClass.PROBLEMbetter fits semantics and UI.PlugwiseBinarySensorEntityDescription( key="motion_config_dirty", translation_key="motion_config_dirty", node_feature=NodeFeature.MOTION_CONFIG, - device_class=BinarySensorDeviceClass.SAFETY, + device_class=BinarySensorDeviceClass.PROBLEM, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, api_attribute="dirty", ), PlugwiseBinarySensorEntityDescription( key="battery_config_dirty", translation_key="battery_config_dirty", node_feature=NodeFeature.BATTERY, - device_class=BinarySensorDeviceClass.SAFETY, + device_class=BinarySensorDeviceClass.PROBLEM, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, api_attribute="dirty", ),Please confirm the intended UX; if these indicate “needs user attention” rather than “safety risk,”
PROBLEMis preferable.custom_components/plugwise_usb/select.py (3)
54-54: Nit: docstring typo- """Set up the USB selectes from a config entry.""" + """Set up the USB selects from a config entry."""
62-69: Minor: use node name consistently in debug logElsewhere you log
node_duc.node.name. Use the same here, and improve message clarity.- _LOGGER.debug("Add select entities for %s | duc=%s", mac, node_duc.name) + _LOGGER.debug("Add select entities for node %s (%s)", node_duc.node.name, mac)
6-6: Remove unused import
Enumisn’t used (ruff F401). It’s not needed onceoptions_enumis typed toMotionSensitivity.-from enum import Enumcustom_components/plugwise_usb/strings.json (1)
53-54: Nit: prefer sentence case for entity names to match surrounding entriesNearby names like “Network roundtrip time”, “Awake reason”, and “Motion reset timer” use sentence case. Consider matching that style.
- "name": "Motion Config Changed" + "name": "Motion configuration changed" @@ - "name": "Battery Config Changed" + "name": "Battery configuration changed"Also applies to: 56-57
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (14)
custom_components/plugwise_usb/__init__.py(1 hunks)custom_components/plugwise_usb/binary_sensor.py(3 hunks)custom_components/plugwise_usb/button.py(1 hunks)custom_components/plugwise_usb/const.py(1 hunks)custom_components/plugwise_usb/coordinator.py(1 hunks)custom_components/plugwise_usb/event.py(1 hunks)custom_components/plugwise_usb/number.py(4 hunks)custom_components/plugwise_usb/select.py(1 hunks)custom_components/plugwise_usb/sensor.py(1 hunks)custom_components/plugwise_usb/services.yaml(0 hunks)custom_components/plugwise_usb/strings.json(2 hunks)custom_components/plugwise_usb/switch.py(1 hunks)custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)
💤 Files with no reviewable changes (1)
- custom_components/plugwise_usb/services.yaml
🚧 Files skipped from review as they are similar to previous changes (7)
- custom_components/plugwise_usb/init.py
- custom_components/plugwise_usb/event.py
- custom_components/plugwise_usb/number.py
- custom_components/plugwise_usb/sensor.py
- custom_components/plugwise_usb/const.py
- custom_components/plugwise_usb/button.py
- custom_components/plugwise_usb/translations/nl.json
🧰 Additional context used
🧬 Code graph analysis (1)
custom_components/plugwise_usb/select.py (2)
custom_components/plugwise_usb/coordinator.py (1)
PlugwiseUSBDataUpdateCoordinator(27-123)custom_components/plugwise_usb/entity.py (2)
PlugwiseUSBEntity(27-75)PlugwiseUSBEntityDescription(21-24)
🪛 Ruff (0.12.2)
custom_components/plugwise_usb/select.py
6-6: enum.Enum imported but unused
Remove unused import: enum.Enum
(F401)
132-132: Trailing whitespace
Remove trailing whitespace
(W291)
151-151: Trailing whitespace
Remove trailing whitespace
(W291)
custom_components/plugwise_usb/coordinator.py
90-90: Private member accessed: _mac_in_str
(SLF001)
🪛 GitHub Actions: Validate with hassfest
custom_components/plugwise_usb/translations/en.json
[error] 1-1: hassfest: Invalid translation key 'HIGH' in translations/en.json; keys must be lowercase and match [a-z0-9-_]+. The dictionary at data['entity']['select']['motion_sensitivity_level']['state'] has keys {'HIGH': 'High', 'MEDIUM': 'Medium', 'OFF': 'Off'}.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Setup for HA-core (release/master)
🔇 Additional comments (7)
custom_components/plugwise_usb/switch.py (1)
98-98: LGTM: dropupdate_before_addand use default add behaviorUsing
async_add_entities(entities)is consistent with recent HA guidance and the rest of this PR. No concerns here.custom_components/plugwise_usb/translations/en.json (2)
51-57: Nice additions: diagnostic binary sensorsThe new translation entries for
motion_config_dirtyandbattery_config_dirtylook good and align with the new entities.
151-155: Buttons: translations OK
ping_nodeandcalibrate_lightentries align with the new button entities.custom_components/plugwise_usb/binary_sensor.py (2)
16-16: Import of EntityCategory is appropriateNeeded for DIAGNOSTIC categorization. Looks good.
91-91: LGTM: default entity addDropping
update_before_addmatches the pattern elsewhere in this PR.custom_components/plugwise_usb/strings.json (2)
52-57: New diagnostic binary_sensors look correct and align with the PR intentThe added translation keys for motion_config_dirty and battery_config_dirty are clear and consistent with HA conventions.
151-156: Translation keys confirmed for new buttons
- Verified
translation_key="ping_node"incustom_components/plugwise_usb/button.py(lines 49–51), matching the JSON entry for “Ping Device”.- Verified
translation_key="calibrate_light"in the same file (lines 56–58), matching the JSON entry for “Schedule Light Sensor Calibration”.No discrepancies found—buttons will render correctly in the UI.
…is not updated yet
…umber functions do not return a number but true/false (maybe this needs to be catched and a notice thrown or something
Add Scan Light Calibration button Enable button even if device is not (yet) available. Entities without api_key do not get a jolt when the device comes available later.
remove available trick
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (4)
custom_components/plugwise_usb/select.py (4)
25-33: Dataclass missing options field; introduce options_enum (Enum type)The description doesn’t declare options, but instances pass options=MotionSensitivity and code accesses entity_description.options. This will raise at construction/runtime. Define options_enum with an Enum type.
Apply:
@@ -from dataclasses import dataclass +from dataclasses import dataclass +from enum import Enum @@ class PlugwiseSelectEntityDescription( PlugwiseUSBEntityDescription, SelectEntityDescription ): """Describes Plugwise select entity.""" async_select_fn: str = "" + # Enum containing the available options (e.g., MotionSensitivity) + options_enum: type[Enum]
34-43: Use options_enum in SELECT_TYPESSwitch the constructor argument from options to options_enum to match the dataclass.
Apply:
@@ node_feature=NodeFeature.MOTION_CONFIG, - options = MotionSensitivity, + options_enum=MotionSensitivity,
98-111: Build options from options_enum; drop redundant reassignmentDerive lowercased options from the Enum and avoid reassigning entity_description (already set by super()).
Apply:
self.async_select_fn = getattr( node_duc.node, entity_description.async_select_fn ) - self._attr_options: list[str] = [o.name.lower() for o in entity_description.options] - self.entity_description = entity_description + self._attr_options = [o.name.lower() for o in entity_description.options_enum] self._node_duc = node_duc
131-137: Normalize/validate input; map back to Enum; update state immediatelyValidate the incoming string, map to Enum via uppercase key, and only expose lowercase to HA. Removes risk of KeyError and ensures UI updates instantly.
Apply:
async def async_select_option(self, option: str) -> None: """Change to the selected entity option.""" - value = self.entity_description.options[option.upper()] - await self.async_select_fn(value) - self._current_option = option - self._attr_current_option = option - self.async_write_ha_state() + normalized = option.strip().lower() + if normalized not in self._attr_options: + raise ValueError(f"Unsupported option: {option}") + value = self.entity_description.options_enum[normalized.upper()] + await self.async_select_fn(value) + self._attr_current_option = normalized + self.async_write_ha_state() + # Optionally: await self.coordinator.async_request_refresh()
🧹 Nitpick comments (5)
custom_components/plugwise_usb/sensor.py (1)
191-193: Confirm initial state without update_before_addDropping update_before_add relies on a prior coordinator refresh or push to populate state; otherwise entities may start as unknown. If the coordinator isn’t refreshed before entity add, consider explicitly requesting a refresh or restoring the old flag where needed.
If needed, you can explicitly request a refresh right after adding entities:
- async_add_entities(entities) + async_add_entities(entities) + await config_entry.runtime_data[NODES][mac].async_request_refresh()custom_components/plugwise_usb/number.py (2)
124-126: Confirm initial state without update_before_addAs with other platforms, ensure the coordinator has refreshed before/at add time so numbers don’t start unknown.
182-186: Reflect number changes immediately in UI; validate/cast inputCurrently we await the device call and write state but don’t set _attr_native_value. Set it optimistically for better UX and normalize to int; optionally clamp to min/max.
Apply:
async def async_set_native_value(self, value: float) -> None: """Update the current value.""" - await self.async_number_fn(int(value)) - self.async_write_ha_state() + new_value = int(value) + # Optional clamp; HA UI enforces bounds but API callers may bypass it + if self.native_min_value is not None: + new_value = max(self.native_min_value, new_value) + if self.native_max_value is not None: + new_value = min(self.native_max_value, new_value) + await self.async_number_fn(new_value) + self._attr_native_value = new_value + self.async_write_ha_state()custom_components/plugwise_usb/select.py (2)
51-51: Typo: “selectes” → “selects”Minor docstring fix.
Apply:
- """Set up the USB selectes from a config entry.""" + """Set up the USB selects from a config entry."""
112-130: Normalize current_option to lowercase (good); consider setting both cached and attrYou set _attr_current_option to lower() which matches emitted options—good. Optionally set a local cache if you rely on it elsewhere (not required for SelectEntity).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (16)
custom_components/plugwise_usb/__init__.py(1 hunks)custom_components/plugwise_usb/binary_sensor.py(3 hunks)custom_components/plugwise_usb/button.py(1 hunks)custom_components/plugwise_usb/const.py(1 hunks)custom_components/plugwise_usb/coordinator.py(1 hunks)custom_components/plugwise_usb/event.py(1 hunks)custom_components/plugwise_usb/manifest.json(1 hunks)custom_components/plugwise_usb/number.py(4 hunks)custom_components/plugwise_usb/select.py(1 hunks)custom_components/plugwise_usb/sensor.py(1 hunks)custom_components/plugwise_usb/services.yaml(0 hunks)custom_components/plugwise_usb/strings.json(2 hunks)custom_components/plugwise_usb/switch.py(1 hunks)custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)pyproject.toml(1 hunks)
💤 Files with no reviewable changes (1)
- custom_components/plugwise_usb/services.yaml
✅ Files skipped from review due to trivial changes (1)
- pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (10)
- custom_components/plugwise_usb/event.py
- custom_components/plugwise_usb/strings.json
- custom_components/plugwise_usb/switch.py
- custom_components/plugwise_usb/coordinator.py
- custom_components/plugwise_usb/init.py
- custom_components/plugwise_usb/button.py
- custom_components/plugwise_usb/translations/nl.json
- custom_components/plugwise_usb/const.py
- custom_components/plugwise_usb/translations/en.json
- custom_components/plugwise_usb/binary_sensor.py
🧰 Additional context used
🧬 Code graph analysis (1)
custom_components/plugwise_usb/select.py (2)
custom_components/plugwise_usb/coordinator.py (1)
PlugwiseUSBDataUpdateCoordinator(27-125)custom_components/plugwise_usb/entity.py (2)
PlugwiseUSBEntity(27-75)PlugwiseUSBEntityDescription(21-24)
🔇 Additional comments (4)
custom_components/plugwise_usb/manifest.json (2)
12-12: Version syncEnsure manifest "version": "0.55.9" matches your tagged release and HACS expectations (pyproject may use a pre-release like 0.55.9a0; the manifest version is what HA shows).
11-12: Confirm plugwise-usb 0.44.12 includes MotionSensitivity API with no breaking changes
- ✅ plugwise-usb 0.44.12 is published on PyPI and its CHANGELOG shows PR #323 adding the MotionSensitivity enum (named levels Off/Medium/High) and light sensitivity calibration for scan devices (raw.githubusercontent.com)
⚠️ There are no “BREAK” or “BREAKING” entries in the v0.44.12 section of the CHANGELOG, indicating no documented breaking changes in this release (raw.githubusercontent.com)- 🔧 Ensure your Home Assistant core environment can install and run plugwise-usb 0.44.12 (e.g. meets its Python requirement and supports USB discovery in custom integrations)
custom_components/plugwise_usb/number.py (2)
72-75: Update sleep_duration max to 1440: confirm device constraintsChanging native_max_value from device-maximum (likely 65535) to 1440 minutes is a behavior change. Validate against device specs and ensure existing user values >1440 are handled gracefully (UI will now clamp/deny).
84-87: Update awake_duration max to 60 seconds: confirm device constraintsSimilar to sleep_duration: verify that 60 seconds is the correct upper bound for all supported nodes to avoid unexpected validation errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (5)
custom_components/plugwise_usb/select.py (5)
22-24: Nit: PARALLEL_UPDATES/SCAN_INTERVAL are likely unused with CoordinatorEntityWith CoordinatorEntity managing updates, these module-level constants are typically ignored for this platform. Consider removing to avoid confusion unless HA still reads them for this integration.
-PARALLEL_UPDATES = 2 -SCAN_INTERVAL = timedelta(seconds=30) +# CoordinatorEntity handles updates; keep only if explicitly needed by HA.
90-96: Optional: guard unsubscribe on unload for robustnessIf setup partially fails or the key isn’t present, this can KeyError. Defensive guard makes unload resilient.
- config_entry.runtime_data[Platform.SELECT][UNSUB_NODE_LOADED]() + unsub = ( + config_entry.runtime_data + .get(Platform.SELECT, {}) + .get(UNSUB_NODE_LOADED) + ) + if unsub: + unsub()
114-131: Optional: handle missing/None values from coordinator dataIf the device temporarily omits the attribute, we can avoid exceptions and log once.
- current_option = getattr( - data, - self.entity_description.key, - ) - self._attr_current_option = current_option.name.lower() + current_option = getattr(data, self.entity_description.key, None) + if current_option is None: + _LOGGER.debug( + "Missing %s for %s (feature %s)", + self.entity_description.key, + self._node_info.mac, + self.entity_description.node_feature, + ) + return + self._attr_current_option = current_option.name.lower() self.async_write_ha_state()
12-16: Prefer HomeAssistantError over ValueError for service-call feedbackRaising HomeAssistantError yields clearer feedback in HA logs and UI.
from homeassistant.core import HomeAssistant, callback +from homeassistant.exceptions import HomeAssistantError
132-141: Map invalid selections to HomeAssistantError; optionally refresh after change
- Raise HomeAssistantError for better UX.
- Optionally request a refresh after the device call to reconcile state.
- if normalized not in self._attr_options: - raise ValueError(f"Unsupported option: {option}") + if normalized not in self._attr_options: + raise HomeAssistantError(f"Unsupported option: {option}") value = self.entity_description.options_enum[normalized.upper()] await self.async_select_fn(value) self._current_option = normalized self._attr_current_option = normalized self.async_write_ha_state() + # Optionally: sync back from device if it doesn’t push state + # await self.coordinator.async_request_refresh()
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
custom_components/plugwise_usb/select.py(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
custom_components/plugwise_usb/select.py (2)
custom_components/plugwise_usb/coordinator.py (1)
PlugwiseUSBDataUpdateCoordinator(27-125)custom_components/plugwise_usb/entity.py (2)
PlugwiseUSBEntity(27-75)PlugwiseUSBEntityDescription(21-24)
🔇 Additional comments (6)
custom_components/plugwise_usb/select.py (6)
26-34: Dataclass shape looks correct and future-proofThe Select entity description cleanly extends the base description and HA’s SelectEntityDescription; typing
options_enum: type[Enum]is appropriate given how it’s used later.
35-44: SELECT_TYPES entry is well-formedGood use of translation_key, EntityCategory.CONFIG, and binding to NodeFeature.MOTION_CONFIG with MotionSensitivity as the options enum.
61-62: LGTM: corrected debug log uses node_duc.node.nameThis addresses the earlier AttributeError risk from using node_duc.name. Thanks for fixing it.
84-88: Preloading already-loaded nodes is correctLooping through api_stick.nodes and seeding selects for loaded nodes ensures entities appear on startup. Looks good.
101-112: Good: options derived from Enum and normalized to lowercaseUsing
entity_description.options_enumand emitting lowercase strings aligns with translations and keeps UI consistent.
54-72: No duplicate event handler registration for SELECTThe
select.pysetup clearsconfig_entry.runtime_data[Platform.SELECT]before subscribing to node events, matching the pattern used in all other platform modules. This reset guarantees that on each reload the previous subscription is discarded and a single, fresh subscription is registered:
- Line 76 in
custom_components/plugwise_usb/select.pyresets the runtime data:
config_entry.runtime_data[Platform.SELECT] = {}- Line 77 then stores the unsubscribe callback returned by
api_stick.subscribe_to_node_events, ensuring proper cleanup on unload.Since the code already clears before reassigning and follows the existing, tested pattern across platforms, no further changes are needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
custom_components/plugwise_usb/translations/en.json (2)
151-155: Align button names to sentence case for consistencyMost entity names use sentence case. These two new buttons read as title case; recommend sentence case for UI consistency.
"ping_node":{ - "name": "Ping Device" + "name": "Ping device" }, "calibrate_light":{ - "name": "Schedule Light Sensor Calibration" + "name": "Schedule light sensor calibration" }
52-57: Replace “config” with “configuration” in translation stringsPlease update the user-facing names in
custom_components/plugwise_usb/translations/en.jsonto avoid the abbreviation “config” and use the full word “configuration” for clarity and consistency:• File:
custom_components/plugwise_usb/translations/en.json
• Lines: 52–57"motion_config_dirty": { - "name": "Motion config changed" + "name": "Motion configuration changed" }, "battery_config_dirty": { - "name": "Battery config changed" + "name": "Battery configuration changed" }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
CHANGELOG.md(1 hunks)custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)pyproject.toml(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
- pyproject.toml
- custom_components/plugwise_usb/translations/nl.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Prepare
🔇 Additional comments (1)
custom_components/plugwise_usb/translations/en.json (1)
60-66: LGTM: Lowercase options and mapping verified
- Translation key remains correct (
motion_sensitivity_level).- Options are emitted in lowercase (
self._attr_options = [o.name.lower() …]at line 109).- Current state is stored in lowercase (
self._attr_current_option = current_option.name.lower()at line 127).- The
async_select_optionmethod normalizes input to lowercase (normalized = option.strip().lower()at line 132).No further changes needed.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
custom_components/plugwise_usb/translations/en.json (1)
150-155: Align button label casing with surrounding styleMost strings here follow sentence case. Recommend “Ping device” (lowercase “device”) for consistency.
"ping_node":{ - "name": "Ping Device" + "name": "Ping device" },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
custom_components/plugwise_usb/translations/en.json(2 hunks)custom_components/plugwise_usb/translations/nl.json(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- custom_components/plugwise_usb/translations/nl.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Setup for HA-core (release/master)
🔇 Additional comments (3)
custom_components/plugwise_usb/translations/en.json (3)
59-66: Translations Verified and Approved
- No remaining misspellings of
motion_sensitivy_levelwere found.- All
motion_sensitivity_levelstate keys are correctly lowercase (high,medium,off).With these checks passing, the translation entries are valid and align with Home Assistant conventions.
51-57: Configuration terminology ready for updateVerified that the keys
motion_config_dirtyandbattery_config_dirtyexist in strings.json and nl.json and that there are no remaining"config changed"entries in en.json. Please apply the following diff to complete the wording polish:custom_components/plugwise_usb/translations/en.json @@ 52,56 - "motion_config_dirty": { - "name": "Motion config changed" - }, + "motion_config_dirty": { + "name": "Motion configuration changed" + }, - "battery_config_dirty": { - "name": "Battery config changed" - } + "battery_config_dirty": { + "name": "Battery configuration changed" + }
160-170: All translation casing consistent across localesThe Dutch translations in nl.json already use sentence case (“Knop I/O groep N gedrukt”) matching the updated English phrasing, so no further changes are needed.
bouwew
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @dirixmjm !



Add MotionSensitivity select configuration parameter
add binary sensor to show configuration has changed
Summary by CodeRabbit
New Features
Chores
Documentation