Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -29,6 +29,7 @@
from .kegtron import parse_kegtron
from .kkm import parse_kkm
from .laica import parse_laica
from .michelin import parse_michelin_tms
from .mikrotik import parse_mikrotik
from .miscale import parse_miscale
from .moat import parse_moat
Expand Down Expand Up @@ -297,6 +298,10 @@ def parse_advertisement(
comp_id = (man_spec_data[3] << 8) | man_spec_data[2]
data_len = man_spec_data[0]
# Filter on Company Identifier
if comp_id == 0x0828:
# Michelin TMS
sensor_data = parse_michelin_tms(self, man_spec_data, mac)
break
if comp_id == 0x0001 and data_len in [0x09, 0x0C, 0x22, 0x25]:
# Govee H5101/H5102/H5106/H5177
sensor_data = parse_govee(self, man_spec_data, service_class_uuid16, local_name, mac)
Expand Down
50 changes: 50 additions & 0 deletions custom_components/ble_monitor/ble_parser/michelin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Parser for Michelin TMS BLE advertisements."""
import logging
from struct import unpack

from .helpers import to_mac, to_unformatted_mac

_LOGGER = logging.getLogger(__name__)


def parse_michelin_tms(self, data: bytes, mac: bytes):
"""Parser for Michelin TMS."""
msg_length = len(data)
device_type = "TMS"
firmware = "TMS"
result = {"firmware": firmware}
frame_type = data[5]
if frame_type in [0x03, 0x04]:
if msg_length != 18:
_LOGGER.error("Found %s bytes from sensor: %s", msg_length, to_mac(mac))
return
(raw_temp, raw_volt, absolute_pressure_bar, tyre_id, steps, frame_counter) = unpack(
"<BBH3sBL", data[6:18]
)
temperature_celcius = raw_temp - 60
battery_voltage = round((raw_volt / 100) + 1.0, 2)
result.update({
"temperature": temperature_celcius,
"voltage": battery_voltage,
"pressure": absolute_pressure_bar,
"count": frame_counter,
"steps": steps,
"text": tyre_id.decode('utf-8', errors='replace'),
})

else:
_LOGGER.info(
"BLE ADV from UNKNOWN TMS DEVICE: MAC: %s, ADV: %s",
to_mac(mac),
data.hex()
)
return None

result.update({
"mac": to_unformatted_mac(mac),
"firmware": firmware,
"type": device_type,
"packet": "no packet id",
"data": True
})
return result
3 changes: 3 additions & 0 deletions custom_components/ble_monitor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2207,6 +2207,7 @@ class BLEMonitorBinarySensorEntityDescription(
'ST10' : [["temperature", "battery", "rssi"], [], []],
'MS1' : [["temperature", "battery", "rssi"], [], []],
'MS2' : [["temperature", "humidity", "battery", "rssi"], [], []],
'TMS' : [["temperature", "voltage", "pressure", "count", "steps", "text", "rssi"], [], []],
'S-MATE' : [["rssi"], ["three btn switch left", "three btn switch middle", "three btn switch right"], []],
'R5' : [["rssi"], ["six btn switch top left", "six btn switch top middle", "six btn switch top right", "six btn switch bottom left", "six btn switch bottom middle", "six btn switch bottom right"], []],
}
Expand Down Expand Up @@ -2360,6 +2361,7 @@ class BLEMonitorBinarySensorEntityDescription(
'ST10' : 'MOCREO',
'MS1' : 'MOCREO',
'MS2' : 'MOCREO',
'TMS' : 'Michelin',
'S-MATE' : 'Sonoff',
'R5' : 'Sonoff',
}
Expand Down Expand Up @@ -2445,6 +2447,7 @@ class BLEMonitorBinarySensorEntityDescription(
'XMOSB01XS' : 'Xiaomi',
'RS1BB' : 'Linptech',
'ES3' : 'Linptech',
'TMS' : 'Michelin',
}


Expand Down
2 changes: 1 addition & 1 deletion custom_components/ble_monitor/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
"btsocket>=0.3.0",
"pyric>=0.1.6.3"
],
"version": "13.11.1"
"version": "13.12.0"
}
26 changes: 26 additions & 0 deletions custom_components/ble_monitor/test/test_michelin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""The tests for the Michelin TMS ble_parser."""
from ble_monitor.ble_parser import BleParser


class TestMichelin:
"""Tests for the Michelin TMS parser"""
def test_parse_michelin_tms(self):
data_string = "043e2102010300e07c03a703bc1502010611ff280801034fc8d403505643017d511e00bc"
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"] == "TMS"
assert sensor_msg["type"] == "TMS"
assert sensor_msg["mac"] == "BC03A7037CE0"
assert sensor_msg["packet"] == "no packet id"
assert sensor_msg["data"] == True
assert sensor_msg["temperature"] == 19
assert sensor_msg["voltage"] == 3.0
assert sensor_msg["pressure"] == 980
assert sensor_msg["count"] == 1986941
assert sensor_msg["steps"] == 1
assert sensor_msg["text"] == "PVC"
assert sensor_msg["rssi"] == -68
22 changes: 22 additions & 0 deletions docs/_devices/Michelin_TMS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
manufacturer: MFP Michelin
name: "TMS"
model: TMS
image: "Michelin_TMS_AL.jpg"
physical_description: "Round body, no screen"
broadcasted_properties:
- temperature
- absolute pressure
- battery
- tire ID
- step (internal FSM)
- count (number of transmitted frames)
- rssi
broadcasted_property_notes:
broadcast_rate:
active_scan:
encryption_key:
custom_firmware:
notes:
- Sold under TMS AF, AL and AQ
---
Binary file added docs/assets/images/Michelin_TMS_AL.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading