[Device Support Request] RTX Zigbee Tuya ZIR aka. TS1201

Is your feature request related to a problem? Please describe.
Adding support for Tuya TS1201 link: https://allegro.pl/oferta/uniwersalny-pilot-ir-tuya-zigbee-smart-remote-360-11845030905
Describe the solution you'd like
Everything is described at https://github.com/Koenkk/zigbee2mqtt/issues/11633

Device signature
{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": 260,
      "device_type": "0xf000",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0xe004",
        "0xed00"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "242": {
      "profile_id": 41440,
      "device_type": "0x0061",
      "in_clusters": [],
      "out_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "_TZ3290_7v1k4vufotpowp9z",
  "model": "TS1201",
  "class": "zigpy.device.Device"
}

Diagnostic information
{
  "home_assistant": {
    "installation_type": "Home Assistant OS",
    "version": "2022.8.1",
    "dev": false,
    "hassio": true,
    "virtualenv": false,
    "python_version": "3.10.5",
    "docker": true,
    "arch": "x86_64",
    "timezone": "Europe/Warsaw",
    "os_name": "Linux",
    "os_version": "5.15.55",
    "supervisor": "2022.07.0",
    "host_os": "Home Assistant OS 8.4",
    "docker_version": "20.10.14",
    "chassis": "vm",
    "run_as_root": true
  },
  "custom_components": {},
  "integration_manifest": {
    "domain": "zha",
    "name": "Zigbee Home Automation",
    "config_flow": true,
    "documentation": "https://www.home-assistant.io/integrations/zha",
    "requirements": [
      "bellows==0.31.2",
      "pyserial==3.5",
      "pyserial-asyncio==0.6",
      "zha-quirks==0.0.78",
      "zigpy-deconz==0.18.0",
      "zigpy==0.48.0",
      "zigpy-xbee==0.15.0",
      "zigpy-zigate==0.9.0",
      "zigpy-znp==0.8.1"
    ],
    "usb": [
      {
        "vid": "10C4",
        "pid": "EA60",
        "description": "*2652*",
        "known_devices": [
          "slae.sh cc2652rb stick"
        ]
      },
      {
        "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"
        ]
      }
    ],
    "codeowners": [
      "@dmulcahey",
      "@adminiuga",
      "@puddly"
    ],
    "zeroconf": [
      {
        "type": "_esphomelib._tcp.local.",
        "name": "tube*"
      },
      {
        "type": "_zigate-zigbee-gateway._tcp.local.",
        "name": "*zigate*"
      }
    ],
    "after_dependencies": [
      "onboarding",
      "usb",
      "zeroconf"
    ],
    "iot_class": "local_polling",
    "loggers": [
      "aiosqlite",
      "bellows",
      "crccheck",
      "pure_pcapy3",
      "zhaquirks",
      "zigpy",
      "zigpy_deconz",
      "zigpy_xbee",
      "zigpy_zigate",
      "zigpy_znp"
    ],
    "is_built_in": true
  },
  "data": {
    "ieee": "**REDACTED**",
    "nwk": 8650,
    "manufacturer": "_TZ3290_7v1k4vufotpowp9z",
    "model": "TS1201",
    "name": "_TZ3290_7v1k4vufotpowp9z TS1201",
    "quirk_applied": false,
    "quirk_class": "zigpy.device.Device",
    "manufacturer_code": 4098,
    "power_source": "Mains",
    "lqi": 99,
    "rssi": null,
    "last_seen": "2022-08-09T15:39:04",
    "available": true,
    "device_type": "Router",
    "signature": {
      "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": 260,
          "device_type": "0xf000",
          "in_clusters": [
            "0x0000",
            "0x0003",
            "0x0004",
            "0x0005",
            "0x0006",
            "0xe004",
            "0xed00"
          ],
          "out_clusters": [
            "0x000a",
            "0x0019"
          ]
        },
        "242": {
          "profile_id": 41440,
          "device_type": "0x0061",
          "in_clusters": [],
          "out_clusters": [
            "0x0021"
          ]
        }
      }
    },
    "active_coordinator": false,
    "entities": [
      {
        "entity_id": "button.uniwersalny_pilot_identifybutton",
        "name": "_TZ3290_7v1k4vufotpowp9z TS1201"
      },
      {
        "entity_id": "switch.uniwersalny_pilot_switch",
        "name": "_TZ3290_7v1k4vufotpowp9z TS1201"
      }
    ],
    "neighbors": [],
    "endpoint_names": [
      {
        "name": "undefined_0xf000"
      },
      {
        "name": "unknown 97 device_type of 0xa1e0 profile id"
      }
    ],
    "user_given_name": "Uniwersalny pilot ",
    "device_reg_id": "1fea9570578603f815e8598267a40c96",
    "area_id": "salon",
    "cluster_details": {
      "1": {
        "device_type": {
          "name": "undefined_0xf000",
          "id": 61440
        },
        "profile_id": 260,
        "in_clusters": {
          "0x0000": {
            "endpoint_attribute": "basic",
            "attributes": {
              "0x0004": {
                "attribute_name": "manufacturer",
                "value": "_TZ3290_7v1k4vufotpowp9z"
              },
              "0x0005": {
                "attribute_name": "model",
                "value": "TS1201"
              }
            },
            "unsupported_attributes": {}
          },
          "0x0004": {
            "endpoint_attribute": "groups",
            "attributes": {},
            "unsupported_attributes": {}
          },
          "0x0005": {
            "endpoint_attribute": "scenes",
            "attributes": {},
            "unsupported_attributes": {}
          },
          "0x0003": {
            "endpoint_attribute": "identify",
            "attributes": {},
            "unsupported_attributes": {}
          },
          "0xed00": {
            "endpoint_attribute": null,
            "attributes": {},
            "unsupported_attributes": {}
          },
          "0xe004": {
            "endpoint_attribute": null,
            "attributes": {},
            "unsupported_attributes": {}
          },
          "0x0006": {
            "endpoint_attribute": "on_off",
            "attributes": {
              "0x0000": {
                "attribute_name": "on_off",
                "value": 1
              }
            },
            "unsupported_attributes": {
              "0x4003": {
                "attribute_name": "start_up_on_off"
              }
            }
          }
        },
        "out_clusters": {
          "0x0019": {
            "endpoint_attribute": "ota",
            "attributes": {},
            "unsupported_attributes": {}
          },
          "0x000a": {
            "endpoint_attribute": "time",
            "attributes": {},
            "unsupported_attributes": {}
          }
        }
      },
      "242": {
        "device_type": {
          "name": "unknown",
          "id": 97
        },
        "profile_id": 41440,
        "in_clusters": {},
        "out_clusters": {
          "0x0021": {
            "endpoint_attribute": "green_power",
            "attributes": {},
            "unsupported_attributes": {}
          }
        }
      }
    }
  }
}

+1 Here!
This is also sold as Moes UFO-R11.
Would very much like to have support for this one.

+1!

Any updates on it ?

Hi, I'm working on it, learning mode is functional, I need to write the code to send IR frames.
I'll do a PR when it'll be finished.

Quirk is functional, here: https://github.com/ferehcarb/zha-device-handlers/blob/dev/zhaquirks/tuya/ts1201.py
Learning mode must be set with "Manage Zigbee Device":

When you click on "Issue Zigbee Command" the blue led on the device should light up.
Then, you press the button on your IR remote and the IR code is available in homeassistant logs, the blue led should turn down.
You can replay the IR code with:

Warning, very early code, I must clean up and better integrate it with HA.

Hey THX a lot for that. I am trying to follow your guide but i don't seem to get any codes in my logs. The blue LED lights up for about 20 seconds if I dont point a remote at it and even earlier if I do, but nothing in the logs. Do you mean the standard home-assistant.log, which is also shown in the settings?

Hey THX a lot for that. I am trying to follow your guide but i don't seem to get any codes in my logs. The blue LED lights up for about 20 seconds if I dont point a remote at it and even earlier if I do, but nothing in the logs. Do you mean the standard home-assistant.log, which is also shown in the settings?

Yes, in the standard logs, file /config/home-assistant.log, you should see "Command 0x05: Ir message really totally received:"  followed by the IR code (base64 encoded).
Your log config must be at least to info I think, I use debug for zha on my side:
logger:
  default: warning
  logs:
    homeassistant.components.zha: warning
    zigpy: debug
    custom_components.zha_toolkit: debug
    custom_zha_quirks: debug
    zhaquirks: debug

Thx, Zigpy logging must be info.

Here is a sample script to send a code:

alias: Vacuum Start
sequence:
  - service: zha.issue_zigbee_cluster_command
    data:
      cluster_type: in
      endpoint_id: 1
      command: 2
      ieee: 38:5b:44:ff:fe:33:11:8a
      command_type: server
      params:
        code: >-
          C7ILsgsfAskBHwLGBYADwAtAB+APA8ArwAfgDyfgIxfAS0AHQDdAB8ADB/pPsguyCx8C4AEXArMCBWCzB8kByQGzAskBQAGAH0AHCR8CyQHJAR8CxgXgBQNAE+A3A+ADU0BL4AMP4AmnAR8CwCNAB+APA0An4AMD4A8n4CMX4AdP4AMP4JWnBLMCxgUfYAPglacJHwLGBR8CxgUfAg==
      cluster_id: 57348
mode: single
icon: mdi:robot-vacuum

You will need to switch out the ieee as well as the code. The cluster_id was translated from 0xe004

@ranton1990 Is it working for your device ?
I developed the last pieces of code outside my home and didn't test it on a real device...

@ferehcarb Yes it is, I can successfully start my Robo Vacuum and send it back to its station.

Hi @ferehcarb i'm trying to use your quirk (first time for me, maybe i missed something), but i have the following errors on stratup :

Any ideas what i'm wrong ?

You have copy the URL for the quirk and not the real file so the system cant loading it.
In the GIT clicking on the file and the raw button and copy the raw data and saving it in your local quirk file then you doing getting the http things with.

