Skip to content
Open
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## Unreleased

### Fixes

- **EU/NA device discovery**: `omron list` and setup device discovery no longer
return an empty list on the EU/NA v2 API. That API omits the `macAddress`
field, so every device was dropped by the "skip device without MAC address"
guard. The MAC is now derived from the BLE local name (e.g.
`blesmart_…` → `28:FF:B2:10:AA:A4`), then from `deviceSerialID`, matching the
value produced by Bluetooth discovery and manual `add --macaddr`.

## v0.3.0

- **Garmin auth rewritten**: Migrated to garminconnect>=0.3.0 due to Garmin SSO/OAuth changes; replaces garth-based authentication. Re-login required.
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,23 @@ OMRAMIN_GARMIN_DEBUG=1 omramin sync # Garmin API only

---

### Troubleshooting

**`omron list` shows no devices, but the device is in the OMRON app**

- **Region mismatch**: the device only appears on the OMRON regional server your
country code maps to. Make sure the country you logged in with matches your
OMRON account's region. Some countries (e.g. `TR`) map to an offline region
with no cloud API.
- **Not synced to the cloud yet**: open the OMRON Connect phone app so it uploads
the latest measurements — `omramin` reads what's on OMRON's servers, not what is
only on the device over Bluetooth.
- **Inspect the raw response**: `omramin --debug omron list` logs the full
`init-user` response (credentials redacted) so you can see the returned
`deviceList`.

---

## Commands

| Command | Description |
Expand Down
28 changes: 27 additions & 1 deletion omronconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,21 @@ def serial_to_mac(serial: str) -> str:
return ":".join(values[5:2:-1] + values[2::-1])


def ble_local_name_to_mac(local_name: str) -> str:
# e.g. blesmart_0001020828ffb210aaa4 to 28:FF:B2:10:AA:A4
# OMRON encodes the MAC as the last 12 hex chars of the BLE local name.
# Mirrors the BLE-scan derivation in omramin.omron_ble_scan.
name = (local_name or "").strip()
# Only OMRON BLE local names carry the MAC this way; guard against deriving a
# bogus MAC from an unrelated name that happens to end in 12 hex chars.
if not name.upper().startswith("BLESMART_"):
return ""
mac_hex = name[-12:].upper()
Comment thread
rencsaridogan marked this conversation as resolved.
if len(mac_hex) != 12 or not all(c in "0123456789ABCDEF" for c in mac_hex):
return ""
return ":".join(mac_hex[i : i + 2] for i in range(0, 12, 2))


def convert_weight_to_kg(weight: T.Union[int, float], unit: int) -> float:
if unit == WeightUnit.G:
return weight / 1000
Expand Down Expand Up @@ -833,9 +848,20 @@ def get_registered_devices(self, days: T.Optional[int] = 30) -> T.Optional[list[
continue

macAddress = attrs.get("macAddress", "").strip()
if not macAddress:
# EU/NA v2 responses omit macAddress; OMRON encodes the MAC in the
# BLE local name (blesmart_<...>) and falls back to deviceSerialID.
macAddress = ble_local_name_to_mac(attrs.get("deviceLocalName", ""))
if not macAddress:
serial = attrs.get("deviceSerialID", "")
if serial:
macAddress = serial_to_mac(serial)
Comment thread
rencsaridogan marked this conversation as resolved.
if not macAddress:
L.debug(f"Skipping device without MAC address: {attrs.get('name', 'unknown')}")
continue
# Normalize case so every discovery path (API macAddress, BLE local
# name, serial fallback) yields the same string for a given device.
macAddress = macAddress.upper()

category = None
deviceCategory = attrs.get("deviceCategory")
Expand All @@ -855,7 +881,7 @@ def get_registered_devices(self, days: T.Optional[int] = 30) -> T.Optional[list[
continue

else:
L.warning(f"Device with unknown category {device.get('deviceModel')}")
L.warning(f"Device with unknown category {deviceModel}")

# Create OmronDevice
deviceModel = attrs.get("deviceModel", attrs.get("identifier", "Unknown"))
Expand Down