zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
728 stars 675 forks source link

[Device Support Request] - SIN-4-FP-21_EQU #2777

Open APCM-1 opened 10 months ago

APCM-1 commented 10 months ago

Problem description

I have a Pilot wire heating module (Leroy Merlin version) and I want to control it via ZHA.

Brand : ADEO Model : SIN-4-FP-21_EQU

3624961

At the moment we don't have mode handling, only On and Off (Hors Gel) with power measurement.

Some people seems to have handle this module with Z2M but not ZHA.

https://www.zigbee2mqtt.io/devices/SIN-4-FP-21_EQU.html

https://github.com/Koenkk/zigbee2mqtt/issues/19169

Solution description

We need to have mode handling. There are 6 modes : confort, confort -1, confort -2, eco, Hors Gel, Off.

Screenshots/Video

Screenshots/Video ![Capture d'écran 2023-11-27 161003](https://github.com/zigpy/zha-device-handlers/assets/141181269/6c43cb65-fdf5-4d3f-8730-e81db0959d95)

Device signature

Device signature ```json { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4727, maximum_buffer_size=82, maximum_incoming_transfer_size=500, server_mask=11264, maximum_outgoing_transfer_size=500, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0702", "0x1000", "0xfc00" ], "output_clusters": [ "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0066", "input_clusters": [ "0x0021" ], "output_clusters": [ "0x0021" ] } }, "manufacturer": "Adeo", "model": "SIN-4-FP-21_EQU", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant Supervised", "version": "2023.11.3", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.6", "docker": true, "arch": "aarch64", "timezone": "Europe/Paris", "os_name": "Linux", "os_version": "6.1.24-v8+", "supervisor": "2023.11.3", "host_os": "Debian GNU/Linux 11 (bullseye)", "docker_version": "24.0.7", "chassis": "", "run_as_root": true }, "custom_components": { "hacs": { "version": "1.33.0", "requirements": [ "aiogithubapi>=22.10.1" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp", "universal_silabs_flasher" ], "requirements": [ "bellows==0.36.8", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.106", "zigpy-deconz==0.21.1", "zigpy==0.59.0", "zigpy-xbee==0.19.0", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.6", "universal-silabs-flasher==0.0.14", "pyserial-asyncio-fast==0.11" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_uzg-01._tcp.local.", "name": "uzg-01*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 41678, "manufacturer": "Adeo", "model": "SIN-4-FP-21_EQU", "name": "Adeo SIN-4-FP-21_EQU", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "quirk_id": null, "manufacturer_code": 4727, "power_source": "Mains", "lqi": 176, "rssi": -56, "last_seen": "2023-11-27T16:20:28", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4727, maximum_buffer_size=82, maximum_incoming_transfer_size=500, server_mask=11264, maximum_outgoing_transfer_size=500, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0702", "0x1000", "0xfc00" ], "output_clusters": [ "0x0019" ] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0066", "input_clusters": [ "0x0021" ], "output_clusters": [ "0x0021" ] } }, "manufacturer": "Adeo", "model": "SIN-4-FP-21_EQU" }, "active_coordinator": false, "entities": [ { "entity_id": "button.chauffage_chambres_identifier", "name": "Adeo SIN-4-FP-21_EQU" }, { "entity_id": "sensor.chauffage_chambres_demande_instantanee", "name": "Adeo SIN-4-FP-21_EQU" }, { "entity_id": "sensor.chauffage_chambres_summation_delivered", "name": "Adeo SIN-4-FP-21_EQU" }, { "entity_id": "switch.chauffage_chambres_commutateur", "name": "Adeo SIN-4-FP-21_EQU" }, { "entity_id": "select.chauffage_chambres_comportement_au_demarrage", "name": "Adeo SIN-4-FP-21_EQU" } ], "neighbors": [ { "device_type": "Coordinator", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0000", "permit_joining": "Unknown", "depth": "0", "lqi": "154" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x1E44", "permit_joining": "Unknown", "depth": "15", "lqi": "114" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x2D56", "permit_joining": "Unknown", "depth": "15", "lqi": "122" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x56B7", "permit_joining": "Unknown", "depth": "15", "lqi": "108" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x88C4", "permit_joining": "Unknown", "depth": "15", "lqi": "88" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x9E18", "permit_joining": "Unknown", "depth": "15", "lqi": "109" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xCF76", "permit_joining": "Unknown", "depth": "15", "lqi": "125" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xD40F", "permit_joining": "Unknown", "depth": "15", "lqi": "123" } ], "routes": [ { "dest_nwk": "0x0000", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x0000" }, { "dest_nwk": "0xAB2E", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xAB2E" }, { "dest_nwk": "0xCF76", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x1E44" }, { "dest_nwk": "0x56B7", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x56B7" }, { "dest_nwk": "0xD40F", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xD40F" } ], "endpoint_names": [ { "name": "SMART_PLUG" }, { "name": "COMBO_BASIC" } ], "user_given_name": "Chauffage Chambres", "device_reg_id": "50237090f1dac5121b7c9eb9b8bdf801", "area_id": "chambre", "cluster_details": { "1": { "device_type": { "name": "SMART_PLUG", "id": 81 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "Adeo" }, "0x0005": { "attribute_name": "model", "value": "SIN-4-FP-21_EQU" } }, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 1 }, "0x4003": { "attribute_name": "start_up_on_off", "value": 255 } }, "unsupported_attributes": {} }, "0x0702": { "endpoint_attribute": "smartenergy_metering", "attributes": { "0x0000": { "attribute_name": "current_summ_delivered", "value": 39737 }, "0x0304": { "attribute_name": "demand_formatting", "value": 19 }, "0x0302": { "attribute_name": "divisor", "value": 1000 }, "0x0400": { "attribute_name": "instantaneous_demand", "value": 1028 }, "0x0306": { "attribute_name": "metering_device_type", "value": 0 }, "0x0301": { "attribute_name": "multiplier", "value": 1 }, "0x0200": { "attribute_name": "status", "value": 0 }, "0x0303": { "attribute_name": "summation_formatting", "value": 59 }, "0x0300": { "attribute_name": "unit_of_measure", "value": 0 } }, "unsupported_attributes": { "0x0100": { "attribute_name": "current_tier1_summ_delivered" }, "0x0102": { "attribute_name": "current_tier2_summ_delivered" }, "0x0104": { "attribute_name": "current_tier3_summ_delivered" }, "0x0106": { "attribute_name": "current_tier4_summ_delivered" }, "0x0108": { "attribute_name": "current_tier5_summ_delivered" }, "0x010a": { "attribute_name": "current_tier6_summ_delivered" } } }, "0x1000": { "endpoint_attribute": "lightlink", "attributes": {}, "unsupported_attributes": {} }, "0xfc00": { "endpoint_attribute": "manufacturer_specific", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "242": { "device_type": { "name": "COMBO_BASIC", "id": 102 }, "profile_id": 41440, "in_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

Logs ```python [Paste the logs here] ```

Custom quirk

Custom quirk ```python [Paste your custom quirk here] ```

Additional information

No response

ConteZer0 commented 10 months ago

Hello, i have those devices since a couple of days. I'm using Deconz (Phoscon) to add device to my zigbee network: devices are recognized as Lamp in Phoscon and i can only On and Off but without power measurement. So there is also no Power Measurement in Home Assistant (ZHA). What have you done to see power measurement please?

Capture d'écran 2023-11-29 105128

APCM-1 commented 10 months ago

Hello,

I just paired modules to Home Assistant and they were recognized as a socket and the consumption information came automatically

ConteZer0 commented 10 months ago

Ok thanks. I finally removed DeconZ and i replaced it with ZHA. I have now "Commutateur", "Demande instantanée" and "Summation delivered" but not "Consommation chauffage". Is it usefull?

APCM-1 commented 10 months ago

Oh yes sorry this one is a manual entry to know how much consumption I have each day

ConteZer0 commented 10 months ago

Great! Can you explain me how to do that please?

romain563 commented 9 months ago

I'm also interested. It will be interesting to check if the device is the same with SIN-4-fp-21 because they are both made by nodon

Ce post m'intéresse aussi. Il serait intéressant de voir si un développement peut permettre de faire fonctionner la référence du fabricant Nodon: la sin-4-fp-21

APCM-1 commented 9 months ago

Great! Can you explain me how to do that please?

Into parameters, in entries tab, create a new one, you need to choose a utiliy meter (water, electricity) in french its "Compteur de services publics (eau, gaz, électricité…)" and set the same parameters as the screenshot

Capture

APCM-1 commented 9 months ago

I'm also interested. It will be interesting to check if the device is the same with SIN-4-fp-21 because they are both made by nodon

Ce post m'intéresse aussi. Il serait intéressant de voir si un développement peut permettre de faire fonctionner la référence du fabricant Nodon: la sin-4-fp-21

I think it's the same, I see somewhere else on github that people reference the SIN-4-FP-21 as the same device as the SIN-4-FP-21_EQU.

ConteZer0 commented 9 months ago

Great! Can you explain me how to do that please?

Into parameters, in entries tab, create a new one, you need to choose a utiliy meter (water, electricity) in french its "Compteur de services publics (eau, gaz, électricité…)" and set the same parameters as the screenshot

Capture

Thnaks!!

stadros83 commented 8 months ago

Any news on this ? Is everything working with ZHA ?

APCM-1 commented 8 months ago

Any news on this ? Is everything working with ZHA ?

Hi,

I asked directly the manufecturer for information. For Z2M the integration will be available in late January but for ZHA it will be available later.

anoril1979 commented 7 months ago

I flag here to follow. I have several of these modules on my heaters and I would like more that consumption and on/off. :)

popof1664 commented 7 months ago

hi, I am also interested in this integration under ZHA: the SIN-4-FP-21 boxes seem very good, I am waiting to be able to control my radiators with them.

laur3nt95 commented 7 months ago

Same issue here. added yesterday to HA through ZHA, it shows a switch toggle, and consumption, but no control to the heater. I aslo have to mention that the "switch" part of the module has no effect on y heater, which is kind of weird to me.

seb-tinet commented 7 months ago

Hi i've asked to Nodon's support and they told me the ZHA intégration is on the pipe and it will be released in the coming weeks. Seb

Le ven. 1 mars 2024, 10:10, laur3nt95 @.***> a écrit :

Same issue here. added yesterday to HA through ZHA, it shows a switch toggle, and consumption, but no control to the heater. I aslo have to mention that the "switch" part of the module has no effect on y heater, which is kind of weird to me.

— Reply to this email directly, view it on GitHub https://github.com/zigpy/zha-device-handlers/issues/2777#issuecomment-1972799249, or unsubscribe https://github.com/notifications/unsubscribe-auth/A6BFTUPNNVFWJL37I4AENT3YWBAXHAVCNFSM6AAAAAA74GUVVWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNZSG44TSMRUHE . You are receiving this because you are subscribed to this thread.Message ID: @.***>

Skunnyk commented 6 months ago

Hi,

I have a SIN-4-FP-21 (the one from Nodon), and I am able to use it with ZHA, via zha_toolkit, with the help of https://github.com/Koenkk/zigbee2mqtt/issues/19169#issuecomment-1801181411 .

You can use zha_toolkit.scan_device to scan your zigbee device for all its informations, and look at the "Manufacture specific" cluster_id:

        "0xfc00": {
          "cluster_id": "0xfc00",
          "title": "Manufacturer Specific",
          "name": "manufacturer_specific",
          "attributes": {
            "0x0000": {
              "attribute_id": "0x0000",
              "attribute_name": "0",
              "value_type": [
                "0x20",
                "uint8_t",
                "Analog"
              ],
              "access": "READ|WRITE|REPORT",
              "access_acl": 7,
              "manf_id": 4747,
              "attribute_value": 1
            }
          },
          "commands_received": {},
          "commands_generated": {}
        }

Now you can send command to the module:

service: zha_toolkit.attr_write
data:
  ieee: xx:xx:xx:xx:xx:xx # your sin-4-fp-21 module id
  manf: 4747 # 0x128b, nodon
  endpoint: 1
  cluster: 64512 # 0xfc00
  attribute: 0 # which attribute we want to write, only 0 / 0x0000 is available in this cluster
  attr_val: "1" # 1: Confort, 2: Eco, 3: Hors Gel, see https://github.com/Koenkk/zigbee2mqtt/issues/19169#issuecomment-1801181411

Et voila©®, you can now integrate it in custom configuration in HA.

I hope this can help you, until Nodon/ZHA-device-handlers integrate this natively :)

Mysticronos commented 6 months ago

They just changed their support page with devices compatibility... Bad news for SIN-4-FP-21, it seems that HA is through Z2M only...

image

steenlarsen commented 6 months ago

Does anybody know if the information above can be used to write a Quirk for ZHA? This would avoid the need for installing zha_toolkit.

Btw. Thanks a lot @Skunnyk for finding this information!

oxillo commented 4 months ago

I've posted a quirk in #3040 that may also support ADEO variant. Feel free to test.

garc33 commented 1 week ago

Hello I made some adaptations of Nodon quirk in #3040 to make it working with Adeo device. Here is the code of custom quirk working for me:

"""Adeo SIN-4-FP-21_EQU pilot wire module."""
from typing import Any, Final
from zigpy.quirks import CustomCluster
from zigpy.quirks.v2 import QuirkBuilder, EntityType, EntityPlatform
from zigpy.zcl.foundation import (
    BaseAttributeDefs,
    BaseCommandDefs,
    ZCLAttributeDef,
    ZCLCommandDef,
    WriteAttributesStatusRecord,
    Status
)

from zigpy.zcl import ClusterType

import zigpy.types as t

import logging
_LOGGER = logging.getLogger(__name__)

class NodonPilotWireMode(t.enum16):
    OFF = 0x00
    COMFORT = 0x01
    ECO = 0x02
    FROST_PROTECTION = 0x03
    COMFORT_MINUS_1 = 0x04
    COMFORT_MINUS_2 = 0x05

NODON_PILOT_WIRE_CLUSTER_ID = 0xfc00  #64512

class NodonPilotWireCluster(CustomCluster):
    """NodOn pilot wire manufacturer-specific cluster."""

    cluster_id: Final = NODON_PILOT_WIRE_CLUSTER_ID
    name: Final = "Pilot Wire"
    ep_attribute: Final = "pilot_wire_cluster"
    manufacturer_id_override: Final = 4747

    class AttributeDefs(BaseAttributeDefs):
        pilot_wire_mode: Final = ZCLAttributeDef(
            id=0x0000, 
            type=NodonPilotWireMode, 
            access="r"
        )

    class ClientCommandDefs(BaseCommandDefs):
        setMode: Final = ZCLCommandDef(
            id=0x0000,
            schema={"mode": NodonPilotWireMode},
            direction=True,
            is_manufacturer_specific=True
        )

    async def write_attributes(
        self, attributes: dict[str | int, Any], manufacturer: int | None = None
    ) -> list:
        """Override writes to the pilot_wire_mode attribute."""
        if "pilot_wire_mode" in attributes:
            await self.client_command(0, attributes.get("pilot_wire_mode"), manufacturer=4747)
            await self.read_attributes(attributes)
            return [[WriteAttributesStatusRecord(Status.SUCCESS)]]
        return await super().write_attributes(attributes, manufacturer=4747)

    async def read_attributes(
        self,
        attributes: list[int | str],
        allow_cache: bool = False,
        only_cache: bool = False,
        manufacturer: int | t.uint16_t | None = None,
    ) -> Any:
        return await super().read_attributes(attributes, allow_cache=False, only_cache=False, manufacturer=4747)

(

    QuirkBuilder("ADEO", "SIN-4-FP-21_EQU")
    .also_applies_to("Adeo","SIN-4-FP-21_EQU")
    .replaces(NodonPilotWireCluster)
    .enum("pilot_wire_mode",NodonPilotWireMode,NODON_PILOT_WIRE_CLUSTER_ID,
        ClusterType.Server,1,EntityType.STANDARD,EntityPlatform.SELECT,False,True)
    .add_to_registry()
)
anoril1979 commented 1 week ago

Will test it ASAP! THANKS!

Mookunicorn commented 1 week ago

Hello I made some adaptations of Nodon quirk in #3040 to make it working with Adeo device. Here is the code of custom quirk working for me:

"""Adeo SIN-4-FP-21_EQU pilot wire module."""
from typing import Any, Final
from zigpy.quirks import CustomCluster
from zigpy.quirks.v2 import QuirkBuilder, EntityType, EntityPlatform
from zigpy.zcl.foundation import (
    BaseAttributeDefs,
    BaseCommandDefs,
    ZCLAttributeDef,
    ZCLCommandDef,
    WriteAttributesStatusRecord,
    Status
)

from zigpy.zcl import ClusterType

import zigpy.types as t

import logging
_LOGGER = logging.getLogger(__name__)

class NodonPilotWireMode(t.enum16):
    OFF = 0x00
    COMFORT = 0x01
    ECO = 0x02
    FROST_PROTECTION = 0x03
    COMFORT_MINUS_1 = 0x04
    COMFORT_MINUS_2 = 0x05

NODON_PILOT_WIRE_CLUSTER_ID = 0xfc00  #64512

class NodonPilotWireCluster(CustomCluster):
    """NodOn pilot wire manufacturer-specific cluster."""

    cluster_id: Final = NODON_PILOT_WIRE_CLUSTER_ID
    name: Final = "Pilot Wire"
    ep_attribute: Final = "pilot_wire_cluster"
    manufacturer_id_override: Final = 4747

    class AttributeDefs(BaseAttributeDefs):
        pilot_wire_mode: Final = ZCLAttributeDef(
            id=0x0000, 
            type=NodonPilotWireMode, 
            access="r"
        )

    class ClientCommandDefs(BaseCommandDefs):
        setMode: Final = ZCLCommandDef(
            id=0x0000,
            schema={"mode": NodonPilotWireMode},
            direction=True,
            is_manufacturer_specific=True
        )

    async def write_attributes(
        self, attributes: dict[str | int, Any], manufacturer: int | None = None
    ) -> list:
        """Override writes to the pilot_wire_mode attribute."""
        if "pilot_wire_mode" in attributes:
            await self.client_command(0, attributes.get("pilot_wire_mode"), manufacturer=4747)
            await self.read_attributes(attributes)
            return [[WriteAttributesStatusRecord(Status.SUCCESS)]]
        return await super().write_attributes(attributes, manufacturer=4747)

    async def read_attributes(
        self,
        attributes: list[int | str],
        allow_cache: bool = False,
        only_cache: bool = False,
        manufacturer: int | t.uint16_t | None = None,
    ) -> Any:
        return await super().read_attributes(attributes, allow_cache=False, only_cache=False, manufacturer=4747)

(

    QuirkBuilder("ADEO", "SIN-4-FP-21_EQU")
    .also_applies_to("Adeo","SIN-4-FP-21_EQU")
    .replaces(NodonPilotWireCluster)
    .enum("pilot_wire_mode",NodonPilotWireMode,NODON_PILOT_WIRE_CLUSTER_ID,
        ClusterType.Server,1,EntityType.STANDARD,EntityPlatform.SELECT,False,True)
    .add_to_registry()
)

Shouldn't the last part with "QuirkBuilder" be like this?

(

    QuirkBuilder("ADEO", "SIN-4-FP-21_EQU")
    .also_applies_to("NodOn","SIN-4-FP-21")
    .replaces(NodonPilotWireCluster)
    .enum("pilot_wire_mode",NodonPilotWireMode,NODON_PILOT_WIRE_CLUSTER_ID,
        ClusterType.Server,1,EntityType.STANDARD,EntityPlatform.SELECT,False,True)
    .add_to_registry()
)
garc33 commented 1 week ago

I’m not sure the manufacturer override works for nodon device. Furthermore the name of manufacturer in signature is Adeo not ADEO on my setup. I don’t it is always the case or not.