Popular Post Paco Gorina Posted February 4, 2016 Popular Post Posted February 4, 2016 (edited) I have tried to unravel the Ninebot One E+ <--> Phone protocol and have had some success. They use Bluetooth LE and Ninebot defines : Service FFE0 Characteristic FFE1 ( Read, Write without response, Notify) Commands are sent from the phone to the 9B writing the variable and answers are recovered subscribing to the variable. All messages are sent as packets like +---+---+---+---+---+---+---+---+---+ |x55|xAA| l |x09|x01| c |...|ck0|ck1| +---+---+---+---+---+---+---+---+---+ Where ... Are a UInt8 array of l-2 elements ck0, ck1 are computed from the elements from l to the last of ... x55 and xAA are fixed and are Beggining of buffer l is the size of ... + 2 x09 and x01 seem fixed for Ninebot One. Not seen other values. c is variable to read or give info about A difficulty is that messages may be spread between different variable updates. I believe that comes from some old software and has been ported here. So we may not just subscribe to the variable and process each update but must look at the x55 xAA for finding the start of buffer and use the len field for getting to the end. I have written all details that I have been able to get in "Protocol Good.txt" including the meaning of some of the variables I have written a dirty and fast Swift class that implements a message, is capable to compute checksums, validate a message, parse the message and generate messages from different sources. It is better than the decompiled code and really works establishing a communication with the Ninebot and getting information. Decoding Fields is a spreadsheet for help in figuring what are and what unit have different variables. I am working in making a better Man in the Middle program (for iOS, sorry no good knowledge of Android) so we can get all the communication between the 9B application and the wheel. I would like to complete it and when I have the Man in the Middle program working will post sources so someone may try with another models. In the following link you may find the files with the information. Would like to start a thread so we may get all the protocol unraveled. The Android Ninebot application has many "switch" for different devices so probably I have only seen a subset of what is capable. https://www.dropbox.com/sh/2dcadhphgktqlgs/AADmFLuGryUfKKd5O90h0oSea?dl=0 Edited February 4, 2016 by Paco Gorina 12 Quote
Richard.D Posted February 5, 2016 Posted February 5, 2016 @Paco Gorina, great job dude! While seems the dropbox page( https://www.dropbox.com/sh/2dcadhphgktqlgs/AADmFLuGryUfKKd5O90h0oSea?dl=0 ) says "This folder is empty"... Quote
Paco Gorina Posted February 5, 2016 Author Posted February 5, 2016 (edited) 1 hour ago, Richard.D said: @Paco Gorina, great job dude! While seems the dropbox page( https://www.dropbox.com/sh/2dcadhphgktqlgs/AADmFLuGryUfKKd5O90h0oSea?dl=0 ) says "This folder is empty"... Sorry, my Dropbox is quit clogged syncing some Gb I post them in this message Now the Dropbox link must be full, Anyway here are the files Protocol Good.txt Decoding Fields.xlsx BLENinebotMessage.swift Edited February 5, 2016 by Paco Gorina 1 Quote
Paco Gorina Posted February 10, 2016 Author Posted February 10, 2016 Added a new file with all the decoded fields I Know, formats and units. Decoded Fields.xlsx I have now a very simple client that works in iOS and allows logging data to a File and presenting it graphically. Hope to have it clean a ready for the Apple Store. Anyway once clean will post a project in Github 3 Quote
Gil Posted February 10, 2016 Posted February 10, 2016 To have a log of current intensity and power would be very useful. It would allow a rider to know whether he plays with limits or drives safely. Impressive work. Thank you. Quote
Paco Gorina Posted February 12, 2016 Author Posted February 12, 2016 Following decoding of NB protocol fields I upload a log with current (variable #80) and field #74 (for the moment unknown) to see if anybody might find a meaning for #74 9B_20160211_224018.xlsx 9B_20160211_224018.txt Quote
Cranium Posted February 12, 2016 Posted February 12, 2016 5 hours ago, Paco Gorina said: Following decoding of NB protocol fields I upload a log with current (variable #80) and field #74 (for the moment unknown) to see if anybody might find a meaning for #74 9B_20160211_224018.xlsx 9B_20160211_224018.txt Looking at the data, it appears that the current has a range of 817A to -235A which is a bit outside the range of abilities for the EU. Any ideas about why it is so far out? Could the positive and negative ranges may need another divisor applied to represent the actual current? The pattern I see in the #74 data is a cycling up and down. It may be gyro data. Can you align this data with speed to see if when you are stopped when it is around the 675 range? Quote
Paco Gorina Posted February 13, 2016 Author Posted February 13, 2016 Looking at the data, it appears that the current has a range of 817A to -235A which is a bit outside the range of abilities for the EU. Any ideas about why it is so far out? Could the positive and negative ranges may need another divisor applied to represent the actual current? Actually current must be divided by 100 to get Amperes. That is between 8.17 to -2.35 A which is much more reasonable. All the protocol uses ints and one must scale to get the units. I will get more varied logs of #74 but or it is. A discrete level variable or it seems to saturate but at different levels depending the moment. Quote
Paco Gorina Posted February 15, 2016 Author Posted February 15, 2016 I have found following code that suggest variable 74 is electric_voltage_12V. (scaled by 100) Also could be information about the lights (taken by bits) private class C1158c extends TimerTask { final /* synthetic */ jm f5976a; private C1158c(jm jmVar) { this.f5976a = jmVar; } public void run() { if (this.f5976a.f5987k != null) { Message message = new Message(); message.what = 0; Bundle bundle = new Bundle(); bundle.putInt("electric_voltage", this.f5976a.f5987k.m5787c(71)); bundle.putInt("electric_voltage_bat1", this.f5976a.f5987k.m5787c(72)); bundle.putInt("electric_voltage_bat2", this.f5976a.f5987k.m5787c(73)); bundle.putInt("electric_voltage_12V", this.f5976a.f5987k.m5787c(74)); bundle.putInt("electric_voltage_5V", this.f5976a.f5987k.m5787c(75)); bundle.putInt("electric_current", this.f5976a.f5987k.m5787c(80)); bundle.putInt("electric_current_moto1", this.f5976a.f5987k.m5787c(81)); bundle.putInt("electric_current_moto2", this.f5976a.f5987k.m5787c(82)); bundle.putInt("electric_current_phase_moto1", this.f5976a.f5987k.m5787c(83)); bundle.putInt("electric_current_phase_moto2", this.f5976a.f5987k.m5787c(84)); message.setData(bundle); this.f5976a.f5990n.sendMessage(message); } } } 1 Quote
Cranium Posted February 15, 2016 Posted February 15, 2016 34 minutes ago, Paco Gorina said: I have found following code that suggest variable 74 is electric_voltage_12V. (scaled by 100) Interesting find but a confusing one as well. The Ninebot uses a step down buck regulator to get the voltage to 13.46V using an LM5005. This voltage can vary slightly based on load on the 13.46V rail but should be pretty constant. I don't see how the "74" would map to this voltage. If we wanted to force it in, you can use "74" = x Where Voltage = 12+ x / 1000. This would provide a range from 12.041 to 13.632 in your spreadsheet but I don't like forcing a value into meeting expectations. Do you have the ability to measure the voltages directly to see if there is a correlation? What are you using to connect to make your BLE connection? I was going to order a BLE sniffer but Adafruit is currently out of stock. 1 Quote
Paco Gorina Posted February 15, 2016 Author Posted February 15, 2016 I am not using a sniffer, I built a program that simulates a client (a client for the Ninebot) and a server (that simulates the Ninebot). I connect the client part to the ninebot and the Ninebot application to the server. Every write to the variable done by the Application I pass to the ninebot and every variable update from the Ninebot I pass to the server. That way I may look at all the communication between the Ninebot and the applications. Hope to have the sources online in one or two days, now cleaning a little. They are for iOS. I have the pure client part that logs directly the data from the wheel and presents it graphically, stores it into a file and updates a mini application in the Apple Watch with the Speed, time and distance and battery level and remaining distance. Finishing some details and making them AppleStore suitable. 2 Quote
Rotator Posted February 15, 2016 Posted February 15, 2016 Great!!! First smartwatch unicycle app made! Quote
Paco Gorina Posted February 15, 2016 Author Posted February 15, 2016 Some screens from application : 2 Quote
Paco Gorina Posted February 16, 2016 Author Posted February 16, 2016 Sending data Seems similar than asking for values but the 0x09 0x01 are changed to 0x09 and 0x03 So to write the “riding mode” (variable 210, 0xd2 ) to 3 (hexa 0x0003)we shoud send 55 aa 04 09 03 d2 0300 1aff When setting speed limit its units must be m/h. For example for setting speed (variable 116 = 0x74) limit to 7 km/h 7 km/h = 7000 m/h = 0x1B58 55 aa 04 09 03 74 581b 08ff Must see what gets changed or not. 1 Quote
bdonkey Posted February 23, 2016 Posted February 23, 2016 (edited) Fantastic work, Paco! I am working on a project to autonomously drive the Ninebot Mini (just ordered one, hope it arrives soon), and plan to reverse engineer the BLE protocol. I hope it will be quite similar to what you've found here. I've got an Adafruit Bluefruit LE sniffer on the way, but have no idea when the Ninebot Mini will arrive... Edited February 23, 2016 by bdonkey Quote
Paco Gorina Posted February 23, 2016 Author Posted February 23, 2016 I think the official client program is the same so protocol must be the same and some of the variables which have no use in Ninebot One may have a use in Ninebot mini, for example there are right wheel and left wheel speeds etc. I don't believe you need the sniffer as you may use a man in the middle approach if it uses Bluetooth LTE. I am finishing to clean a bit the code of the MiM and the client to publish it in the Apple Store and it should work the same with the Ninebot mini but I have not way to checking it but I am bit delayed. Will see if I may add some additional fields from the disassembled Android code and will publish the findings in the protocol excel in a separate speculative section. As controlling the mini from an application I have no idea if it is possible. The One only has the maximum speed and som flags that may be set but I have not tried to change anything. Quote
bdonkey Posted February 23, 2016 Posted February 23, 2016 The Mini is supposed to be controllable from their app; I would expect it should use the same protocol, but we will see. 1 Quote
Paco Gorina Posted March 2, 2016 Author Posted March 2, 2016 Sent application to the Apple Store *9BMetrics"., will see if it passes the review. 1 Quote
bdonkey Posted March 3, 2016 Posted March 3, 2016 Cool, Paco! I only have an Android, unfortunately, but have been able to capture some wireshark packet traces of the BLE between the Ninebot Mini and the Ninebot app. The packet format looks similar to what you described, but I have not figured out the mapping from the handles to the specific characteristic UUIDs yet. ninebot-advertise-enterapp-enterremote-exitremote-exitapp.pcapng.gz ninebot-advertise-enterapp-exitapp.pcapng.gz nrfmastercontrolpanel-gatt-discovery.pcapng.gz ninebot-advertise-enterapp-enterremote-foward-backward-left-right-exitremote-exitapp.pcapng.gz 1 Quote
Paco Gorina Posted March 3, 2016 Author Posted March 3, 2016 (edited) I would look at the following variable/values as they seem related to two wheel or two battery devices. Especifically 33 handler angle should apply. Speed left and right should be speed of left and right wheel 33 handler_angle 63 T Bat 1 64 T Bat 2 38 speed average? 39 speed left 40 speed right 167 angle left 168 angle right Angle no idea what means Edited March 3, 2016 by Paco Gorina Quote
Jonathan Tolhurst Posted March 3, 2016 Posted March 3, 2016 This is excellent work @Paco Gorina. Next time it rains all weekend I will try cooking something up for Android (and hopefully Android Wear). 1 Quote
Popular Post Paco Gorina Posted March 4, 2016 Author Popular Post Posted March 4, 2016 While waiting the Apple approves the application all information and access to sources sumarized at : http://www.gorina.es/9BMetrics/ 4 Quote
OliverH Posted March 4, 2016 Posted March 4, 2016 Great work. This can be used also for an App for Open Source Boards using BLE communication. 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.