Direct HomePod Streaming Unresponsive
TheSpookyCat opened this issue ยท 50 comments
The current release of master is non-functional on Windows devices. No exception, no error, no requests even so much as logged to console. Going to test by going back a bunch of commits until I find out where it broke.
Update 1: I've gone all the way back to d28733e (when #4 was merged) and it's still not working. Very bizarre, likely just something to do with my setup.
Update 2: Restarted the device though I don't think that was the issue. I've tested it twice now and when I initiate the music playing from my HomePod, and then use my phone to also enable streaming to the receiver, it rejects the connection. Would love to know if someone else can repro
So rolling back past all PR/commits in the last week is still the same behaviour?
So rolling back past all PR/commits in the last week is still the same behaviour?
Yes. I've been unsuccessful getting it to work since. I've managed to get to the pairing stage, but even then it doesn't matter which OS version I'm on it just dies mid-pair and the connect fails ;/
can you try this https://github.com/glmnet/airplay2-receiver/tree/mix?
can you try this https://github.com/glmnet/airplay2-receiver/tree/mix?
Works a charm on iOS 15 once I disable the HKPairing flag. I've upgraded to Public Beta 1 now and that's still an issue though. See #29 for further details on that.
I can only assume something you're working on that branch has altered whatever was breaking - good job.
Looks like natis97 figured out that direct HomePod streaming doesn't work: https://github.com/natis97/airplay2-receiver-sound/blame/master/README.md#L42
I can confirm that even on your mix branch glmnet that HomePod streaming to this script does not work and that appears to be the main problem.
Repro steps:
- Select the AirPlay icon on any device
- Select 'Control Other Speakers & TVs'
- Select any HomePod and play music through it
- Attempt to sync audio playback with ap2-receiver
- HomePod will stop playing music, error message will appear on the device controlling the HomePod, and the entire playback queue of the HomePod will disappear like it was never there.
I'm testing only from iPhone 14.5 local music (actually YouTube Music app mostly, not Apple Music and not "Controlling other devices") also HK Pairing to the home app does not work for me (I get a POST pair-add/ which yields in a 404, I'm not sure what the state of this is so far)
If PTP is active as master is, and your device "qualifies" for dictating the PTP clock (kind of being master) it does not work unless you don't announce yourself as a PTP source, I've made a comment about that somewhere. You can check if that is the issue easily by removing these:
airplay2-receiver/ap2-receiver.py
Lines 231 to 238 in 543dd0c
I don't know what else can be making a difference.
also HK Pairing to the home app does not work for me (I get a POST pair-add/ which yields in a 404, I'm not sure what the state of this is so far)
In regards to this, I get the same:
POST /pair-add Not implemented!
192.168.1.113 - - [13/Jul/2021 20:24:52] code 404, message Not Found
Seems like a portion of airplay is missing for HK to function. pair-add
endpoint is unimplemented. There's pair-setup
to build the pair, then adding to that pair via pair-add
, which I guess involves a number of crypto operations to add a node to a group is performed.
Actually, it may be achievable. The PDF at the link you provided here https://developer.apple.com/homekit/specification/ suggests all of the M1-M6 steps are already available in our framework. But the endpoint is not added yet.
We have pair-setup
, but the doc lists in table 5-15 e.g. With the relevant sections being 5.10 - 5.15
Value | Description |
---|---|
0 | PairSetup |
1 | PairSetupwithAuth |
2 | PairVerify |
3 | AddPairing |
4 | RemovePairing |
5 | ListPairings |
without specifically mentioning POST pair-add
(above tables are likely TLVs). Although I suspect this is a tip of the iceberg: there may be an enormous amount that needs implementing.
Could you try the new branch https://github.com/openairplay/airplay2-receiver/tree/pair-add for this?
It's skeleton functionality for pair-add
, pair-remove
and pair-list
. It might even work directly to add. ( Altho I think any sane device will do a pair-list
first to see what's there. )
Read the included comments.
@LewdNeko and @glmnet do you have HK devices to test? If so, would you be willing to flesh out the skeleton methods with some read/write logic to save the pairings to a file?
Yeah, I can but we need to fix #29 for me to be able to test it at all.
OK - I just pushed what I think is a fix to the branch. Please give it a try :)
POST /pair-add
----- Pair-Add [1/1]
[Redacted]
----- ENCRYPTED CHANNEL -----
----------------------------------------
Exception occurred during processing of request from ('192.168.1.113', 49653)
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\socketserver.py", line 316, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 347, in process_request
self.finish_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Program Files\Python39\lib\socketserver.py", line 720, in __init__
self.handle()
File "C:\Program Files\Python39\lib\http\server.py", line 429, in handle
self.handle_one_request()
File "C:\Program Files\Python39\lib\http\server.py", line 395, in handle_one_request
self.raw_requestline = self.rfile.readline(65537)
File "C:\Program Files\Python39\lib\socket.py", line 704, in readinto
return self._sock.recv_into(b)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 596, in recv_into
data = self.recv(nbytes, flags)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 614, in recv
block_length_bytes = self.socket.recv(self.LENGTH_LENGTH)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 605, in recv
assert not flags and buflen > self.LENGTH_LENGTH
AssertionError
----------------------------------------
Let me know if you need more details.
can you comment out those assert directives and see how it proceeds?
assert not flags and buflen > self.LENGTH_LENGTH
force pushed some extra comments and class Permissions
can you comment out those assert directives and see how it proceeds?
assert not flags and buflen > self.LENGTH_LENGTH
Commented out - I see a POST /pair-add, the encryption data, and then nothing. My phone shows "Unable to Add Accessory".
Note in regard to fixing #29: new error.
POST /pair-verify
----- Pair-Verify [1/2]
----------------------------------------
Exception occurred during processing of request from ('192.168.1.113', 49719)
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\socketserver.py", line 316, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 347, in process_request
self.finish_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Program Files\Python39\lib\socketserver.py", line 720, in __init__
self.handle()
File "C:\Program Files\Python39\lib\http\server.py", line 429, in handle
self.handle_one_request()
File "C:\Program Files\Python39\lib\http\server.py", line 415, in handle_one_request
method()
File "E:\Projects\Web Dev\airplay2-receiver\ap2-receiver.py", line 368, in do_POST
self.handle_pair_verify()
File "E:\Projects\Web Dev\airplay2-receiver\ap2-receiver.py", line 700, in handle_pair_verify
res = self.server.hap.pair_verify(body)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 152, in pair_verify
res = self.pair_verify_m1_m2(req[Tlv8.Tag.PUBLICKEY])
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 486, in pair_verify_m1_m2
accessory_signed = self.accessory_ltsk.sign(accessory_info)
AttributeError: 'Hap' object has no attribute 'accessory_ltsk'
accessory_ltsk
OK - force pushed maybe a fix - can you try to repro this error again @LewdNeko ?
Could you try the new branch https://github.com/openairplay/airplay2-receiver/tree/pair-add for this?
It's skeleton functionality for
pair-add
,pair-remove
andpair-list
. It might even work directly to add. ( Altho I think any sane device will do apair-list
first to see what's there. )Read the included comments.
@LewdNeko and @glmnet do you have HK devices to test? If so, would you be willing to flesh out the skeleton methods with some read/write logic to save the pairings to a file?
At this point I managed to pair the receiver. iOS 14.5.
I don't understand what you need help with. I have an airport express and a HomePod mini
Didn't test your pushes after this point
Note in regard to fixing #29: new error.
AttributeError: 'Hap' object has no attribute 'accessory_ltsk'
What number is in the X-Apple-HKP header, if present, just before it stops?
Could you try the new branch https://github.com/openairplay/airplay2-receiver/tree/pair-add for this?
It's skeleton functionality forpair-add
,pair-remove
andpair-list
. It might even work directly to add. ( Altho I think any sane device will do apair-list
first to see what's there. )
Read the included comments.
@LewdNeko and @glmnet do you have HK devices to test? If so, would you be willing to flesh out the skeleton methods with some read/write logic to save the pairings to a file?At this point I managed to pair the receiver. iOS 14.5.
I don't understand what you need help with. I have an airport express and a HomePod miniDidn't test your pushes after this point
Good to know. So this branch fixes something for you? Wondering whether you have any devices running HomeKit (HK) and how they behave with this.
Play music:
POST /pair-verify
----- Pair-Verify [1/2]
----------------------------------------
Exception occurred during processing of request from ('192.168.1.113', 50125)
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\socketserver.py", line 316, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 347, in process_request
self.finish_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Program Files\Python39\lib\socketserver.py", line 720, in __init__
self.handle()
File "C:\Program Files\Python39\lib\http\server.py", line 429, in handle
self.handle_one_request()
File "C:\Program Files\Python39\lib\http\server.py", line 415, in handle_one_request
method()
File "E:\Projects\Web Dev\airplay2-receiver\ap2-receiver.py", line 368, in do_POST
self.handle_pair_verify()
File "E:\Projects\Web Dev\airplay2-receiver\ap2-receiver.py", line 700, in handle_pair_verify
res = self.server.hap.pair_verify(body)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 154, in pair_verify
res = self.pair_verify_m1_m2(req[Tlv8.Tag.PUBLICKEY])
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 488, in pair_verify_m1_m2
accessory_signed = self.accessory_ltsk.sign(accessory_info)
AttributeError: 'int' object has no attribute 'sign'
Add to HomeKit (with hap.py#L618 commented out):
Failure at POST /pair-add
still. Is pair_Add_m1_m2
missing some code?
Note in regard to fixing #29: new error.
AttributeError: 'Hap' object has no attribute 'accessory_ltsk'What number is in the X-Apple-HKP header, if present, just before it stops?
Here's the X-Apple-X headers:
X-Apple-AbsoluteTime: 648005521
X-Apple-HKP: 6
X-Apple-Client-Name: iphon ;3
X-Apple-PD: 1
I'm assuming the failure is because we're not returning a success?
# TODO: Point 3: the accessory must return success - what flags = success?
My Discord is Neko#0013
if that makes this easier to debug - I'm completely clueless as to what's going on with hap.py
Update: I've tried adding
self.accessory_ltsk = nacl.signing.SigningKey.generate()
self.accessory_ltpk = bytes(self.accessory_ltsk.verify_key)
to Hap.__init__
- That 'works' now. Only issue is that afterwards I get a POST /fp-setup
after which the server just hangs and the phone eventually times out the setup.
X-Apple-HKP: 6
X-Apple-Client-Name: iphon ;3
X-Apple-PD: 1
OK - in my setup it's 4. Remember, this is skeleton code, so no IDs are saved. If you nacl.signing.SigningKey.generate()
then you will overwrite the key already generated in an earlier stage. Pull my latest branch (with --force
)
X-Apple-HKP: 6
X-Apple-Client-Name: iphon ;3
X-Apple-PD: 1OK - in my setup it's 4. Remember, this is skeleton code, so no IDs are saved. If you
nacl.signing.SigningKey.generate()
then you will overwrite the key already generated in an earlier stage. Pull my latest branch (with--force
)
I've implemented the skeleton code locally. Currently, if I return a response from pair_add_m1_m2()
which has more than 2 items in the list I get the following error:
Exception occurred during processing of request from ('192.168.1.113', 50395)
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\socketserver.py", line 316, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 347, in process_request
self.finish_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Program Files\Python39\lib\socketserver.py", line 720, in __init__
self.handle()
File "C:\Program Files\Python39\lib\http\server.py", line 429, in handle
self.handle_one_request()
File "C:\Program Files\Python39\lib\http\server.py", line 415, in handle_one_request
method()
File "E:\Projects\Web Dev\airplay2-receiver\ap2-receiver.py", line 372, in do_POST
self.handle_pairing('add')
File "E:\Projects\Web Dev\airplay2-receiver\ap2-receiver.py", line 722, in handle_pairing
res = self.server.hap.pair_add(body)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 219, in pair_add
return Tlv8.encode(res)
File "E:\Projects\Web Dev\airplay2-receiver\ap2\pairing\hap.py", line 101, in encode
length = len(value)
TypeError: object of type 'int' has no len()
Easily repro-able by returning something like:
return [
Tlv8.Tag.STATE, PairingState.M2,
Tlv8.Tag.ERROR, PairingErrors.AUTHENTICATION
]
However, if it returns the "success state":
return [
Tlv8.Tag.STATE, PairingState.M2,
]
The phone you are pairing from will return an "Accessory Not Working" error. Is it possible that this "success state" is incorrect?
However, if it returns the "success state":
return [ Tlv8.Tag.STATE, PairingState.M2, ]The phone you are pairing from will return an "Accessory Not Working" error. Is it possible that this "success state" is incorrect?
Possibly..... Success isn't defined anywhere that I can find it (yet).
OK - in my setup it's 4. Remember, this is skeleton code, so no IDs are saved. If you
nacl.signing.SigningKey.generate()
then you will overwrite the key already generated in an earlier stage. Pull my latest branch (with--force
)
Not seeing any changes that might be fixing the earlier issue of .
accessory_signed = self.accessory_ltsk.sign(accessory_info)
AttributeError: 'int' object has no attribute 'sign'
Got a link handy? systemcrash/airplay2-receiver@pair-add and openairplay/airplay2-receiver@pair-add seem to be identical and not updated with whatever you did :)
TypeError: object of type 'int' has no len()
Might need an if/else to take care of length = len(value)
it's trying to get the data length. (TLV).
Not seeing any changes that might be fixing this. Got a link handy? :)
Just the pair-add
branch :)
Not seeing any changes that might be fixing this. Got a link handy? :)
Just the
pair-add
branch :)
Yeah I'm on the pair-add branch (latest) and still no cigar with that AttributeError
. Almost as if that Signing Key isn't being generated in any earlier stage for me.
You might need to stash your local changes and rebase.
accessory_signed = self.accessory_ltsk.sign(accessory_info)
AttributeError: 'int' object has no attribute 'sign'
If this is the error, then I think doing this should be correct:
self.accessory_ltsk = nacl.signing.SigningKey.generate() self.accessory_ltpk = bytes(self.accessory_ltsk.verify_key)
If this is the error, then I think doing this should be correct:
Yeah, I thought so too but it just does nothing until the phone times out. Really unsure what's going on with iOS 15 and AP2 xD
Even weirder, with the current pair-add branch I don't even see so much as a POST request when trying to pair using a device running iOS 14. Even normal music streaming doesn't work from iOS 14 unless I do as glmnet said before:
If PTP is active as master is, and your device "qualifies" for dictating the PTP clock (kind of being master) it does not work unless you don't announce yourself as a PTP source, I've made a comment about that somewhere. You can check if that is the issue easily by removing these
Enabling/disabling whether this speaker is the "master" should probably also be a command-line option.
Hmm - I'll see what I can do about that PTP bit.
I think the TLV encoding should be fine it we don't init LTSK to e.g. 0.
I was so tired and defeated last night I didn't even think of trying this with the latest changes on iOS 15
With these lines commented out, as well as adding the following to pair_verify_m1_m2
self.accessory_ltsk = nacl.signing.SigningKey.generate()
self.accessory_ltpk = bytes(self.accessory_ltsk.verify_key)
I've managed to get streaming from iOS 15 to the ap2 receiver working almost perfectly, meaing anything related to #29 is 100% fixed provided the above two lines exist.
With these lines commented out, as well as adding the following to
pair_verify_m1_m2
self.accessory_ltsk = nacl.signing.SigningKey.generate() self.accessory_ltpk = bytes(self.accessory_ltsk.verify_key)
OK!
I did some digging: could it be that the statusFlags are wrong? (ap2-receiver.py#L216)
https://openairplay.github.io/airplay-spec/status_flags.html
I think that ckdo's branch-sender made a start on this, and could be what we're missing. One of the flags in that spec is DeviceWasSetupForHKAccessControl
. Maybe if this flag does not get set, iOS thinks that pairing failed?
https://github.com/ckdo/airplay2-receiver/tree/branch-persistentpairings works for pairing but not audio playback. Going to try salvage what I can from it and include in a PR.
https://github.com/ckdo/airplay2-receiver/tree/branch-persistentpairings works for pairing but not audio playback. Going to try salvage what I can from it and include in a PR.
It's funny you should want to have a go at that. I just spent the last hour or so fixing exactly this in HAP! See latest commit ;)
Weird how we're thinking the same thing
Edit: ( non-transient pairing, which might not be the same as persistent pairing )
I'll rebase the pair-add branch onto this latest fix, if you think it helps. ( Will mean you have to rebase your branch, but... progress ).
Apologies - just force-pushed to master (to clarify last commit).
Apologies for my premature close - this issue is not yet fixed per-se.
After doing as you recommended systemcrash, I found that when selecting the speaker in HomeKit, it had solved an issue I didn't expect it to, one that I was going to raise in a separate thread. HomeKit now correctly displays the currently playing track whilst streaming to the speaker.
However, we are still not currently at a stage where a HomePod can stream to this receiver.
I have tested with and without the newly added -npm
flag to no avail. I can only think of two reasons why this may be the case:
- The current default feature set is incorrect.
- PTP needs to be wholly implemented.
What is the status of #35? What needs doing?
* The current default feature set is incorrect. * PTP needs to be wholly implemented.
What is the status of #35? What needs doing?
You could try turning off PTP and/or transient pairing:
-ftxor 48 41
When I disable PTP, I get a shk error for audio type 96... so:
-ftxor 48
* The current default feature set is incorrect. * PTP needs to be wholly implemented.
What is the status of #35? What needs doing?
You could try turning off PTP and/or transient pairing:
-ftxor 48 41When I disable PTP, I get a shk error for audio type 96... so:
-ftxor 48
For me, I get:
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\socketserver.py", line 316, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 347, in process_request
self.finish_request(request, client_address)
File "C:\Program Files\Python39\lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Program Files\Python39\lib\socketserver.py", line 720, in __init__
self.handle()
File "C:\Program Files\Python39\lib\http\server.py", line 429, in handle
self.handle_one_request()
File "C:\Program Files\Python39\lib\http\server.py", line 415, in handle_one_request
method()
File "E:\Projects\Web Dev\airplay2-receiver-lewdneko\ap2-receiver.py", line 379, in do_POST
self.handle_pair_setup()
File "E:\Projects\Web Dev\airplay2-receiver-lewdneko\ap2-receiver.py", line 735, in handle_pair_setup
res = self.server.hap.pair_setup(body)
File "E:\Projects\Web Dev\airplay2-receiver-lewdneko\ap2\pairing\hap.py", line 209, in pair_setup
res = self.pair_setup_m5_m6(req[Tlv8.Tag.ENCRYPTEDDATA])
File "E:\Projects\Web Dev\airplay2-receiver-lewdneko\ap2\pairing\hap.py", line 381, in pair_setup_m5_m6
self.pair_setup_m5_m6_2(dec_tlv)
File "E:\Projects\Web Dev\airplay2-receiver-lewdneko\ap2\pairing\hap.py", line 414, in pair_setup_m5_m6_2
with open("./pairings/" + self.device_id.decode("utf-8") + ".pub", "wb") as device_pairing_file:
OSError: [Errno 22] Invalid argument: './pairings/D4:F4:6F:06:49:82.pub'
Why are we trying to write a pairing at this point? This must've been something I missed when merging ckdo's branch into my own.
I think I fixed all the most recent errors here. But not sure about Streaming. I think this may be a product if how HAP should work. The spec mandates up to 8 connections. Whereas AP2 in this module supports ONE. So if another iDevice is online with this receiver, the HomePod might just crap out.
So... in my dev branch there are some developments. I opened Pandora's box: multi-threading.
@LewdNeko if you can test from my dev branch, and see how that works for you and your HP, I'd appreciate it.
So... in my dev branch there are some developments. I opened Pandora's box: multi-threading.
@LewdNeko if you can test from my dev branch, and see how that works for you and your HP, I'd appreciate it.
You my friend are pure magic. Streaming audio to the receiver & any amount of extra compatible devices works regardless of which device starts receiving first.
I did encounter a whole host of issues but these are all present with the master branch too so I would say your implementation for Ft59 is working flawlessly. Great job!