~hww3/org.openhab.binding.appletv

use pyatv install in userdata/tmp
remove colons from device id

clone

read-only
https://git.sr.ht/~hww3/org.openhab.binding.appletv
read/write
git@git.sr.ht:~hww3/org.openhab.binding.appletv

You can also use your local clone with git send-email.

#Apple-TVBinding (org.openhab.binding.appletv)

This openHAB 3 Binding implements control for the Apple-TV devices. This includes sending remote keys (control the Apple-TV from openHAB).

Author: Markus Michels (markus7017) Author: William Welliver (hww3) Check https://community.openhab.org/t/binding-for-apple-tv for more information, questions and contributing ideas. Any comment is welcome!

Release: alpha2, check master branch for stable release

This version of the Apple TV binding communicates with AppleTV devices using enhanced versions of the PyATV command line utilities. These utilities run continuously sending updates and receiving commands. Because they remain running at all times, the delays associated with starting new instances with each command. It also receives status updates from the AppleTV as the player state changes, so that most fields are always up to date without polling delays.

I've been using this binding for a week or two and things seem to work as I'd expect (subject to some of the constraints outlined in the rest of this document). You mileage may vary. This code is not well tested and may misbehave in myriad ways. If you encounter problems, please report them so that we can improve this binding for everyone.

New features:

  • Updated for OpenHAB 3.3 milestone. May work on earlier versions of 3.x. Will not work on 2.x.
  • Communicates with AppleTV via a pipe to PyATV command line tools rather than an embedded python running PyATV.
  • Receives power and play status updates from AppleTV dynamically so that polling is not required to keep fields (other than Current Position) up to date.
  • Power state channel (read-write) added with the ability to wake or put the device to sleep. This appears to be a feature of newer TvOS and commands sent to a sleeping device seem to be ignored.
  • Episode-related channels (read-only) added for applications that provide the breakdown.
  • Artwork channel (read-only) added to provide artwork Image data
  • App Name channel (read-only) added to display name of app playing (which is not necessarily the app currently on screen)
  • App Id channel (read-write) added to display the bundle identifier of the app playing. Can be written to in order to request a given application be launched. There seem to be certain constraints on this, it /seems/ that the play state must be stopped in order for the new application to be launched. This is likely an AppleTV side limitation.
  • Support for HomePods and other devices
  • Binding now understands which protocols must be paired and will indicate this during thing configuration.
  • Binding has very primitive support for using HomePods and AppleTV devices as audio sinks. This is preliminary and has a number of restrictions

##Installing:

Install pyatv

The AppleTV binding uses pyatv to communicate with the various Apple devices it supports. I’ve made some enhancements to pyatv in order to support more features than currently exists in the main pyatv project. So, for now, the easiest thing we can do to prevent conflicts if you might already have pyatv installed is to use python’s “virtual environments” feature. This allows you to have multiple independent copies of python modules installed so that they don’t need to be installed in python’s main system location.

First, make sure you’ve got python 3 installed (I’m using python 3.8). Also, make sure you have git and gcc and friends, required to install pytv’s dependencies. There’s usually a build-essentials package that will install all of this for you.

Now, run:

#my copy of openhab is installed in /opt/openhab3; you’ll want to set this to

#whatever folder contains your user data director.

OH_HOME=/opt/openhab3 python3.8 -m venv $OH_HOME/userdata/tmp/appletv-binding source $OH_HOME/userdata/tmp/appletv-binding/bin/activate pip3.8 install git+https://git.sr.ht/~hww3/pyatv

At this point, you’ve got a private installation of my customized pyatv located in the openhab temp directory. If you clear this out, you’ll need to reinstall pyatv.

Eventually, I’m going to attempt to automate this process so it won’t need to be done manually in the future.

If you want to try out the pyatv installation, enable the python virtual environment you created by running:

source $OH_HOME/userdata/tmp/appletv-binding/bin/activate

And the command prompt should change to reflect this. Now you can run something like:

atvremote scan

And you should see output that shows your AppleTV and HomePod devices.

Now, you’ll need to make sure that openhab can find this, and the easiest way to do that is to add that “activate” line above to your openhab startup script. For me, that’s in the $OH_HOME/start.sh script.

If the binding can’t find the atvscript command (in particular), things won’t work and you’ll see failures in the log when the binding tries to do discovery and such.

Install the binding

Download the binding jar and place it in your OpenHAB addons/ directory. It should be detected automatically and be loaded.

Standard binding troubleshooting applies here:

  - delete your old AppleTV things.
  - check the log files for errors.
  - bundle:status in the openhab cli client.
  - Restarting openhab might be helpful.

The binding should auto-discover your devices. You'll need to generate pairing credentials and put them in your thing configuration. If you don't see your devices in the inbox after a few minutes, you should check the log files to see if there are errors related to running the pyatv tools (atvscript scan, etc). This is usually an indication that the pyatv tools aren't in the PATH that OpenHAB is looking in.

