You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Bluetooth_MI32.md
+131-80
Original file line number
Diff line number
Diff line change
@@ -1,41 +1,58 @@
1
+
---
2
+
tags:
3
+
- Bluetooth
4
+
- BLE
5
+
- Berry
6
+
- Mijia
7
+
- Xiaomi
8
+
- ESP32
9
+
---
10
+
1
11
# MI32 legacy
2
12
3
-
The MI32-driver focuses on the passive observation of BLE sensors of the Xiaomi/Mijia universe, thus only needing a small memory footprint. Berry can be used to create generic applications.
4
-
Currently supported are all members of the ESP32 family with Bluetooth capabilities.
5
-
The driver can be built to use Bluetooth version 5.x.
13
+
Focus on the passive observation of BLE sensors of the Xiaomi/Mijia universe with a small memory footprint.
14
+
Create generic Bluetooth applications with Berry.
15
+
6
16
7
17
## Usage
8
18
9
-
This driver is not part of any standard build. To self compile it is recommended to add build environments to `platformio_tasmota_cenv.ini`. This file needs to be created first.
10
-
Add this section (change accordingly for the other chipsets or use one of the examples in `platformio_tasmota_cenv.ini` with naming scheme `tasmota32xx-mi32`):
If you want to try out Bluetooth version 5.x, which consumes a bit more memory and has limited capabilities on the platform itself, a custom build is needed, e.g.:
It is probably necessary to restart your IDE (i.e. Visual Studio Code) to see the option to build this environment.
19
+
Currently supported are all members of the ESP32 family with Bluetooth capabilities.
20
+
This driver is not part of any standard build. To self compile it is recommended to use `platformio_tasmota_cenv.ini`, which needs to be created first.
21
+
Use or change one of the existing example sections with naming scheme `tasmota32xx-mi32`.
If you want to try out Bluetooth version 5.x, which consumes a bit more memory and has limited capabilities on the ESP platform itself, a custom build is needed, e.g.:
;It is probably necessary to restart your IDE (i.e. Visual Studio Code) to see the option to build this environment.
52
+
```
53
+
Basically every consumer BLE device with "BLE 5" capabilities has only hardware support for Bluetooth 5.x.
54
+
At the time of writing there is not a single widely used product out there, that has the software support enabled.
55
+
The only known exception is the open source firmware on [pvvx.github.io](https://pvvx.github.io) with possible BLE long range support, but due to hardware limitations the ESP32 platform does not gain much (aka nothing) here.
39
56
40
57
## Tasmota and BLE-sensors
41
58
@@ -54,14 +71,14 @@ Other sensors like the MJYD2S and nearly every newer device are not usable witho
54
71
55
72
The idea is to provide as many automatic functions as possible. Besides the hardware setup, there are zero or very few things to configure.
56
73
The sensor namings are based on the original sensor names and shortened if appropriate (Flower care -> Flora). A part of the MAC will be added to the name as a suffix.
57
-
All sensors are treated as if they are physically connected to the ESP32 device. For motion and remote control sensors MQTT-messages will be published in (nearly) real time.
74
+
All sensors are treated as if they are physically connected to the ESP32 device. For motion and remote control sensors MQTT-messages will be published in (nearly) real time.
58
75
59
76
### Supported Devices
60
77
61
78
!!! note "It can not be ruled out, that changes in the device firmware may break the functionality of this driver completely!"
62
79
63
-
The naming conventions in the product range of bluetooth sensors in XIAOMI-universe can be a bit confusing. The exact same sensor can be advertised under slightly different names depending on the seller (Mijia, Xiaomi, Cleargrass, ...).
64
-
If an unknown "Mijia" sensor is found it will be added with naming scheme `MI_`+`PID` and if the builtin parser of the driver supports the packet type, it will work too.
80
+
The naming conventions in the product range of bluetooth sensors in XIAOMI-universe can be a bit confusing. The exact same sensor can be advertised under slightly different names depending on the seller (Mijia, Xiaomi, Cleargrass, ...).
81
+
If an unknown "Mijia" sensor is found it will be added with naming scheme `MI_`+`PID` and if the builtin parser of the driver supports the packet type, it will work too.
65
82
66
83
<table>
67
84
<tr>
@@ -161,8 +178,10 @@ If an unknown "Mijia" sensor is found it will be added with naming scheme `MI_`+
161
178
<td class="tg-lboi">passive only with decryption (legacy decryption)<br>both versions reported as YLKG08</td>
162
179
</tr>
163
180
</table>
164
-
passive: data is received via BLE advertisements
165
-
active: data is received via bidirectional connection to the sensor
181
+
182
+
[passive]: data is received via BLE advertisements
183
+
[active]: data is received via bidirectional connection to the sensor
184
+
166
185
167
186
#### Devices with payload encryption
168
187
@@ -180,9 +199,9 @@ rule1 on System#Boot do backlog MI32key 00112233445566778899AABBCCDDEEFF11223344
180
199
181
200
### Tracking of BLE devices and "iPhone presence detection"
182
201
183
-
It is possible to track generic BLE devices with `mi32option5 1>`. This includes every device with a public address (aka a fixed MAC address) out of the box.
184
-
Additionally it is possible to observe (typically more modern) BLE devices with a *Random Private Resolvable Address* or in short RPA, which includes iPhones and other Apple devices.
185
-
For the latter it is necessary to retrieve the Identiy Resolving Key (= IRK), which is supported in directly the driver with the help of a Berry script:
202
+
It is possible to track generic BLE devices with `mi32option5 1`. This includes every device with a public address (aka a fixed MAC address) out of the box.
203
+
Additionally it is possible to observe (typically more modern) BLE devices with a *Random Private Resolvable Address* or in short RPA, which includes iPhones and other Apple devices.
204
+
For the latter it is necessary to retrieve the Identiy Resolving Key (= IRK), which is supported directly by the driver with the help of a Berry script:
186
205
187
206
??? example " Retrieve IRK from BLE device with RPA"
188
207
@@ -421,8 +440,8 @@ MI32Option5|`0` = do not report generic BLE devices (default)<br>`1` = report ev
421
440
422
441
## Mi Dashboard
423
442
424
-
The driver provides an extended web GUI to show the observed Xiaomi sensors in a widget style, that features a responsive design to use the screen area as effective as possible. The other advantage is, that only the widget with new data gets redrawn (indicated by a fading circle) and no unnecessary refresh operations will happen. A simple graph shows if valid data for every hour was received in the last 24h, where only one gap for the coming hour is not a sign of an error. Configured sensors with no received packet since boot or key/decryption errors are dimmed.
425
-
Own widgets can be added with Berry using the `MI32` module, thus allowing to create small Apps or visualizing the state of arbitrary BLE devices.
443
+
The driver provides an extended web GUI to show the observed Xiaomi sensors in a widget style, that features a responsive design to use the screen area as effective as possible. The other advantage is, that only the widget with new data gets redrawn (indicated by a fading circle) and no unnecessary refresh operations will happen. A simple graph shows if valid data for every hour was received in the last 24h, where only one gap for the coming hour is not a sign of an error. Configured sensors with no received packet since boot or key/decryption errors are dimmed.
444
+
Own widgets can be added with Berry using the `MI32` module, thus allowing to create small Apps or visualizing the state of arbitrary BLE devices.
426
445
427
446
428
447
## Homeassistant and Tasmota - BLE sensors
@@ -561,6 +580,15 @@ We just have to provide a pointer to a (callback) function and a byte buffer. T
561
580
1 byte -lengthof payload
562
581
n bytes - payload data
563
582
```
583
+
```mermaid
584
+
packet-beta
585
+
0-5: "MAC"
586
+
6: "t"
587
+
7: "R"
588
+
8: "l"
589
+
9-40: "payload data (up to 31 byte)"
590
+
41-71: "optional scan response (up to 31 byte)"
591
+
```
564
592
565
593
The advertisement callback function provides 2 arguments, which are indices of the whole buffer that point to optional parts of the payload. A value of 0 means, this type of of element is not in the payload.
566
594
1. svc (= service data index) - index of service data in the advertisement buffer
@@ -588,40 +616,55 @@ cbuf = bytes(-64)
588
616
def cb(error,op,uuid,handle)
589
617
end
590
618
591
-
cbp = tasmota.gen_cb(cb)
619
+
cbp = tasmota.gen_cb(/e,o,u,h->cb)
592
620
BLE.conn_cb(cbp,cbuf)
593
621
```
594
622
595
-
#####Return values of the callback function
596
-
597
-
Error (codes):
598
-
599
-
- 0 - no error
600
-
- 1 - connection error
601
-
- 2 - did disconnect
602
-
- 3 - did not get service
603
-
- 4 - did not get characteristic
604
-
- 5 - could not read value
605
-
- 6 - characteristic can not notify
606
-
- 7 - characteristic not writable
607
-
- 8 - did not write value
608
-
- 9 - timeout: did not read on notify
609
-
610
-
Op (codes):
611
-
612
-
- 1 - read
613
-
- 2 - write
614
-
- 3 - subscribe - direct response after launching a run command to subscribe
615
-
- 5 - disconnect
616
-
- 6 - retrieve all *services* of connected device
617
-
- 7 - retrieve all *characteristics* and *GATT Characteristic Property Flags* of a service
618
-
- 103 - notify read - the notification with data from the BLE server
619
-
620
-
uuid:
621
-
Returns the 16 bit UUID of the characteristic as a number, even if the UUID was 128 bit.
622
-
623
-
handle:
624
-
Returns the 16 bit handle of the characteristic as a number.
623
+
```mermaid
624
+
---
625
+
title: "Return values of the callback function"
626
+
---
627
+
classDiagram
628
+
class cb{
629
+
<<function>>
630
+
error, operation, uuid, handle
631
+
}
632
+
class error{
633
+
<<int>>
634
+
0 - no error
635
+
1 - connection error
636
+
2 - did disconnect
637
+
3 - did not get service
638
+
4 - did not get characteristic
639
+
5 - could not read value
640
+
6 - characteristic can not notify
641
+
7 - characteristic not writable
642
+
8 - did not write value
643
+
9 - timeout: did not read on notify
644
+
}
645
+
class operation{
646
+
<<int>>
647
+
1 - read
648
+
2 - write
649
+
3 - subscribe - response to command to subscribe, not a notification
650
+
5 - disconnect
651
+
6 - retrieve all services of connected device
652
+
7 - retrieve all characteristics and GATT Characteristic Property Flags of a service
653
+
103 - notify read - the notification with data from the BLE server
654
+
}
655
+
class uuid{
656
+
<<int>>
657
+
16-bit uuid
658
+
}
659
+
class handle{
660
+
<<int>>
661
+
16-bit handle
662
+
}
663
+
cb --|> error
664
+
cb --|> operation
665
+
cb --|> uuid
666
+
cb --|> handle
667
+
```
625
668
626
669
Internally this creates a context, that can be modified with the following methods:
627
670
@@ -644,7 +687,7 @@ Finally run the context with the specified properties and (if you want to get da
644
687
645
688
- 11 - read - then disconnect (returns 1 in the callback)
646
689
- 12 - write - then disconnect (returns 2 in the callback)
647
-
- 13 - subscribe - then disconnect after waiting for notification(returns 3 in the callback)
690
+
- 13 - subscribe - then disconnect after waiting for notification(returns 3 in the callback)
648
691
649
692
The buffer format for reading and writing is in the format (length - data):
650
693
```
@@ -654,7 +697,9 @@ n bytes - data
654
697
655
698
#### Central role (aka server)
656
699
657
-
The server is initiated similarly with `BLE.serv_cb(cbp,cbuf)`. After that you have to construct the server by first adding all *characteristics* and finally starting it, by setting the *advertisement* data for the first time. Setting *advertisement* data without adding *characteristics* will not start a BLE server but only a BLE Broadcaster, which is totally fine for some use cases (i.e. Beacons, BTHome).
700
+
The server is initiated similarly with `BLE.serv_cb(cbp,cbuf)`.
701
+
After that you have to construct the server by first adding all *characteristics* and finally starting it, by setting the *advertisement* data for the first time.
702
+
Setting *advertisement* data without adding *characteristics* will not start a BLE server but only a BLE Broadcaster, which is totally fine for some use cases (i.e. Beacons, BTHome).
658
703
The BLE server can be stopped with `BLE.serv_cb(nil)`, which will restart the "BLE Scan Task".
659
704
660
705
The callback functions returns error, operation, 16-bit-uuid and 16-bit-handle.
@@ -674,9 +719,13 @@ BLE.serv_cb(cbp,cbuf)
674
719
675
720
####Command op codes:
676
721
677
-
- 201 - add and/or set advertisement data according to the BLE standard, typically chaining small packets in the in the format of `length-type-data`. When called for the first time, will return a bytes buffer, that represents an array of the 16-bit-handles of all characteristics in the order of addition.
722
+
- 201 - add and/or set advertisement data according to the BLE standard, typically chaining small packets in the in the format of `length-type-data`.
723
+
When called for the first time, will return a bytes buffer, that represents an array of the 16-bit-handles of all characteristics in the order of addition.
678
724
- 202 - add and/or set scan response data, according to the BLE standard which is equally to the advertisement data. Should be used sparsely.
679
-
- 211 - add and/or set characteristic with value of bytes buffer. For simplicity a `Client Characteristic Configuration Descriptor` (aka 0x2902) will be added on construction of every characteristic and read, write, notification and indication is enabled. You can select write with or without response withe the optional boolean of `BLE.set_chr(string, bool)`, which defaults to "write with no response". The function call will always trigger a *notification*. As every *characteristic* belongs to a *service*, `BLE.set_svc(string)` must have been called before.
725
+
- 211 - add and/or set characteristic with value of bytes buffer.
726
+
For simplicity a `Client Characteristic Configuration Descriptor` (aka 0x2902) will be added on construction of every characteristic and read, write, notification and indication is enabled.
727
+
You can select write with or without response withe the optional boolean of `BLE.set_chr(string, bool)`, which defaults to "write with no response".
728
+
The function call will always trigger a *callback*. As every *characteristic* belongs to a *service*, `BLE.set_svc(string)` must have been called before.
680
729
681
730
####Response op codes (triggered when a client interacts with the server):
682
731
@@ -693,15 +742,17 @@ BLE.serv_cb(cbp,cbuf)
693
742
694
743
!!! tip
695
744
696
-
By default the synchronization between the BLE framework and Berry happens every 50 milliseconds, which should be enough for the majority of use cases. For very fast BLE devices it can be necessary to use Berrys `fast_loop` to trigger this at maximum speed (of about every 5 milliseconds). This is typically done in an init function of a class like that:
745
+
By default the synchronization between the BLE framework and Berry happens every 50 milliseconds, which should be enough for the majority of use cases.
746
+
For very fast BLE devices it can be necessary to use Berrys `fast_loop` to trigger this at maximum speed (of about every 5 milliseconds).
747
+
This is typically done in an init function of a class like that:
697
748
`tasmota.add_fast_loop(/-> BLE.loop())`
698
749
699
750
####Configuration op codes (return immediately, no callback involved):
700
751
701
752
- 231 - set own address to random with `BLE.set_MAC(bytes("aabbccddeeff"),1)`
702
753
- 232 - set advertising parameters with bytes() descriptor of length 5 [advType:byte, minInterval:uint16_t, max interval: uint16_t]
703
754
- 233 - set GAP name with `string` in bytes buffer (must be null terminated)
704
-
755
+
705
756
### Berry examples
706
757
707
758
Here is an implementation of the "old" MI32 commands:
0 commit comments