Tuesday, December 14, 2021

Reverse engineering the Laotie Ti30 scooter LCD display - part 3 - Encryption Broken!



In the previous post I had the chance of discovering and documenting most of what there is to learn about the communication between the LCD unit and the master ESC (speed controller) that drives the e-Scooter rear motor.

This is interesting information for anyone willing to build something that interfaces directly with these components. For example if the user wants to write an app that captures the speed information and other status data, knowing the serial protocol is of great use in order to implement a Bluetooth module that acts as man in the middle, and sends the data to a smartphone. Alternatively one might be interested in building a hardware device that fully replaces the LCD unit, e.g. exposing a fancy TFT LCD display with more features than currently provided by these units.

Because I didn't want to leave this topic incomplete, I decided to keep on digging and try to figure out what was that mystery byte B05 sent by the LCD in every transmitted frame. Because its value would both change erratically, and because I could not find how the gear data was being sent to the ESC, I got intrigued and suspected that this information had to be contained in this byte and sent with some form of encryption.

I started by a entering a John Nash kind of groove, while looking at long sequences of numbers and obsessively searching for a pattern.

While I realized that these sequences didn't seem that random anymore, there was still something missing in order to get the complete picture.

That is when I had the idea of throwing the values into an Excel spreadsheet, and get a plot of it. What a better way to understand patterns, than to represent these visually.

I could immediately tell that there was a fixed pattern that would repeat every 128 frames. By adding the frame sequence number to the graph, I could verify that (conveniently) there was correlation between the frame number and the increment relative to the previous value. 

This meant that the mystery field was a value being encrypted with a simple substitution cipher (pretty much a form of Vigenère cipher). So in principle extracting this collection of offsets from a certain chunk of ciphertext should get us the key. Because the exact values of this pattern would simply repeat over time, I took the assumption that the plaintext was not varying. And assuming that these were indeed offsets, I took the minimum value in the collection and built a key map by subtracting the minimum from each value in the latter.

Ran the key map against a larger dataset, and voilà:

I could see what appeared to be actual data.

Thinking back about the frame sent by the ESC, where I assumed that byte B03 was just an offset for providing entropy to other bytes of the payload, I decided to run the same type of analysis on the sequence of this "entropy" field, and I realized that just like in the LCD frame, albeit different, it was a pattern that also varied according to the frame:

Taking this information into consideration, I changed the two Python scripts (one for the LCD and one for the ESC frames) to decrypt the fields based on these two key maps. And to my satisfaction, this was correct. I could now understand what was the "mystery" field. It was nothing more than (as I suspected) the encoded gear value. As I varied the gear in the LCD unit, I would obtain the following values in binary:

  • Gear 1 - 0b00000101
  • Gear 2 - 0b00001010
  • Gear 3 - 0b00001111

For converting to the gear number I would simply mask the 6 most significant bits. So far I did not see other bits varying differently in this byte.

As before, the protocol details and the python scripts can be found here:

I also replaced the decryption of the ESC frames, by using the offset map as well, as given what I learned in this iteration, there is the possibility that what I considered as an entropy key, i.e. the byte B03, is also an encrypted field, even though so far from my observations it is always constant.

This information is valid for the LCD and Speed Controller manufactured by the company named Jipin (often also labeled as J&P). As I have mentioned in a previous post, this frame follows the same overall structure as the QS-S4 display, even though the meaning of the fields is not entirely the same in the latter.


Alex said...

So you are saying that the QS-S4 display can be a replacement display for the Ti30?
Would you loose anything when switching the two?

What would be the best P-settings for speed?

Thank you.

Creation Factory said...

Hello @Alex,

"So you are saying that the QS-S4 display can be a replacement display for the Ti30?"

No. The two use very similar messages, but there are some differences such as the byte used for encoding the gear. Eventually some functions may work, but there is no way of telling without testing with an actual QS-S4. At least the gear change would not work correctly, but other important things such as the P-settings don't entirely correspond between the two. Also, the encrypted fields can also be different or encoded with a different key (don't have enough data samples from the QS-S4 in order to determine if the encryption key is the same or not).

You may compare the differences, by looking at the info shared by the user @raxrip regarding the QS-S4:


Creation Factory said...

@Alex, regarding you second question:

"What would be the best P-settings for speed?"

