@@ -26,10 +26,15 @@ class BTHome:
2626 # Device name used in BLE advertisements.
2727 _local_name = ""
2828
29- # Naming convention is:
29+ # For most sensors, naming convention is:
3030 # <const_name> ::= <property> "_" <data-type> "_x" <inverse of factor>
31- # For example , temperature sint16 0.01 becomes:
31+ # Example , temperature sint16 0.01 becomes:
3232 # TEMPERATURE _ SINT16 _x 100
33+ # For binary sensors (0x15 .. 0x2D), naming convention is:
34+ # <const_name> ::= <property> "_" BINARY
35+ # Example, "battery charging" becomes:
36+ # BATTERY_CHARGING_BINARY
37+ # All binary sensors are packed as 8-bit unsigned bytes.
3338 # See "Sensor Data" table at https://bthome.io/format/
3439 BATTERY_UINT8_X1 = const (0x01 ) # %
3540 TEMPERATURE_SINT16_X100 = const (0x02 ) # °C
@@ -45,9 +50,19 @@ class BTHome:
4550 VOLTAGE_UINT16_X1000 = const (0x0C ) # V
4651 PM2_5_UINT16_X1 = const (0x0D ) # ug/m^3
4752 PM10_UINT16_X1 = const (0x0E ) # ug/m^3
53+ GENERIC_BOOLEAN = const (0x0F ) # 0 (False = Off) 1 (True = On)
4854 CO2_UINT16_X1 = const (0x12 ) # ppm
4955 TVOC_UINT16_X1 = const (0x13 ) # ug/m^3
5056 MOISTURE_UINT16_X100 = const (0x14 ) # %
57+ BATTERY_LOW_BINARY = const (0x15 ) # 0 (False = Normal) 1 (True = Low)
58+ BATTERY_CHARGING_BINARY = const (0x16 ) # 0 (False = Not Charging) 1 (True = Charging)
59+ CARBON_MONOXIDE_BINARY = const (0x17 ) # 0 (False = Not detected) 1 (True = Detected)
60+ COLD_BINARY = const (0x18 ) # 0 (False = Normal) 1 (True = Cold)
61+ CONNECTIVITY_BINARY = const (0x19 ) # 0 (False = Disconnected) 1 (True = Connected)
62+ DOOR_BINARY = const (0x1A ) # 0 (False = Closed) 1 (True = Open)
63+ GARAGE_DOOR_BINARY = const (0x1B ) # 0 (False = Closed) 1 (True = Open)
64+ GAS_BINARY = const (0x1C ) # 0 (False = Clear) 1 (True = Detected)
65+ HEAT_BINARY = const (0x1D ) # 0 (False = Normal) 1 (True = Hot)
5166 HUMIDITY_UINT8_X1 = const (0x2E ) # %
5267 MOISTURE_UINT8_X1 = const (0x2F ) # %
5368 COUNT_UINT16_X1 = const (0x3D )
@@ -77,7 +92,7 @@ class BTHome:
7792 VOLUME_STORAGE_UINT32_X1000 = const (0x55 ) # L
7893 CONDUCTIVITY_UINT16_X1 = const (0x56 ) # µS/cm
7994 TEMPERATURE_SINT8_X1 = const (0x57 ) # °C
80- # Skipping 0x58 due to strange factor of 0.35
95+ # Skipping temperature 0x58 due to strange factor of 0.35
8196 COUNT_SINT8_X1 = const (0x59 )
8297 COUNT_SINT16_X1 = const (0x5A )
8398 COUNT_SINT32_X1 = const (0x5B )
@@ -90,75 +105,102 @@ class BTHome:
90105 # There is more than one way to represent most sensor properties. This
91106 # dictionary maps the object id to the property name.
92107 _object_id_properties = {
93- BATTERY_UINT8_X1 : "battery" ,
94- TEMPERATURE_SINT16_X100 : "temperature" ,
95- HUMIDITY_UINT16_X100 : "humidity" ,
96- PRESSURE_UINT24_X100 : "pressure" ,
97- ILLUMINANCE_UINT24_X100 : "illuminance" ,
98- MASS_KG_UINT16_X100 : "mass" ,
99- MASS_LB_UINT16_X100 : "mass" ,
100- DEWPOINT_SINT16_X100 : "dewpoint" ,
101- COUNT_UINT8_X1 : "count" ,
102- ENERGY_UINT24_X1000 : "energy" ,
103- POWER_UINT24_X100 : "power" ,
104- VOLTAGE_UINT16_X1000 : "voltage" ,
105- PM2_5_UINT16_X1 : "pm2.5" ,
106- PM10_UINT16_X1 : "pm10" ,
107- CO2_UINT16_X1 : "co2" ,
108- TVOC_UINT16_X1 : "tvoc" ,
109- MOISTURE_UINT16_X100 : "moisture" ,
110- HUMIDITY_UINT8_X1 : "humidity" ,
111- MOISTURE_UINT8_X1 : "moisture" ,
112- COUNT_UINT16_X1 : "count" ,
113- COUNT_UINT32_X1 : "count" ,
114- ROTATION_SINT16_X10 : "rotation" ,
115- DISTANCE_MM_UINT16_X1 : "distance" ,
116- DISTANCE_M_UINT16_X10 : "distance" ,
117- DURATION_UINT24_X1000 : "duration" ,
118- CURRENT_UINT16_X1000 : "current" ,
119- TEMPERATURE_SINT16_X10 : "temperature" ,
120- UV_INDEX_UINT8_X10 : "uv_index" ,
121- VOLUME_L_UINT16_X10 : "volume" ,
122- VOLUME_ML_UINT16_X1 : "volume" ,
123- VOLUME_FLOW_RATE_X1000 : "volume_flow_rate" ,
124- VOLTAGE_UINT16_X10 : "voltage" ,
125- GAS_UINT24_X1000 : "gas" ,
126- GAS_UINT32_X1000 : "gas" ,
127- ENERGY_UINT32_X1000 : "energy" ,
128- VOLUME_UINT32_X1000 : "volume" ,
129- WATER_UINT32_X1000 : "water" ,
130- TIMESTAMP_UINT48_X1 : "timestamp" ,
131- ACCELERATION_UINT16_X1000 : "acceleration" ,
132- GYROSCOPE_UINT16_X1000 : "gyroscope" ,
133- VOLUME_STORAGE_UINT32_X1000 : "volume_storage" ,
134- CONDUCTIVITY_UINT16_X1 : "conductivity" ,
135- TEMPERATURE_SINT8_X1 : "temperature" ,
136- COUNT_SINT8_X1 : "count" ,
137- COUNT_SINT16_X1 : "count" ,
138- COUNT_SINT32_X1 : "count" ,
139- POWER_SINT16_X100 : "power" ,
140- CURRENT_SINT16_X1000 : "current" ,
141- DIRECTION_UINT16_X100 : "direction" ,
142- PRECIPITATION_UINT16_X1 : "precipitation" ,
143- CHANNEL_UINT8_X1 : "channel"
108+ BATTERY_UINT8_X1 : "battery" , # 0x01
109+ TEMPERATURE_SINT16_X100 : "temperature" , # 0x02
110+ HUMIDITY_UINT16_X100 : "humidity" , # 0x03
111+ PRESSURE_UINT24_X100 : "pressure" , # 0x04
112+ ILLUMINANCE_UINT24_X100 : "illuminance" , # 0x05
113+ MASS_KG_UINT16_X100 : "mass" , # 0x06
114+ MASS_LB_UINT16_X100 : "mass" , # 0x07
115+ DEWPOINT_SINT16_X100 : "dewpoint" , # 0x08
116+ COUNT_UINT8_X1 : "count" , # 0x09
117+ ENERGY_UINT24_X1000 : "energy" , # 0x0A
118+ POWER_UINT24_X100 : "power" , # 0x0B
119+ VOLTAGE_UINT16_X1000 : "voltage" , # 0x0C
120+ PM2_5_UINT16_X1 : "pm2.5" , # 0x0D
121+ PM10_UINT16_X1 : "pm10" , # 0x0E
122+ GENERIC_BOOLEAN : "generic_boolean" , # 0x0F
123+ CO2_UINT16_X1 : "co2" , # 0x12
124+ TVOC_UINT16_X1 : "tvoc" , # 0x13
125+ MOISTURE_UINT16_X100 : "moisture" , # 0x14
126+ BATTERY_LOW_BINARY : "battery_low" , # 0x15
127+ BATTERY_CHARGING_BINARY : "battery_charging" , # 0x16
128+ CARBON_MONOXIDE_BINARY : "carbon_monoxide" , # 0x17
129+ COLD_BINARY : "cold" , # 0x18
130+ CONNECTIVITY_BINARY : "connectivity" , # 0x19
131+ DOOR_BINARY : "door" , # 0x1A
132+ GARAGE_DOOR_BINARY : "garage_door" , # 0x1B
133+ GAS_BINARY : "gas_detected" , # 0x1C
134+ HEAT_BINARY : "heat" , # 0x1D
135+ HUMIDITY_UINT8_X1 : "humidity" , # 0x2E
136+ MOISTURE_UINT8_X1 : "moisture" , # 0x2F
137+ COUNT_UINT16_X1 : "count" , # 0x3D
138+ COUNT_UINT32_X1 : "count" , # 0x3E
139+ ROTATION_SINT16_X10 : "rotation" , # 0x3F
140+ DISTANCE_MM_UINT16_X1 : "distance" , # 0x40
141+ DISTANCE_M_UINT16_X10 : "distance" , # 0x41
142+ DURATION_UINT24_X1000 : "duration" , # 0x42
143+ CURRENT_UINT16_X1000 : "current" , # 0x43
144+ SPEED_UINT16_X100 : "speed" , # 0x44
145+ TEMPERATURE_SINT16_X10 : "temperature" , # 0x45
146+ UV_INDEX_UINT8_X10 : "uv_index" , # 0x46
147+ VOLUME_L_UINT16_X10 : "volume" , # 0x47
148+ VOLUME_ML_UINT16_X1 : "volume" , # 0x48
149+ VOLUME_FLOW_RATE_X1000 : "volume_flow_rate" , # 0x49
150+ VOLTAGE_UINT16_X10 : "voltage" , # 0x4A
151+ GAS_UINT24_X1000 : "gas" , # 0x4B
152+ GAS_UINT32_X1000 : "gas" , # 0x4C
153+ ENERGY_UINT32_X1000 : "energy" , # 0x4D
154+ VOLUME_UINT32_X1000 : "volume" , # 0x4E
155+ WATER_UINT32_X1000 : "water" , # 0x4F
156+ TIMESTAMP_UINT48_X1 : "timestamp" , # 0x50
157+ ACCELERATION_UINT16_X1000 : "acceleration" , # 0x51
158+ GYROSCOPE_UINT16_X1000 : "gyroscope" , # 0x52
159+ TEXT_BYTES : "text" , # 0x53
160+ RAW_BYTES : "raw" , # 0x54
161+ VOLUME_STORAGE_UINT32_X1000 : "volume_storage" , # 0x55
162+ CONDUCTIVITY_UINT16_X1 : "conductivity" , # 0x56
163+ TEMPERATURE_SINT8_X1 : "temperature" , # 0x57
164+ # Skipping 0x58 temperature due to strange factor of 0.35
165+ COUNT_SINT8_X1 : "count" , # 0x59
166+ COUNT_SINT16_X1 : "count" , # 0x5A
167+ COUNT_SINT32_X1 : "count" , # 0x5B
168+ POWER_SINT16_X100 : "power" , # 0x5C
169+ CURRENT_SINT16_X1000 : "current" , # 0x5D
170+ DIRECTION_UINT16_X100 : "direction" , # 0x5E
171+ PRECIPITATION_UINT16_X1 : "precipitation" , # 0x5F
172+ CHANNEL_UINT8_X1 : "channel" # 0x60
144173 }
145174
146175 # Properties below are updated externally when sensor values are read.
176+ # There is some overlap in property names in the BTHome format. For
177+ # example: moisture as in percent and moisture as in detected.
178+ # In these cases, the binary property will have "_detected" appended.
147179 # See "Sensor Data" table at https://bthome.io/format/ Property column.
148180 acceleration = 0
149181 battery = 0
182+ battery_low = False
183+ battery_charging = False
184+ carbon_monoxide = False
150185 channel = 0
151186 co2 = 0
187+ cold = False
152188 conductivity = 0
189+ connectivity = False
153190 count = 0
154191 current = 0
155192 dewpoint = 0
156193 direction = 0
157194 distance = 0
195+ door = False
158196 duration = 0
159197 energy = 0
198+ garage_door = False
160199 gas = 0
200+ gas_detected = False
201+ generic_boolean = False
161202 gyroscope = 0
203+ heat = False
162204 humidity = 0
163205 illuminance = 0
164206 mass = 0
@@ -196,6 +238,10 @@ def local_name(self):
196238 # is based on 3.4. Also, __func__ and __get()__ workarounds throw errors in
197239 # MicroPython. [^4]
198240
241+ # Binary flag (true/false, on/off)
242+ def _pack_binary (self , object_id , value ):
243+ return pack ("BB" , object_id , 1 if (value is True ) else 0 )
244+
199245 # 8-bit integer with scaling of 1 (no decimal places)
200246 def _pack_int8_x1 (self , object_id , value ):
201247 return pack ("BB" , object_id , round (value ))
@@ -246,23 +292,33 @@ def _pack_raw_text(self, object_id, value):
246292 return packed_value
247293
248294 _object_id_functions = {
249- BATTERY_UINT8_X1 : _pack_int8_x1 ,
250- TEMPERATURE_SINT16_X100 : _pack_int16_x100 ,
251- HUMIDITY_UINT16_X100 : _pack_int16_x100 ,
252- PRESSURE_UINT24_X100 : _pack_int24_x100 ,
253- ILLUMINANCE_UINT24_X100 : _pack_int24_x100 ,
254- MASS_KG_UINT16_X100 : _pack_int16_x100 ,
255- MASS_LB_UINT16_X100 : _pack_int16_x100 ,
256- DEWPOINT_SINT16_X100 : _pack_int16_x100 ,
257- COUNT_UINT8_X1 : _pack_int8_x1 ,
258- ENERGY_UINT24_X1000 : _pack_int24_x1000 ,
259- POWER_UINT24_X100 : _pack_int24_x100 ,
260- VOLTAGE_UINT16_X1000 : _pack_int16_x1000 ,
261- PM2_5_UINT16_X1 : _pack_int16_x1 ,
262- PM10_UINT16_X1 : _pack_int16_x1 ,
263- CO2_UINT16_X1 : _pack_int16_x1 ,
295+ BATTERY_UINT8_X1 : _pack_int8_x1 , # 0x01
296+ TEMPERATURE_SINT16_X100 : _pack_int16_x100 , # 0x02
297+ HUMIDITY_UINT16_X100 : _pack_int16_x100 , # 0x03
298+ PRESSURE_UINT24_X100 : _pack_int24_x100 , # 0x04
299+ ILLUMINANCE_UINT24_X100 : _pack_int24_x100 , # 0x05
300+ MASS_KG_UINT16_X100 : _pack_int16_x100 , # 0x06
301+ MASS_LB_UINT16_X100 : _pack_int16_x100 , # 0x07
302+ DEWPOINT_SINT16_X100 : _pack_int16_x100 , # 0x08
303+ COUNT_UINT8_X1 : _pack_int8_x1 , # 0x09
304+ ENERGY_UINT24_X1000 : _pack_int24_x1000 , # 0x0A
305+ POWER_UINT24_X100 : _pack_int24_x100 , # 0x0B
306+ VOLTAGE_UINT16_X1000 : _pack_int16_x1000 , # 0x0C
307+ PM2_5_UINT16_X1 : _pack_int16_x1 , # 0x0D
308+ PM10_UINT16_X1 : _pack_int16_x1 , # 0x0E
309+ GENERIC_BOOLEAN : _pack_binary , # 0x0F
310+ CO2_UINT16_X1 : _pack_int16_x1 , # 0x12
264311 TVOC_UINT16_X1 : _pack_int16_x1 ,
265312 MOISTURE_UINT16_X100 : _pack_int16_x100 ,
313+ BATTERY_LOW_BINARY : _pack_binary ,
314+ BATTERY_CHARGING_BINARY : _pack_binary ,
315+ CARBON_MONOXIDE_BINARY : _pack_binary ,
316+ COLD_BINARY : _pack_binary ,
317+ CONNECTIVITY_BINARY : _pack_binary ,
318+ DOOR_BINARY : _pack_binary ,
319+ GARAGE_DOOR_BINARY : _pack_binary ,
320+ GAS_BINARY : _pack_binary ,
321+ HEAT_BINARY : _pack_binary ,
266322 HUMIDITY_UINT8_X1 : _pack_int8_x1 ,
267323 MOISTURE_UINT8_X1 : _pack_int8_x1 ,
268324 COUNT_UINT16_X1 : _pack_int16_x1 ,
0 commit comments