Skip to content

Commit

Permalink
Merge pull request #30 from Ernst79/july-update
Browse files Browse the repository at this point in the history
July update [WIP]
  • Loading branch information
Ernst79 committed Jul 5, 2022
2 parents c13d966 + da277f1 commit 34a6f3e
Show file tree
Hide file tree
Showing 38 changed files with 799 additions and 387 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ Supported sensor brands

- Acconeer
- Air Mentor
- Almendo bluSensor
- AltBeacon
- ATC (custom firmware for Xiaomi/Qingping sensors)
- BlueMaestro
- Brifit
- b-parasite
- Govee
- HA BLE
- HHCC
- iBeacon
- Inkbird
- iNode
- Jinou
- Kegtron
- KKM
- Mikrotik
- Moat
- Oral-B
- Qingping
Expand All @@ -36,6 +40,7 @@ Supported sensor brands
- Switchbot
- Teltonika
- Thermoplus
- Thermopro
- Tilt
- Xiaogui (Scale)
- Xiaomi (MiBeacon)
Expand Down Expand Up @@ -67,7 +72,7 @@ ble_parser = BleParser(

**report_unknown**

Report unknown sensors. Can be set to `ATC`, `b-parasite`, `BlueMaestro`, `Brifit`, `Govee`, `Inkbird`, `iNode`, `Jinou`, `Kegtron`, `KKM`, `Moat`, `Mi Scale`, `Oral-B`, `Qingping`, `Ruuvitag`, `SensorPush`, `Sensirion`, `Teltonika`, `Thermoplus`, `Xiaogui` or `Xiaomi` to report unknown sensors of a specific brand to the logger. You can set it to `Other` to report all unknown advertisements to the logger. Default: `False`
Report unknown sensors. Can be set to `ATC`, `b-parasite`, `BlueMaestro`, `Brifit`, `Govee`, `Inkbird`, `iNode`, `Jinou`, `Kegtron`, `KKM`, `Mikrotik`, `Moat`, `Mi Scale`, `Oral-B`, `Qingping`, `Ruuvitag`, `SensorPush`, `Sensirion`, `Teltonika`, `Thermoplus`, `Thermopro`, `Xiaogui` or `Xiaomi` to report unknown sensors of a specific brand to the logger. You can set it to `Other` to report all unknown advertisements to the logger. Default: `False`

**discovery**

Expand Down
25 changes: 19 additions & 6 deletions package/bleparser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
from .bluemaestro import parse_bluemaestro
from .bparasite import parse_bparasite
from .brifit import parse_brifit
from .const import GATT_CHARACTERISTICS, TILT_TYPES
from .const import TILT_TYPES
from .govee import parse_govee
from .ha_ble import parse_ha_ble
from .ha_ble_legacy import parse_ha_ble_legacy
from .hhcc import parse_hhcc
from .ibeacon import parse_ibeacon
from .inkbird import parse_inkbird
Expand All @@ -21,6 +20,7 @@
from .kegtron import parse_kegtron
from .kkm import parse_kkm
from .laica import parse_laica
from .mikrotik import parse_mikrotik
from .miscale import parse_miscale
from .moat import parse_moat
from .oral_b import parse_oral_b
Expand All @@ -32,6 +32,7 @@
from .switchbot import parse_switchbot
from .teltonika import parse_teltonika
from .thermoplus import parse_thermoplus
from .thermopro import parse_thermopro
from .tilt import parse_tilt
from .xiaomi import parse_xiaomi
from .xiaogui import parse_xiaogui
Expand Down Expand Up @@ -184,10 +185,6 @@ def parse_data(self, data):
# UUID16 = FIDO (used by Cleargrass)
sensor_data = parse_qingping(self, service_data, mac, rssi)
break
elif uuid16 in GATT_CHARACTERISTICS and shortened_local_name == "HA_BLE":
# HA BLE legacy (deprecated)
sensor_data = parse_ha_ble_legacy(self, service_data_list, mac, rssi)
break
elif uuid16 == 0x2A6E or uuid16 == 0x2A6F:
# UUID16 = Temperature and Humidity (used by Teltonika)
if len(service_data_list) == 2:
Expand Down Expand Up @@ -221,6 +218,10 @@ def parse_data(self, data):
# Ruuvitag V3/V5
sensor_data = parse_ruuvitag(self, man_spec_data, mac, rssi)
break
elif comp_id == 0x094F and data_len == 0x15:
# Mikrotik
sensor_data = parse_mikrotik(self, man_spec_data, mac, rssi)
break
elif comp_id == 0x06E8:
# Almendo (Blusensor)
sensor_data = parse_almendo(self, man_spec_data, mac, rssi)
Expand Down Expand Up @@ -283,10 +284,18 @@ def parse_data(self, data):
# Jinou BEC07-5
sensor_data = parse_jinou(self, man_spec_data, mac, rssi)
break
elif service_class_uuid16 == 0x5182 and data_len == 0x14:
# Govee H5182
sensor_data = parse_govee(self, man_spec_data, mac, rssi)
break
elif service_class_uuid16 == 0x5183 and data_len == 0x11:
# Govee H5183
sensor_data = parse_govee(self, man_spec_data, mac, rssi)
break
elif service_class_uuid16 == 0x5185 and data_len == 0x17:
# Govee H5185
sensor_data = parse_govee(self, man_spec_data, mac, rssi)
break
elif service_class_uuid16 == 0xF0FF:
if comp_id in [0x0010, 0x0011, 0x0015] and data_len in [0x15, 0x17]:
# Thermoplus
Expand Down Expand Up @@ -314,6 +323,10 @@ def parse_data(self, data):
# Inkbird IBS-TH
sensor_data = parse_inkbird(self, man_spec_data, complete_local_name, mac, rssi)
break
elif complete_local_name[0:5] == "TP359" and data_len == 0x07:
# Thermopro
sensor_data = parse_thermopro(self, man_spec_data, complete_local_name[0:5], mac, rssi)
break

# Filter on other parts of the manufacturer specific data
elif data_len == 0x1B and ((man_spec_data[4] << 8) | man_spec_data[5]) == 0xBEAC:
Expand Down
16 changes: 8 additions & 8 deletions package/bleparser/acconeer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
import logging
from struct import unpack

from .helpers import (
to_mac,
to_unformatted_mac,
)

_LOGGER = logging.getLogger(__name__)

ACCONEER_SENSOR_IDS = {
Expand All @@ -23,7 +28,7 @@ def parse_acconeer(self, data, source_mac, rssi):
result = {"firmware": firmware}

if msg_length == 19 and device_id in ACCONEER_SENSOR_IDS:
"""Acconeer Sensors"""
# Acconeer Sensors
device_type = ACCONEER_SENSOR_IDS[device_id]
measurements = MEASUREMENTS[device_id]
(
Expand All @@ -44,7 +49,7 @@ def parse_acconeer(self, data, source_mac, rssi):
})

result.update({
"battery": battery_level,
"battery": battery_level,
})
else:
device_type = None
Expand Down Expand Up @@ -79,15 +84,10 @@ def parse_acconeer(self, data, source_mac, rssi):

result.update({
"rssi": rssi,
"mac": ''.join('{:02X}'.format(x) for x in acconeer_mac[:]),
"mac": to_unformatted_mac(acconeer_mac),
"type": device_type,
"packet": packet_id,
"firmware": firmware,
"data": True
})
return result


def to_mac(addr: int):
"""Return formatted MAC address"""
return ':'.join('{:02x}'.format(x) for x in addr).upper()
8 changes: 4 additions & 4 deletions package/bleparser/almendo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Parser for Almendo bluSensor BLE advertisements"""
# black -l 79
import logging
from struct import unpack
from .helpers import (
Expand All @@ -16,6 +15,7 @@ def parse_almendo(self, data, source_mac, rssi):
"mac": to_unformatted_mac(source_mac),
"rssi": rssi,
"data": False,
"packet": "no packet id"
}
adstruct_type = data[1]
if adstruct_type == 0xFF:
Expand All @@ -27,17 +27,17 @@ def parse_almendo(self, data, source_mac, rssi):
if version == 1 and dmodel == 0x0A:
# Almendo bluSensor V1 format (BSP02AIQ)
# sensor_state, temp, humi, co2e, tvoc, aiq
(_, temp, humi, co2e, tvoc, aiq) = unpack(
(_, temp, humi, co2e, tvoc, aqi) = unpack(
"<BhHHHB", data[10:20]
)

result.update(
{
"temperature": round(temp / 100, 2),
"humidity": round(humi / 100, 2),
"co2e": co2e,
"co2": co2e,
"tvoc": tvoc,
"aiq": aiq,
"aqi": aqi,
"firmware": "Almendo V1",
"type": "bluSensor Mini",
"data": True,
Expand Down
12 changes: 6 additions & 6 deletions package/bleparser/bluemaestro.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
import logging
from struct import unpack

from .helpers import (
to_mac,
to_unformatted_mac,
)

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -51,15 +56,10 @@ def parse_bluemaestro(self, data, source_mac, rssi):

result.update({
"rssi": rssi,
"mac": ''.join('{:02X}'.format(x) for x in bluemaestro_mac[:]),
"mac": to_unformatted_mac(bluemaestro_mac),
"type": device_type,
"packet": log_cnt,
"firmware": firmware,
"data": True
})
return result


def to_mac(addr: int):
"""Return formatted MAC address"""
return ':'.join(f'{i:02X}' for i in addr)
9 changes: 7 additions & 2 deletions package/bleparser/bparasite.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
import logging
from struct import unpack

from .helpers import (
to_mac,
to_unformatted_mac,
)

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -38,7 +43,7 @@ def parse_bparasite(self, data, source_mac, rssi):
_LOGGER.info(
"BLE ADV from UNKNOWN b-parasite DEVICE: RSSI: %s, MAC: %s, AdStruct(%d): %s",
rssi,
(source_mac),
to_mac(source_mac),
msg_length,
data.hex()
)
Expand All @@ -63,7 +68,7 @@ def parse_bparasite(self, data, source_mac, rssi):

result.update({
"rssi": rssi,
"mac": ''.join('{:02X}'.format(x) for x in bpara_mac[:]),
"mac": to_unformatted_mac(bpara_mac),
"type": device_type,
"packet": packet_id,
"firmware": firmware,
Expand Down
12 changes: 6 additions & 6 deletions package/bleparser/brifit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
import logging
from struct import unpack

from .helpers import (
to_mac,
to_unformatted_mac,
)

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -49,15 +54,10 @@ def parse_brifit(self, data, source_mac, rssi):

result.update({
"rssi": rssi,
"mac": ''.join('{:02X}'.format(x) for x in brifit_mac[:]),
"mac": to_unformatted_mac(brifit_mac),
"type": device_type,
"packet": "no packet id",
"firmware": firmware,
"data": True
})
return result


def to_mac(addr: int):
"""Return formatted MAC address"""
return ':'.join(f'{i:02X}' for i in addr)
20 changes: 1 addition & 19 deletions package/bleparser/const.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Constants for the ble_parser"""
from typing import Final

CONF_MAC: Final = "mac"
Expand Down Expand Up @@ -25,25 +26,6 @@

DEFAULT_MANUFACTURER: Final = "Other"

GATT_CHARACTERISTICS: Final = {
0x2A4D: "packet id",
0x2A19: "battery",
0x2A6D: "pressure",
0x2A6E: "temperature",
0x2A6F: "humidity",
0x2A7B: "dewpoint",
0x2A98: "weight",
0x2AE2: "binary",
0x2AEA: "count",
0x2AEB: "count",
0X2AF2: "energy",
0X2AFB: "illuminance",
0x2B05: "power",
0x2B18: "voltage",
0x2BD6: "pm2.5",
0x2BD7: "pm10",
}

MANUFACTURER_DICT: Final = {
0x0000: "Ericsson Technology Licensing",
0x0001: "Nokia Mobile Phones",
Expand Down

0 comments on commit 34a6f3e

Please sign in to comment.