For the Laotie, in order to maximize top speed, you need to set this P-setting to 100%:

P08 - Performance (0-100%): 100

Even though in some scooters people play with the parameter:

P00 - Wheel diameter: 11

In this particular scooter I don't think that this makes any difference in manipulating the top speed, because it does not look like this value is sent to the speed controller, only used for calculating the speed presented in the display I believe.

Unknown said...

@Alex, thanks a lot for your job.

More people have Problem with cut off level. the scooter cut with battery 55V.

the P01 46V and the rear controler cut the battery. you know hgow we can solve this trouble with physical adjustment in controler or flash programmation ?


Creation Factory said...


There are usually two different devices in the scooter which will do a voltage based power cutoff: one is the speed controller, and the threshold is defined by that P-setting. The other one is the BMS (Battery Management System) which is mounted within the battery itself. Now matter how low you set the cutoff voltage at the controller, if that threshold is lower than the BMS own threshold, the latter will kick in first.

Regarding the BMS, even if you are able to hack into it and change that value, it is a dangerous idea, as you increase the risk of battery dendrites and potentially a fire, or at least a damaged battery pack due to the deep discharge.

I personally prefer to stick to the controller default setting, and even then I don't let the battery discharge to the level where it shuts down the scooter.

Having the controller setting be so low that the BMS threshold is triggered also has the inconvenience that it might take some time until the BMS unlocks the battery protection.


Mr.Anonymus said...

Hello CF!
First of, thank you for sharing all of this with us!
I recently bought a Ti30 and it is scary fast. Have you come up with a way of having "ECO" mode while no speed limit? It sure would be interesting!

Thanks in advance!

Creation Factory said...

Hello @Mr.Anonymus, no unfortunately I haven't yet found a way of removing speed limit from ECO mode. That would be great though, because the throttle curve is much smoother in that mode.


Unknown said...

i want to use the software and it given this error
Traceback (most recent call last):
File "C:\Users\pc\Desktop\escooter-lcd-esc-decode-master\", line 4, in
import serial
ModuleNotFoundError: No module named 'serial'

Creation Factory said...

Hi @Unknown,

This script requires the "pyserial" module. Try installing it by typing:

$ pip install pyserial


Unknown said...

It says i have it installed

Creation Factory said...

What version of python are you using?


Unknown said...

It is 3.10.6

Unknown said...


Unknown said...

I attempted to run the script in Linux and received this message.

usage: [-h] serial_port error: the following arguments are required: serial_port

s it because the USB to serial cable is not plugged in, and what is the best one? Can you send a link thanks in advanced. love the work you do for the Laotie Ti30 community.

Creation Factory said...

Hi @Unknown,

You can use virtually any serial adaptor, as long as it provides 5 Volt TTL levels. If you want to tap into both TX and RX at the same time, you need two adaptors and have the two scripts running at the same time.

For example the FTDI FT232RL is a good option. There are plenty of places where you can find a board with these (e.g. Aliexpress, Banggood). Make sure you set the jumper on the board for 5 Volts.

Once connected, you can find the exact USB device that was assigned, by typing:

$ dmesg|grep ttyUSB


s1m0n said...

Hello, very great work ! The QS-S4 display is also included with the Vsett Scooter. The Vsett Scooter has a Vsett Controller and a Vsett Display. The Vsett display (and thus also QS-S4) is also compatible with the Kaabo controller. To the Kaabo controller belongs the LT-01 display ... but this offers less P-Settings than the Vsett display.

s1m0n said...

Hello, very great work ! The QS-S4 display is also included with the Vsett Scooter. The Vsett Scooter has a Vsett Controller and a Vsett Display. The Vsett display (and thus also QS-S4) is also compatible with the Kaabo controller. To the Kaabo controller belongs the LT-01 display ... but this offers less P-Settings than the Vsett display.

Ant said...

Hi there,
I have s861 display and it looks like it has the same protocol as you've decoded here.
Were you able to communicate from PC to the LCD or ESC?

I would appreciate your reply


Creation Factory said...

Hi @Ant,

I haven't tried implementing something to emulate the display or the ESC on the PC, based on this information it should be relatively easy to write something. One idea would be to replace the LCD altogether with something custom (e.g. a different board with a more sophisticated microcontroller and color display), but haven't found the time yet :)


Luis Teixeira