Ogadai / zwift-mobile-api

MIT License
120 stars 25 forks source link

ZML emulation prototype #13

Closed wiedmann closed 6 years ago

wiedmann commented 6 years ago

This is a first pass at providing a way to emulate ZML. This version is fairly basic. I've just reverse engineered enough to get the player map updates. My protobuf decoding may not be correct. I thought I'd publish this in case somebody else is working on something that needs the same functionality.

usage: appConnection = account.getProfile(profile.id).getAppConnection()

Appconnection emits connected, msg, and playerInfo events. msg is the entire message, playerInfo just the playerInfo structures received (see proto file for fields).

Ogadai commented 6 years ago

Hi @wiedmann

This looks great!!

Am I right in thinking that it creates a server that listens on the (local) network and waits for the Zwift game to connect to it? It then pretends to be an iPhone and gives Zwift the Rider ID its logged in as (presumably so that Zwift agrees to the connection), and listens for messages.

It looks like there's a ton of info in those messages if we can figure out what it means :-)

Ogadai commented 6 years ago

I guess a side-effect would be that you wouldn't be able to use the actual ZML at the same time?

wiedmann commented 6 years ago

Correct on both accounts. There may be a way to do this as a proxy and forward all the messages to the real ZML, given that this is not an encrypted channel. I'm not sure of the right way to intercept the original connection request, though.

wiedmann commented 6 years ago

Oh and Pete Buckney did some work with a prior version of ZML that gives the rider list instead of 3D updates. I'm going to try to integrate that functionality as well at some point.

Ogadai commented 6 years ago

Ok, great! I'm happy to merge this as it is, as work-in-progress. When we get as far as documenting it in the readme, I think we need to make it clear that the usage is quite different from the other classes.

Thanks for this. I'm just starting to imagine all the interesting ways this could be used...

Ogadai commented 6 years ago

Hi @wiedmann

I've started updating zwift-mobile-link to work with the upcoming developer API. The old Protobuf calls are going to be json going forwards, so a lot of that Protobuf decoding stuff will no longer be needed.

It's looking a lot like the ZML emulation (communicating with Zwift on the local network), would be better off in its own repo. Would you be interested in taking that over and starting a new repo for it? You could take the Protobuf definitions too.

That would allow me to strip this repo down to the essentials, which is pretty much just helping with the credentials and authentication token handling.

wiedmann commented 6 years ago

I can do that, but it may take some time (busy at my day job right now). Would you be willing to keep the APIs and just deprecate them for now until I get the time to create the new project?

Ogadai commented 6 years ago

Yep, that should be fine.

snicker commented 2 years ago

did either of you happen to make any further progress here?

I've been maintaining the HomeAssistant integration for Zwift and I keep thinking about the usefulness of being able to rely on these local network communications.

@wiedmann - I think you had a packet sniffer for the UDP packets, will this work if it is running on another machine on the network?

wiedmann commented 2 years ago

@snicker - unfortunately I'm no longer doing Zwift development. Zwift has had a somewhat hostile stance towards outside development, so the incentive to do things isn't as high.

Promiscuous mode sniffing is theoretically possible, but whether you'll get the UDP packets from your Zwift machine(s) depends on your network architecture. Emulating the companion app is probably a more reliable approach, with the caveat that this may mean that the real companion app can't connect at the same time.

Another option would be to write a small agent that can be installed on the Zwift machine to forward data either to your Home Assistant plugin or MQTT. That way you wouldn't need promiscuous mode to get access to the UDP stream.