Skip to content

Convert Schneider outlet to quirks v2, add missing controls - #4521

Open
uvNikita wants to merge 8 commits into
zigpy:devfrom
uvNikita:se/outlet
Open

Convert Schneider outlet to quirks v2, add missing controls#4521
uvNikita wants to merge 8 commits into
zigpy:devfrom
uvNikita:se/outlet

Conversation

@uvNikita

Copy link
Copy Markdown
Contributor

Proposed change

Fixes: #4503
Part of: #1705

Additional information

Spec docs:
ZB Spec - Socket Outlets - 200522.pdf

Device diagnostics

Checklist

  • The changes are tested and work correctly
  • pre-commit checks pass / the code has been formatted using Black
  • Tests have been added to verify that the new code works
  • Device diagnostics data has been attached

@TheJulianJES TheJulianJES added the priority: medium This should be addressed or looked at soon label Nov 25, 2025
@codecov

codecov Bot commented Nov 25, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.41%. Comparing base (e2cafc6) to head (1e597ec).
⚠️ Report is 13 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev    #4521   +/-   ##
=======================================
  Coverage   92.40%   92.41%           
=======================================
  Files         416      416           
  Lines       14314    14327   +13     
=======================================
+ Hits        13227    13240   +13     
  Misses       1087     1087           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread zhaquirks/schneiderelectric/outlet.py Outdated
@nnae06

nnae06 commented Nov 27, 2025

Copy link
Copy Markdown

Hello.

I have tried this quirks.
Indicator luminance level - nothing happens when adjusting, not sure what should happen either.
Indicator mode - fully functional, can change indication mode.
Local control mode - does not work, gets error message. Check picture.
1
2

@uvNikita

Copy link
Copy Markdown
Contributor Author

@nnae06 I don't have this device, so great that you can check it.

I pushed fix for Local control mode that hopefully should resolve the issue.

As for Indicator luminance level, not sure what else I can do there. Everything looks good to me according to the specification.
Can you try to read value from the attribute after changing it in UI? Go to "Manage Zigbee device" -> SEOutletConfiguration Cluster -> se_indicator_luminance_level -> Click on "Read attribute"

@uvNikita

Copy link
Copy Markdown
Contributor Author

Indicator luminance level - nothing happens when adjusting, not sure what should happen either.

AFAIK, it should adjust led brightness:

image

@nnae06

nnae06 commented Nov 27, 2025

Copy link
Copy Markdown

Thanks for your help. Even if you don't have the device yourself.

I tried your updated code, unfortunately without success. Still getting that error message.

When I tried to add controls for Schneider motion dimmer I encountered the same problem. I couldn't figure out what the problem was.
1

@uvNikita

Copy link
Copy Markdown
Contributor Author

The error seem to indicate that this attribute (0x0050) doesn't exist on your device, so I guess spec doc is incorrect, or has a mistake in it.

Can you post signature of this device? To do that, go to "Manage Zigbee Device" -> "Signature"

@uvNikita

Copy link
Copy Markdown
Contributor Author

Actually, it doesn't look like signature will give us a list of attributes. Not sure if there is a way to get the list of attributes from manufacturer specific cluster.

@TheJulianJES Let me know if you have some pointers, if not, I can remove se_local_control_mode attribute from the PR.

@nnae06

nnae06 commented Nov 28, 2025

Copy link
Copy Markdown

{
"node_descriptor": {
"logical_type": 1,
"complex_descriptor_available": 0,
"user_descriptor_available": 0,
"reserved": 0,
"aps_flags": 0,
"frequency_band": 8,
"mac_capability_flags": 142,
"manufacturer_code": 4190,
"maximum_buffer_size": 82,
"maximum_incoming_transfer_size": 82,
"server_mask": 11264,
"maximum_outgoing_transfer_size": 82,
"descriptor_capability_field": 0
},
"endpoints": {
"6": {
"profile_id": "0x0104",
"device_type": "0x0009",
"input_clusters": [
"0x0000",
"0x0003",
"0x0004",
"0x0005",
"0x0006",
"0x0702",
"0x0708",
"0x0b04",
"0x0b05",
"0xfc04"
],
"output_clusters": [
"0x0019"
]
},
"242": {
"profile_id": "0xa1e0",
"device_type": "0x0061",
"input_clusters": [],
"output_clusters": [
"0x0021"
]
}
},
"manufacturer": "Schneider Electric",
"model": "SOCKET/OUTLET/1",
"class": "zigpy.quirks.v2.CustomDeviceV2"
}

@uvNikita

uvNikita commented Nov 28, 2025

Copy link
Copy Markdown
Contributor Author

Zigbee2Mqtt also doesn't have LocalControl attribute. Also their luminance level is enum, but spec says that it's uint8:

https://github.com/Koenkk/zigbee-herdsman-converters/blob/177e497e56b8482d71d65ebf62846d935f0fb419/src/devices/schneider_electric.ts#L154-L174

@nnae06

nnae06 commented Apr 6, 2026

Copy link
Copy Markdown

I have now been running this code for a few months without any problems. Everything works flawlessly, the indication on the socket can be adjusted with animation.

"""Schneider Electric (Wiser) Outlet Quirks."""

from typing import Final

from zigpy import types as t
from zigpy.quirks import CustomCluster
from zigpy.quirks.v2 import QuirkBuilder
from zigpy.zcl.clusters.smartenergy import Metering
from zigpy.zcl.foundation import DataTypeId, ZCLAttributeDef

from zhaquirks.schneiderelectric import SE_MANUF_NAME, SEBasic

