Skip to content
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

[Device Support Request] SOC001 - Philips Contact sensor #3314

Closed
mguaylam opened this issue Aug 24, 2024 · 8 comments · Fixed by #3432 or #3541
Closed

[Device Support Request] SOC001 - Philips Contact sensor #3314

mguaylam opened this issue Aug 24, 2024 · 8 comments · Fixed by #3432 or #3541

Comments

@mguaylam
Copy link
Contributor

mguaylam commented Aug 24, 2024

Problem description

Signify released a while a go a contact sensor to extend their security product portfolio.
Unfortunately they almost exclusively putted all relevant attributes in their manufacturer cluster.
Good news is that the device seems to overall have a good behaviour continuing the reputation of Signify.

Solution description

  1. Implement the manufacturer specific cluster :
  • PhilipsContactCluster : 0xFC06
  1. Implements the associated attributes :
  • Contact
    Attribute: 0x0100
    Data Type: 8-Bit Enumeration (0x30)
    Uint8: 1 (0x01)

  • Last contact change (10th of a second)
    Attribute: 0x0101
    Data Type: 32-Bit Unsigned Integer (0x23)
    Uint32: 0 (0x00000000)

  • Tamper
    Attribute: 0x0102
    Data Type: 8-Bit Enumeration (0x30)
    Uint8: 0 (0x00)

  • Last tamper change (10th of a second)
    Attribute: 0x0103
    Data Type: 32-Bit Unsigned Integer (0x23)
    Uint32: 12425 (0x00003089)

  1. Handle the on_off cluster as it is stateless and only meant for biding with lights.

Screenshots/Video

Screenshots/Video

[Paste/upload your media here]

Device signature

Device signature
{
  "node_descriptor": {
    "logical_type": 2,
    "complex_descriptor_available": 0,
    "user_descriptor_available": 0,
    "reserved": 0,
    "aps_flags": 0,
    "frequency_band": 8,
    "mac_capability_flags": 128,
    "manufacturer_code": 4107,
    "maximum_buffer_size": 82,
    "maximum_incoming_transfer_size": 128,
    "server_mask": 11264,
    "maximum_outgoing_transfer_size": 128,
    "descriptor_capability_field": 0
  },
  "endpoints": {
    "2": {
      "profile_id": "0x0104",
      "device_type": "0x0402",
      "input_clusters": [
        "0x0000",
        "0x0001",
        "0x0003",
        "0xfc06"
      ],
      "output_clusters": [
        "0x0000",
        "0x0003",
        "0x0006",
        "0x0019"
      ]
    }
  },
  "manufacturer": "Signify Netherlands B.V.",
  "model": "SOC001",
  "class": "soc001.SignifyContact"
}

Diagnostic information

Diagnostic information
None

Logs

Logs
None

Custom quirk

Custom quirk
"""Signify SOC001 device."""

from zigpy.quirks.v2 import QuirkBuilder,ClusterType,BinarySensorDeviceClass
import zigpy.types as types
from zigpy.quirks import CustomCluster

class PhilipsManufacturerSpecific(CustomCluster):
    """Philips Contact manufacturer cluster."""

    cluster_id: types.uint16_t = 0xFC06
    name = "Philips Manufacturer specific"
    ep_attribute = "philips_manufacturer_specific"
    attributes = {
        0x0100: ("contact", types.enum8, True),
        0x0101: ("last_contact_change", types.uint32_t, True),
        0x0102: ("tamper", types.enum8, True),
        0x0103: ("last_tamper_change", types.uint32_t, True),
    }

(
    QuirkBuilder("Signify Netherlands B.V.", "SOC001")
    .removes(
        cluster_id=6,
        endpoint_id=2,
        cluster_type=ClusterType.Client
    )
    .replaces(
        replacement_cluster_class=PhilipsManufacturerSpecific,
        cluster_id=64518,
        endpoint_id=2
    )
    .binary_sensor(
        attribute_name="contact",
        cluster_id=64518, #0xfc06,
        endpoint_id=2,
        device_class=BinarySensorDeviceClass.OPENING
    )
    .binary_sensor(
        attribute_name="tamper",
        cluster_id=64518, #0xfc06,
        endpoint_id=2,
        device_class=BinarySensorDeviceClass.TAMPER
    )
    .add_to_registry()
)

Additional information

