GithubHelp home page GithubHelp logo

boostreveng's Introduction

BOOSTreveng

Documenting my findings on reverse engineering the LEGO BOOST Move Hub.

My main interest is using Linux (MINDSTORMS EV3 with ev3dev) but this information might be usefull to everybody.

In Linux (Ubuntu) I usually use the gatttool command (from BlueZ 5) for simple bash scripts and pybluez (or just gattlib, https://bitbucket.org/OscarAcena/pygattlib) for python scripts. Usually same scripts run fine on ev3dev but since bluez, pybluez and the linux kernel are a bit behind Ubuntu sometimes I need to call gatttool from python as a workaround.

You should also see these other projects:

DISCLAIMER:

LEGO and BOOST are Trademarks from The LEGO Company, which does not support (most probably doesn't even know about) this project. And of course I'm not responsible for any damage on your LEGO BOOST devices.

Method: I'm using an ubertooth BLE sniffer with my Ubuntu laptop. Installed LEGO BOOST App on my Android phone (Huawey P8, not supported but it works, just need to get the full APK+OBB, there are a few sources like APKPure).

It's not easy to get consistent results. I'm using Wireshark and a filter for ATT protocol ("btl2cap.cid==0x004"). Have to try several times until I capture something useful - it seems that restarting Bluetooth on Android and restarting App helps. Also disabling my laptop internal BT and not running heavy programs seems to help.

Progress so far:

  • RGB LED color control
  • Motors (A, B, A+B, C, D) speed/timed control (also angle/rotation control but not complete yet)
  • Color Sensor- can identify colors
  • Distance Sensor - can measure distances
  • Motor rotation readings (A, B, A+B, C, D)
  • Button state reading
  • MIT App Inventor 2 released last month a new version of the BLE extension with lots of new features... and it works!

People: I was amazed by having people making questions and suggestions the very same day I started this project. Lately two github users joined in and gave a strong push, revising my confusing notes, testing on their own, starting their own projects and even also bringing their own BLE sniffers.

They've created a Slack group where people can work together.

I probably should add more names here but things are going too fast for me to keep up so please forgive me.

Content:

  • details of what we've found
  • a few bash scripts for Linux, even fewer python scripts also for Linux and one or two Android MIT AppInventor examples
  • some text files trying to explain how to use bash or python

Things will look somewhat chaotic for a while. Please accept that I lack a programming background and also that I'm not writing a book.

Roadmap:

  • Move Hub 6-axis tilt sensor readings [on progress]
  • Color sensor colored-light mode
  • Color sensor ? light intensity ?

Totally blind yet:

  • battery level - why didn't LEGO used the standard characteristic?!?
  • scan hardware configuration, detect changes

Issues:

  • although gatttool works fine, I'm having problems with gattlib
  • MIT AppInventor 2 is a pain, I believe I'm having a similar problem with encoding

I really don't understand why LEGO developers opted to put everything in just one handle. It forces us to send a long string even for simple commands, which increases latency. Using MIT App Inventor 2 (and probably other blockly languages like Scratch) with long commands gets difficult and clumsy.

UPDATE: https://github.com/LEGO/lego-ble-wireless-protocol-docs LEGO released a detailed (but still draft) specification of the BLE specs (officially named LEGO Wireless Protocol, LWP)

boostreveng's People

Contributors

dlech avatar helje5 avatar hobbyquaker avatar jorgepe avatar nathankellenicki avatar undera avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

boostreveng's Issues

First byte in commands

To further help (a little) in reverse engineering the protocol: Looking at all the example commands, the first byte must be the total number of bytes in the command:

  • 0c:00:81:37:11:09:64:00:32:64:7f:03 is 12 bytes (0x0C)
  • 0d:01:81:39:11:0a:64:00:32:32:64:7f:03 is 13 bytes (0x0D)
  • 08:00:81:32:11:51:00:01 is 8 bytes (0x08)
    and from the BoostRemote example app:
  • 09:00:81:(port):11:07:(power):64:03 is 9 bytes (0x09)

Create a Slack for coordination

A Slack would be nice to talk about stuff? I made a LegoBoost one, want to use this? Just let me know so I can add people.

D = 02

Confirmed that you can drive motor plugged into D with 02. (from the Boost Remote app code, and tested with gatttool)

gattlib not working

This works from Ubuntu 17.04 shell:

gatttool -b 00:16:53:A4:CD:7E --char-write-req --handle=0x0e --value=0c018139110a00069B9B647f03

This doesn't:

#!/usr/bin/env python3
from gattlib import GATTRequester, GATTResponse
from time import sleep

req = GATTRequester("00:16:53:A4:CD:7E",True,"hci0")
response = GATTResponse()
req.write_by_handle_async(0x0e, "\x0C\x01\x81\x39\x11\x0A\x00\x06\x9B\x9B\x64\x7F\x03", response)
while not response.received():
    sleep(0.1)
    print(response.received())
print(req.read_by_handle(0x0e))

Output:

['\x13']
['\x0c\x01\x819\x11\n\x00\x06\x9b\x9bd\x7f\x03']

Also replacing with a shorter command like changing LED color

gatttool -b 00:16:53:A4:CD:7E --char-write-req --handle=0x0e --value=080081321151000A

returns

['\x13']
['\x08\x00\x812\x11Q\x00\n']

Something is wrong after 3rd byte ?!?

Capture packets to figure out how to move a interactive motor to a precise angle

I’m a little stuck w/ the interactive motor. The angle based motor movement works kinda ok, but if I move forward and backward by say 40 degrees, the movement isn’t exact (also it is a move-by, not a move-to-angle). i.e. Vernie’s head doesn’t end up in the same position.

My assumption was that the interactive motto should be able to do this? And maybe even report the current position (but subscribing to the port values on 0x2 gives seemingly random values?)

However, it seems like the iPad app can do this. Shaking the head, it always seems to return the head to the 0-degree position.
It would be great to get some packets which reveal how to do this. I would think there is either a different command than the angle-one we currently have (a turn(to: angle) instead of turn(by: angle)), or there are notifications which report the current angle (so that the application can adjust it until it hits 0-degree).

Thanks! :-)

BLE protocol changed

Just for your information:

My BOOST Move Hub got firmware update from lego recently and
BLE protocol seems to have changed.

For example, motors command now has length 15(0x0f).

cmd=0f008110110cc2010000cece647f03

identify LEGO App blocks

There are lots of blocks in the App. I understand the purpose of most but there a few I am not sure (having a small phone instead of a tablet doesn't help).

Even when knowing the purpose of a block, I don't know the proper way to refer it unless call it "the 13th orange block from the left".

I have put a few screenshots in [this folder] (https://github.com/JorgePe/BOOSTreveng/tree/master/LEGO_BOOST_App_blocks) and I was thinking on creating some kind of page with an explanation of all blocks.

ColorSensors: Byte 2/3/4.

Color Sensor says:

2nd, 3rd and 4th bytes = 00 45 01 are still unknown

I think the second byte might be the high byte of the length, there are just no packets longer than 0xFF yet. Or reserved, not sure.

The 3rd byte is quite clearly the packet type.

The 4th byte seems to be the port (as registered by the 0x4 packets). 0x01, the color-distance sensor, at least in my setup.

6-axis tilt sensor

I have a doubt: is it possible to read yaw with the App?
I mean, with the Move Hub always horizontal, measure when it rotates left or right?

I can read roll and pitch but not yaw. Both with the App and directly through gatttool.
I was expecting that a 6-axis tilt sensor would get all 3 types of movement.

Train motor AutoID/resistor?

Hi Jorge,

Do you happen to know/are you able to measure the resistance for the AutoID on the train motor?

I ask as using a 2k2 resistor should mimic a WeDo motor, but when used with a Powered UP controller, this will result in "bang-bang" style on/off operation. If we can mimic a train motor instead, then it will allow continuous variable power to be provided when using a PUP controller.

Cheers,
Nathan

BLE Advertising Data

I just made an interesting discovery about the BLE manufacturer-specific advertising data on the BOOST Move Hub and Powered Up Smart Hub.

The first byte seems to indicate the button position. Normally it is 0x00, but if the button is pressed, it changed to 0x01. (On the Smart Hub, some of the other bytes change too, but I haven't figured out what that means).

Here are some other speculations:

Hub Boot Mode Example Advertising Data
Move Hub Normal 0x004006FE4100, 0x014006FE4100
Move Hub Firmware Update 0x000000104002
Smart Hub Normal 0x004107004300, 0x014107006300
Smart Hub Firmware Update 0x000000104002
Handset Normal 0x00420A134100, 0x01420A004100, 0x00420A006100

Interpretation of Normal mode data:

  • 1st byte is button state (0x00 for released, 0x01 for pressed).
  • 2nd byte is Hub ID (matches 5th byte in firmware update mode advertising data and matches the value returned by the 0x0B device info command). 0x40 = Move Hub, 0x41 = Smart Hub, 0x42 = Handset.
  • 3rd byte is alternate Hub ID? 0x06 = Move Hub, 0x07 = Smart Hub, 0x0A = Handset.
  • 4th byte is connection ID? - at least on Smart Hub and Remote. When you "reset" the hub (by pressing and holding the button for 5 sec during power up until the LED turns pale purple) this value is reset to 0x00. When you link a Handset to the Smart Hub, this seems to be assigned a random number that matches on both devices. Resetting and re-linking results in a different number each time.
  • 5th byte??? On Smart Hub bit 0x20 of this byte is set when the button is pressed and is cleared when the button is released (after a delay). On Handset, bit 0x20 is set when the button is released and cleared after a delay.
  • 6th byte (0x00) means normal firmware boot mode?

Interpretation of Firmware Update mode data:

  • 1st-4th bytes look like a version number as in the 0x03 device info command (i.e. 1.0.00.0000).
  • 5th byte is hub id (see 2nd byte in Normal mode).
  • 6th byte (0x02) means firmware update boot mode?

Note: Firmware Update mode is what you get when you press and hold the button for 5 seconds when powering on and the light turns pale purple. Once a connection is made, the lights change to alternating red, green, blue to indicate that firmware update is in progress. The Handset does not have bluetooth active in this mode, so presumably the firmware cannot be updated on that device - it just seems this is used to reset the channel selection.

Anyone have any other insights? Anyone have a Duplo hub (what is the advertising data there)?

BOOST Color and Distance Sensor info

I've been spying on my BOOST Color and Distance sensor

Like EV3 UART sensors, Powered Up UART devices (can't say "sensors" anymore since BOOST Interactive Motor is also UART) send data about the device at 2400 baud until the brick syncs with the device.

Here is the data that I captured and the interpretation according to lms2012.h and d_uart_mod.c.

Recorded bytes and interpretation (click to expand)
40  MESSAGE_CMD + LENGTH_1 + CMD_TYPE
25  Type = 37; BOOST Color and Distance Sensor
9a  checksum; 0xff ^ 0x40 ^ 0x25
51  MESSAGE_CMD + LENGTH_4 + CMD_MODES (similar to EV3 CMD_MODES with 2 extra bytes)
07  7 + 1; Modes = 8 (value used on EV3)
07  7 + 1; Views = 8 (value used on EV3)
0a  10 + 1; Modes = 11 (value used on Powered Up)
07  7 + 1; Views = 8 (value used on Powered Up)
a3  checksum; 0xff ^ 0x51 ^ 0x07  ^ 0x07 ^ 0x0a ^ 0x07
52  MESSAGE_CMD + LENGTH_4 + CMD_SPEED
00  LSB
c2  ..
01  ..
00  MSB; BitRate = 115200
6e  checksum; 0xff ^ 0x52 ^ 0x00 ^ 0xc2 ^ 0x01 ^ 0x00
5f  MESSAGE_CMD + LENGTH_8 + CMD_UNK1 (new PF2 command)
00  LSB
00  ..
00  ..
10  MSB; ??? = 0x10000000
00  LSB
00  ..
00  ..
10  MSB; ??? = 0x10000000
a0  checksum; 0xff ^ 0x5f ^ 0x00 ^ 0x00 ^ 0x10 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x10
9a  MESSAGE_INFO + LENGTH_8 + MODE_2; really mode 10
20  MODE_PLUS_8 + INFO_NAME
43  'C'
41  'A'
4c  'L'
49  'I'
42  'B'
00  ''
00  ''
00  ''; Name = "CALIB"
00  checksum; 0xff ^ 0x9a ^ 0x20 ^ 0x43 ^ 0x41 ^ 0x4c ^ 0x49 ^ 0x42 ^ 0x00 ^ 0x00 ^ 0x00
9a  MESSAGE_INFO + LENGTH_8 + MODE_2; really mode 10
21  MODE_PLUS_8 + INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
ff  ..
7f  ..
47  MSB; RawMax = 65535.0
83  checksum; 0xff ^ 0x9a ^ 0x21 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0xff ^ 0x7f ^ 0x47
9a  MESSAGE_INFO + LENGTH_8 + MODE_2; really mode 10
22  MODE_PLUS_8 + INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
cd  checksum; 0xff ^ 0x9a ^ 0x22 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0xc8 ^ 0x42
9a  MESSAGE_INFO + LENGTH_8 + MODE_2; really mode 10
23  MODE_PLUS_8 + INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
ff  ..
7f  ..
47  MSB; SiMax = 65535.0
81  checksum; 0xff ^ 0x9a ^ 0x23 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0x00 ^ 0xff ^ 0x7f ^ 0x47
92  MESSAGE_INFO + LENGTH_4 + MODE_2; really mode 10
24  MODE_PLUS_8 + INFO_SYMBOL
4e  'N'
2f  '/'
41  'A'
00  ''; Symbol = "N/A"
69  checksum; 0xff ^ 0x92 ^ 0x24 ^ 0x4e ^ 0x2f ^ 0x41 ^ 0x00
8a  MESSAGE_INFO + LENGTH_2 + MODE_2; really mode 10
25  MODE_PLUS_8 + INFO_UNK1 (new PF2 info)
10  ???
00  ???
40  checksum; 0xff ^ 0x8a ^ 0x25 ^ 0x10 ^ 0x00
92  MESSAGE_INFO + LENGTH_4 + MODE_2; really mode 10
a0  MODE_PLUS_8 + INFO_FORMAT
08  DataSets = 8
01  Format = DATA16
05  Figures = 5
00  Decimals = 0
c1  checksum; 0xff ^ 0x92 ^ 0xa0 ^ 0x08 ^ 0x01 ^ 0x05 ^ 0x00
99  MESSAGE_INFO + LENGTH_8 + MODE_1; really mode 9
20  MODE_PLUS_8 + INFO_NAME
44  'D'
45  'E'
42  'B'
55  'U'
47  'G'
00  ''
00  ''
00  ''; Name = "DEBUG"
17  checksum
99  MESSAGE_INFO + LENGTH_8 + MODE_1; really mode 9
21  MODE_PLUS_8 + INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
c0  ..
7f  ..
44  MSB; RawMax = 1023.0
bc  checksum
99  MESSAGE_INFO + LENGTH_8 + MODE_1; really mode 9
22  MODE_PLUS_8 + INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
ce  checksum
99  MESSAGE_INFO + LENGTH_8 + MODE_1; really mode 9
23  MODE_PLUS_8 + INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; SiMax = 10.0
24  checksum
91  MESSAGE_INFO + LENGTH_4 + MODE_1; really mode 9
24  MODE_PLUS_8 + INFO_SYMBOL
4e  'N'
2f  '/'
41  'A'
00  ''; Symbol = "N/A"
6a  checksum
89  MESSAGE_INFO + LENGTH_2 + MODE_1; really mode 9
25  MODE_PLUS_8 + INFO_UNK1 (new PF2 info)
10  ???
00  ???
43  checksum
91  MESSAGE_INFO + LENGTH_4 + MODE_1; really mode 9
a0  MODE_PLUS_8 + INFO_FORMAT
02  DataSets = 2
01  Format = DATA16
05  Figures = 5
00  Decimals = 0
c8  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0; really mode 8
20  MODE_PLUS_8 + INFO_NAME
53  'S'
50  'P'
45  'E'
43  'C'
20  ' '
31  '1'
00  ''
00  ''; "SPEC 1"
53  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0; really mode 8
21  MODE_PLUS_8 + INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
7f  ..
43  MSB; RawMax = 255.0
7a  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0; really mode 8
22  MODE_PLUS_8 + INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
cf  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0; really mode 8
23  MODE_PLUS_8 + INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
7f  ..
43  MSB; SiMax = 255.0
78  checksum
90  MESSAGE_INFO + LENGTH_4 + MODE_0; really mode 8
24  MODE_PLUS_8 + INFO_SYMBOL
4e  'N'
2f  '/'
41  'A'
00  ''; Symbol = "N/A"
6b  checksum
88  MESSAGE_INFO + LENGTH_2 + MODE_0; really mode 8
25  MODE_PLUS_8 + INFO_UNK1 (new PF2 info)
00  ???
00  ???
52  checksum
90  MESSAGE_INFO + LENGTH_4 + MODE_0; really mode 8
a0  MODE_PLUS_8 + INFO_FORMAT
04  DataSets = 4
00  Format = DATA8
03  Figures = 3
00  Decimals = 1
c8  checksum
9f  MESSAGE_INFO + LENGTH_8 + MODE_7
00  INFO_NAME
49  'I'
52  'R'
20  ' '
54  'T'
78  'x'
00  ''
00  ''
00  ''; "IR Tx"
77  checksum
9f  MESSAGE_INFO + LENGTH_8 + MODE_7
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
ff  ..
7f  ..
47  MSB; RawMax = 65535.0
a6  checksum
9f  MESSAGE_INFO + LENGTH_8 + MODE_7
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
e8  checksum
9f  MESSAGE_INFO + LENGTH_8 + MODE_7
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
ff  ..
7f  ..
47  SiMax = 65535.0
a4  checksum
97  MESSAGE_INFO + LENGTH_4 + MODE_7
04  INFO_NAME
4e  'N'
2f  '/'
41  'A'
00  ''; Symbol = "N/A"
4c  checksum
8f  MESSAGE_INFO + LENGTH_2 + MODE_7
05  INFO_UNK1
00  ???
04  ???
71  checksum
97  MESSAGE_INFO + LENGTH_4 + MODE_7
80  INFO_FORMAT
01  DataSets = 1
01  Format = DATA16
05  Figures = 5
00  Decimals = 0
ed  checksum
9e  MESSAGE_INFO + LENGTH_8 + MODE_6
00  INFO_NAME
52  'R'
47  'G'
42  'B'
20  ' '
49  'I'
00  ''
00  ''
00  ''; Name = "RGB I"
5f  checksum
9e  MESSAGE_INFO + LENGTH_8 + MODE_6
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
c0  ..
7f  ..
44  MSB; RawMax = 1023.0
9b  checksum
9e  MESSAGE_INFO + LENGTH_8 + MODE_6
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
e9  checksum
9e  MESSAGE_INFO + LENGTH_8 + MODE_6
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
c0  ..
7f  ..
44  MSB = 1023.0
99  checksum
96  MESSAGE_INFO + LENGTH_4 + MODE_6
04  INFO_SYMBOL
52  'R'
41  'A'
57  'W'
00  ''; Symbol = "RAW"
29  checksum
8e  MESSAGE_INFO + LENGTH_2 + MODE_6
05  INFO_UNK1
10  ???
00  ???
64  checksum
96  MESSAGE_INFO + LENGTH_4 + MODE_6
80  INFO_FORMAT
03  DataSets = 3
01  Format = DATA16
05  Figures = 5
00  Decimals = 0
ee  checksum
9d  MESSAGE_INFO + LENGTH_8 + MODE_5
00  INFO_NAME
43  'C'
4f  'O'
4c  'L'
20  ' '
4f  'O'
00  ''
00  ''
00  ''; Name = "COL O"
4d  checksum
9d  MESSAGE_INFO + LENGTH_8 + MODE_5
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; RawMax = 10.0
02  checksum
9d  MESSAGE_INFO + LENGTH_8 + MODE_5
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
ea  checksum
9d  MESSAGE_INFO + LENGTH_8 + MODE_5
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; SiMax = 10.0
00  checksum
95  MESSAGE_INFO + LENGTH_4 + MODE_5
04  INFO_SYMBOL
49  'I'
44  'D'
58  'X'
00  ''; Symbol = "IDX"
3b  checksum
8d  MESSAGE_INFO + LENGTH_2 + MODE_5
05  INFO_UNK1
00  ???
04  ???
73  checksum
95  MESSAGE_INFO + LENGTH_4 + MODE_5
80  INFO_FORMAT
01  DataSets = 1
00  Format = DATA8
03  Figures = 3
00  Decimals = 0
e8  checksum
94  MESSAGE_INFO + LENGTH_4 + MODE_4
00  INFO_NAME
41  'A'
4d  'M'
42  'B'
49  'I'; Name = 'AMBI'
6c  checksum
9c  MESSAGE_INFO + LENGTH_8 + MODE_4
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; RawMax = 100.0
e8
9c  MESSAGE_INFO + LENGTH_8 + MODE_4
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
eb  checksum
9c  MESSAGE_INFO + LENGTH_8 + MODE_4
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; SiMax = 100.0
ea  checksum
94  MESSAGE_INFO + LENGTH_4 + MODE_4
04  INFO_SYMBOL
50  'P'
43  'C'
54  'T'
00  ''; Symbol = 'PCT'
28  checksum
8c  MESSAGE_INFO + LENGTH_2 + MODE_4
05  INFO_UNK1
10  ???
00  ???
66  checksum
94  MESSAGE_INFO + LENGTH_4 + MODE_4
80  INFO_FORMAT
01  DataSets = 1
00  Format = DATA8
03  Figures = 3
00  Decimals = 0
e9  checksum
9b  MESSAGE_INFO + LENGTH_8 + MODE_3
00  INFO_NAME
52  'R'
45  'E'
45  'F'
4c  'L'
54  'T'
00  ''
00  ''
00  ''; Name = "REFLT"
2d  checksum
9b  MESSAGE_INFO + LENGTH_8 + MODE_3
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; RawMax = 100.0
ef  checksum
9b  MESSAGE_INFO + LENGTH_8 + MODE_3
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
ec  checksum
9b  MESSAGE_INFO + LENGTH_8 + MODE_3
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; SiMax = 100.0
ed  checksum
93  MESSAGE_INFO + LENGTH_4 + MODE_3
04  INFO_SYMBOL
50  'P'
43  'C'
54  'T'
00  ''; Symbol = "PCT"
2f  checksum
8b  MESSAGE_INFO + LENGTH_2 + MODE_3
05  INFO_UNK1
10  ???
00  ???
61  checksum
93  MESSAGE_INFO + LENGTH_4 + MODE_3
80  INFO_FORMAT
01  DataSets = 1
00  Format = DATA8
03  Figures = 3
00  Decimals = 0
ee  checksum
9a  MESSAGE_INFO + LENGTH_8 + MODE_2
00  INFO_NAME
43  'C'
4f  'O'
55  'U'
4e  'N'
54  'T'
00  ''
00  ''
00  ''; Name = "COUNT"
26  checksum
9a  MESSAGE_INFO + LENGTH_8 + MODE_2
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; RawMax = 100.0
ee  checksum
9a  MESSAGE_INFO + LENGTH_8 + MODE_2
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
ed  checksum
9a  MESSAGE_INFO + LENGTH_8 + MODE_2
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; SiMax = 100.0
ec  checksum
92  MESSAGE_INFO + LENGTH_4 + MODE_2
04  INFO_SYMBOL
43  'C'
4e  'N'
54  'T'
00  ''; Symbol = "CNT"
30  checksum
8a  MESSAGE_INFO + LENGTH_2 + MODE_2
05  INFO_UNK1
08  ???
00  ???
78  checksum
92  MESSAGE_INFO + LENGTH_4 + MODE_2
80  INFO_FORMAT
01  DataSets = 1
02  Format = DATA32
04  Figures = 4
00  Decimals = 0
ea  checksum
91  MESSAGE_INFO + LENGTH_4 + MODE_1
00  INFO_NAME
50  'P'
52  'R'
4f  'O'
58  'X'; Name = "PROX"
7b  checksum
99  MESSAGE_INFO + LENGTH_8 + MODE_1
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; RawMax = 10.0
06  checksum
99  MESSAGE_INFO + LENGTH_8 + MODE_1
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
ee  checksum
99  MESSAGE_INFO + LENGTH_8 + MODE_1
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; SiMax = 10.0
04  checksum
91  MESSAGE_INFO + LENGTH_4 + MODE_1
04  INFO_SYMBOL
44  'D'
49  'I'
53  'S'
00  ''; Symbol = "DIS"
34  checksum
89  MESSAGE_INFO + LENGTH_2 + MODE_1
05  INFO_UNK1
50  ???
00  ???
23  checksum
91  MESSAGE_INFO + LENGTH_4 + MODE_1
80  INFO_FORMAT
01  DataSets = 1
00  Format = DATA8
03  Figures = 3
00  Decimals = 0
ec  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0
00  INFO_NAME
43  'C'
4f  'O'
4c  'L'
4f  'O'
52  'R'
00  ''
00  ''
00  ''; Name = "COLOR"
3a  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0
01  INFO_RAW
00  LSB
00  ..
00  ..
00  MSB; RawMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; RawMax = 10.0
07  checksum
98  MESSAGE_INFO + LENGTH_8 + MODE_0
02  INFO_PCT
00  LSB
00  ..
00  ..
00  MSB; PctMin = 0.0
00  LSB
00  ..
c8  ..
42  MSB; PctMax = 100.0
ef
98  MESSAGE_INFO + LENGTH_8 + MODE_0
03  INFO_SI
00  LSB
00  ..
00  ..
00  MSB; SiMin = 0.0
00  LSB
00  ..
20  ..
41  MSB; SiMax = 10.0
05  checksum
90  MESSAGE_INFO + LENGTH_4 + MODE_0
04  INFO_SYMBOL
49  'I'
44  'D'
58  'X'
00  ''; Symbol = "IDX"
3e  checksum
88  MESSAGE_INFO + LENGTH_2 + MODE_0
05  INFO_UNK1
c4  ???
00  ???
b6  checksum
90  MESSAGE_INFO + LENGTH_4 + MODE_0
80  INFO_FORMAT
01  DataSets = 1
00  Format = DATA8
03  Figures = 3
00  Decimals = 0
ed  checksum
88  MESSAGE_INFO + LENGTH_2 + MODE_0
06  INFO_UNK2 (second new PF2 info - others are 05)
4f  ???
00  ???
3e  checksum
04  MESSAGE_SYS + BYTE_ACK
00  MESSAGE_SYS + BYTE_SYNC

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.