Rotator Posted March 4, 2016 Share Posted March 4, 2016 I would say that open source firmware could use this protocol so we can use ninebot client apps with any generic euc. Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 4, 2016 Author Share Posted March 4, 2016 A possible compatible protocol that allows better performance when supported in the application and maintains compatibility could be : - Let the request of a value be a "subscription" to the value. It would be in effect till it is cancelled in some way. That way the application doesn't need to flood the wheel with requests, just one and would continue to receive updates automatically. - A Legacy application would send many requests but most would have no effect. - As the Wheel knows when values change it would only notify a value when it changes or if it receives the request so new applications would be simpler. - Also I woud try not to split answers between many packets. Probably it is the same to the Nindroid application as far as we don't send packets too long (I believe is 28 bytes). It would be better to send more answers. That mades the client application near stateless which is always a plus. Quote Link to comment Share on other sites More sharing options...
bdonkey Posted March 10, 2016 Share Posted March 10, 2016 (edited) I'm now able to remotely control and drive the motion of the Ninebot mini, it's quite similar to what Paco described in the OP. Here are the additional details: The Ninebot mini uses a UART-style interface, similar to what Paco described, with some slight differences. It actually uses the same UUIDs as the "Noridc UART Service" 6e400001-b5a3-f393-e0a9-e50e24dcca9e WRITE COMMANDs (Write without response) are sent from the app to the "RX Characteristic" 6e400002-b5a3-f393-e0a9-e50e24dcca9e ("RX" is from the point-of-view of the Ninebot mini) NOTIFICATIONS of "TX Characteristic" value changes occur on 6e400003-b5a3-f393-e0a9-e50e24dcca9e Again, all messages are sent as packets structured like +---+---+---+---+---+---+---+---+---+ |x55|xAA| l | b1| b2| c |dat|ck0|ck1| +---+---+---+---+---+---+---+---+---+ x55 and xAA are indeed a fixed header; you can see that if you take a look through the decompiled Android app. b1 and b2 can vary, they are usually x09 and x01, respectively, as Paco observed, but for a lot of the "command" types that change something on the Ninebot mini, b2 is x03. I loosely suspect that b2=x01 means "get status variable / info" and b2=x03 often means "command" I haven't looked at all the messages yet, so I don't know if messages are still spread across multiple packets in some cases. Remote control of the Ninebot mini To enter remote control mode for the Ninebot mini, b1 = 0x0A, b2 = 0x03, c = 0x7A, and data = 0x0100 To send a drive command, b1 = 0x0A, b2 = 0x03, c = 0x7B, and data is 4 bytes, organized as such: +---+---+---+---+---+---+---+---+---+---+---+---+ |x55|xAA|x06|x0A|x03|x7B|s_l|s_h|r_l|r_h|ck0|ck1| +---+---+---+---+---+---+---+---+---+---+---+---+ where [s_l:s_h] is a 16-bit value (s_l is low bits, s_h is high bits) to set the target speed forward / backward. (The Ninebot mini figures out how much to tilt and when to reduce tilt angle / tilt in the opposite direction when it goes over the target speed, it has some sort of simple onboard feedback loop to try to reach the target speed). [s_h:s_l] from 0x7FFF to 0x0000 ranges from maximum forward speed to 0 forward speed [s_h:s_l] from 0x8000 to 0xFFFF ranges from maximum backward speed to 0 backward speed [t_l:t_h] is a 16-bit value (t_l is low bits, t_h is high bits) to set the turning speed left or right. [t_h:t_l] from 0x7FFF to 0x0000 ranges from maximum turning speed left to 0 turning speed left [t_h:t_l] from 0x8000 to 0xFFFF ranges from maximum turning speed right to 0 turning speed right Probably for safety reasons, you must continuously send these drive commands to keep the Ninebot mini in motion. If you stop sending drive commands, after a second or so, the Ninebot mini stops moving. Edited March 10, 2016 by bdonkey 3 Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 10, 2016 Author Share Posted March 10, 2016 Great!!! I found the Nordic service in dcompiled code but I didn't knew its use. As I understand the MIni doesn't have accurate movement (distance or angle) sensors? Nor, of cours GPS? Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 10, 2016 Author Share Posted March 10, 2016 An interesting finding : Variable 116 is the Speed Limit (you set it in m/h)(meters/hour). The Ninebot application only allows to fix it till 10 km/h. but the protocol allows other values and they are stored correctly and survive between stop/start of the wheel. Not checked if it really affects behavior but would be very interesting. Also variable 115 seems to be the maximum speed. Well, probably the speed to begin tilt back. In my Ninebot One E+ is set to 20 km/h. it would be interesting to know what is the value for the P. The application doesn't allow to change it but the protocol allows to change it to more or less than 20km/h and also survives between stop/start of the wheel. Not tested if it affects behavior. Will try after work. 1 Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 10, 2016 Author Share Posted March 10, 2016 Tested in the field : Update of speed limit is instantaneous but seems a firmware limit over 10 km/h but much less than 15 although you may set the speed limit at any value the maximum appears. Also updating the max speed does not allow you to run faster without tilt back. There must be some limit that is not up datable. Quote Link to comment Share on other sites More sharing options...
jesi Posted March 11, 2016 Share Posted March 11, 2016 Android version, please Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 11, 2016 Author Share Posted March 11, 2016 Sorry, I Don't have enough Android programming knowledge and experience to do it Quote Link to comment Share on other sites More sharing options...
jesi Posted March 11, 2016 Share Posted March 11, 2016 @esaj ? Quote Link to comment Share on other sites More sharing options...
esaj Posted March 11, 2016 Share Posted March 11, 2016 Well, Wheelemetrics is still the one and only Android-app I've ever written, plus I have no experience with Bluetooth LE. Maybe one day, if I get a wheel with BT LE, and have the time & energy... 1 Quote Link to comment Share on other sites More sharing options...
Popular Post Paco Gorina Posted March 21, 2016 Author Popular Post Share Posted March 21, 2016 Finals 9BMetrics 1.0 is ready in the App Store !!! Versión 1.1 near finished 6 Quote Link to comment Share on other sites More sharing options...
Chriull Posted March 22, 2016 Share Posted March 22, 2016 10 hours ago, Paco Gorina said: Finals 9BMetrics 1.0 is ready in the App Store !!! Versión 1.1 near finished Thank you! Made my first testride yesterday evening! To take our conversation from the "Anatomy of an Overlean" to were it belongs: On 18.3.2016 at 9:34 AM, Paco Gorina said: Made some tests and got sampling periods of aprox 0.05 s (varying) by changing to another thread and just don't waiting. Just made preliminary tests so I don't know if it has any impact in the wheel performance FYI the timing of my 9bots data comming in (all in sec) - I assume by now the version witht he event queue is now in the app store (and not the "fast" one with thread switching) Alt Current Speed Temp Voltage min 0,13070 0,00010 0,00020 0,01740 0,01870 max 0,26340 1,47750 0,25110 0,56080 1,82250 average 0,13956 0,01410 0,01191 0,12412 0,20685 Anyway - by this my 9bot just behaved very normal. The graphical representation is by now not implemented in the app? Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 22, 2016 Author Share Posted March 22, 2016 Yes, the version in the AppStore is the 1.0 without the fast reading. Unfortunately fast reading generates Big Files (easy 10Mb or more) so I am trying to reduce them. Yes graphical representation IS working in the v 1.0, just open the log and put your iPhone in Landscape position. It changes automatically. The data you present comes from? Data is from the screen of from the file?. Alt is change in altitude, not absolute altitude. It always begins with 0 and changes as you run. My "not moving data" for example is : Speed 0.00 Km/h Voltage 60.30V Current 0.04A Temp 23.9ºC in the screen Sorry for last answer. I misunderstood the values. Are seconds between samples. To explain better the log information, the file logs repeated values as 2 values. For example if you are looking into voltage and recieve 6100 (10 time) 6059(1 time) 6058 (1 time) you get 2 samples gor 6100 one with first time and the other with last time the application received 6100 The a sample for 6059 and another one for 6058 So the variation in Voltage timings is logical. Max is when the application receives many same values and doesn't stores them. Alt is totally different as it is loaded from the Altimeter. It also uses the same algorithm of not storing repeated values but frquency of updates is form another queue that is userd just for the altimeter manager. 1 Quote Link to comment Share on other sites More sharing options...
Chriull Posted March 25, 2016 Share Posted March 25, 2016 I used your app now again for a bigger tour through the city - works really great! I played now a little with awk and gnuplot to get the graphs ... need just a little bit more of formatting On two logs out of six (i always stopped recording for each longer stop - i assume i could have "restarted" by reconnecting in the same log file?) the app did not log the Current (80) - all other values where fine! Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted March 25, 2016 Author Share Posted March 25, 2016 The problem with current is known and solved in next version. Probably will upload one on Monday with some improvements. Problem is when it stops with a current = -0.01A It tinterprets it as No Value and doesn't save the data. In principle It should reconnect and probably will ask you for the device. In next version I doesn't ask. When reconnecting when you stop and start the wheel most values continue ok except things as distance that go to 0. Also in next version there is an easy export option which exports a selection of the track in TAB separated format, which is possible to import directly to Excel an most analysis programs. 3 Quote Link to comment Share on other sites More sharing options...
Jonathan Tolhurst Posted May 2, 2016 Share Posted May 2, 2016 Hi, Well I have picked up a sporting injury (unrelated to riding my EUC) so may have some time to attempt to create something for Android. I haven't built an Android app in several years and I'm unfamiliar with BLE but have managed to rework a BLE tutorial to connect to my NB1 and see some of the services and associated characteristics. @Paco Gorina - Can you confirm that I need to focus on service 0000ffe0-0000-1000-8000-00805f9b34fb and characteristic 0000ffe1-0000-1000-8000-00805f9b34fb Quote Link to comment Share on other sites More sharing options...
Paco Gorina Posted May 2, 2016 Author Share Posted May 2, 2016 You may get MY code, it is IN Swift and for iOS but changing to Java/Android should not be difficult. Connection code and service/variables are in BLEConnection.swift file Protocol is in BLEMessage and BLESimulatedClient. in http://www.gorina.es/9BMetrics/ there are pages for protocol and variable meaning. The wheel starts a server which offers Service FFE0 who has Characteristic FFE1 with attributes Read Write without response Notify Communication is always started by the application writing to the characteristic and answers are "notified" by the wheel varying the value of the characteristic. Hope that works for you. Get better for the injury. It is near 4 months I Amber fighting a Plantar Fascitis and it mines your moral. Quote Link to comment Share on other sites More sharing options...
Skara Posted May 20, 2016 Share Posted May 20, 2016 On 2 May 2016 at 8:52 PM, Paco Gorina said: It is near 4 months I Amber fighting a Plantar Fascitis and it mines your moral. Beside topic, but can't help commenting: good luck with the Plantar Fascitis! Mine was diagnosed a year ago, a standing desk being the probable cause. It is much better now, but I still can't walk more than a kilometer per day, which is miserable. However, the EUC is a great walking assistance device and the 9B1 greatly extended my territory. Quote Link to comment Share on other sites More sharing options...
androidian Posted February 24, 2017 Share Posted February 24, 2017 HELLO, Tthanks for the grate post @Paco Gorina i'm trying to communicate with my ninebot mini i need java code for the checksum method of w byte[] .. like you did in swift : func check(bArr : [UInt8], len : Int) -> (UInt8, UInt8) { //Comença a i2 = 2 per c bytes var i : UInt16 = 0; for i2 in 2 ..< len + 2 { i = (i + UInt16(bArr[i2])) } let v : UInt16 = (i ^ 0xFFFF) & self.CUSTOMER_ACTION_MASK return( UInt8(v & UInt16(255)), UInt8(v>>8)) } what i find so far is this code : long checksum(byte[] buf, int length) { int i = 0; long sum = 0; while (length > 2) { sum += (buf[i++] & 0xff) << 8; if ((--length) == 0) break; sum += (buf[i++] & 0xff); --length; } return (~((sum & 0xFFFF) + (sum >> 16))) & 0xFFFF; } CAN YOU HELP ME !! Quote Link to comment Share on other sites More sharing options...
Kinergy Posted September 3, 2017 Share Posted September 3, 2017 Great work and thanks for all the info! I'd like to write an app that records the forward/backward and left/right commands of an actual Ninebot rider while they are riding. I've got the basics working in an iOS app, I can get attributes from the Ninebot but it seems that the tilt angles attribute is actually the tilt angle of the Ninebot itself, not the control stick you push with your knees. Does anybody know which attribute might represent information related to the control stick angle that the rider is using? Also the same for the speed. Thanks! Quote Link to comment Share on other sites More sharing options...
Maksim Diakonov Posted May 8, 2018 Share Posted May 8, 2018 (edited) @bdonkey Could you please explain how to Unlock/Lock Ninebot Mini, I tried to write 55aa04090170000081ff to RX characteristics with no luck. Edited May 8, 2018 by Keith Linked bdonkey correctly but don’t hold your breath he hasn’t been here since 12/2016 Quote Link to comment Share on other sites More sharing options...
Chriull Posted May 8, 2018 Share Posted May 8, 2018 3 hours ago, Maksim Diakonov said: @bdonkey ... AST VISITED December 9, 2016 Quote Link to comment Share on other sites More sharing options...
ir_fuel Posted June 6, 2018 Share Posted June 6, 2018 This project is pretty dead it seems Quote Link to comment Share on other sites More sharing options...
infodev Posted June 26, 2018 Share Posted June 26, 2018 On 3/10/2016 at 4:04 AM, bdonkey said: I'm now able to remotely control and drive the motion of the Ninebot mini, it's quite similar to what Paco described in the OP. Here are the additional details: The Ninebot mini uses a UART-style interface, similar to what Paco described, with some slight differences. It actually uses the same UUIDs as the "Noridc UART Service" 6e400001-b5a3-f393-e0a9-e50e24dcca9e WRITE COMMANDs (Write without response) are sent from the app to the "RX Characteristic" 6e400002-b5a3-f393-e0a9-e50e24dcca9e ("RX" is from the point-of-view of the Ninebot mini) NOTIFICATIONS of "TX Characteristic" value changes occur on 6e400003-b5a3-f393-e0a9-e50e24dcca9e Again, all messages are sent as packets structured like +---+---+---+---+---+---+---+---+---+ |x55|xAA| l | b1| b2| c |dat|ck0|ck1| +---+---+---+---+---+---+---+---+---+ x55 and xAA are indeed a fixed header; you can see that if you take a look through the decompiled Android app. b1 and b2 can vary, they are usually x09 and x01, respectively, as Paco observed, but for a lot of the "command" types that change something on the Ninebot mini, b2 is x03. I loosely suspect that b2=x01 means "get status variable / info" and b2=x03 often means "command" I haven't looked at all the messages yet, so I don't know if messages are still spread across multiple packets in some cases. Remote control of the Ninebot mini To enter remote control mode for the Ninebot mini, b1 = 0x0A, b2 = 0x03, c = 0x7A, and data = 0x0100 To send a drive command, b1 = 0x0A, b2 = 0x03, c = 0x7B, and data is 4 bytes, organized as such: +---+---+---+---+---+---+---+---+---+---+---+---+ |x55|xAA|x06|x0A|x03|x7B|s_l|s_h|r_l|r_h|ck0|ck1| +---+---+---+---+---+---+---+---+---+---+---+---+ where [s_l:s_h] is a 16-bit value (s_l is low bits, s_h is high bits) to set the target speed forward / backward. (The Ninebot mini figures out how much to tilt and when to reduce tilt angle / tilt in the opposite direction when it goes over the target speed, it has some sort of simple onboard feedback loop to try to reach the target speed). [s_h:s_l] from 0x7FFF to 0x0000 ranges from maximum forward speed to 0 forward speed [s_h:s_l] from 0x8000 to 0xFFFF ranges from maximum backward speed to 0 backward speed [t_l:t_h] is a 16-bit value (t_l is low bits, t_h is high bits) to set the turning speed left or right. [t_h:t_l] from 0x7FFF to 0x0000 ranges from maximum turning speed left to 0 turning speed left [t_h:t_l] from 0x8000 to 0xFFFF ranges from maximum turning speed right to 0 turning speed right Probably for safety reasons, you must continuously send these drive commands to keep the Ninebot mini in motion. If you stop sending drive commands, after a second or so, the Ninebot mini stops moving. I was trying to send such packets my ninebot mini plus using 6e400002-b5a3-f393-e0a9-e50e24dcca9e Characteristic but nothing didn't work, I also tried to send write command packets I copied from Wireshark sniffing app, but also didn't help Also I see that official Ninebot bot app sends some Write Request (only once) after connecting to device mb we also need this? (command packets won't work without it?) https://stackoverflow.com/questions/51041629/android-ble-how-to-send-write-request-instead-of-write-command Quote Link to comment Share on other sites More sharing options...
pradeep narava Posted August 8, 2018 Share Posted August 8, 2018 Hi, I had seen reverse engineering(https://github.com/lukaville/mijia-scooter-reverse-engineering) code but was not able to find how to lock/unlock.Can anyone help me. Quote Link to comment Share on other sites More sharing options...
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.