Unfortunately the device does not respond it's attributes whatsoever, probably to make our life a little bit harder.
To discover the attributes, I iterated all attribute addresses and read them to get the following data :

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2024-08-19T04 37 20.475616+00 0 Manufacturer Specific 256 enum8.undefined_0x00 0x0100 0xFC06 2 0 17 88 1 0d ce f9 51 0x100B 0x30
2024-08-19T04 37 25.483887+00 0 Manufacturer Specific 257 47103 0x0101 0xFC06 2 0 17 88 1 0d ce f9 51 0x100B 0x23
2024-08-19T04 37 30.487990+00 0 Manufacturer Specific 258 enum8.undefined_0x00 0x0102 0xFC06 2 0 17 88 1 0d ce f9 51 0x100B 0x30
2024-08-19T04 37 35.495690+00 0 Manufacturer Specific 259 172317 0x0103 0xFC06 2 0 17 88 1 0d ce f9 51 0x100B 0x23

But realised afterward that ebaauw did all the work here : dresden-elektronik/deconz-rest-plugin#7226

@mguaylam mguaylam changed the title [Device Support Request] Philips Contact sensor [Device Support Request] SOC001 - Philips Contact sensor Aug 24, 2024
@puddly
Copy link
Contributor

puddly commented Oct 15, 2024

Is tamper available via the usual IAS zone alarm bitfield?

@mguaylam
Copy link
Contributor Author

Yes it's bit number 2. But I went the v2 route as it was easier. I would have preferred this way initially. I didn't make a PR for it yet, I don't have any test : dev...mguaylam:zha-device-handlers:soc001

@dmulcahey
Copy link
Collaborator

Is tamper available via the usual IAS zone alarm bitfield?

It is, IIRC there is no programmatic way to know if a device actually supports it. This is why we haven’t implemented it as a std entity yet.

@TheJulianJES
Copy link
Collaborator

TheJulianJES commented Oct 15, 2024

Just to clarify, the Hue sensor does NOT have an IAS Zone Cluster. The open/closed state is sent using OnOff cluster commands.
The tamper attribute is only available on the manufacturer cluster. It also has an additional attribute for open/closed which is readable/pollable (the sensor is not really asleep, like the Hue motion sensors.
The advantage of the custom open/closed attribute is that it would be readable/pollable after a power outage (where OnOff cluster commands may be missed).

There's a thread on Discord with more info on this device: https://discord.com/channels/330944238910963714/1292736317569896591

@MattWestb
Copy link
Contributor

I think some tuya / LIDL motion sensors have it but last time i was triggering it ZHA have not the right logic for alarm / tamper so alarm is not being retested if temper status is changed in the same time frame.
I think best implanting the tamper sensor in ZHA and users can disabling it if its not working so not interfering with the alarm cycle.

@TheJulianJES
Copy link
Collaborator

Copying my answer from the Discord thread:
So, for ZHA to expose the IAS tamper bit as an entity, something like this might work: zigpy/zha@dev...TheJulianJES:zha:tjj/ias_tamper_test
(If this were to actually be implemented, there should be an IasBase class, so the device class + translation key don't need to be overridden like that)

We could still do that for Tuya devices that explicitly support the attribute.

@TheJulianJES
Copy link
Collaborator

Auto-closed with the PR, but reopening this for the discussion around the Hue-specific contact attribute/entity.

@TheJulianJES TheJulianJES reopened this Oct 20, 2024
@mguaylam
Copy link
Contributor Author

mguaylam commented Oct 20, 2024

Thanks for keeping it open.

I think you mentioned that reconfiguration will be needed. Would that be enough to justify the breaking change anyway?

Unless we could make some sort of version and discriminate current installations, you suggested :

Block the OnOff entity from being created directly in ZHA

Allow quirks to properly disable individual entity generation

That would be an awesome feature in quirk v2 with something like block entire cluster or entity generation for cases like the Sage doorbell sensor that has a % battery attribute but reports nothing at all. In the meantime, I would consider other options.

Use a LocalDataCluster and make the on_off attribute unsupported so ZHA doesn't create one (just marking the on_off attribute as unsupported)

I like this one.

Have both entities (temporarily)

It's ugly but might give time to people to switch and avoid a hack down the years. Since people will need to re-add or reconfigure the device anyway, we just need to tell them somehow it will disappear one day but I don't know how we can do that. We would also need to tell them to not use the on_off.

There was also this option you suggested with the least impact :

Redirecting attribute reports from the custom Hue cluster to the OnOff cluster would get those 15 minute interval reports to come through. Depending on the implementation, it may also allow for manual polling.

The hardest I guess, will also create a forever hack?

Since we are producing new entities and require a reconfiguration or re-add of the device to make everything work properly anyway I think the LocalDataCluster route would be the most interesting until something more official handle it.

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