Table of Contents
- Fake Device
A few tools are shipped with pyatv that are only used internally or serving as help during development. This page gives a brief introduction to them.
This section describes how to work with Google Protobuf in pyatv. Protobuf is used by the
MRP protocol only.
All Protobuf definitions (
.proto files) are located in
pyatv/mrp/protobuf. Currently the generated files, including mypy hints (
.pyifiles) are checked in to the repository. Preferably only the
.proto files should be checked in and in the future this might be the case.
To simplify working with Protobuf messages in code, an auto-generated wrapper is used. This wrapper is generated by
scripts/protobuf.py and provides some convenience:
- Message constants are available at top level (
- Messages are more easily available (
inner()will return the encapsulated message from a
The file is checked into the repository and located here: mrp/protobuf/__init__.py. See Making Changes on how to generate this file.
You shall not modify this file manually. Instead modify the
.proto files and re-generate
the wrapper code. If something is missing or wrong in the wrapper code, make changes
If you add new
.proto files or modify existing files, you need to re-generate the message files. This is done with
$ ./scripts/protobuf.py --download generate Downloading https://github.com/protocolbuffers/protobuf/... Extracting bin/protoc Writing mypy to pyatv/mrp/protobuf/PlaybackQueueCapabilities_pb2.pyi Writing mypy to pyatv/mrp/protobuf/DeviceInfoMessage_pb2.pyi ...
See Protobuf Compiler for more details.
It is possible to verify if current messages are up-to-date using
$ ./scripts/protobuf.py --download verify Not downloading protoc (already exists) Generated code is up-to-date!
tox -e generated will ensure that this file is up-to-date. It is always run when checking in code.
See Protobuf Compiler for more details.
NB: This only verifies that the wrapper code is up-to-date at the moment.
A specific version of the protobuf compiler is used to generate the message to make sure they are always generated in the same way (version is hardcoded into
protobuf.by and may be bumped when needed).
--download will download and extract
protoc into the
bin directory. This works for Linux (x86_64), macOS and Windows (x64). If the file is already downloaded,
--download does nothing.
protobuf.py will verify that the downloaded version matches the version hardcoded into the script before generating messages. If there is a mismatch, just add
--force to make the script re-download the compiler again.
A fake device is used in the functional tests to verify that pyatv works as expected. It is however convenient to have a fake device that you can interact with using
atvremote. The script
scripts/fake_device.py is supposed to fill this gap until proper support is built into pyatv (see #334 and #518).
Beware that command line flags and options might change at any time due to new features. This script is only meant as development aid.
This is the current feature set:
- All protocols are supported - amount of functionality varies
- Protocols are found when scanning, e.g. supports Zeroconf
- Device reports idle state (nothing playing) by default
- Commands sent to it are mostly just logged to console
- A “demo” mode is included, which cycles between example video, example music and nothing playing every three seconds
No attempts have been made to integrate this with the real Remote app in iOS, which means that it probably doesn’t work. At least basic support for this would be nice.
Feel free to improve this script and the protocols implemented by fake device!
By default, the device will broadcast
127.0.0.1 as IP address in Zeroconf, so it is only usable on localhost. You can change this with
--local-ip. It is also possible to enable debug logs with
--debug. No protocol is selected by default, so you need to specify at least one for the script to run (but you may specify as many as you like). Valid flags are
MRP fake device:
$ ./scripts/fake_device.py --mrp Press ENTER to quit
atvremote from another terminal:
$ atvremote scan Scan Results ======================================== Name: FakeATV Model/SW: Unknown Model tvOS 13.x build 17K499 Address: 127.0.0.1 MAC: 40:CB:C0:12:34:56 Identifiers: - 6D797FD3-3538-427E-A47B-A32FC6CF3A69 Services: - Protocol: MRP, Port: 32781, Credentials: None $ atvremote -n FakeATV playing Media type: Unknown Device state: Idle Repeat: Off Shuffle: Off $ atvremote -n FakeATV --protocol mrp pair Enter PIN on screen: 1111 Pairing seems to have succeeded, yey! You may now use these credentials: e734ea6c2b6257de7...
It is possible to use multiple protocols:
$ ./scripts/fake_device.py --mrp --dmap --airplay Press ENTER to quit
And then scan for them:
$ atvremote scan Scan Results ======================================== Name: FakeATV Model/SW: 3 tvOS 13.x build 17K499 Address: 127.0.0.1 MAC: 40:CB:C0:12:34:56 Identifiers: - fakedev - 6D797FD3-3538-427E-A47B-A32FC6CF3A69 - 00:01:02:03:04:05 Services: - Protocol: DMAP, Port: 40747, Credentials: 12345678-6789-1111-2222-012345678911 - Protocol: MRP, Port: 40521, Credentials: None - Protocol: AirPlay, Port: 54472, Credentials: None
To interact with a particular protocol:
$ atvremote --id fakedev --protocol dmap playing Media type: Unknown Device state: Idle Repeat: Off Shuffle: Off
There is a “demo mode” that changes between various things that are playing that can be enabled with
$ atvremote -n FakeATV playing Media type: Music Device state: Paused Title: music Artist: artist Album: album Genre: genre Position: 22/49s (44.9%) Repeat: Off Shuffle: Off $ atvremote -n FakeATV playing Media type: Unknown Device state: Idle Repeat: Off Shuffle: Off
MRP supports push update (
DMAP get stuck in a loop):
$ atvremote -n FakeATV push_updates Press ENTER to stop Media type: Unknown Device state: Idle Repeat: Off Shuffle: Off -------------------- Media type: Video Device state: Paused Title: dummy Position: 3/123s (2.4%) Repeat: Off Shuffle: Off -------------------- Media type: Music Device state: Paused Title: music Artist: artist Album: album Genre: genre Position: 22/49s (44.9%) Repeat: Off Shuffle: Off -------------------- Media type: Unknown Device state: Idle Repeat: Off Shuffle: Off --------------------
Play Media with AirPlay
There is very limited support for
AirPlay. It is possible to “play” something, but it is just reported as “finished playing”, so nothing really happens. But it is possible to call
$ atvremote --id fakedev --airplay-credentials 75FBEEC773CFC563:8F06696F2542D70DF59286C761695C485F815BE3D152849E1361282D46AB1493 play_url=http://test
Some level of support for pairing is supported. Each section describes the limitations.
More or less full support for pairing is supported. Credentials and PIN code are however hardcoded, so the process will always look the same:
$ atvremote --id fakedev --protocol mrp pair Enter PIN on screen: 1111 Pairing seems to have succeeded, yey! You may now use these credentials: e734ea6c2b6257de72355e472aa05a4c487e6b463c029ed306df2f01b5636b58:b7e8e084ca1a31dee7dd5fd0ddb1c4cacdc99f5aa0b27f178ecc34bd369c7ad2:35443739374644332d333533382d343237452d413437422d413332464336434633413639:62386265346261642d393338662d343765652d613735632d346238396666393134626430 $ atvremote --id fakedev --protocol mrp --mrp-credentials e734ea6c2b6257de72355e472aa05a4c487e6b463c029ed306df2f01b5636b58:b7e8e084ca1a31dee7dd5fd0ddb1c4cacdc99f5aa0b27f178ecc34bd369c7ad2:35443739374644332d333533382d343237452d413437422d413332464336434633413639:62386265346261642d393338662d343765652d613735632d346238396666393134626430 playing Media type: Unknown Device state: Idle Repeat: Off Shuffle: Off
It is possible to initiate the pairing process with
DMAP, but since verification is usually done on the Apple TV (PIN code is entered on the Apple TV), it is not possible to finish it. Should be easy to fix.
Pairing is supported, but only with a specific set of credentials. This is because
AirPlay lacks generic pairing support and just use a static pairing sequence. But it can be done like this:
$ atvremote --id fakedev --airplay-credentials 75FBEEC773CFC563:8F06696F2542D70DF59286C761695C485F815BE3D152849E1361282D46AB1493 --protocol airplay pair Enter PIN on screen: 2271 Pairing seems to have succeeded, yey! You may now use these credentials: 75FBEEC773CFC563:8F06696F2542D70DF59286C761695C485F815BE3D152849E1361282D46AB1493
Streaming files and most other feature should work to some extent. Encryption is not supported.
Partial support for maintaining device state is implemented, but not for everything. Here is a simple example:
$ atvremote -n FakeMRP power_state PowerState.On $ atvremote -n FakeMRP turn_off $ atvremote -n FakeMRP power_state PowerState.Off $ atvremote -n FakeMRP turn_on $ atvremote -n FakeMRP power_state PowerState.On
What is currently playing is currently configured per protocol but should be consolidated in the future (the same thing should be configured once and reported the same over all protocols).