External integration - Apple TV

Hello everyone,

After more than ten years of following this project (Gladys) without really taking the time to install and configure it, I’m finally back with a first external integration: Apple TV.

It relies on pyatv in Python (like HA) and node-pyatv on the Node.js side (wrapper).

Disclaimer: The integration was heavily developed by GPT 5.6 Sol (Codex).

Great job on the integration, it interests me because I have an Apple TV at home :grin: I’m going to try it out!

I tested and got this error:

Codex might be less strict than Claude aha, but Claude always thinks to run the validator before publishing:

The command:

npx github:GladysAssistant/integration-store .

Oh! I’ll look at that a bit later… it’s strange because I did an installation last night and it was working :o

The error is:

{
    "status": 422,
    "code": "UNPROCESSABLE_ENTITY",
    "properties": "actions[1].depends_on: unknown field ; actions[2].depends_on: unknown field"
}

I’ll add the error to the interface so it’s easier to debug :slight_smile:

New release available, try again and let me know if something needs fixing :slight_smile:

This time I managed to install but I have an error during the scan:

I asked Claude and it is indeed a bug in the integration, not Gladys:

[2026-08-03T12:51:38.091Z] [INFO] [apple-tv] Starting the Gladys Apple TV integration
[2026-08-03T12:51:38.288Z] [INFO] [gladys-sdk] connected to Gladys (http://172.30.0.1:80)
[2026-08-03T12:51:41.621Z] [INFO] [apple-tv] Starting mediated Apple TV discovery
[2026-08-03T12:51:42.339Z] [INFO] [apple-tv] Starting mediated Apple TV discovery
[2026-08-03T12:51:42.356Z] [ERROR] [apple-tv] Mediated mDNS discovery failed GladysApiError: Conflict
    at HttpClient.request (/app/node_modules/@gladysassistant/integration-sdk/lib/http-client.js:49:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
    at async AppleTvIntegration.scan (file:///app/src/integration.js:76:29)
    at async GladysIntegration._runHandler (/app/node_modules/@gladysassistant/integration-sdk/lib/gladys-integration.js:1166:7)
    at async GladysIntegration._handleMessage (/app/node_modules/@gladysassistant/integration-sdk/lib/gladys-integration.js:1022:9) {
  status: 409,
  code: 'CONFLICT'
}
[2026-08-03T12:51:50.977Z] [ERROR] [apple-tv] Apple TV probe failed for 3 candidate host(s) Error: Unable to find any devices, but received 1 error: [
  {
    "result": "failure",
    "datetime": "2026-08-03T14:51:50.763359+02:00",
    "exception": "Expected 4 octets in 'fd33:5f93:3f40:49cd:3:fd3b:c82a:7ced'",
    "stacktrace": "Traceback (most recent call last):\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/scripts/atvscript.py\", line 413, in appstart\n    args.output(await _handle_command(args, abort_sem, storage, loop)),\n                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/scripts/atvscript.py\", line 285, in _handle_command\n    return await _scan_devices(loop, storage, args.scan_hosts)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/scripts/atvscript.py\", line 231, in _scan_devices\n    for atv in await scan(loop, hosts=hosts, storage=storage):\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/__init__.py\", line 68, in scan\n    scanner = UnicastMdnsScanner([IPv4Address(host) for host in hosts], loop)\n                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/__init__.py\", line 68, in <listcomp>\n    scanner = UnicastMdnsScanner([IPv4Address(host) for host in hosts], loop)\n                                  ^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3.11/ipaddress.py\", line 1319, in __init__\n    self._ip = self._ip_int_from_string(addr_str)\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3.11/ipaddress.py\", line 1206, in _ip_int_from_string\n    raise AddressValueError(\"Expected 4 octets in %r\" % ip_str)\nipaddress.AddressValueError: Expected 4 octets in 'fd33:5f93:3f40:49cd:3:fd3b:c82a:7ced'\n"
  }
]
    at e.find (file:///app/node_modules/@sebbo2002/node-pyatv/dist/lib-DynU3Xla.mjs:7:8365)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
    at async AppleTvIntegration.scan (file:///app/src/integration.js:95:15)
    at async GladysIntegration._runHandler (/app/node_modules/@gladysassistant/integration-sdk/lib/gladys-integration.js:1166:7)
    at async GladysIntegration._handleMessage (/app/node_modules/@gladysassistant/integration-sdk/lib/gladys-integration.js:1022:9)
[2026-08-03T12:51:58.718Z] [INFO] [apple-tv] Starting mediated Apple TV discovery
[2026-08-03T12:52:07.997Z] [ERROR] [apple-tv] Apple TV probe failed for 3 candidate host(s) Error: Unable to find any devices, but received 1 error: [
  {
    "result": "failure",
    "datetime": "2026-08-03T14:52:07.795239+02:00",
    "exception": "Expected 4 octets in 'fd33:5f93:3f40:49cd:3:fd3b:c82a:7ced'",
    "stacktrace": "Traceback (most recent call last):\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/scripts/atvscript.py\", line 413, in appstart\n    args.output(await _handle_command(args, abort_sem, storage, loop)),\n                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/scripts/atvscript.py\", line 285, in _handle_command\n    return await _scan_devices(loop, storage, args.scan_hosts)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/scripts/atvscript.py\", line 231, in _scan_devices\n    for atv in await scan(loop, hosts=hosts, storage=storage):\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/__init__.py\", line 68, in scan\n    scanner = UnicastMdnsScanner([IPv4Address(host) for host in hosts], loop)\n                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/pyatv/lib/python3.11/site-packages/pyatv/__init__.py\", line 68, in <listcomp>\n    scanner = UnicastMdnsScanner([IPv4Address(host) for host in hosts], loop)\n                                  ^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3.11/ipaddress.py\", line 1319, in __init__\n    self._ip = self._ip_int_from_string(addr_str)\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3.11/ipaddress.py\", line 1206, in _ip_int_from_string\n    raise AddressValueError(\"Expected 4 octets in %r\" % ip_str)\nipaddress.AddressValueError: Expected 4 octets in 'fd33:5f93:3f40:49cd:3:fd3b:c82a:7ced'\n"
  }
]
    at e.find (file:///app/node_modules/@sebbo2002/node-pyatv/dist/lib-DynU3Xla.mjs:7:8365)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
    at async AppleTvIntegration.scan (file:///app/src/integration.js:95:15)
    at async GladysIntegration._runHandler (/app/node_modules/@gladysassistant/integration-sdk/lib/gladys-integration.js:1166:7)
    at async GladysIntegration._handleMessage (/app/node_modules/@gladysassistant/integration-sdk/lib/gladys-integration.js:1022:9)

Well, well! :joy: I just made a new release :+1: (in progress…)
If it still doesn’t work, in the meantime, you can already enter your Apple TV’s IP directly in the config tab.

We’re making progress, but this time I have another error:

The selector could be a bit more unique than that ^^

Codex still has some work to do :joy:

I may have been a bit « cheap » with the reasoning used haha
But it’s true that he didn’t bother for this one :joy:

New release available, I asked him to self-review and fix other potential issues of the same style!

Don’t hesitate to let me know if you encounter other issues if needed

I was able to add the Apple TV this time :slight_smile:

However, the device name could contain « Apple TV », because right now it’s just the room name (it must be the name given by Apple to my Apple TV), and so it’s not very readable:

Otherwise, I tried turning on the Apple TV with the « Power » type, but it does nothing:

The logs show nothing special:

[2026-08-03T15:22:33.784Z] [INFO] [apple-tv] Starting the Gladys Apple TV integration
[2026-08-03T15:22:33.982Z] [INFO] [gladys-sdk] connected to Gladys (http://172.30.0.1:80)
[2026-08-03T15:22:39.142Z] [INFO] [apple-tv] Starting mediated Apple TV discovery
[2026-08-03T15:22:48.502Z] [INFO] [apple-tv] Discovery completed: 1 Apple TV device(s) from 1 candidate host(s)
[2026-08-03T15:24:50.959Z] [WARN] [apple-tv] Apple TV real-time updates unavailable for Salon: Got pyatv Error: power_state is not supported; using polling
[2026-08-03T15:24:55.556Z] [WARN] [apple-tv] Apple TV real-time updates unavailable for Salon: Got pyatv Error: power_state is not supported; using polling

Does it work for you?

Attention, your integration has been listed on the integrations store even though it’s not functional yet. The idea is to only publish it once it’s operational. :wink:

In the meantime, you can remove the GitHub topic. This will prevent users from discovering it too early and being disappointed during their tests. :slightly_smiling_face:

Oops… I retracted! Codex added the tag without telling me! Sorry

I’m looking to fix it, but yes, Power was working for me last night.