| Back to Project Index | http://graham.auld.me.uk | E-Mail me |
| GitHub - no project here yet |
So it's 2025 and I thought a little electric bike would be a good answer for commuting to work. Took a test ride on a 2021 Zero FXE and it was an absolute hoot - bought it.
There's the option to custom configure a drive mode with limited power - sounded great for winter riding given the insane amount of torque available on tap. So I downloaded the Zero Motorcycles NextGen app, fiddled around a bit to get it connected via Bluetooth and found it did the modern EV thing of telling you how much was in your battery, how long till it's charged etc. I thought it would be great to be able to use that to decide when to schedule charging in cheap overnight slots and perhaps keep a log of miles done over time.
Now the only connectivity on this bike is bluetooth to the phone app, no modern GSM back to the cloud for always on data access experience. Well clearly this is a problem to be solved!
I quite like the ESP8266/ESP32 devices and Tasmota, I'm already using a socket with an ESP8266 to switch on and off the charging supply so it's simply a little embedded software to use the bluetooth on that unit to speak to the bike (and it can even turn on the bike to wake it up) - that could then feed data back over the wifi to my MQTT server for further automation.
The other option I'm considering is an ESP device just run off the bike supply so when it's powered up it can act as BT to Wifi bridge to do that job, theoretically if I made that a CYD then I could have a secondary display with pointless extra information available.
The only thing getting in the way of me cracking on with one of these options is not knowing what's going on with the protocol on that bluetooth link to the app!
These are the steps I followed but given lots of it depends on your exact device and version either you know how to do it or you can search to work out how to do these actions on your device
On an Android phone - enable developer mode, enable the bluetooth HCI log. Restart bluetooth radio then connect up and use the app.
Next download the bluetooth log - easiest way may be to create a bug report and pull the log from that zip file.
using wireshark you can open up that log and there'll be loads of packets. Of practical interest is that there's an RFCOMM connection running Serial Protocol Profile - use the btspp filter in wireshark to show just those packets
Now you've a whole bunch of serial port traffic flying back and forth.
Any embedded developer will probably have dealt with multiple serial protocols and maybe designed their own and there are a few common factors: Headers, packet types, packet lengths, footers and checksums. Headers are a great way to have some vaguely unusual bytes to help your reciever spot the start of a message. A message type lets your reciever know what you expect it to do, a length is pretty much essential to allow sending variable amounts of data. Footers are good for the same reason as headers, makes it easy to spot and parse packets. Checksums are good for data integrity (or spotting problems and ignoring junk)
Looking at transmission from the from the app to the bike, This data falls into that standard pattern:
4 bytes of common header
4 bytes of zeros
4 bytes of ASCII range data where we see a subset of values that kind of maybe look like commands
4 bytes of common footer
4 bytes of random data (probably a checksum)
Looking at the data coming back, it's similar structure but those zeros look like a little endian 32 bit number which varies with packet length
The ASCII range data is repeated back (probably echoing the request type in the response)
Now we see some extra data before the footer - coincidentally the same number of 4 byte groups as that little endian non zero number - ahha, this will be the data and that other bit will be packet length
This kind of looks like we're doing things with 32bit numbers and that's maybe a 32bit CRC on the end - so we take all the data between the header and footer, shove with through the common CRC32 algorithms... Ah ha, make the result little endian and a common CRC32 algorithm protects the packets!
Fairly standard structure then for the packets, it's request and response with a bunch of types, each type has a specific response and those types can have differing length responses.
What on earth do all those number mean that come back?????