Yes, no more error with the correct file :+1:
But when adding my device it is not using the quirk :
{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": 260,
      "device_type": "0xf000",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0xe004",
        "0xed00"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "242": {
      "profile_id": 41440,
      "device_type": "0x0061",
      "in_clusters": [],
      "out_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "_TZ3290_7v1k4vufotpowp9z",
  "model": "TS1201",
  "class": "zigpy.device.Device"
}

Then you must updating the signature in the quirk so it matching your device then the system can loading it.

Hi, the signature for "_TZ3290_7v1k4vufotpowp9z" is already in the quirk.
Did you specify the custom directory for quirks in your config ?

Yes, and i can see a "pycache" folder in my custom quirk folder.
I have delete and add again the device but still the same class.

@ferehcarb
Could this help ?

@ferehcarb I think the problem is this :
Checking quirks for _TZ3290_7v1k4vufotpowp9z TS1201 (dc:8e:95:ff:fe:f4:28:56)
Considering <class 'ts1201.ZosungIRBlaster'>
Fail because endpoint list mismatch: {1} {1, 242}

The signature of my device did not match the ENDPOINTS list in the quirk

Well seen.
Try to remove this lines:

https://github.com/ferehcarb/zha-device-handlers/blob/dev/zhaquirks/tuya/ts1201.py#L436
https://github.com/ferehcarb/zha-device-handlers/blob/dev/zhaquirks/tuya/ts1201.py#L457
It seems there isn't PowerConfiguration cluster on your device.

Arf... you have another endpoint (242) too.
You should add to "ENDPOINTS" dictionary signature I think.

I wasn't know quirks 2 days ago 😅
What should i add as endpoint for 242 ?for profil, device type and clusters ?

Neither me, I wasn't know what it was 2 months ago ;-)
I pushed a new version with your device signature, give it a try.

@ferehcarb Thx ! Seems to have worked :

I'll try with an IR remote tonigth at home or tomorow :)

Bye the way, now you can get the learned IR code with an attribute:

You don't need any more to catch it in the hommeassistant logs.

@ferehcarb I have this error when triggering the IRLearn :

And i cannot set the value to true :

What is this sorcery ?
Can you put zha in debug mode and post logs please ?
Something like this:
logger:
  default: warning
  logs:
    homeassistant.components.zha: debug
    zigpy: debug
    custom_components.zha_toolkit: debug
    custom_zha_quirks: debug
    zhaquirks: debug

I think related logs is there :
2023-03-15 09:33:40.442 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Received ZCL frame: b'\x08\x1a\n\x01\x00 F\xe2\xff \x1f\xe4\xff \x00'
2023-03-15 09:33:40.443 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=26, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2023-03-15 09:33:40.445 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Decoded ZCL frame: Basic:Report_Attributes(attribute_reports=[Attribute(attrid=0x0001, value=TypeValue(type=uint8_t, value=70)), Attribute(attrid=0xFFE2, value=TypeValue(type=uint8_t, value=31)), Attribute(attrid=0xFFE4, value=TypeValue(type=uint8_t, value=0))])
2023-03-15 09:33:40.446 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Received command 0x0A (TSN 26): Report_Attributes(attribute_reports=[Attribute(attrid=0x0001, value=TypeValue(type=uint8_t, value=70)), Attribute(attrid=0xFFE2, value=TypeValue(type=uint8_t, value=31)), Attribute(attrid=0xFFE4, value=TypeValue(type=uint8_t, value=0))])
2023-03-15 09:33:40.447 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Attribute report received: app_version=70, 0xFFE2=31, 0xFFE4=0
2023-03-15 09:33:40.450 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=26, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2023-03-15 09:33:40.451 DEBUG (MainThread) [zigpy.zcl] [0x56C3:1:0x0000] Sending reply: Default_Response(command_id=10, status=<Status.SUCCESS: 0>)
2023-03-15 09:33:42.645 DEBUG (MainThread) [homeassistant.components.zha.api] Requested attributes for: cluster_id: 57348, cluster_type: 'in', endpoint_id: 1, response: [{'id': 0, 'name': 'last_learned_ir_code'}]
2023-03-15 09:33:42.646 DEBUG (MainThread) [homeassistant.components.zha.api] Requested commands for: cluster_id: 57348, cluster_type: 'in', endpoint_id: 1, response: [{'type': 'server', 'id': 0, 'name': 'data'}, {'type': 'server', 'id': 1, 'name': 'IRLearn'}, {'type': 'server', 'id': 2, 'name': 'IRSend'}]
2023-03-15 09:33:44.091 DEBUG (MainThread) [zigpy.zcl] [0xC78F:1:0x0b04] Received ZCL frame: b'\x18\xf8\n\x0f\x05!\xac\r'
2023-03-15 09:33:44.092 DEBUG (MainThread) [zigpy.zcl] [0xC78F:1:0x0b04] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=248, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2023-03-15 09:33:44.093 DEBUG (MainThread) [zigpy.zcl] [0xC78F:1:0x0b04] Decoded ZCL frame: ElectricalMeasurement:Report_Attributes(attribute_reports=[Attribute(attrid=0x050F, value=TypeValue(type=uint16_t, value=3500))])
2023-03-15 09:33:44.093 DEBUG (MainThread) [zigpy.zcl] [0xC78F:1:0x0b04] Received command 0x0A (TSN 248): Report_Attributes(attribute_reports=[Attribute(attrid=0x050F, value=TypeValue(type=uint16_t, value=3500))])
2023-03-15 09:33:44.094 DEBUG (MainThread) [zigpy.zcl] [0xC78F:1:0x0b04] Attribute report received: apparent_power=3500
2023-03-15 09:33:45.028 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Received ZCL frame: b'\x08g\n\x00\x00\x10\x00'
2023-03-15 09:33:45.029 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=103, command_id=10, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2023-03-15 09:33:45.031 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Decoded ZCL frame: OnOff:Report_Attributes(attribute_reports=[Attribute(attrid=0x0000, value=TypeValue(type=Bool, value=<Bool.false: 0>))])
2023-03-15 09:33:45.031 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Received command 0x0A (TSN 103): Report_Attributes(attribute_reports=[Attribute(attrid=0x0000, value=TypeValue(type=Bool, value=<Bool.false: 0>))])
2023-03-15 09:33:45.032 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Attribute report received: on_off=<Bool.false: 0>
2023-03-15 09:33:45.033 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=103, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2023-03-15 09:33:45.034 DEBUG (MainThread) [zigpy.zcl] [0x9A87:1:0x0006] Sending reply: Default_Response(command_id=10, status=<Status.SUCCESS: 0>)
2023-03-15 09:33:48.677 DEBUG (MainThread) [zigpy.zcl] [0x7C0E:1:0xe004] Receive command with args: () and kwargs {}
2023-03-15 09:33:48.678 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140043253743920] 'on_off'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 200, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1738, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1775, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 746, in admin_handler
await result
File "/usr/src/homeassistant/homeassistant/components/zha/api.py", line 1273, in issue_zigbee_cluster_command
response = await zha_device.issue_cluster_command(
File "/usr/src/homeassistant/homeassistant/components/zha/core/device.py", line 677, in issue_cluster_command
response = await cluster.command(
File "/config/zha_quirks/ts1201.py", line 119, in command
if kwargs["on_off"]:
KeyError: 'on_off'

full log is here : https://gist.github.com/loclamor/07218efd03849c66696785f107f451aa

You can try to call the service with the "Developper Tools":

@ferehcarb I was not up-to-date... i'm now on Home Assistant 2023.3.4 :
Zigbee cluster :

cluster command :

Seems promizing... I will try soon !

Thank you for your work @ferehcarb !
I have manage to learn a code from my climatiser remote and succesfully emit it from ha ! 😍
now i have to manage an automation with all possible temperatures and fan speed, for heat and freeze 😅

Good news, thank you for your perseverance, we've got now another device supported by the quirk.
I think yours is not battery powered but by charger, right ?

@ferehcarb sadly yes !

Good news, I think it's time to create a PR.

Good news, I think it's time to create a PR.

I've tested this I'm having an issue with commands that require a long press it's only sending a short press anyway to fix this please?

@blair287 have you tried sending the same command in rapid succession? you could write a home assistant script that issues a set of zigbee cluster commands N times to simulate your key hold or long press. That's usually all that the remote is doing.

@blair287 have you tried sending the same command in rapid succession? you could write a home assistant script that issues a set of zigbee cluster commands N times to simulate your key hold or long press. That's usually all that the remote is doing.

Broadlink shows different commands for long and short but they aren't in tje same format this returns a short press even though your still holding the button

Not sure when it first happened, but today I noticed this while starting HA:
`2023-04-06 13:35:17.633 ERROR (MainThread) [zhaquirks] Unexpected exception importing custom quirk 'ts1201'
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/zhaquirks/init.py", line 418, in setup
importer.find_module(modname).load_module(modname)

File "", line 548, in _check_name_wrapper
File "", line 1063, in load_module
File "", line 888, in load_module
File "", line 290, in _load_module_shim
File "", line 719, in _load
File "", line 688, in _load_unlocked
File "", line 883, in exec_module
File "", line 241, in _call_with_frames_removed
File "/config/custom_zha_quirks/ts1201.py", line 53, in
class ZosungIRControl(CustomCluster):

File "/config/custom_zha_quirks/ts1201.py", line 65, in ZosungIRControl
0x00: foundation.ZCLCommandDef(

TypeError: ZCLCommandDef.init() got an unexpected keyword argument 'is_reply'`

After removing all is_reply lines in the py file, it works again perfectly.

After removing all is_reply lines in the py file, it works again perfectly.

We must replace is_reply=True by direction = Direction.Client_to_Server or something like this , and the invert for is_reply=False.
The zigbbe lib code has changed and dropped this attribute I think.
is_reply is necessary, otherwise, without it, frames from the devices are repeated and there is much delay to learn or send the IR code.

@ranton1990 , fixed with this commit

@ranton1990 , fixed with this commit

Any idea how to get long presses working at all?

Hi!
I have a similar zigbee IR Remote Controller. It looks different, but identifies as TS1201 by _TZ3290_ot6ewjvmejq5ekhl: https://www.ebay.com/itm/275310058694
I can confirm that it works with this custom quirk. I tried it with a Yamaha amplifier (power on/off and volume up/down). Both learning and sending IR codes.
Thank you for your work!

what did you do for the config after

Hi!
I have a similar zigbee IR Remote Controller. It looks different, but identifies as TS1201 by _TZ3290_ot6ewjvmejq5ekhl: https://www.ebay.com/itm/275310058694
I can confirm that it works with this custom quirk. I tried it with a Yamaha amplifier (power on/off and volume up/down). Both learning and sending IR codes.
Thank you for your work!

how did you configure the IR Blaster? I'm not sure what settings i need to select on all the drop down menus. I have the same blaster as you except its the Wired version.

Here is a sample script to send a code:
alias: Vacuum Start
sequence:

service: zha.issue_zigbee_cluster_command
data:
cluster_type: in
endpoint_id: 1
command: 2
ieee: 38:5b:44:ff:fe:33:11:8a
command_type: server
params:
code: >-
C7ILsgsfAskBHwLGBYADwAtAB+APA8ArwAfgDyfgIxfAS0AHQDdAB8ADB/pPsguyCx8C4AEXArMCBWCzB8kByQGzAskBQAGAH0AHCR8CyQHJAR8CxgXgBQNAE+A3A+ADU0BL4AMP4AmnAR8CwCNAB+APA0An4AMD4A8n4CMX4AdP4AMP4JWnBLMCxgUfYAPglacJHwLGBR8CxgUfAg==
cluster_id: 57348
mode: single
icon: mdi:robot-vacuum
You will need to switch out the ieee as well as the code. The cluster_id was translated from 0xe004

did you need to manage device before doing this or did you just add the device to ZHA and make that script?

I have this IR blaster:
https://www.aliexpress.com/item/1005003813684787.html?spm=a2g0o.order_list.order_list_main.15.575d1802a2M0rC
I am unable to get IR learn and IR send Clusters in any of these drop down menu's. How do I get this? I'm running the newest Home assistant update with a sky connect

@ranton1990 do you have a link to the one you have?

@ferehcarb I checked all in those drop down menus and I couldn't find it

@ferehcarb
I am unfortunately unable to get to the physical device and it's found on my network but unable to connect. I can access the logs but do you just need the IEEE and NWK?

@ferehcarb
I am unfortunately unable to get to the physical device and it's found on my network but unable to connect. I can access the logs but do you just need the IEEE and NWK?

No, I need the manufacturer code, like here and here .
If your manufacturer code is not in the list, it won't work.
The code is in the signature tab:

@ranton1990 do you have a link to the one you have?

Should be this one:
https://de.aliexpress.com/item/1005005230661089.html

Hi, does anyone know why if there a reason why the zha_toolkit : attr_read command can read the 'learned' IR code:

Logger: custom_components.zha_toolkit.zcl_attr
Source: custom_components/zha_toolkit/zcl_attr.py:303
Integration: 🧰 ZHA Toolkit (documentation, issues)
First occurred: 22:23:48 (2 occurrences)
Last logged: 22:28:14

Result: [ReadAttributeRecord(attrid=0x0000)] - Attribute 0 not in read ({0: 'DUAjlBEoAigCXQJ9Bl0CQAdAA8ALQAcDfQYoAoABgAuAD8ALAV0CgAsBXQKAAwUoAigCXQLAAwR9Bl0CKGABQAeAAwJ9BijgAAMBKAJADwldAt6cQCO5CCgC'}, [ReadAttributeRecord(attrid=0x0000)])```

More details in the issue I raised here: https://github.com/mdeweerd/zha-toolkit/issues/157

Hi, does anyone know if there a reason why the zha_toolkit : attr_read command can't read the 'learned' IR code:
....
More details in the issue I raised here: mdeweerd/zha-toolkit#157

Hi, I think the answer is in this comment, if you test the change and it's ok, tell it me, I'll update the code.

Yes, mdeweerd suggested change works for me.

Yes, mdeweerd suggested change works for me.

Quirk updated, thank you for the report.

@ferehcarb
I am unfortunately unable to get to the physical device and it's found on my network but unable to connect. I can access the logs but do you just need the IEEE and NWK?

No, I need the manufacturer code, like here and here .
If your manufacturer code is not in the list, it won't work.
The code is in the signature tab:

"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *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": 260,
"device_type": "0xf000",
"in_clusters": [
"0x0000",
"0x0003",
"0x0004",
"0x0005",
"0x0006",
"0xe004",
"0xed00"
],
"out_clusters": [
"0x000a",
"0x0019"
]
},
"242": {
"profile_id": 41440,
"device_type": "0x0061",
"in_clusters": [],
"out_clusters": [
"0x0021"
]
}
},
"manufacturer": "_TZ3290_acv1iuslxi3shaaj",
"model": "TS1201",
"class": "zigpy.device.Device

@Manbearpig92 quirk updated, give it a try.

Hi, I just got a Zigbee IR blaster but I'm lost with all these messages. I have a TS1201 too. In "Manage Zigbee Device", all I have is this:

I can't find how to get IR controls to appear. I was using Zigbee2MQTT before and it was working. Could someone help me please ? How can I add more "clusters" ?

I can't find how to get IR controls to appear. I was using Zigbee2MQTT before and it was working. Could someone help me please ? How can I add more "clusters" ?

Hi, in the signature you've got: "class": "zigpy.device.Device", it should be "class": "ts1201.ZosungIRBlaster"
I think the custom quirk is not used. Have you configured the path for custom quirks and put the file in the right place (ts1201.py) ?
Something like this in configuration.yaml:
zha:
  custom_quirks_path: /config/custom_zha_quirks/

Thanks a lot for the explaination, I've just added the file, and rebooted.
I now have the following in my list:

But I don't have any ZosungIRBlaster, is that normal ? I've choosed ZosungIRControl for now.
Is there further configuration to do ?

Ok apparently ts1201.ZosungIRBlaster quirk is correctly applied. Thanks a lot. But is there more things to do to have controls from the HA UI ? I would like to be able to send codes from a button on HA, or being able to send codes within automations.

Read the thread, you've got an example in this comment.

Ok apparently ts1201.ZosungIRBlaster quirk is correctly applied. Thanks a lot. But is there more things to do to have controls from the HA UI ? I would like to be able to send codes from a button on HA, or being able to send codes within automations.

Read the thread, you've got an example in this comment.

Hi, I just tried the script and it works very well. Thanks a lot for your help and your work, it's amazing.
I am curious if there is a tool to quickly create scripts like this ? I'm looking to have all the buttons for all my remotes and devices within HA, and use this sort of lovelace cards to control my devices : https://community.home-assistant.io/t/how-do-i-actually-make-a-tv-remote-control-work-well-in-the-gui/212392 . But did someone make a manager for it ? Maybe something similar to Logitech Harmony software ?
Have a great day

@ferehcarb I'm not sure if I am doing something incorrectly but i cant get my IR blaster to send a mute command to my soundbar. a few questions i have:
1. do i need to bind my blaster to my skyconnect? my ir blaster shows up on my zigbee network and says its connected but there is no bridge from the blaster to the sky connect unlike the other devices i have.

Sorry, I don't known how the skyconnect works.

2. i put in a hexidecimal code (mute) into the IRLearn and issued the ZigBee command. Is this necessary or will writing a script with the example in the comment above do what i just did?

Which code did you put ? You've to put the learned code from the blaster.
First you send an IRLearn command, push your remote's button and then you can read the code with the attribute last_learned_ir_code.

Neither me, I wasn't know what it was 2 months ago ;-) I pushed a new version with your device signature, give it a try.

Thanks this new quirk worked for me as well.

I want to make commands for the air conditioner. Tell me how to do this, and where to add the script file?

As I mentioned before, I am using this device and it works with this custom quirk:  https://www.ebay.com/itm/275310058694
Before I switched to this device I used a NodeMCU to generate infra signals using the IRremoteESP8266 library.
E.g to turn on/off my Samsung TV I used the sendSAMSUNG() method (https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp#L95) to send this code: E0E040BF.
Can you, please, explain how could I transform this code for this quirk?

Can you, please, explain how could I transform this code for this quirk?

You can't, the quirk has only one mode: learn an IR code from a remote and replay it.
It seems that the official tuya app has other modes but the protocol hasn't been reverse ingeneered.

Anyone know if this would ever be merged into the main branch?

@ferehcarb - thanks so much for making this quirk. New to HA and with a bit of playing got my MEOS UFO-R11 working to control my Air Con perfectly. Per migration into the main branch is there a way to make a Learn Code and Send Last Learnt Code UI button appear out of the box to encourage us newbies :) I would have given up without finding this thread. Cheers

Not sure if this is the right place to post.
What is the format of the Base64 code string? Is it possible to generate the Base64 from information such as these?

I was able to learn the codes via "manage Zigbee device" UI. But for some reason sending those via the IRsend command from the very same UI has no effect (I do see that it attempts to send it though, in the logs, the example below sends BS4jaREvAuAXAQGMBuAVA0ABwCNAAUAL4AMB4AMPwAtAB8ADCWSdLiOoCC8C code)...
 I got it all working (sending and receiving) by setting on_off to true.

This was fairly simple to implement, but doesn't (at least for me)  seems to be stable..  :neutral_face: It just randomly stops working and spits out:
Logger: zigpy_deconz.uart
Source: custom_zha_quirks/ts1201.py:305
First occurred: 18:35:35 (13 occurrences)
Last logged: 18:35:56

Unexpected error handling the frame
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/zigpy_deconz/uart.py", line 84, in data_received
    self._api.data_received(frame)
  File "/usr/local/lib/python3.11/site-packages/zigpy_deconz/api.py", line 373, in data_received
    getattr(self, f"_handle_{command.name}")(data)
  File "/usr/local/lib/python3.11/site-packages/zigpy_deconz/api.py", line 505, in _handle_aps_data_indication
    self._app.handle_rx(
  File "/usr/local/lib/python3.11/site-packages/zigpy_deconz/zigbee/application.py", line 460, in handle_rx
    self.packet_received(
  File "/usr/local/lib/python3.11/site-packages/zigpy/application.py", line 1006, in packet_received
    self.handle_message(
  File "/usr/local/lib/python3.11/site-packages/zigpy/application.py", line 522, in handle_message
    return sender.handle_message(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/zigpy/device.py", line 367, in handle_message
    self.endpoints[src_ep].handle_message(
  File "/usr/local/lib/python3.11/site-packages/zigpy/endpoint.py", line 235, in handle_message
    handler(hdr, args, dst_addressing=dst_addressing)
  File "/usr/local/lib/python3.11/site-packages/zigpy/zcl/__init__.py", line 424, in handle_message
    self.handle_cluster_request(hdr, args, dst_addressing=dst_addressing)
  File "/config/custom_zha_quirks/ts1201.py", line 305, in handle_cluster_request
    irmsg = self.endpoint.device.ir_msg_to_send[seq]
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
KeyError: 3

I get a feeling that this seems to be "more stable"/the issue is not occurring just after restarting Home Assistant for some reason.. 😕

I still have issues with this and trying to narrow it down, but with somewhat success. I can't say for sure, but I think the problem might be my somewhat rapid automation used to switch source on the TV. The automation below does the following:

Presses the Source button once.
Then presses down 9 times, with a slight delay of 1 second between the IR commands.
Finishing off by pressing the OK button, which selects the current selected HDMI source.

My theory goes that the device (perhaps more specific the battery-operated model) is meant to send a single command for e.g. change mode on an air conditioner, turn on the stereo amplifier etc, but when several commands are introduced in a row, it doesn't keep up and stops working (for a while).
alias: Living room - Change TV source to gaming console
description: ""
trigger: []
condition: []
mode: single
action:
  - if:
      - condition: and
        conditions:
          - condition: state
            entity_id: input_text.tv_source
            state: HDMI4
          - condition: device
            type: is_on
            device_id: e17b4a09a31ef45ae5fb212b75f65d7c
            entity_id: 4cf89d24d396a0ee2b20e1b1078864af
            domain: switch
    then:
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              B7IRshE5AoQG4AED4AsB4Bsf4BcB4AND4AcLB+23shGyETkC4AMX4AsB4Bsf4BcB4AND4AQLAgY5Ag==
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              CK8RrxEJArsGZyADgAcBCQJAA+ADAQFnAsAbQAcBZwLgAQNAAUAP4AcXwBPgAxdAC+ADA0AjQANAEwcPuK8RrxEJAkALwANAG+AHA8AbQAfgBxtAD+ALF0ATQANAH0ADQAvgAwMLZwIJAmcCCQK7BgkC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - service: zha.issue_zigbee_cluster_command
        data:
          cluster_type: in
          ieee: 94:34:69:ff:fe:5f:67:09
          command_type: server
          params:
            code: >-
              B7oRuhE1ApAG4AED4AsB4Bcf4AMBQCtAAUAHQANAAUAHwANAAUALwAFACwfat7oRuhE1AkALwAPgCwHAG0AH4BcBwCNAB0ADQAFAB8ADQAFAC8ABQAvgfIcCBjUC
          cluster_id: 57348
          endpoint_id: 1
          command: 2
      - service: input_text.set_value
        data:
          value: HDMI3
        target:
          entity_id: input_text.tv_source

Maybe the lastest HA update break somthing ?

You've got an old version of the quirk, it was fixed in this commit.
Update to the latest version.

Does somebody know whether it's somehow possible to simulate a button long press? When reading the IR command it just records the normal press command and compared to the Broadlink intregration (num_repeats attribute) this quirk and probably the device in general doesn't seem to support the direct repetition of commands. Will try to create a sequence which repeats the command 10-15 times to see whether that could emulate a long press of a button.

Thanks ferehcarb for delivering this great piece of code!
It's really a nice added-value to my HA automations
It gave me a chance to learn IR codes from my shutters remote
However, 2 points I'd like to share, on which you probably can provide a comment:
-) For every run of "IRLearn", I get a new code. Does not seem to be a problem though, but I expected it to be a fixed value all time
-) The "OPEN" command is perfectly reproduced, but I'm not able to replicate the "CLOSE" command. Doing the same exact procedure, but it does not work at all
If you have any idea or can shed light on this last point, I will greatly appreciate
Last attempts:
CLOSE (does not close the shutters !):
-) BTcDxwGIAcADF/sENwM3A5YG+wSIATcDiAGWBogBNwM3A0AHD8cBKgI3A4gBNwM3A4gBxwGAEwM3A8cBIAkOA4gBxwGIAYgBiAH7BIgB
-) BUUDygGIAcADFwcFRQNFA5AGBwWIAUUDiAGQBogBRQNFA0AHD2AC1QBFA4gBRQNFA8oBygFAEwGIAUALEZAGRQOIAcoBiAHKAYgBBwWIAQ==
OPEN (perfectly open the shutters)
-) BU4DwQGCAcADF/UE9QTBAa4G9QSCAU4DggGuBoIBTgNOA0AHCMEBggFOA04DwSAFA8EBggFAExP1BBUITgOCAcEBggFOA4IBggFOAw==
-)
A1kDmQGAAQvPAZkB6QTpBJkBqAZABUAZB6gGmQFZA1kDQAdAAQNZA1kDQAUDmQGZAUATA+kEGwiADQmZAVkDmQGZAVkD

I have add  : ("_TZ3290_gnl5a6a5xvql7c2a", "TS1201"), and works

Looking for some direction...I'm unable to learn any IR codes and bemused as to why...
Quirk is loaded.  I have no errors in the logs.  I'm using the Manage zigbee device; I can select ZosungIRControl cluster and it shows last learned attribute, but no values get populated.  I've tried using read attribute then pressing remote, tried remote separately to no avail.  I've turned on and off device from device control, in case it was 'disabled'  nothing seems to work...
All the remotes can be read by other learning devices so i know they are known TX codes.   I have 3 remotes to learn adn none register on the blaster.
Any ideas anyone?  Thanks in advance

The values appears in the Home assistant log

Thank you Drlabel fro replying; i was trying to use the read/write attribute/value per the Mar 14 comment on 'new feature' above, ratehr than looking on logs.   I am now a step closer.. using this helpful comment https://github.com/zigpy/zha-device-handlers/issues/1687#issuecomment-1671814503  i set/sent the IRlearn value to true command and could then read my remote.  I have errors saving/setting the attribute/value, probably my naivety, however will revert to yaml for my automation for now.   Thanks

Thank you Drlabel for replying; i was trying to use the read/write attribute/value per the Mar 14 comment on 'new feature' above, rather than looking on logs. I am now a step closer.. re-reading the thread and using #1687 (comment) and this helpful reminder comment #1687 (comment) i set/sent the IRlearn value to true command and could then read my remote. I have errors saving/setting the attribute/value, probably my naivety, however will revert to yaml for my automation for now.  Thanks

Read attribute last_learned_ir_code should give you the IR code if the command IRLearn was successfull.
If not paste your debug logs here.

I have add : ("_TZ3290_gnl5a6a5xvql7c2a", "TS1201"), and works, if you can update your code Thanks for your work

Hi, where did you add this model info ? In ZosungIRBlaster or in ZosungIRBlaster_ZS06 class ?
The first one is for battery powered devices, the second one for USB powered.

-) For every run of "IRLearn", I get a new code. Does not seem to be a problem though, but I expected it to be a fixed value all time

It seems that the blaster device samples the IR signal, so it's a sort of analog to digital conversion, this is not really reproducible.

-) The "OPEN" command is perfectly reproduced, but I'm not able to replicate the "CLOSE" command. Doing the same exact procedure, but it does not work at all If you have any idea or can shed light on this last point, I will greatly appreciate

Can't really help you on this, the base64 encoded IR data is a black box for me.

I have add : ("_TZ3290_gnl5a6a5xvql7c2a", "TS1201"), and works, if you can update your code Thanks for your work

Hi, where did you add this model info ? In ZosungIRBlaster or in ZosungIRBlaster_ZS06 class ? The first one is for battery powered devices, the second one for USB powered.

In the 2, I try to delete from the first one and see if it works.

I have add : ("_TZ3290_gnl5a6a5xvql7c2a", "TS1201"), and works, if you can update your code Thanks for your work

Hi, where did you add this model info ? In ZosungIRBlaster or in ZosungIRBlaster_ZS06 class ? The first one is for battery powered devices, the second one for USB powered.

in this one :

-) For every run of "IRLearn", I get a new code. Does not seem to be a problem though, but I expected it to be a fixed value all time

It seems that the blaster device samples the IR signal, so it's a sort of analog to digital conversion, this is not really reproducible.

-) The "OPEN" command is perfectly reproduced, but I'm not able to replicate the "CLOSE" command. Doing the same exact procedure, but it does not work at all If you have any idea or can shed light on this last point, I will greatly appreciate

Can't really help you on this, the base64 encoded IR data is a black box for me.

I tested with my TV remote and here's what I get

First time:
CzUJnwJ2BJ8CHAKfAsAHwAtAD0ADQA/gAQMBm2PgwjMCAhwC
2nd time:
CzMJmAJ/BJgCIQKYAsAHwAtAD0ADQA/gAQMBoGPg9jMCAiEC
3rd time:
CzoJlQKDBJUCJAKVAsAHwAtAD0ADQA/gAgMAY+DCMwICJAI=
I cannot imagine this one is also generating analog signal
Tested another TV remote, a TNT decoder: same result
Is there anything I'm doing wrong ?

Hi
I can get to this step

But here nothing happens. There is no blue light on the Ir blaster and my air conditioning won't turn on

Where i'm wrong?

rk9qn3j:

I still have issues with this and trying to narrow it down, but with somewhat success. I can't say for sure, but I think the problem might be my somewhat rapid automation used to switch source on the TV. The automation below does the following:

Presses the Source button once.
Then presses down 9 times, with a slight delay of 1 second between the IR commands (I have tried to increase the delay, by half a second or 1 second, but the issue is still there).
Finishing off by pressing the OK button, which selects the current selected HDMI source.

My theory goes that the device (perhaps more specific the battery-operated model) is meant to send a single command for e.g. change mode on an air conditioner, turn on the stereo amplifier etc, but when several commands are introduced in a row, it doesn't keep up and stops working (for a while).

Were you ever able to get this to work correctly? I think I'm running into a similar issue with multiple IR commands in a row.

@SethJMoore Unfortunately no. :neutral_face: I have also tried to create automations with like 3 IR commands in a row, but even then, it's not reliable.

But since the latest versions of Home Assistant, the following error messages have started to appear in the logs right after the IR blaster stops working:
Logger: zigpy_deconz.api
Source: runner.py:188
First occurred: 21:06:07 (1 occurrences)
Last logged: 21:06:07
Duplicate or delayed response for 0x:e9 sequence

Logger: zigpy_deconz.zigbee.application
Source: runner.py:188
First occurred: 21:06:31 (2 occurrences)
Last logged: 21:06:31

    Unexpected transmit confirm for request id 54, Status: TXStatus.SUCCESS
    Unexpected transmit confirm for request id 66, Status: TXStatus.SUCCESS

@rk9qn3j thanks for the reply. Since I added a 2 second delay in between calls to the blaster, it seems to be working ok for me, but that makes it pretty slow.

Since I added a 2 second delay in between calls to the blaster, it seems to be working ok for me, but that makes it pretty slow.

@SethJMoore Works ok, as in reliable? 😉 I have also tried to increase the delay between the commands, but unfortunately, that doesn't make any difference in stability.
And one more thing, I don't know if there's something wrong with one of my IR commands, the quirk itself, or something else, but suddenly I got e.g. double IR commands for "up", even though my automation only says "up" once.
I wonder if there is a firmware available, that could fix these issues.. 🤔
I'm just curious - does anybody else have issues with multiple IR commands in a row? If not, are you running the non-battery-powered version?

Has anyone figured out how to repeat a code multiple times? My TV uses a single code to turn on and then expects the same code to be repeated rapidly (i.e. a long press on the remote) to turn off. I tried base64 decoding the code, repeating the byte string 100 times, base64 encoding again and then re-running, but that doesn't seem to do it.

Do I understand correctly that the quirk currently doesn't add a "remote" entity for the remote and you have to do all the learning and sending through zigbee cluster commands, instead of an IR learn/send service like with broadlinks?

@tannisroot you understand correctly.

Here's the script I'm using to call the blaster. I have the codes saved as attributes in a sensor template.
alias: Blast IR code
fields:
  code_name:
    name: IR Code
    description: The code to be blasted through the IR blaster
    required: true
    selector:
      attribute:
        entity_id: sensor.ir_blaster_codes
sequence:
  - service: zha.issue_zigbee_cluster_command
    data:
      cluster_type: in
      endpoint_id: 1
      command: 2
      ieee: f0:82:c0:ff:fe:fd:e9:d6
      command_type: server
      params:
        code: "{{ state_attr('sensor.ir_blaster_codes', code_name) }}"
      cluster_id: 57348
  - delay:
      hours: 0
      minutes: 0
      seconds: 2
      milliseconds: 0
icon: mdi:remote
mode: queued
max: 50

Where and how do I configure the codes as attributes in a sensor template? Thanks a lot for this example

@sjors-lemniscap Glad to hear you figured it out. I'll go ahead and post an example of mine in case anyone else could use it.
I have the following in my templates.yaml file:
- sensor:
  - name: " IR Blaster Codes"
    unique_id: "sensor.ir_blaster_codes"
    state: none
    attributes:
      tv_power: "BW4jyBE+AsABA5EGPgLgCwFAF0ADQAFAB+AHA+ADAUAb4AcBQBPAA0ABwAvABwf3nW4jAAk+Ag=="
      tv_input_next: "B3MjkRFkAhsCgAMEhAZkAhtgAeADBwFkAkAXQAPgAwtAD+APA8AnQAfgCwNANwAbIAEBhAZAAxFkAgydcyPLCGQC//9zI8sIZAI="
      tv_channel_up: "BUQj3xE8AsABA5EGPALgCwFAF0ADQAFAB+AHA+AXAeAHL+AHDwfinUQj9Ag8Ag=="
      tv_channel_down: "BYgjwBE8AsABA5UGPALgCwFAF0ADQAFAB+ALA+AXAeALM8ATB+CdiCPdCDwC"
      tv_nav_up: "BXsjwBE8AsABA5IGPALgCwFAF0ADQAFAB+ALA0ABQBfgAwHgAw/AC0AHwANAAQuSBjwCyJ17I/EIPAI="
      tv_nav_down: "BUEj3xE8AsABA5QGPALgCwFAF0ADQAFAB+AHA0ABwBPgAwFAE0ABwAdAAUALwANAAQuUBjwC1p1BI/YIPAI="
      tv_nav_left: "BVgjwxE7AsABA5cGOwLgCwFAF0ADQAFAB+ATA+ADAUAn4AcBQBPAA0ABC5cGOwLKnVgj7wg7Ag=="
      tv_nav_right: "BVkjxBE6AsABA5UGOgLgCwFAF0ADQAFAB+AHA+ADAUAbwAHAC0AHwANAAeAHCwfPnVkjBwk6Ag=="
      tv_nav_ok: "BWAjwBE7AsABA5QGOwLgCwFAF0ADQAFAB+AHA8ABQBfgAwHAD0AHQANAAUAHwAMHOwI7ApQGOwI="

Hi! I'm jumping on this conversation for hopefully a bit of help with some devices. I've installed the quirks and have successfully already automated quite a lot of devices using the information from this topic, thanks a lot for the work being done!
But there's one device that eludes me, and it's a fan controller. The original remote is a "Distech Controls V13R", and I can't for the life of me capture any of its signals. Well, I've captured ONE for a test originally, but did not save it, and now I am having absolutely no luck.
When captured with a Flipper Zero, the data looks like this:
#
name: FanAuto
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 14991 1640 3325 1678 6657 1643 1684

I've been trying to convert this data to the base64(-like?) format this integration uses. I found for instance tools such as https://github.com/elupus/irgen but it only knows about the Broadlink base64 format, which is apparently not what the TS1201 is using (well, at least, it does not work).
Decoding the base64 payloads I had already captured (from other remotes) with the TS1201 don't give me any hints. They look like gibberish to me. I'm probably doing a lot of things wrong when experimenting, mind you.
I'd like to know is there's a specific way I could transform the raw data captured with my Flipper, into a payload I can blast with the TS1201. Would anyone have a clue on where to start? Thanks,

@MairusuPawa This is an interesting question! After some digging, I captured the following info, hope it helps you.
Here's a review that has photos of the board: https://smarthomescene.com/reviews/tuya-zigbee-infrared-ir-remote-zs06-review/.
The ODM (Zosung) has a sales page here: https://www.zosung.com/products/tuya-zigbee-infrared-remote-control-smart-ir-automatic-scenario. There are no datasheets that list an encoding scheme or other revealing info.
This comment seems to indicate the device uses a custom protocol, invented by Tuya/Zosung: https://github.com/Koenkk/zigbee2mqtt/issues/11633#issuecomment-1122820185.
Further digging led me to the Zosung ZS08 (a similar device). There is thankfully a Gist published that documents the protocol for it: https://gist.github.com/mildsunrise/1d576669b63a260d2cff35fda63ec0b5.
Included is a Python script that seems to take codes and convert them to/from the Tuya IR format, mostly. They also link to another Gist with info: https://gist.github.com/andrewcchen/f16eb20d19ea64d9f997c470e2addeaa.
Please take a look and let me know if this makes sense to you? I have not interrogated the IR codes from my Flipper Zero yet, but hope to be able to figure this out Soon™. If you're willing, I could use the help! :)
Thanks!

hi! as mentioned in the other issue, my module should work with this model as well. for example, trying the codes and signals posted above:
>>> import tuya
>>> tuya.decode_ir('BW4jyBE+AsABA5EGPgLgCwFAF0ADQAFAB+AHA+ADAUAb4AcBQBPAA0ABwAvABwf3nW4jAAk+Ag==')
[9070, 4552, 574, 574, 574, 574, 574, 1681, 574, 574, 574, 574, 574, 574, 574, 574, 574, 574, 574, 1681, 574, 1681, 574, 574, 574, 1681, 574, 1681, 574, 1681, 574, 1681, 574, 1681, 574, 574, 574, 574, 574, 574, 574, 1681, 574, 574, 574, 574, 574, 574, 574, 574, 574, 1681, 574, 1681, 574, 1681, 574, 574, 574, 1681, 574, 1681, 574, 1681, 574, 1681, 574, 40439, 9070, 2304, 574]
>>> tuya.encode_ir([14991, 1640, 3325, 1678, 6657, 1643, 1684])
'DY86aAb9DI4GARprBpQG'

however, the signal 14991 1640 3325 1678 6657 1643 1684 seems too short to me, i think your flipper captured only a small initial portion.

Has anyone figured out how to repeat a code multiple times? My TV uses a single code to turn on and then expects the same code to be repeated rapidly (i.e. a long press on the remote) to turn off. I tried base64 decoding the code, repeating the byte string 100 times, base64 encoding again and then re-running, but that doesn't seem to do it.

the reason this doesn't work is that a signal is a list of numbers, beginning with a HIGH, then LOW, then HIGH, etc. and ending in a HIGH. simply duplicating the list will not work, because the initial HIGH in the second list gets interpreted as LOW (because it's just after a HIGH), and so on.
to do that, insert a single number between the signals (spacing time), such as 20000 (20ms).
for example, to repeat the code 2 times:
>>> signal = tuya.decode_ir('BW4jyBE+AsABA5EGPgLgCwFAF0ADQAFAB+AHA+ADAUAb4AcBQBPAA0ABwAvABwf3nW4jAAk+Ag==')
>>> tuya.encode_ir(signal + [20000] + signal)
'BW4jyBE+AsABAZEG4AEL4AMBQBfAG8AL4AMD4Acr4A8/4A9DCfedbiMACT4CIE7ghY8='

however keep in mind that the device seems to have a size limit, so it could discard your code if it's too big.
also keep in mind that my code hasn't received much testing yet. maybe the generated codes don't work well.

For every run of "IRLearn", I get a new code. Does not seem to be a problem though, but I expected it to be a fixed value all time

this is extremely normal, as the captured signal will have some noise and the numbers won't be exactly the same every time. also, the device seems to quantize the numbers (possibly so that the LZ77 compression is more effective)

hi! as mentioned in the other issue, my module should work with this model as well. for example, trying the codes and signals posted above:
>>> import tuya
>>> tuya.decode_ir('BW4jyBE+AsABA5EGPgLgCwFAF0ADQAFAB+AHA+ADAUAb4AcBQBPAA0ABwAvABwf3nW4jAAk+Ag==')
[9070, 4552, 574, 574, 574, 574, 574, 1681, 574, 574, 574, 574, 574, 574, 574, 574, 574, 574, 574, 1681, 574, 1681, 574, 574, 574, 1681, 574, 1681, 574, 1681, 574, 1681, 574, 1681, 574, 574, 574, 574, 574, 574, 574, 1681, 574, 574, 574, 574, 574, 574, 574, 574, 574, 1681, 574, 1681, 574, 1681, 574, 574, 574, 1681, 574, 1681, 574, 1681, 574, 1681, 574, 40439, 9070, 2304, 574]
>>> tuya.encode_ir([14991, 1640, 3325, 1678, 6657, 1643, 1684])
'DY86aAb9DI4GARprBpQG'

however, the signal 14991 1640 3325 1678 6657 1643 1684 seems too short to me, i think your flipper captured only a small initial portion.

Hi! Thanks a lot for the script. I too was surprised by the signal's length, but sending it through the Flipper did work. And here, lo and behold: the payload "DY86aAb9DI4GARprBpQG" absolutely works too, using the TS1201 to blast it. Awesome work!
I now have to capture everything else on this remote :)

@mildsunrise I have codes from manual for my TV defined just as one hex value - how can I use them with Tuya IR blaster? I want to use them since I found that the ones learned are sometimes unreliable (works from time to time).

Since I added a 2 second delay in between calls to the blaster, it seems to be working ok for me, but that makes it pretty slow.

@SethJMoore Works ok, as in reliable? 😉 I have also tried to increase the delay between the commands, but unfortunately, that doesn't make any difference in stability.
And one more thing, I don't know if there's something wrong with one of my IR commands, the quirk itself, or something else, but suddenly I got e.g. double IR commands for "up", even though my automation only says "up" once.
I wonder if there is a firmware available, that could fix these issues.. 🤔
I'm just curious - does anybody else have issues with multiple IR commands in a row? If not, are you running the non-battery-powered version?

I have an issue with doubled codes, but I think it was caused by learning more then one code, when I pushed button little bit longer. I learn that code again and it was ok.
Other thing is that delay. Is it really needed for anything? I think it causing problems with triggering codes in a short time.

Also, I have an impression that first code send to a blaster after a while of not using it is lost. Can it be some issue with waking device up?

Here is a sample script to send a code:
alias: Vacuum Start
sequence:

service: zha.issue_zigbee_cluster_command
data:
cluster_type: in
endpoint_id: 1
command: 2
ieee: 38:5b:44:ff:fe:33:11:8a
command_type: server
params:
code: >-
C7ILsgsfAskBHwLGBYADwAtAB+APA8ArwAfgDyfgIxfAS0AHQDdAB8ADB/pPsguyCx8C4AEXArMCBWCzB8kByQGzAskBQAGAH0AHCR8CyQHJAR8CxgXgBQNAE+A3A+ADU0BL4AMP4AmnAR8CwCNAB+APA0An4AMD4A8n4CMX4AdP4AMP4JWnBLMCxgUfYAPglacJHwLGBR8CxgUfAg==
cluster_id: 57348
mode: single
icon: mdi:robot-vacuum
You will need to switch out the ieee as well as the code. The cluster_id was translated from 0xe004

@ranton1990 Where are you entering this script on home assistant?

Where are you entering this script on home assistant?

@jacobvohs

Go to Settings -> Automation & Scenes -> Scripts tab -> + Add Script button.
Create new Script
Click on the 3 horizontal dots upper left
Click on Edit in YAML

Don't forget to change the ieee to the address of your device! View/expand Device info in the ZHA integration.

@sjors-lemniscap Glad to hear you figured it out. I'll go ahead and post an example of mine in case anyone else could use it.
I have the following in my templates.yaml file:
- sensor:
  - name: " IR Blaster Codes"
    unique_id: "sensor.ir_blaster_codes"
    state: none
    attributes:
      tv_power: "BW4jyBE+AsABA5EGPgLgCwFAF0ADQAFAB+AHA+ADAUAb4AcBQBPAA0ABwAvABwf3nW4jAAk+Ag=="
      tv_input_next: "B3MjkRFkAhsCgAMEhAZkAhtgAeADBwFkAkAXQAPgAwtAD+APA8AnQAfgCwNANwAbIAEBhAZAAxFkAgydcyPLCGQC//9zI8sIZAI="
      tv_channel_up: "BUQj3xE8AsABA5EGPALgCwFAF0ADQAFAB+AHA+AXAeAHL+AHDwfinUQj9Ag8Ag=="
      tv_channel_down: "BYgjwBE8AsABA5UGPALgCwFAF0ADQAFAB+ALA+AXAeALM8ATB+CdiCPdCDwC"
      tv_nav_up: "BXsjwBE8AsABA5IGPALgCwFAF0ADQAFAB+ALA0ABQBfgAwHgAw/AC0AHwANAAQuSBjwCyJ17I/EIPAI="
      tv_nav_down: "BUEj3xE8AsABA5QGPALgCwFAF0ADQAFAB+AHA0ABwBPgAwFAE0ABwAdAAUALwANAAQuUBjwC1p1BI/YIPAI="
      tv_nav_left: "BVgjwxE7AsABA5cGOwLgCwFAF0ADQAFAB+ATA+ADAUAn4AcBQBPAA0ABC5cGOwLKnVgj7wg7Ag=="
      tv_nav_right: "BVkjxBE6AsABA5UGOgLgCwFAF0ADQAFAB+AHA+ADAUAbwAHAC0AHwANAAeAHCwfPnVkjBwk6Ag=="
      tv_nav_ok: "BWAjwBE7AsABA5QGOwLgCwFAF0ADQAFAB+AHA8ABQBfgAwHAD0AHQANAAUAHwAMHOwI7ApQGOwI="

@SethJMoore Could you give a bit more hints as to how/where I put this? I don't see a templates.yaml in my File Editor, even after I added the Templates addon. Or do I just make it from scratch?
Thanks.

Hello, I'm trying to use a _TZ3290_ot6ewjvmejq5ekhl with this quirk (latest version in the dev branch).
I can see that the quirk is picked up by the device and I can see the ZosungIRControl cluster but in there I have only the last_learned_ir_code (0x0). How do I put the device in IR learning? I have no 0x1 command.
What am I missing?

Got one of these yesterday. Added the custom quirk paired the device all good thanks. I can do the ir learn and read the code back as an attribute. But I can't seem to send anything out. I tried using the cluster commands where you set it to learn and it gives me the green tick but the device seems to not respond no blinking blue led my TV didn't do anything. Using ha v 2024.03.03 in docker with an xbee as the cordinator

Hello,
given the conflict between Zigbee HA and Zigbee2MQTT I decided to work only with Zigbee HA.
I have this device also and by following the guide and trend I managed to memorize the 2 codes of my air conditioner for true and false.
Now how do I associate these 2 values to the ON (true) and OFF (false) switch so both bringing it to the dashboard and structuring some automations?

Hi,
I've found that a workaround for the KeyError issues is to ensure a delay between zha calls. In my case 1 second is sufficient. Probably it is a fault/weekness in the quirk code, I don't know, but the workaround has been working for me.

I was searching for a solution to make it easier to work with the current state in Home Assistant. The proposed PR is not creating a remote entity in HA, but only allows to control the IR remote using services (now called actions).
I proposed a templated remote feature in the HA forum, and a moderator helped me find an interesting solution.
The idea is to use scripts to make the work easier. I've seen the examples in this issue to use a template sensor to store the codes, I think that the following is an interesting alternative solution.
So, I have in my configuration.yaml:
script: !include scripts.yaml

And in scripts.yaml I created a script which has the codes:
remote_escritorio:
  variables:
    config:
      kvm1_in_1: BVcjihFBAuATAQGZBuAVA0ABQCPgFwFAI+APAwdim1cj2whBAg==
      kvm1_in_2: BVUjqBE+AuANAQJqAj4gAQGdBuAVA0ABwCPgFwHAJ+AHBwd5m1Uj7wg+Ag==
      kvm1_liga: BUYjzRE+AuATAQGiBuAVA8ABQCfgDwHAG0AH4AsDB3ibRiPYCD4C
      # others...
  sequence:
    - condition: template
      value_template: "{{ command is defined and command in config }}"
    - alias: envia o comando para o IR
      service: zha.issue_zigbee_cluster_command
      data:
        cluster_type: in
        command: 2
        endpoint_id: 1
        params:
          code: "{{ config.get(command) }}"
        cluster_id: 57348
        ieee: "0c:ef:f6:ff:fe:a9:fe:93"
        command_type: server

And I am calling it like this (in automations, templates etc):
service: script.remote_escritorio
data:
  command: tomate_mts_2032_liga

This works, everything is centralized in the same place and it is fine.
The only thing that is going to give me a lot of work I mentioned in the last comment I made on the forum thread: to learn tens of codes will take a lot of time, and using a remote entity in HA would make it much easier.
So I leave this comment as a way to help others and also to ask if it is possible that the proposed PR might create a remote entity in HA, which would make all this much easier. To @ferehcarb, who created the PR, would you know if that is possible?

I just updated Home Assistant Core to 2024.8 and it's seem to of broken this custom quirk for me.
My coding knowledge is not good enough to know how to fix this.
Is anyone else having this problem?
This is my error log

Logger: zhaquirks
Source: /usr/local/lib/python3.12/site-packages/zhaquirks/__init__.py:461
First occurred: 4:29:48 PM (1 occurrences)
Last logged: 4:29:48 PM
Unexpected exception importing custom quirk 'ts1201'

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/zhaquirks/__init__.py", line 459, in setup
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/config/custom_zha_quirks/ts1201.py", line 377, in <module>
    class ZosungIRBlaster(CustomDevice):
  File "/config/custom_zha_quirks/ts1201.py", line 382, in ZosungIRBlaster
    last_learned_ir_code = t.CharacterString()
                           ^^^^^^^^^^^^^^^^^^^
TypeError: CharacterString.__new__() missing 1 required positional argument: 'value'

I found other people having the same issue, the quick fix is to change
last_learned_ir_code = t.CharacterString()
to
last_learned_ir_code = t.CharacterString(value="")

I found other people having the same issue, the quick fix is to change last_learned_ir_code = t.CharacterString() to last_learned_ir_code = t.CharacterString(value="")

This change is not backward compatible, I am on 2024.7.4 and after adding it the quirk stopped working.
This is problematic. I am new to this quirks, are they supposed to stop working when HA updates like that? Is that common?

I suspect this issue has come about from the large change in ZHA in Core update  2024.8
https://www.home-assistant.io/blog/2024/08/07/release-20248/#zigbee-home-automation-zha-updates
You won't need to do this is you are not using core 2024.8
I've only been using HA since the beginning of this year and this is the only custom quirk I use, but this is the first time I've had an issue like this

I found other people having the same issue, the quick fix is to change last_learned_ir_code = t.CharacterString() to last_learned_ir_code = t.CharacterString(value="")

This worked for me, Thanks!!

I found other people having the same issue, the quick fix is to change last_learned_ir_code = t.CharacterString() to last_learned_ir_code = t.CharacterString(value="")

This works for me too.
Thanks :)

This is problematic. I am new to this quirks, are they supposed to stop working when HA updates like that? Is that common?

Custom quirks are really meant for development and testing purposes. They are not meant to be used as the primary way to interact with a device unless you are willing to maintain the code and fix it when it breaks.
It's important that any popular quirk such as this be finished, tested, and merged into this repository so that we can actually release fixes for problems such as this. Otherwise, every person will manually have to fix things.

This is problematic. I am new to this quirks, are they supposed to stop working when HA updates like that? Is that common?

Custom quirks are really meant for development and testing purposes. They are not meant to be used as the primary way to interact with a device unless you are willing to maintain the code and fix it when it breaks.
It's important that any popular quirk such as this be finished, tested, and merged into this repository so that we can actually release fixes for problems such as this. Otherwise, every person will manually have to fix things.

100% agree, but following the discussion in #2336 it seems like the final fixes and request to merge it into a release was never followed-up on while the quirk keeps growing in popularity.
Think this one could've been prevented. Hoping it will shed some light again on reviewing the original PR so that it hopefully can be included in a near-future release.

I was searching for a solution to make it easier to work with the current state in Home Assistant. The proposed PR is not creating a remote entity in HA, but only allows to control the IR remote using services (now called actions).
I proposed a templated remote feature in the HA forum, and a moderator helped me find an interesting solution.
The idea is to use scripts to make the work easier. I've seen the examples in this issue to use a template sensor to store the codes, I think that the following is an interesting alternative solution.
So, I have in my configuration.yaml:
script: !include scripts.yaml

And in scripts.yaml I created a script which has the codes:
remote_escritorio:
  variables:
    config:
      kvm1_in_1: BVcjihFBAuATAQGZBuAVA0ABQCPgFwFAI+APAwdim1cj2whBAg==
      kvm1_in_2: BVUjqBE+AuANAQJqAj4gAQGdBuAVA0ABwCPgFwHAJ+AHBwd5m1Uj7wg+Ag==
      kvm1_liga: BUYjzRE+AuATAQGiBuAVA8ABQCfgDwHAG0AH4AsDB3ibRiPYCD4C
      # others...
  sequence:
    - condition: template
      value_template: "{{ command is defined and command in config }}"
    - alias: envia o comando para o IR
      service: zha.issue_zigbee_cluster_command
      data:
        cluster_type: in
        command: 2
        endpoint_id: 1
        params:
          code: "{{ config.get(command) }}"
        cluster_id: 57348
        ieee: "0c:ef:f6:ff:fe:a9:fe:93"
        command_type: server

And I am calling it like this (in automations, templates etc):
service: script.remote_escritorio
data:
  command: kvm1_liga

This works, everything is centralized in the same place and it is fine.
The only thing that is going to give me a lot of work I mentioned in the last comment I made on the forum thread: to learn tens of codes will take a lot of time, and using a remote entity in HA would make it much easier.
So I leave this comment as a way to help others and also to ask if it is possible that the proposed PR might create a remote entity in HA, which would make all this much easier. To @ferehcarb, who created the PR, would you know if that is possible?

I am trying to set this up, however i need my fake_remote to send a sequence of signals and there might be a need for a quick pause between the signals as I realized it takes around 2-4 seconds to eventually receive the IR commands by the device itself since I press the Issue zigbee command in HA.
I want my amplifier to not only be switched on, but volume up several times.
Can I just make this in the automations.yaml?:
  - service: script.fake_remote
    metadata: {}
    data:
      command: amp_toggle
      command: amp_vol_up
      command: amp_vol_up
      command: amp_vol_up

I am trying to set this up, however i need my fake_remote to send a sequence of signals and there might be a need for a quick pause between the signals as I realized it takes around 2-4 seconds to eventually receive the IR commands by the device itself since I press the Issue zigbee command in HA. I want my amplifier to not only be switched on, but volume up several times. Can I just make this in the automations.yaml?:
  - service: script.fake_remote
    metadata: {}
    data:
      command: amp_toggle
      command: amp_vol_up
      command: amp_vol_up
      command: amp_vol_up

@cslev No, this would only be defining the command 3 times.
What you need to do is add a delay under the sequence, in scripts.yaml. I haven't tested this, I'm writting by memory, but something like this:
sequence:
- delay: 2s
- alias: Issue a command via the remote # etc...

so if I add delay in the scripts.yaml, then my automation part can remain and it won't define the command 3 times but create and send those commands 3 times due to the delay feature?

It does not work. First, the delay is required to be defined in HH:MM:SS format, but even after that nothing is changed, I can still send only one command. In fact, in my automations.yaml I have those commands multiple times but in the user interface it only shows the last one added. This also indicates that sequences should not be sent like this.
Gotta dig deeper in this, or worst case I call my fake_remote 15 times :(((

According to all the comments and descriptions here and there, I managed to add this device to Home Assistant using ZHA only. I also managed to do automation. Thanks for all the comments.
If anyone is interested I made a video tutorial about my struggles and successful integration. I hope it will help for newcomers.
https://cslev.medium.com/adding-a-zigbee-infrared-blaster-to-home-assistant-using-nothing-but-zha-f651b7da5429
Cheers

I'm getting information, but I cannot seem to figure out what the IR code is from what is received in the logs.
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 73): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=73, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (1 enqueued)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=127, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (2 enqueued)
2024-12-28 12:41:00.575 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received data 2439b1ed542e14b2b4954b25aa5592c46afad20a12cc5a82b7c56382fc493fa7ebfc9e6ccffe87dcd48f6bcc552108ea521ba6ef2880659a7d312453b6607338386e00b4f34cd1a98292109cb06043e01edc3737fd37cf7e
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received frame DataFrame(frm_num=2, re_tx=0, ack_num=4, ezsp_frame=b'{\x90E\x00\x04\x01\x00\xed\x01\x01\x00\x00\x00\x00\x8d\xf6\xb4\xf5\xa1\xff\x02=\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_')
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending frame AckFrame(res=0, ncp_ready=0, ack_num=3) + FLAG
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending data  83401b7e
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.ezsp.protocol] Received command incomingMessageHandler: {'type': <EmberIncomingMessageType.INCOMING_UNICAST: 0>, 'apsFrame': EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 'lastHopLqi': 246, 'lastHopRssi': -76, 'sender': 0xA1F5, 'bindingIndex': 255, 'addressIndex': 2, 'messageContents': b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'}
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.zigbee.application] Received incomingMessageHandler frame with [<EmberIncomingMessageType.INCOMING_UNICAST: 0>, EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 246, -76, 0xA1F5, 255, 2, b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_']
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(timestamp=datetime.datetime(2024, 12, 28, 17, 41, 1, 335565, tzinfo=datetime.timezone.utc), priority=0, src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xA1F5), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=141, profile_id=260, cluster_id=60672, data=Serialized[b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=246, rssi=-76)
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received ZCL frame: b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x09>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=74, command_id=3, *direction=<Direction.Server_to_Client: 1>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 74): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=74, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (3 enqueued)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=128, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (4 enqueued)
2024-12-28 12:41:01.337 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:01.338 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed

I'm getting information, but I cannot seem to figure out what the IR code is from what is received in the logs.
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 73): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=73, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (1 enqueued)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=127, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (2 enqueued)
2024-12-28 12:41:00.575 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received data 2439b1ed542e14b2b4954b25aa5592c46afad20a12cc5a82b7c56382fc493fa7ebfc9e6ccffe87dcd48f6bcc552108ea521ba6ef2880659a7d312453b6607338386e00b4f34cd1a98292109cb06043e01edc3737fd37cf7e
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received frame DataFrame(frm_num=2, re_tx=0, ack_num=4, ezsp_frame=b'{\x90E\x00\x04\x01\x00\xed\x01\x01\x00\x00\x00\x00\x8d\xf6\xb4\xf5\xa1\xff\x02=\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_')
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending frame AckFrame(res=0, ncp_ready=0, ack_num=3) + FLAG
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending data  83401b7e
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.ezsp.protocol] Received command incomingMessageHandler: {'type': <EmberIncomingMessageType.INCOMING_UNICAST: 0>, 'apsFrame': EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 'lastHopLqi': 246, 'lastHopRssi': -76, 'sender': 0xA1F5, 'bindingIndex': 255, 'addressIndex': 2, 'messageContents': b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'}
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.zigbee.application] Received incomingMessageHandler frame with [<EmberIncomingMessageType.INCOMING_UNICAST: 0>, EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 246, -76, 0xA1F5, 255, 2, b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_']
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(timestamp=datetime.datetime(2024, 12, 28, 17, 41, 1, 335565, tzinfo=datetime.timezone.utc), priority=0, src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xA1F5), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=141, profile_id=260, cluster_id=60672, data=Serialized[b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=246, rssi=-76)
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received ZCL frame: b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x09>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=74, command_id=3, *direction=<Direction.Server_to_Client: 1>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 74): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=74, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (3 enqueued)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=128, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (4 enqueued)
2024-12-28 12:41:01.337 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:01.338 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed

You don't need to look in the log anymore. The IR code is available via the interface parameter
checkout post https://github.com/zigpy/zha-device-handlers/issues/1687#issuecomment-1467868376

I'm getting information, but I cannot seem to figure out what the IR code is from what is received in the logs.
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 73): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=73, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (1 enqueued)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=127, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (2 enqueued)
2024-12-28 12:41:00.575 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received data 2439b1ed542e14b2b4954b25aa5592c46afad20a12cc5a82b7c56382fc493fa7ebfc9e6ccffe87dcd48f6bcc552108ea521ba6ef2880659a7d312453b6607338386e00b4f34cd1a98292109cb06043e01edc3737fd37cf7e
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received frame DataFrame(frm_num=2, re_tx=0, ack_num=4, ezsp_frame=b'{\x90E\x00\x04\x01\x00\xed\x01\x01\x00\x00\x00\x00\x8d\xf6\xb4\xf5\xa1\xff\x02=\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_')
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending frame AckFrame(res=0, ncp_ready=0, ack_num=3) + FLAG
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending data  83401b7e
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.ezsp.protocol] Received command incomingMessageHandler: {'type': <EmberIncomingMessageType.INCOMING_UNICAST: 0>, 'apsFrame': EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 'lastHopLqi': 246, 'lastHopRssi': -76, 'sender': 0xA1F5, 'bindingIndex': 255, 'addressIndex': 2, 'messageContents': b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'}
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.zigbee.application] Received incomingMessageHandler frame with [<EmberIncomingMessageType.INCOMING_UNICAST: 0>, EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 246, -76, 0xA1F5, 255, 2, b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_']
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(timestamp=datetime.datetime(2024, 12, 28, 17, 41, 1, 335565, tzinfo=datetime.timezone.utc), priority=0, src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xA1F5), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=141, profile_id=260, cluster_id=60672, data=Serialized[b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=246, rssi=-76)
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received ZCL frame: b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x09>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=74, command_id=3, *direction=<Direction.Server_to_Client: 1>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 74): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=74, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (3 enqueued)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=128, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (4 enqueued)
2024-12-28 12:41:01.337 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:01.338 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed

You don't need to look in the log anymore. The IR code is available via the interface parameter checkout post #1687 (comment)

I did try that and only once did I get an attribute of last code used, but it didn't appear to work when I tested the .send function.
I'm going to start over again when I get back home, but while everything appeared to be working, I was having some issue.  How do I know if the quirks loaded correctly?  Perhaps that has something to do with it?

I'm getting information, but I cannot seem to figure out what the IR code is from what is received in the logs.
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 73): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=73, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (1 enqueued)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=127, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (2 enqueued)
2024-12-28 12:41:00.575 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received data 2439b1ed542e14b2b4954b25aa5592c46afad20a12cc5a82b7c56382fc493fa7ebfc9e6ccffe87dcd48f6bcc552108ea521ba6ef2880659a7d312453b6607338386e00b4f34cd1a98292109cb06043e01edc3737fd37cf7e
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received frame DataFrame(frm_num=2, re_tx=0, ack_num=4, ezsp_frame=b'{\x90E\x00\x04\x01\x00\xed\x01\x01\x00\x00\x00\x00\x8d\xf6\xb4\xf5\xa1\xff\x02=\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_')
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending frame AckFrame(res=0, ncp_ready=0, ack_num=3) + FLAG
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending data  83401b7e
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.ezsp.protocol] Received command incomingMessageHandler: {'type': <EmberIncomingMessageType.INCOMING_UNICAST: 0>, 'apsFrame': EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 'lastHopLqi': 246, 'lastHopRssi': -76, 'sender': 0xA1F5, 'bindingIndex': 255, 'addressIndex': 2, 'messageContents': b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'}
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.zigbee.application] Received incomingMessageHandler frame with [<EmberIncomingMessageType.INCOMING_UNICAST: 0>, EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 246, -76, 0xA1F5, 255, 2, b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_']
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(timestamp=datetime.datetime(2024, 12, 28, 17, 41, 1, 335565, tzinfo=datetime.timezone.utc), priority=0, src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xA1F5), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=141, profile_id=260, cluster_id=60672, data=Serialized[b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=246, rssi=-76)
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received ZCL frame: b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x09>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=74, command_id=3, *direction=<Direction.Server_to_Client: 1>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 74): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=74, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (3 enqueued)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=128, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:01.337 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (4 enqueued)
2024-12-28 12:41:01.337 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:01.338 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.335565, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:01.339 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed

You don't need to look in the log anymore. The IR code is available via the interface parameter checkout post #1687 (comment)

I did try that and only once did I get an attribute of last code used, but it didn't appear to work when I tested the .send function.
I'm going to start over again when I get back home, but while everything appeared to be working, I was having some issue. How do I know if the quirks loaded correctly? Perhaps that has something to do with it?

Do you see the led on the device blink when you try to send a code. I am able to read codes but mine does not send codes for some reason

I'm getting information, but I cannot seem to figure out what the IR code is from what is received in the logs.
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 73): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=73, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)
2024-12-28 12:41:00.574 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (1 enqueued)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request header: ZCLHeader(frame_control=FrameControl<0x05>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), manufacturer=4098, tsn=127, command_id=4, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending request: receive_ir_frame_04(zero0=0, seq=11, zero1=0)
2024-12-28 12:41:00.575 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying device request (2 enqueued)
2024-12-28 12:41:00.575 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0})
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method execute of sqlite3.Connection object at 0x7a5bbb1e6f20>, 'UPDATE devices_v13\n                    SET last_seen=:ts\n                    WHERE ieee=:ieee AND :ts - last_seen > :min_update_delta', {'ts':<PHONE_NUMBER>.57366, 'ieee': d8:7a:3b:ff:fe:d3:4c:f2, 'min_update_delta': 30.0}) completed
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] executing functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>)
2024-12-28 12:41:00.576 DEBUG (Thread-7) [aiosqlite] operation functools.partial(<built-in method commit of sqlite3.Connection object at 0x7a5bbb1e6f20>) completed
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received data 2439b1ed542e14b2b4954b25aa5592c46afad20a12cc5a82b7c56382fc493fa7ebfc9e6ccffe87dcd48f6bcc552108ea521ba6ef2880659a7d312453b6607338386e00b4f34cd1a98292109cb06043e01edc3737fd37cf7e
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Received frame DataFrame(frm_num=2, re_tx=0, ack_num=4, ezsp_frame=b'{\x90E\x00\x04\x01\x00\xed\x01\x01\x00\x00\x00\x00\x8d\xf6\xb4\xf5\xa1\xff\x02=\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_')
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending frame AckFrame(res=0, ncp_ready=0, ack_num=3) + FLAG
2024-12-28 12:41:01.334 DEBUG (bellows.thread_0) [bellows.ash] Sending data  83401b7e
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.ezsp.protocol] Received command incomingMessageHandler: {'type': <EmberIncomingMessageType.INCOMING_UNICAST: 0>, 'apsFrame': EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 'lastHopLqi': 246, 'lastHopRssi': -76, 'sender': 0xA1F5, 'bindingIndex': 255, 'addressIndex': 2, 'messageContents': b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'}
2024-12-28 12:41:01.335 DEBUG (MainThread) [bellows.zigbee.application] Received incomingMessageHandler frame with [<EmberIncomingMessageType.INCOMING_UNICAST: 0>, EmberApsFrame(profileId=260, clusterId=60672, sourceEndpoint=1, destinationEndpoint=1, options=<EmberApsOption.APS_OPTION_NONE: 0>, groupId=0, sequence=141), 246, -76, 0xA1F5, 255, 2, b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_']
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(timestamp=datetime.datetime(2024, 12, 28, 17, 41, 1, 335565, tzinfo=datetime.timezone.utc), priority=0, src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0xA1F5), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=141, profile_id=260, cluster_id=60672, data=Serialized[b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=246, rssi=-76)
2024-12-28 12:41:01.335 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received ZCL frame: b'\tJ\x03\x00\x0b\x007\x00\x00\x001@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02_'
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x09>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=74, command_id=3, *direction=<Direction.Server_to_Client: 1>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Decoded ZCL frame: ZosungIRTransmit:resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Received command 0x03 (TSN 74): resp_ir_frame_03(zero=0, seq=11, position=55, msgpart=b'@\x03@\x01@\x07\x01]\x02@\x13\x02\xa1\x06$ \x03\x05]\x02$\x02]\x02@\x07\x80\x03\x00$`\x07\x0f\x16\x86\xb4#\xc7\x08]\x02\xff\xff\xb4#\xc7\x08]\x02', msgpartcrc=95)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply header: ZCLHeader(frame_control=FrameControl<0x10>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 0>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True), tsn=74, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 0>)
2024-12-28 12:41:01.336 DEBUG (MainThread) [zigpy.zcl] [0xA1F5:1:0xed00] Sending reply: Default_Response(command_id=3, status=<Status.SUCCESS: 0>)