Skip to content

Add Sonoff SNZB-03P motion sensor #3979

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Changes from all commits
Commits
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
64 changes: 64 additions & 0 deletions zhaquirks/sonoff/snzb03p.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Sonoff SNZB-03P - Zigbee motion sensor."""

from zigpy.quirks import CustomCluster
from zigpy.quirks.v2 import EntityPlatform, EntityType, NumberDeviceClass, QuirkBuilder
from zigpy.quirks.v2.homeassistant import UnitOfTime
import zigpy.types as t
from zigpy.zcl.clusters.measurement import OccupancySensing
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl.foundation import BaseAttributeDefs, ZCLAttributeDef


class LastIlluminationState(t.enum8):
"""Last measureed state of illumination enum."""

Dark = 0x00
Light = 0x01


class SonoffIlluminationCluster(CustomCluster):
"""Custom Sonoff illumination cluster."""

cluster_id = 0xFC11

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

last_illumination_state = ZCLAttributeDef(
id=0x2001,
type=LastIlluminationState,
access="rp",
is_manufacturer_specific=True,
)

@property
def _is_manuf_specific(self):
return False

Check warning on line 36 in zhaquirks/sonoff/snzb03p.py

View check run for this annotation

Codecov / codecov/patch

zhaquirks/sonoff/snzb03p.py#L36

Added line #L36 was not covered by tests
Comment on lines +34 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we can use manufacturer_id_override: t.uint16_t = foundation.ZCLHeader.NO_MANUFACTURER_ID instead. See this PR as an example: https://github.com/zigpy/zha-device-handlers/pull/3910/files#diff-6c9212ca1af0b4604a20edb89247ceb6d30b010041e81fde812465a2f73a3ccbR24

Copy link
Author

Choose a reason for hiding this comment

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

Can not be used.

Replace with manufacturer_id_override: t.uint16_t = foundation.ZCLHeader.NO_MANUFACTURER_ID is broken:

  • eWeLink SNZB-03P is always detected
  • Last illumination state is Unavailable

2025-03-26 10 11 35

With _is_manuf_specific(self): return False is right:

2025-03-26 10 14 24

Copy link
Collaborator

Choose a reason for hiding this comment

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

eWeLink SNZB-03P is always detected
Last illumination state is Unavailable

Adding manufacturer_id_override on the SonoffIlluminationCluster won't influence the motion entity/attribute, since it's on another cluster.

And last illumination sensor being unavailable also can't be a result of adding that. Did you see any errors in the logs when adding manufacturer_id_override to that cluster, similar to how it's done in the linked PR above?

Maybe you forgot to import from zigpy.zcl import foundation at the top?

Comment on lines +34 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

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

Z2M seems to specify a manufacturer code: https://github.com/Koenkk/zigbee-herdsman-converters/blob/216ba1a56f1b21fda7de7204839f0fb838df0b85/src/devices/sonoff.ts#L1162
Do we even need this at all? By default, zigpy will use the manufacturer code for the device if the attribute is marked as is_manufacturer_specific (it is) and if the cluster is in the manufacturer specific range (it is).

I guess this is only really needed if we explicitly poll/read the attribute ourselves though (through the "Manage Zigbee device -> Clusters" debug menu).



(
QuirkBuilder("eWeLink", "SNZB-03P")
.replaces(SonoffIlluminationCluster)
.removes(IasZone.cluster_id) # IasZone cluster 0x0500: remove motion detection
Copy link
Collaborator

Choose a reason for hiding this comment

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

So the IasZone cluster doesn't do anything at all?
Can we use .prevent_default_entity_creation(endpoint_id=1, cluster_id=IasZone.cluster_id) here instead?
It's a new functionality that doesn't entirely remove the cluster for us, just disables the auto discovery for ZHA entities on that cluster.

Copy link
Author

@panther7 panther7 Mar 26, 2025

Choose a reason for hiding this comment

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

Yes, cluster is always "unavailable".

.number(
OccupancySensing.AttributeDefs.ultrasonic_o_to_u_delay.name,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, interesting. This is a default attribute. It's also used by the Hue motion sensors, though it's reported as an "unsupported attribute" if we read it during pairing, for some reason, so I've not added that as a config entity for now. We could add the entities via quirks v2 for both sensors, but we might be able to add this as a general entity in ZHA. I'll have to come back to this.

Copy link
Author

Choose a reason for hiding this comment

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

If removed, then same issue like #3979 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant potentially removing the whole .number() method for ultrasonic_o_to_u_delay.
It won't cause other entities to break if removed like that.

Perhaps we can keep this though. I'll have to check back with how we want to implement config support for this entity in ZHA.

OccupancySensing.cluster_id,
min_value=5,
max_value=60,
step=1,
unit=UnitOfTime.SECONDS,
device_class=NumberDeviceClass.DURATION,
translation_key="motion_timeout",
fallback_name="Presence detection timeout",
)
.enum(
SonoffIlluminationCluster.AttributeDefs.last_illumination_state.name,
LastIlluminationState,
SonoffIlluminationCluster.cluster_id,
entity_platform=EntityPlatform.SENSOR,
entity_type=EntityType.STANDARD,
translation_key="last_illumination_state",
fallback_name="Last illumination state",
)
.add_to_registry()
)
Loading