node-pyatv icon indicating copy to clipboard operation
node-pyatv copied to clipboard

Connect via MAC address instead of host

Open maxileith opened this issue 1 year ago • 9 comments

Hi @sebbo2002,

your pyatv wrapper currently uses atvscript --scan-hosts 42.42.42.42 ... to connect to an Apple TV. Could you implement a way, to connect to an Apple TV using the MAC Address? The command would be atvscript --id AA:BB:CC:DD:EE:FF. Connecting via the ID has the benefit that this does work across subnets, with the --scan-hosts option, you need to be on the same subnet.

Many Greetings Maxi

maxileith avatar Dec 09 '24 11:12 maxileith

id is already implemented, just pass it instead of host / hosts.

Let me know if you need any help implementing it or I've missed something. ☺️

sebbo2002 avatar Dec 09 '24 12:12 sebbo2002

Problem is that host is not optional when adding a device:

https://github.com/sebbo2002/node-pyatv/blob/48dabfd2f994f50a8d896c0eb5544f673dcc3e3c/src/lib/types.ts#L169-L179

Addditonally, it would be nice to create a device with the complete set of attributes (host & mac) and still be able to tell the library which attribute to preferr when connecting to Apple TVs.

maxileith avatar Dec 09 '24 12:12 maxileith

Note: I am not talking about discovering devices but creating them manully via NodePyATVInstance.device.

maxileith avatar Dec 09 '24 12:12 maxileith

Ah, I see. Yes, in NodePyATVDevice the host is mandatory currently. get name() also returns a string, so changing this would be a breaking change. Have you tried setting host and id, does this work out for you? But do I understand you correctly that you actually want to have a new parameter that is then used instead of the parameters created in getParameters()?

sebbo2002 avatar Dec 09 '24 12:12 sebbo2002

Yes, in NodePyATVDevice the host is mandatory currently. get name() also returns a string, so changing this would be a breaking change.

From my POV, the signature of the getName() method does not need to be changed as I would only make the host attribute of NodePyATVDeviceOptions optional. I would keep the name attribute mandatory.

Have you tried setting host and id, does this work out for you?

Yes, currently I am doing exactly that in my homebridge plugin. However, the result is that the node-pyatv libarary sets the -s and -i option when calling atvscript. Unfortunately atvscript scans via the host / IP in that case.

But do I understand you correctly that you actually want to have a new parameter that is then used instead of the parameters created in getParameters()?

No, I don´t. In the comments before I've ment to have an option which allows to set the preferred way of connecting to an Apple TV. E.g. if you provide the host and mac address, instead of sending both (by default) you can somehow tell your library to only use --id or --scan-hosts but not both.

However, now that you have mentioned the getParameter function, there might be an easier solution. The easieast solution might be to only pass the -i argument if there is an ID, like that:

export function getParameters(options: NodePyATVFindAndInstanceOptions = {}): string[] {
    const parameters: string[] = [];

    if (options.hosts) {
        parameters.push('-s', options.hosts.join(','));
    } else if (options.id) {
        parameters.push('-i', options.id);
    } else if (options.host) {
        parameters.push('-s', options.host);
    }
    if (options.protocol) {
        parameters.push('--protocol', options.protocol);
    }
    ...

maxileith avatar Dec 09 '24 13:12 maxileith

Or even better imo:

export function getParameters(options: NodePyATVFindAndInstanceOptions = {}): string[] {
    const parameters: string[] = [];

    if (options.hosts) {
        parameters.push('-s', options.hosts.join(','));
    } else if (options.mac) {
        parameters.push('-i', options.mac);
    } else if (options.id) {
        parameters.push('-i', options.id);
    } else if (options.host) {
        parameters.push('-s', options.host);
    }
    if (options.protocol) {
        parameters.push('--protocol', options.protocol);
    }
    ...

maxileith avatar Dec 09 '24 13:12 maxileith

Sorry, I meant get host() of course. To be honest, I'm not sure whether it would make sense to implement it the way you proposed. If you then set hosts and id in a search (for example WiFi + Ethernet IPs), only -s would be passed to pyatv, which may give other responses then the previous approach.

I currently see these possibilities:

  • Fix it upstream and make pyatv handle it 🤪
  • Make NodePyATVDeviceOptions.host non-mandatory. Small breaking change, but it makes the most sense to me at the moment.
  • Add new parameter to control the way of connecting. By default, the behavior would be the same as currently, but optionally the parameter could be set to id or host. Quick fix, but somehow doesn't feel right to me.

I'll think about it some more, maybe I'll come up with something more useful.

sebbo2002 avatar Dec 09 '24 16:12 sebbo2002

If there is no urgent need here, I would release this feature at the end of April, when support for node.js v18 is discontinued as well. Then it will only be one breaking change. If this is somehow important or time-critical, please let me know again, we can of course prioritize it differently.

sebbo2002 avatar Jan 05 '25 15:01 sebbo2002

Waiting for new pyatv release to get tests through… https://github.com/postlund/pyatv/issues/2645

sebbo2002 avatar Apr 16 '25 17:04 sebbo2002

:tada: This issue has been resolved in version 9.0.0-develop.1 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

sebbo2002 avatar May 12 '25 16:05 sebbo2002

:tada: This issue has been resolved in version 9.0.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

sebbo2002 avatar May 12 '25 16:05 sebbo2002

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related issues and reference this one.

github-actions[bot] avatar Jul 13 '25 00:07 github-actions[bot]