class SEIndicatorMode(t.enum8):
"""Indicator mode."""

InverseOfOutput = 0x00
FollowsOutput = 0x01
AlwaysOff = 0x02
AlwaysOn = 0x03

class SEOutletConfiguration(CustomCluster):
"""Schneider Electric Outlet Configuration cluster."""

cluster_id = 0xFC04
name = "SEOutletConfiguration"

class AttributeDefs(CustomCluster.AttributeDefs):
    """Attribute definitions."""

    se_indicator_mode: Final = ZCLAttributeDef(
        id=0x0002,
        type=SEIndicatorMode,
        zcl_type=DataTypeId.uint8,
        access="rw",
        is_manufacturer_specific=True,
    )

class SEMeteringCluster(CustomCluster, Metering):
"""Fix instantaneous demand value multiplied by 1000."""

def _update_attribute(self, attrid, value):
    if attrid == self.AttributeDefs.instantaneous_demand.id:
        value = value / 1000
    super()._update_attribute(attrid, value)

(
QuirkBuilder(SE_MANUF_NAME, "SOCKET/OUTLET/1")
.applies_to(SE_MANUF_NAME, "SOCKET/OUTLET/2")
.replaces(SEBasic, endpoint_id=6)
.replaces(SEMeteringCluster, endpoint_id=6)
.replaces(SEOutletConfiguration, endpoint_id=6)
.enum(
cluster_id=SEOutletConfiguration.cluster_id,
endpoint_id=6,
attribute_name=SEOutletConfiguration.AttributeDefs.se_indicator_mode.name,
enum_class=SEIndicatorMode,
translation_key="indicator_mode",
fallback_name="Indicator mode",
)
.add_to_registry()
)

@nnae06

nnae06 commented Apr 7, 2026

Copy link
Copy Markdown

outlet.py

@uvNikita

Copy link
Copy Markdown
Contributor Author

Rebased on top of the current dev, migrated to new manufacturer_code. @TheJulianJES should be ready for merge.

zigpy-review-bot added a commit to zigpy/zha that referenced this pull request Jun 24, 2026
Updated for the v2 conversion and added controls in zigpy/zha-device-handlers#4521.
zigpy-review-bot added a commit to zigpy/zha that referenced this pull request Jun 24, 2026
Updated for the v2 conversion and added controls in zigpy/zha-device-handlers#4521.
@zigpy-review-bot

Copy link
Copy Markdown
Collaborator

Updated to work with the recent quirks/ZHA refactor (#5113).
The refactor is part of HA Core 2026.7.0 (beta) and newer, so this quirk won’t work when installed as a custom quirk on previous HA versions.

@TheJulianJES TheJulianJES added the smash This PR is close to be merged soon label Jun 24, 2026
@zigpy-review-bot zigpy-review-bot added bot: ready PR generally in good state per LLM bot: 2.0 migration done PR is on the ZHA/quirks 2.0.0 API (migrated or written for 2.0) per LLM enhancement Improve an existing quirk labels Jul 21, 2026
@TheJulianJES TheJulianJES added the bot-trigger: post review Pending/new review is posted some time after this label is applied label Jul 29, 2026

@zigpy-review-bot zigpy-review-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving — clean v1→v2 migration, and the new controls check out against the vendor spec.

Verified against the attached spec PDF. All three 0xFC04 attribute types match exactly: IndicatorLuminanceLevel (0x0000) is uint8, IndicatorMode (0x0002) is uint8, and LocalControl (0x0050) is enum8. So the asymmetric zcl_type=DataTypeId.uint8 on se_indicator_mode but not on se_local_control_mode is correct — it faithfully reproduces the spec rather than being an oversight. The enum value sets match too, including the inverted luminance scale (0 = 100%, 5 = 0%).

Zigbee2MQTT independently corroborates the indicator mode: its manuSpecificSchneiderFanSwitchConfiguration (also cluster 0xFC04) defines ledIndication at 0x0002 as UINT8 with reverse_with_load: 0, consistent_with_load: 1, always_off: 2, always_on: 3 — the same ordering as SEIndicatorMode.

No entity breakage for existing users. I regenerated both ZHA diagnostics snapshots (schneider-electric-socket-outlet-1/2-0x020612ff.json) against this branch. The delta is purely additive — three new entities on endpoint 6 (se_indicator_luminance_level number, se_indicator_mode and se_local_control_mode selects) — with every pre-existing entity, including the StartUpOnOff select and all metering/electrical sensors, unchanged. ZHA core has no Schneider cluster handler for 0xFC04, so there is no native-vs-quirk entity collision and no duplicate entities. The snapshots will need regenerating in zigpy/zha after the next zha-quirks release.

git merge dev applies cleanly and the full test suite passes.

cluster_id=SEOutletConfiguration.cluster_id,
endpoint_id=6,
min_value=0,
max_value=5,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Optional: the scale here is inverted (0 = brightest, 5 = off), which is a little unintuitive as a bare number in the UI. Z2M exposes the same attribute as a named lookup ("100", "80", … "0" percent). Since a number entity was the explicitly requested shape in the earlier review round, this is fine as-is — just noting that an enum with percentage-named members would be self-documenting if you ever want to revisit. The comment on the attribute definition already covers the mapping.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot: ready PR generally in good state per LLM bot: 2.0 migration done PR is on the ZHA/quirks 2.0.0 API (migrated or written for 2.0) per LLM enhancement Improve an existing quirk priority: medium This should be addressed or looked at soon smash This PR is close to be merged soon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose entities for Schneider Electric outlet SOCKET/OUTLET/1 SOCKET/OUTLET/2

4 participants