Support different firmware versions in ZHA quirk

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"
}