Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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 @@ -50,6 +50,7 @@
from .tilt import parse_tilt
from .xiaogui import parse_xiaogui
from .xiaomi import parse_xiaomi
from .michelin import parse_michelin_tms

_LOGGER = logging.getLogger(__name__)

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
49 changes: 49 additions & 0 deletions custom_components/ble_monitor/ble_parser/michelin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""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"
result = {"type": device_type}
frame_type = data[5]

if frame_type in [0x03, 0x04]:
if msg_length != 14:
_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,
})

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": "TMS",
"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 @@ -2204,6 +2204,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 @@ -2354,6 +2355,7 @@ class BLEMonitorBinarySensorEntityDescription(
'ST10' : 'MOCREO',
'MS1' : 'MOCREO',
'MS2' : 'MOCREO',
'TMS' : 'MICHELIN',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'TMS' : 'MICHELIN',
'TMS' : 'Michelin',

'S-MATE' : 'Sonoff',
'R5' : 'Sonoff',
}
Expand Down Expand Up @@ -2439,6 +2441,7 @@ class BLEMonitorBinarySensorEntityDescription(
'XMOSB01XS' : 'Xiaomi',
'RS1BB' : 'Linptech',
'ES3' : 'Linptech',
'TMS' : 'MICHELIN',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'TMS' : 'MICHELIN',
'TMS' : 'Michelin',

}


Expand Down
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 = "043E2002010000332211A703BC1B02010611FF2808010351C6C00350345301C6000000D1"
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"

Check failure on line 15 in custom_components/ble_monitor/test/test_michelin.py

View workflow job for this annotation

GitHub Actions / Run tests

TestMichelin.test_parse_michelin_tms TypeError: 'NoneType' object is not subscriptable
assert sensor_msg["type"] == "TMS"
assert sensor_msg["mac"] == "BC03A7112233"
assert sensor_msg["packet"] == "no packet id"
assert sensor_msg["data"] == True
assert sensor_msg["temperature"] == 22
assert sensor_msg["voltage"] == 2.98
assert sensor_msg["pressure"] == 960
assert sensor_msg["count"] == 198
assert sensor_msg["steps"] == 1
assert sensor_msg["text"] == "P4S"
assert sensor_msg["rssi"] == -47
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