Zigbee2MQTT: add WOOX R7051 smart siren#2477
Zigbee2MQTT: add WOOX R7051 smart siren#2477William-De71 wants to merge 4 commits intoGladysAssistant:masterfrom
Conversation
📝 WalkthroughWalkthroughThis PR adds comprehensive support for siren device features with configurable modes, volume levels, and strobe settings. It introduces new React components for mode/level selection, backend mappings for zigbee2mqtt siren exposures, composite feature handling with parent-child relationships, and internationalized UI text across German, English, and French languages, alongside extensive test coverage. Changes
Sequence DiagramsequenceDiagram
participant Device as Siren Device
participant MQTT as MQTT Broker
participant Handler as handleMqttMessage
participant FindExpose as findMatchingExpose
participant ReadValue as readValue
participant StateManager as State Manager
participant UI as Frontend UI
Device->>MQTT: Publish siren state (warning: {mode, level, strobe})
MQTT->>Handler: MQTT message received
Handler->>Handler: Detect composite object value
Handler->>FindExpose: Find expose for 'warning'
FindExpose-->>Handler: {expose: warning, parent: undefined}
Handler->>Handler: Iterate subFields (mode, level, strobe)
loop For each sub-field
Handler->>FindExpose: Find expose for sub-field
FindExpose-->>Handler: {expose: subExpose, parent: warning}
Handler->>ReadValue: readValue(subExpose, subValue)
ReadValue-->>Handler: Converted value
Handler->>StateManager: Emit NEW_STATE with subFeature
end
StateManager->>UI: Update siren components
UI->>UI: Render mode, level, strobe selections
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
server/test/services/zigbee2mqtt/lib/findMatchingExpose.test.js (1)
51-56: Rename this test for accuracy.The title says “with parent” but the assertions validate
parentisundefined. Please rename to avoid ambiguity.✏️ Suggested rename
- it('expose discovered with parent on cover position', () => { + it('expose discovered without parent on cover position', () => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@server/test/services/zigbee2mqtt/lib/findMatchingExpose.test.js` around lines 51 - 56, The test title is misleading: the it() string "expose discovered with parent on cover position" claims a parent but assertions check parent is undefined; update the test description to reflect that no parent is present (e.g., "expose discovered without parent on cover position" or "expose discovered with no parent on cover position") in the test that calls zigbee2MqttService.device.findMatchingExpose('0x00158d00045b2740', 'position') so the name matches the assertions checking result.parent === undefined.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@server/test/services/zigbee2mqtt/lib/findMatchingExpose.test.js`:
- Around line 59-61: The test currently dereferences sirenDevice and its
friendly_name without asserting the fixture exists; add an explicit assertion
that the fixture was found (e.g., assert(sirenDevice) or
expect(sirenDevice).toBeDefined()) before assigning to
zigbee2MqttService.device.discoveredDevices and before calling
zigbee2MqttService.device.findMatchingExpose('0x00158d00045b2741','mode');
repeat the same explicit existence check for the other fixture use around the
block referenced at lines 70-72 so failures report a clear missing-fixture error
rather than a TypeError; use the sirenDevice variable and the
zigbee2MqttService.device.discoveredDevices lookup to locate where to add the
assertion.
---
Nitpick comments:
In `@server/test/services/zigbee2mqtt/lib/findMatchingExpose.test.js`:
- Around line 51-56: The test title is misleading: the it() string "expose
discovered with parent on cover position" claims a parent but assertions check
parent is undefined; update the test description to reflect that no parent is
present (e.g., "expose discovered without parent on cover position" or "expose
discovered with no parent on cover position") in the test that calls
zigbee2MqttService.device.findMatchingExpose('0x00158d00045b2740', 'position')
so the name matches the assertions checking result.parent === undefined.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
front/src/components/boxs/device-in-room/DeviceRow.jsxfront/src/components/boxs/device-in-room/device-features/SirenLevelDeviceFeature.jsxfront/src/components/boxs/device-in-room/device-features/SirenModeDeviceFeature.jsxfront/src/config/i18n/de.jsonfront/src/config/i18n/en.jsonfront/src/config/i18n/fr.jsonfront/src/utils/consts.jsserver/services/zigbee2mqtt/exposes/binaryType.jsserver/services/zigbee2mqtt/exposes/compositeType.jsserver/services/zigbee2mqtt/exposes/enumType.jsserver/services/zigbee2mqtt/exposes/numericType.jsserver/services/zigbee2mqtt/lib/findMatchingExpose.jsserver/services/zigbee2mqtt/lib/handleMqttMessage.jsserver/services/zigbee2mqtt/lib/readValue.jsserver/services/zigbee2mqtt/lib/setValue.jsserver/test/services/zigbee2mqtt/exposes/compositeType.test.jsserver/test/services/zigbee2mqtt/exposes/warningLevelEnumType.test.jsserver/test/services/zigbee2mqtt/exposes/warningModeEnumType.test.jsserver/test/services/zigbee2mqtt/lib/findMatchingExpose.test.jsserver/test/services/zigbee2mqtt/lib/getDiscoveredDevices.test.jsserver/test/services/zigbee2mqtt/lib/handleMqttMessage.test.jsserver/test/services/zigbee2mqtt/lib/payloads/event_device_result.jsonserver/test/services/zigbee2mqtt/lib/payloads/mqtt_devices_get.jsonserver/test/services/zigbee2mqtt/lib/readValue.test.jsserver/test/services/zigbee2mqtt/lib/setValue.test.jsserver/utils/constants.js
| const sirenDevice = discoveredDevices.find((d) => d.friendly_name === '0x00158d00045b2741'); | ||
| zigbee2MqttService.device.discoveredDevices[sirenDevice.friendly_name] = sirenDevice; | ||
| const result = zigbee2MqttService.device.findMatchingExpose('0x00158d00045b2741', 'mode'); |
There was a problem hiding this comment.
Add an explicit fixture existence assertion before dereferencing.
If the fixture entry is missing/renamed, this will fail with a generic TypeError instead of a clear test failure.
✅ Suggested hardening
const sirenDevice = discoveredDevices.find((d) => d.friendly_name === '0x00158d00045b2741');
+ assert.isDefined(sirenDevice, 'Expected siren fixture 0x00158d00045b2741 to exist in mqtt_devices_get.json');
zigbee2MqttService.device.discoveredDevices[sirenDevice.friendly_name] = sirenDevice;Also applies to: 70-72
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@server/test/services/zigbee2mqtt/lib/findMatchingExpose.test.js` around lines
59 - 61, The test currently dereferences sirenDevice and its friendly_name
without asserting the fixture exists; add an explicit assertion that the fixture
was found (e.g., assert(sirenDevice) or expect(sirenDevice).toBeDefined())
before assigning to zigbee2MqttService.device.discoveredDevices and before
calling
zigbee2MqttService.device.findMatchingExpose('0x00158d00045b2741','mode');
repeat the same explicit existence check for the other fixture use around the
block referenced at lines 70-72 so failures report a clear missing-fixture error
rather than a TypeError; use the sirenDevice variable and the
zigbee2MqttService.device.discoveredDevices lookup to locate where to add the
assertion.
#3964 Bundle Size — 11.4MiB (+0.1%).4919757(current) vs 8db6b0d master#3902(baseline) Warning Bundle contains 2 duplicate packages – View duplicate packages Bundle metrics
Bundle size by type
Bundle analysis report Branch William-De71:features/woox-siren Project dashboard Generated by RelativeCI Documentation Report issue |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2477 +/- ##
==========================================
+ Coverage 98.74% 98.79% +0.04%
==========================================
Files 990 1006 +16
Lines 17114 17514 +400
==========================================
+ Hits 16900 17303 +403
+ Misses 214 211 -3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Pull Request check-list
To ensure your Pull Request can be accepted as fast as possible, make sure to review and check all of these items:
npm teston both front/server)npm run eslinton both front/server)npm run prettieron both front/server)npm run compare-translationson front)front/src/config/demo.js) so that the demo website is working without a backend? (if needed) See https://demo.gladysassistant.com.NOTE: these things are not required to open a PR and can be done afterwards / while the PR is open.
Description of change
Add support of WOOX R7051 Smart siren

Summary by CodeRabbit
Release Notes