Skip to content

Commit 8560ed2

Browse files
bthome.py - add some binary sensors
1 parent 782f67f commit 8560ed2

File tree

1 file changed

+125
-69
lines changed

1 file changed

+125
-69
lines changed

src/bthome.py

Lines changed: 125 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)