I’ve made a custom quirk for one of my devices, that I am looking to implement in ZHA. The device has recently been modified heavily in the firmware, so it matches the Zigbee standard a bit better. My device doesn’t support OTA, so I need to be able to achieve the same using already existing devices on the old firmware. I thought about looking at the date_code, but by investigating, I need to call those async, and I’m not sure if that’s possible with the signature.
I’m guessing I need to have two signatures and one replacement, but the documentation doesn’t help me much, and neither does existing quirks. Any help is greatly appreciated!
My custom device:
class QUAD_ZIG_SW(CustomDevice):
def __init__(self, *args, **kwargs):
"""Init device."""
super().__init__(*args, **kwargs)
signature = {
MODELS_INFO: [("smarthjemmet.dk", MODEL_ID)],
ENDPOINTS: {
# <SimpleDescriptor endpoint=1 profile=260 device_type=65535
# input_clusters=[0, 1, 7]
# output_clusters=[0, 1, 18, 6]>
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [Basic.cluster_id, PowerConfiguration.cluster_id, OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [Basic.cluster_id, PowerConfiguration.cluster_id, CustomMultistateInputCluster.cluster_id, OnOff.cluster_id],
},
# <SimpleDescriptor endpoint=2 profile=260 device_type=65535
# input_clusters=[7]
# output_clusters=[18, 6]>
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id, OnOff.cluster_id],
},
# <SimpleDescriptor endpoint=3 profile=260 device_type=65535
# input_clusters=[7]
# output_clusters=[18, 6]>
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id, OnOff.cluster_id],
},
# <SimpleDescriptor endpoint=4 profile=260 device_type=65535
# input_clusters=[7]
# output_clusters=[18, 6]>
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id, OnOff.cluster_id],
},
# <SimpleDescriptor endpoint=5 profile=260 device_type=65535
# input_clusters=[7]
# output_clusters=[18, 6]>
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id, OnOff.cluster_id],
}
},
}
replacement = {
SKIP_CONFIGURATION: True,
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [Basic.cluster_id, CR2032PowerConfigurationCluster],
OUTPUT_CLUSTERS: [Basic.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [CustomMultistateInputCluster, OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [CustomMultistateInputCluster, OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [CustomMultistateInputCluster, OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [CustomMultistateInputCluster, OnOffConfiguration.cluster_id],
OUTPUT_CLUSTERS: [CustomMultistateInputCluster.cluster_id],
}
},
}
device_automation_triggers = {
(SHORT_PRESS, "button_1"): {COMMAND: COMMAND_SINGLE, ENDPOINT_ID: 2},
(DOUBLE_PRESS, "button_1"): {COMMAND: COMMAND_DOUBLE, ENDPOINT_ID: 2},
(TRIPLE_PRESS, "button_1"): {COMMAND: COMMAND_TRIPLE, ENDPOINT_ID: 2},
(LONG_PRESS, "button_1"): {COMMAND: COMMAND_HOLD, ENDPOINT_ID: 2},
(LONG_RELEASE, "button_1"): {COMMAND: COMMAND_RELEASE, ENDPOINT_ID: 2},
(SHORT_PRESS, "button_2"): {COMMAND: COMMAND_SINGLE, ENDPOINT_ID: 3},
(DOUBLE_PRESS, "button_2"): {COMMAND: COMMAND_DOUBLE, ENDPOINT_ID: 3},
(TRIPLE_PRESS, "button_2"): {COMMAND: COMMAND_TRIPLE, ENDPOINT_ID: 3},
(LONG_PRESS, "button_2"): {COMMAND: COMMAND_HOLD, ENDPOINT_ID: 3},
(LONG_RELEASE, "button_2"): {COMMAND: COMMAND_RELEASE, ENDPOINT_ID: 3},
(SHORT_PRESS, "button_3"): {COMMAND: COMMAND_SINGLE, ENDPOINT_ID: 4},
(DOUBLE_PRESS, "button_3"): {COMMAND: COMMAND_DOUBLE, ENDPOINT_ID: 4},
(TRIPLE_PRESS, "button_3"): {COMMAND: COMMAND_TRIPLE, ENDPOINT_ID: 4},
(LONG_PRESS, "button_3"): {COMMAND: COMMAND_HOLD, ENDPOINT_ID: 4},
(LONG_RELEASE, "button_3"): {COMMAND: COMMAND_RELEASE, ENDPOINT_ID: 4},
(SHORT_PRESS, "button_4"): {COMMAND: COMMAND_SINGLE, ENDPOINT_ID: 5},
(DOUBLE_PRESS, "button_4"): {COMMAND: COMMAND_DOUBLE, ENDPOINT_ID: 5},
(TRIPLE_PRESS, "button_4"): {COMMAND: COMMAND_TRIPLE, ENDPOINT_ID: 5},
(LONG_PRESS, "button_4"): {COMMAND: COMMAND_HOLD, ENDPOINT_ID: 5},
(LONG_RELEASE, "button_4"): {COMMAND: COMMAND_RELEASE, ENDPOINT_ID: 5}
}
Old firmware 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": 4447,
"maximum_buffer_size": 80,
"maximum_incoming_transfer_size": 160,
"server_mask": 0,
"maximum_outgoing_transfer_size": 160,
"descriptor_capability_field": 0
},
"endpoints": {
"1": {
"profile_id": "0x0104",
"device_type": "0xfffe",
"input_clusters": [
"0x0000",
"0x0001",
"0x0007"
],
"output_clusters": [
"0x0000",
"0x0001",
"0x0012"
]
},
"2": {
"profile_id": "0x0104",
"device_type": "0xfffe",
"input_clusters": [
"0x0007"
],
"output_clusters": [
"0x0012"
]
},
"3": {
"profile_id": "0x0104",
"device_type": "0xfffe",
"input_clusters": [
"0x0007"
],
"output_clusters": [
"0x0012"
]
},
"4": {
"profile_id": "0x0104",
"device_type": "0xfffe",
"input_clusters": [
"0x0007"
],
"output_clusters": [
"0x0012"
]
},
"5": {
"profile_id": "0x0104",
"device_type": "0xfffe",
"input_clusters": [
"0x0007"
],
"output_clusters": [
"0x0012"
]
}
},
"manufacturer": "smarthjemmet.dk",
"model": "QUAD-ZIG-SW",
"class": "zigpy.device.Device"
}
New firmware 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": 4447,
"maximum_buffer_size": 80,
"maximum_incoming_transfer_size": 160,
"server_mask": 0,
"maximum_outgoing_transfer_size": 160,
"descriptor_capability_field": 0
},
"endpoints": {
"1": {
"profile_id": "0x0104",
"device_type": "0x0006",
"input_clusters": [
"0x0000",
"0x0001"
],
"output_clusters": [
"0x0000"
]
},
"2": {
"profile_id": "0x0104",
"device_type": "0x0006",
"input_clusters": [
"0x0007",
"0x0012"
],
"output_clusters": [
"0x0012"
]
},
"3": {
"profile_id": "0x0104",
"device_type": "0x0006",
"input_clusters": [
"0x0007",
"0x0012"
],
"output_clusters": [
"0x0012"
]
},
"4": {
"profile_id": "0x0104",
"device_type": "0x0006",
"input_clusters": [
"0x0007",
"0x0012"
],
"output_clusters": [
"0x0012"
]
},
"5": {
"profile_id": "0x0104",
"device_type": "0x0006",
"input_clusters": [
"0x0007",
"0x0012"
],
"output_clusters": [
"0x0012"
]
}
},
"manufacturer": "smarthjemmet.dk",
"model": "QUAD-ZIG-SW",
"class": "QUAD-ZIG-SW.QUAD_ZIG_SW"
}