When you have added a new AppleTV thing and configured it properly with pairing information, it will be listed as "Online".

Note: Each AppleTV thing should cause 2 copies of atvscript to run on your openhab host: atvscript push_updates and atvscript command_loop. The binding uses these to communicate with your AppleTV to receive status updates and send commands, respectively. If you see more than one of each running for each AppleTV thing (and especially if you see many more), please report it as a bug!

Pairing:

There are a number of protocols in use by AppleTV and similar devices. Which protocols are supported will depend on your device and the version of software it's running. For each device, you should "pair" with all the protocols it supports. You can do this by using the "atvremote" commands.

For example:

#$ atvremote scan Scan Results

   Name: Living Room

Model/SW: Apple TV 4, tvOS 15.4.1 Address: 192.168.1.136 MAC: C8:69:CD:80:02:EA Deep Sleep: False Identifiers:

  • C8:69:CD:80:02:EA
  • C869CD8002EA Services:
  • Protocol: Companion, Port: 49152, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
  • Protocol: AirPlay, Port: 7000, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
  • Protocol: RAOP, Port: 7000, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory

This is my AppleTV Gen4 which I've cleverly named "Living Room" with an identifier of "C869CD8002EA". It's fairly up-to-date, and we see it supports 3 protocols: Companion, AirPlay and RAOP. We'll pair each:

atvremote pair -i C869CD8002EA --protocol raop

You should get a prompt to enter the PIN displayed on screen:

Enter PIN on screen:

If you enter the PIN and hit Return, you should get a pairing authentication string that you can copy and paste into the appropriate spot in your configuration. In order to get the most functionality, you'll need to perform this operation with each of the protocols your device supports. Each authentication string needs to be placed in the appropriate configuration setting; they're not interchangeable and are specific to the device you've paired with.

To pair the remaining 2 protocols, I used the following commands:

atvremote pair -i C869CD8002EA --protocol airplay atvremote pair -i C869CD8002EA --protocol companion

Once you've paired and entered the authentication strings into your thing configuration, the binding should connect and start receiving updates automatically. The binding currently outputs a good deal of information about the process, so if things don't seem to be working, you should check your openhab log file.

##UPDATES:

  • Added a number of new remote keys, such as Home, Home Hold and Skip Forward/Backward
  • Shuffle mode, Repeat mode and Position are wired up for setting
  • App Name and App ID channels are now updated properly

##TODO:

  • Better error handling when pyATV has a problem
  • Need to control restarting of pyATV tools so that if the tool fails to start repeatedly, we back off. (in progress)
  • Ought to queue commands so that they aren't lost if the pyATV connection is temporarily down.
  • Ought to set thing to offline if our connections to pyATV are not up.
  • Need to permit location of pyATV tools to be specified (python venv?)
  • Should detect available features (in progress)
  • Need to submit pyATV enhancements upstream
  • Broader support for more ATV features: sending streams to airplay, text to speech, etc. (in progress)
  • Easier installation (perhaps automate the python setup process?)
  • Easier pairing (maybe?)

Notes from previous version of the binding:

Known issues:

  • Binding configuration and device pairing needs to be implemented
  • On macOS Python 3.6 is used, on Linux Python 3.5
  • Support for Synology NAS (amd64) is not verified
  • Not yet very well tested with more than one Apple-TV (should work, may cause timing issues)
  • The binding copies the embedded pyatv modules to a temp folder on each startup, this will be solved with upcoming binding configuration.
  • If some special conditions you'll see tons of exceptions when the binding is started. This needs to be reproduced and fixed.
  • The Python module contains some output to stdout/debug, this needs to be optimzed

Please note: This is a beta release, it has bugs, requires manual install etc. Questions, feedback and contributions are welcome (e.g. improving this documentation).

Looking for contribution: If you are familar with HTML and CSS you are welcome to contribute a nice HABpanel widget. ;-)


#Supported Devices, Platforms

Devices

  • Apple-TV 4 - fully supported, verified by community
  • Apple-TV 3 - latest firmware - fully supported, development environment
  • Apple-TV 2 - no information, won't expect to work

Platforms

  • macOS - dev environment is Mojave, but should also work with Sierra and High Sierra
  • Raspberyy with OpenHabian - default test environment
  • Ubuntu 18.04 - verified by the community
  • Synology NAS - supported running a virual environment, native support not yet verified
  • Win32 - only on request and with support of the user, because I know there are relevant differences in running Python on Win32 -> contact author
  • others currently not supported - contact author

#Supported Things

Thing Type
device Represents an Apple-TV device

#Discovery

