Bot and Controller are Bluetooth LE devices with a single Service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
The Service exposes 2 characteristics:
6E400002-B5A3-F393-E0A9-E50E24DCCA9E
with propertieswrite
/writeNoReply
6E400003-B5A3-F393-E0A9-E50E24DCCA9E
with propertynotify
Each packet is composed of a 1 byte header with value 254
, followed by the encoded payload.
Encoded payload are generated by appending a crc16 to the original payload and then encoding the result as follow:
- replace
253
by the 2 bytes sequence253
/221
- replace
254
by the 2 bytes equence253
/222
The crc16 checksum is a 2 bytes value computed like this:
func crc16(_ data: [UInt8]) -> UInt16 {
var crc: UInt16 = 0xffff;
for byte in data {
crc = crc.byteSwapped ^ UInt16(byte);
crc = crc ^ (crc & 255) >> 4;
crc = crc ^ (crc << 12);
crc = crc ^ (crc & 255) << 5;
}
return crc;
}
To control a device, first lookup for a device with the right characteristics.
On dicover -> start listening on the notify
characteristic.
Once the connection is setup, the device will start broadcasting every second its identity (null terminated string like Car:[0x87]\n
) on the notify channel, waiting for an handshake.
The handshake content remains to be defined, but for a controller app like MatataCode, it is the following payload: [0x07, 0x7e, 0x2, 0x2, 0x0, 0x0]
The device should answer a 5 bytes payload like: [0x06, 0x7e, 0x02, 0x00, 0x00]
payload[3] ≠ 0
means that this is a controller that is itself connected to a bot that must be updated.payload[4] ≠ 0
means that the device version do not match the extension version and that the device must be updated.
When connected to a Matata Controller, it can also broadcast periodically information about its configuration.
[0x04, 0x87, 0x01]
: Bot connected.[0x04, 0x87, 0x02]
: No Bot connected.
After each request, the controller send a reply:
[0x04, 0x88, 0x00]
: request OK.[0x04, 0x88, 0x01]
: request failed (invalid CRC, …).[0x04, 0x88, 0x07]
: the controller is not in sensor mode.
Prefix | Command | Parameters |
---|---|---|
0x10 0x01 |
Forward | distance in mm (16 bits) |
0x10 0x02 |
Backward | distance in mm (16 bits) |
0x10 0x03 |
Turn Left | angle in degree (16 bits) |
0x10 0x04 |
Turn Right | angle in degree (16 bits) |
0x11 - |
Wheel Motion | See below |
0x12 0x01 |
Dance | Dance [0x1; 0x6] |
0x13 0x01 |
Action | Action [0x1; 0x6] |
0x15 - |
Play Note | beat (16 bits) / note (16 bits) |
0x16 0x01 |
Play Melody | Melody [0x1; 0xa] |
0x16 0x01 |
Play Music | Music [0x11; 0x16] |
0x16 0x01 |
Play Sound | Music [0x21; 0x2f] |
0x17 - |
Eyes | bit field (left: 1, right: 2) / r, g, b [0;255] |
First byte is a bit field:
left: 0x01
right: 0x02
For each wheel, append 3 bytes:
- direction:
forward: 0x01
backward: 0x02
- speed (16 bits).
- speed 1 is
70
- speed 6 is
245
- speed 1 is
Controller supports only LEDs commands
Prefix | Command | Parameters |
---|---|---|
0x18 0x02 |
Show all | <color> <level [1;6]> |
0x18 0x03 |
Show all (RGB) | <r> <g> <b> |
0x18 0x04 |
Show previous LED | <color> <level [1;6]> |
0x18 0x05 |
Show next LED | <color> <level [1;6]> |
0x18 0x06 |
Show LED animation | <animation [1;6]> |
0x18 0x07 |
Show all (advanced) | 12 × <r> <g> <b> |
0x18 0x08 |
Show single LED | <index [0; 11]> <r> <g> <b> |
color:
- 1: white
- 2: red
- 3: yellow
- 4: green
- 5: blue
- 6: purple
- 7: black
animation:
- 1: spoondrift
- 2: meteor
- 3: rainbow
- 4: firefly
- 5: colorwipe
- 6: breathe
Request sensor status.
For each request, the response is composed of 4 bytes (including the request) followed by the queried value.
Request | Command | Response |
---|---|---|
0x20 0x01 <color> |
is color detected | > 0 if true |
0x20 0x05 0x01 |
is bright | > 0 if true |
0x20 0x05 0x02 |
is dark | > 0 if true |
0x28 0x02 0x01 |
get red value | value[0;255] |
0x28 0x02 0x02 |
get green value | value[0;255] |
0x28 0x02 0x03 |
get blue value | value[0;255] |
0x28 0x02 0x04 |
get light strength | intensity[0;255] |
color:
- 1: white
- 2: red
- 3: yellow
- 4: green
- 5: blue
- 6: purple
- 7: black
Request | Command | Response |
---|---|---|
0x20 0x02 0x01 |
is shaked | > 0 if true |
0x20 0x02 0x02 |
is halo up | > 0 if true |
0x20 0x02 0x03 |
is halo down | > 0 if true |
0x20 0x02 0x04 |
is tilted left | > 0 if true |
0x20 0x02 0x05 |
is tilted right | > 0 if true |
0x20 0x02 0x06 |
is tilted forward | > 0 if true |
0x20 0x02 0x07 |
is tilted backward | > 0 if true |
0x20 0x02 0x08 |
is falling | > 0 if true |
0x28 0x01 0x01 |
get X acceleration | 32 bits LE float |
0x28 0x01 0x02 |
get Y acceleration | 32 bits LE float |
0x28 0x01 0x03 |
get Z acceleration | 32 bits LE float |
0x28 0x01 0x04 |
get roll | 32 bits LE float |
0x28 0x01 0x05 |
get pitch | 32 bits LE float |
0x28 0x01 0x06 |
get yaw | 32 bits LE float |
0x28 0x01 0x07 |
get shake strength | 32 bits LE float |
Request | Command | Response |
---|---|---|
0x20 0x03 |
is sound detected | > 0 if true |
0x20 0x04 |
is obstacle ahead | > 0 if true |
0x20 0x07 <button> |
is button pressed | > 0 if true |
0x20 0x06 0x01 <msg> |
send message | - |
0x20 0x06 0x02 |
get received message | message |
button:
- 1: play
- 2: delete
- 3: turn right
- 4: forward
- 5: turn left
- 6: music
- 7: backward