Skip to content

Commit

Permalink
Merge pull request #1380 from zt8989/master
Browse files Browse the repository at this point in the history
Add initial support for Senssun scale
  • Loading branch information
Ernst79 authored Jul 31, 2024
2 parents d8518a9 + 532717b commit 4777397
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ This custom component for [Home Assistant](https://www.home-assistant.io) passiv
- Ruuvitag
- Sensirion
- SensorPush
- Senssun (Scale)
- SmartDry
- Switchbot
- Teltonika
Expand Down
5 changes: 5 additions & 0 deletions custom_components/ble_monitor/ble_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .ruuvitag import parse_ruuvitag
from .sensirion import parse_sensirion
from .sensorpush import parse_sensorpush
from .senssun import parse_senssun
from .smartdry import parse_smartdry
from .switchbot import parse_switchbot
from .teltonika import parse_teltonika
Expand Down Expand Up @@ -422,6 +423,10 @@ def parse_advertisement(
# Laica
sensor_data = parse_laica(self, man_spec_data, mac)
break
elif comp_id == 0x0100 and data_len == 0x14:
# Senssun IF_B7
sensor_data = parse_senssun(self, man_spec_data, mac)
break

# Filter on part of the UUID16
elif man_spec_data[2] == 0xC0 and data_len == 0x10:
Expand Down
50 changes: 50 additions & 0 deletions custom_components/ble_monitor/ble_parser/senssun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Parser for Senssun Scale BLE advertisements"""

import logging
from struct import unpack

from .helpers import to_mac, to_unformatted_mac

_LOGGER = logging.getLogger(__name__)


def read_stable(ctr1):
"""Parse Stable"""
return int((ctr1 & 0xA0) == 0xA0)

def parse_senssun(self, data: bytes, mac: str):
"""Parser for Senssun Scales."""
xvalue = data[13:19]

(division, weight, impedance, ctr1) = unpack(">bhhb", xvalue)
result = {
"type": "Senssun Smart Scale",
"firmware": "Senssun",
"mac": to_unformatted_mac(mac),
"data": True,
"impedance": impedance,
"weight": weight / 100.0,
"stabilized": read_stable(ctr1),
}

# Check for duplicate messages
packet_id = xvalue.hex()
try:
prev_packet = self.lpacket_ids[mac]
except KeyError:
# start with empty first packet
prev_packet = None
if prev_packet == packet_id:
# only process new messages
if self.filter_duplicates is True:
return None
self.lpacket_ids[mac] = packet_id
if prev_packet is None:
if self.filter_duplicates is True:
# ignore first message after a restart
return None

result.update({
"packet": packet_id,
})
return result
2 changes: 2 additions & 0 deletions custom_components/ble_monitor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -1975,6 +1975,7 @@ class BLEMonitorBinarySensorEntityDescription(
'K6 Sensor Beacon' : [["temperature", "humidity", "acceleration", "voltage", "battery", "rssi"], [], []],
'DSL-C08' : [["battery", "rssi", "voltage"], [], ["lock", "childlock"]],
'SmartDry cloth dryer' : [["temperature", "humidity", "voltage", "battery", "shake", "rssi"], [], ["switch"]],
'Senssun Smart Scale' : [["rssi"], ["weight", "impedance"], []],
}

# Sensor manufacturer dictionary
Expand Down Expand Up @@ -2111,6 +2112,7 @@ class BLEMonitorBinarySensorEntityDescription(
'Laica Smart Scale' : 'Laica',
'K6 Sensor Beacon' : 'KKM',
'SmartDry cloth dryer' : 'SmartDry',
'Senssun Smart Scale' : 'Senssun',
}


Expand Down
28 changes: 28 additions & 0 deletions custom_components/ble_monitor/test/test_senssun_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""The tests for the Senssun ble_parser."""

import datetime

from ble_monitor.ble_parser import BleParser


class TestSenssun:
"""Tests for the Senssun parser"""

def test_Senssun_IF_B7(self):
"""Test Senssun parser for IF_B7."""
data_string = "043E2B0201030033B3C1937A181F020106060949465F423714FF0001020311187A93C1B333021A4500B4A1AB61C5"
data = bytes(bytearray.fromhex(data_string))

# pylint: disable=unused-variable
ble_parser = BleParser()
sensor_msg, tracker_msg = ble_parser.parse_raw_data(data)

assert sensor_msg["firmware"] == "Senssun"
assert sensor_msg["type"] == "Senssun Smart Scale"
assert sensor_msg["mac"] == "187A93C1B333"
assert sensor_msg["packet"] == "021a4500b4a1"
assert sensor_msg["data"]
assert sensor_msg["weight"] == 67.25
assert sensor_msg["stabilized"] == 1
assert sensor_msg["impedance"] == 180
assert sensor_msg["rssi"] == -59
17 changes: 17 additions & 0 deletions docs/_devices/Senssun_Smart_Scale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
manufacturer: Senssun
name: Senssun Smart Scale
model: IF_B7
image: IF_B7.jpg
physical_description:
broadcasted_properties:
- weight
- impedance
- rssi
broadcasted_property_notes:
broadcast_rate:
active_scan:
encryption_key:
custom_firmware:
notes:
---
Binary file added docs/assets/images/IF_B7.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/config_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Data from sensors with other addresses will be ignored. Default value: True

**Report unknown sensors**

(`Off`, `Acconeer`, `Air Mentor`, `Amazfit`, `ATC`, `BlueMaestro`, `Blustream`, `Brifit`, `BTHome`, `Chef iQ`, `Govee`, `Grundfos`, `HolyIOT`, `Hormann`, `HHCC`, `iNode`, `iBeacon`, `Jinou`, `Kegtron`, `Mi Scale`, `Mi Band`,`Mikrotik`, `Oras`, `Qingping`, `Relsib`, `rbaron`, `Ruuvitag`, `Sensirion`, `SensorPush`, `SmartDry`, `Switchbot`, `Teltonika`, `Thermoplus`, `Xiaogui`, `Xiaomi`, `Other` or `False`)(Optional) This option is needed primarily for those who want to request an implementation of device support that is not in the list of [supported sensors](devices). If you set this parameter to one of the sensor brands, then the component will log all messages from unknown devices of the specified brand to the Home Assistant log (`logger` component must be enabled at info level, see for instructions the [FAQ](faq#my-sensor-from-the-xiaomi-ecosystem-is-not-in-the-list-of-supported-ones-how-to-request-implementation)). Using a sensor brand might not catch all BLE advertisements.
(`Off`, `Acconeer`, `Air Mentor`, `Amazfit`, `ATC`, `BlueMaestro`, `Blustream`, `Brifit`, `BTHome`, `Chef iQ`, `Govee`, `Grundfos`, `HolyIOT`, `Hormann`, `HHCC`, `iNode`, `iBeacon`, `Jinou`, `Kegtron`, `Mi Scale`, `Mi Band`,`Mikrotik`, `Oras`, `Qingping`, `Relsib`, `rbaron`, `Ruuvitag`, `Sensirion`, `SensorPush`, `Senssun`, `SmartDry`, `Switchbot`, `Teltonika`, `Thermoplus`, `Xiaogui`, `Xiaomi`, `Other` or `False`)(Optional) This option is needed primarily for those who want to request an implementation of device support that is not in the list of [supported sensors](devices). If you set this parameter to one of the sensor brands, then the component will log all messages from unknown devices of the specified brand to the Home Assistant log (`logger` component must be enabled at info level, see for instructions the [FAQ](faq#my-sensor-from-the-xiaomi-ecosystem-is-not-in-the-list-of-supported-ones-how-to-request-implementation)). Using a sensor brand might not catch all BLE advertisements.

If you can't find the advertisements in this way, you can set this option to `Other`, which will result is all BLE advertisements being logged. You can also enable this option at device level. **Attention!** Enabling this option can lead to huge output to the Home Assistant log, especially when set to `Other`, do not enable it if you do not need it! If you know the MAC address of the sensor, its advised to set this option at device level. Details in the [FAQ](faq#my-sensor-from-the-xiaomi-ecosystem-is-not-in-the-list-of-supported-ones-how-to-request-implementation). Default value: `Off`

Expand Down
1 change: 1 addition & 0 deletions info.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ This custom component for [Home Assistant](https://www.home-assistant.io) passiv
- Ruuvitag
- Sensirion
- SensorPush
- Senssun
- SmartDry
- Switchbot
- Teltonika
Expand Down

0 comments on commit 4777397

Please sign in to comment.