The binding supports auto discovery of Apple-TVs on the local network. Once the Apple-TV (using atvremote) the binding could discover the device. Integration of pairing functionality is planned for an upcoming release. For now you need to pair your device first (using atvremote cli) before performing auto discovery in Paper UI.

  • make sure all required packages have been installed
  • run "atvremote scan" - this will show you the ip address of your Apple TV device
  • run "atvremote pair -r openHAB - this will initialte the pairing process
  • On your Appe TV screen go to Settings->General->Remotes
  • you should see the openHAB remote - if not you need to restart the Apple TV
  • select the "openHAB" entry - the Apple TV requests a pairing code
  • enter "1234" - the process should be completed without an error
  • you could terminate the "atvremote pair" command with [Return]
  • you should see the login id, which will be required for the thing configuration

Proceed with Thing Configuration below.

#Binding installation

For now the bindinng is not available on the Eclipse Smart Home Market Place nor part of the openHAB distribution so you need to install it manually.

As described the binding integrates the Phyton-based PyATV project so you need to install Python 3.5 and the required modules:

  • Platform software packages: sudo apt-get update sudo apt-get install python3.5 python3-pip libpython3.5 python3-jpy sudo apt-get install avahi-utils Python 3.5 for macOS can be found here: https://www.python.org/downloads/mac-osx/

  • Python modules: sudo python3.5 -m pip install pyatv zeroconf sh On macOS use Homebrew to install the Python 3.6(!) and additional modules. Make sure those modules go into the Python 3.5/3.6 folders. if you have multiple versions installed (by using the pip3.5/pip3.6 command).

  • Verification You should verify the installation before installing/configuring the binding: atvremote --address --login_id top_menu should work without error messages and move the focus on the Apple-TV to the top menu.

  • The binding itself Copy the binding jar to openHAB's addons folder, add the thing in Paper UI (see below) and restart openHAB.

#Binding Configuration

There are no textual configuration files.

#Thing Configuration

Before adding the thing make sure that all pre-requisites are met and all modules have been installed (see above).

You could use Paper UI to run auto discvery from the Inbox or to add a thing manually

  • Go to Configuration->Things and click on '+'
  • Select Apple TV Binding
  • fill in the device's ip address and login id as discovered through the pairing process
  • Once you save the configuration the thing should become online

#Channels

Group Channel Type
control remoteKey Send a key or key sequence to the Apple-TV, see below for valid keys
----------- ----------- ----------------------------------------------------------------------------------
playStatus playMode Current play mode: No Media/Idle/Loading/Playing/Paused/Fast Forward/Fast Backward
mediaType Media type being played: None/Music/Video/TV/Unknown ]
title Title of current media. ]
artist Artist - only for Media Music ]
album Album - only for Media Music ]
genre Genre - only for Media Music ]
position Position within the media. While playing the position gets updated in intervals. ]
The position could be changed, send the following format to the channel. ]
+: Move forward, e.g. +10 moves 10sec forward; +5:00 moves 5min forward. ]
-: Move reverse, e.g. -10 moves 10sec backward; +7:00 moves 7min backward. ]
totalTime Total time/duration of the media currently plaing. Note: could be 00:00:00! ]
shuffle Music Shuffle Mode - True: shuffeling, False: no shuffeling ]
repeat Music Repeat Mode - Off: no repeat, Track: repeat track, All: repeat playlis ]

#Keys

The following keys could ne semd with channel remoteKey

  • up - Press key up
  • down - Press key down
  • left - Press key left
  • right - Press key right
  • select - Press key select
  • play - Press key play
  • pause - Press key play
  • next - Press key next
  • previous - Press key previous
  • stop - Press key stop
  • top_menu - Go to main menu (long press menu)
  • menu - Press key menu

There are special keys, which will be mapped into a key sequence:

  • movie - go to the Movie selection
  • music - go to the Music selection
  • tvshows - go to the TV Show selection

The key sequences can be configured in the thing settings if the defaults don't work for your setup. RThe sequence must match the order of the menu items on the main menu.

Note: You could also send a key sequence, e.g. "top_menu up up left left select"

#Full Example

Note: PaperUI is recommended, if you want to use text files make sure to replace the thing id from you channel definition

  • .things

  • .items String Atv_Remote "ATV [%s]" {channel="appletv:device:34fc39d8:control#remoteKey"}

  • .sitemap Switch item=Atv_Remote mappings=[up = "^" ] Switch item=Atv_Remote mappings=[left = "<", select = "Sel", right = ">" ] Switch item=Atv_Remote mappings=[menu = "Menu", down = " v ", play = "Play" ] Switch item=Atv_Remote mappings=[previous='Prev', pause='Pause', next='Next']

  • .rules // wakeup the Apple-TV sendCommand(Atv_Remote, "top_menu")

#Notes

It integrates the PyATV Python library, which implements the protocol layer. The binding includes also platform specific stuff (jpy Java/Phyton bridge). All modules are included in the binding package and the binding tries to auto-select them. An upcoming version will allow to overwrite this auto-detection in case something went wrong or you have specific installation requirements.

Thanks postlund for his great work in contributing the PyATV library (https://github.com/postlund/pyatv) and the jpy team (https://github.com/bcdev/jpy).