electric-monk / pycarplay

Python Carplay library for the "Autobox" dongles
MIT License
268 stars 36 forks source link

iOS 14 #5

Open bnazari opened 3 years ago

bnazari commented 3 years ago

Amazing program! Have you had a chance to update the code to make it work with iOS14. The phone recognizes the device and adds it to the list of cars, but the protocol.py kicks out a "struct.error: unpack requires a buffer of 24 bytes" error. Not sure if this is a IOS14 issue or an issue with what I'm doing.

bnazari commented 3 years ago

So after messing around with the some more, it turns out the apk only works with the Carlinkit dongle and not one of the clones.

electric-monk commented 3 years ago

Ahh, that's a shame (also sorry for the late reply). I'm surprised it doesn't work on the clones though, I'd expect things to be pretty similar - is there a specific point where it fails, or are they totally different?

bnazari commented 3 years ago

No need to apologize for the late reply...what you have made is incredible. I changed the dongle on a whim after seeing this:

https://www.reddit.com/r/CarPlay/comments/iwch1s/autokit_android_carlinkit_worked_for_a_while_then/

Not sure at what point it fails, but definitely before the phone connection is made.

I was thinking of doing something slightly different (though my python skills are horrid.) It might be possible to display the H264 data on X and then VNC into it. Might end up having less overhead. Currently trying to understand your code a bit more. Attempted to play the audio packets through sounddevice, but I'm fairly far from being able to manage the speaker and microphone connection for now.

Like you, I am annoyed with the shenanigans of Tesla's refusal to allow CarPlay.

harrylepotter commented 3 years ago

I seem to have similar issues, even with the Carlinkit dongle mentioned on the readme on iOS 14:

Found USB device...
Connected!
Connection started!
Exception in thread Thread-103:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/home/pi/dev/pycarplay/link.py", line 77, in _read_thread
    msg = header.upgrade(self._ep_in.read(needlen))
  File "/home/pi/dev/pycarplay/protocol.py", line 36, in upgrade
    upd._setdata(bodydata)
  File "/home/pi/dev/pycarplay/protocol.py", line 164, in _setdata
    (v,) = struct.unpack("<L", data)
struct.error: unpack requires a buffer of 4 bytes

The device appears to register its name, and even the carkit logo appears, but then dies and nothing seems to get piped through afterwards. Running the .apk on an old android device w/USB OTG seems to work, which would suggest the dongle isn't faulty, but is perhaps running a new software version?

bnazari commented 3 years ago

@harrylepotter Quick suggestion... If you have an RPi lying around, try throwing Android on it and see if the Carlinkit app works on it. I discovered that the knock-off version of the dongle I bought on Amazon didn't even work with the app on Android.

harrylepotter commented 3 years ago

@bnazari - i tried this on an old Nexus 5 i had sitting in a drawer and the carplay works perfectly. I'm suspecting there may have been some changes to the box fw - according to the app it's running 2020.08.07.1519

harrylepotter commented 3 years ago

update: I found an older (jadx-able) 2019 version of the APK. Have observed that the files uploaded seem to differ in the older release.

harrylepotter commented 3 years ago

...From what i can see it initialized the car audio, but then i get this message back (protocol.py:164): array('B', [4, 0, 0, 0, 57, 48, 58, 65, 50, 58, 53, 66, 58, 67, 66, 58, 68, 65, 58, 57, 48, 234, 95, 115]) Seems like this is maybe a frame we should be dropping/ignoring, perhaps?

electric-monk commented 3 years ago

Most of that is clearly ASCII, and it decodes to "90:A2:5B:CB:DA:90" which looks like a MAC address. I assume it's something to do with the wifi/Bluetooth support (which my dongle never had, so I was unable to debug it).

harrylepotter commented 3 years ago

update: ignoring that message (the mac address seems to be the Bluetooth mac address of my iphone) results in a working implementation of teslabox.py:

index d2e1dfd..50a798b 100644
--- a/protocol.py
+++ b/protocol.py
@@ -38,6 +38,9 @@ class Message:
         except KeyError:
             upd=Unknown(self.type)
             upd._setdata(bodydata)
+        except struct.error:
+            upd=Unknown(self.type)
+            upd._setdata(bodydata)
         return upd

@electric-monk i dont suppose whist on your jadx adventures you found anything referencing sending keypresses? I'm trying to retrofit an old audi headunit with carplay. Noticed in the android app there's config to map keycodes to things like left/right/select/etc. I have a feeling like this is possibly a msgtype=8 with Value=4, and then some additional metadata on the keycode?

electric-monk commented 3 years ago

I'm sure I saw some mention of it (as you've also noticed). If I did I likely updated the "function name map" file I was using with jadx to show something more human readable, I thought I'd recently uploaded that into the repo but it looks like I didn't, I'll see if I can find it again as that might have some extra clues for anyone who wants to continue poking around in there.

harrylepotter commented 3 years ago

Amazing! thankyou so much!

harrylepotter commented 3 years ago

added support for buttons on another thread. Gist of protocol from Jad here: https://gist.github.com/harrylepotter/f4bfb37f11faf9efcfd6cd4b189cfa33

electric-monk commented 3 years ago

I uploaded the JADX function file to https://github.com/electric-monk/pycarplay/blob/master/Autokit.jobf, hopefully it has some useful extra function names in it (some that are just guesses).