Skip to content

Add BPM Vision (48) and BeamO (71) device models - #888

Open
proscar87 wants to merge 2 commits into
joostlek:mainfrom
proscar87:add-bpm-vision-and-beamo
Open

Add BPM Vision (48) and BeamO (71) device models#888
proscar87 wants to merge 2 commits into
joostlek:mainfrom
proscar87:add-bpm-vision-and-beamo

Conversation

@proscar87

@proscar87 proscar87 commented Aug 10, 2026

Copy link
Copy Markdown

Closes #886 and #599.

model_id 48 is the BPM Vision and 71 is the BeamO.

Where that comes from

A live account with seven Withings devices. Those two are the only ones reaching to_enum's fallback — 106 warnings logged across two days.

The identification doesn't rest on elimination this time. getdevice returns a human-readable model alongside model_id, and this library already keeps it as Device.raw_model. The account's own response:

# raw_model model_id mapped
0 Thermo 70
1 BPM Connect 45
2 BPM Connect 45
3 Body Cardio 6
4 BPM Vision 48
5 Body Scan 10
6 BeamO 71

Exactly two unmapped devices, exactly two unsupported values, and the names come from Withings rather than from a guess.

The order also matches independently: to_enum warns while parsing, in array order, and the two distinct messages were first seen as 48 then 71 — the same order as positions 4 and 6.

Credit where it belongs: 48 is not a new identification. #599 has been open since May 2025 naming it as the BPM Vision, with five reporters. All my capture adds there is the raw_model string confirming it. I said otherwise in a comment on #886 and have corrected that.

71 is the one this settles: #729 guessed wrong twice, #886 reasoned it out by elimination, and the raw_model string removes the need for the reasoning.

Tests

tests/test_device_models.py: both ids parse to their member with the correct raw_model and produce no log output, plus a check that a genuinely unknown id still falls back to UNKNOWN and still warns — otherwise this would trade one gap for another.

Full suite: 63 passed, 39 snapshots unchanged. ruff check and ruff format --check clean on the pinned 0.15.22.

One note so it isn't mistaken for a regression: the 100% coverage gate fails on this branch at tests/test_withings.py:121, and it fails identically on an unmodified main (99.60% there, 99.62% here). Not introduced by this change.

Unrelated observation

to_enum warns on every parse, so an unmapped device produces one warning per device per fetch — that's where 106 came from for two devices. If that's ever felt noisy, warning once per (enum, value) would cut it without losing the report. Happy to open that separately; not folding it in here.

🤖 Generated with Claude Code

Both ids come from a live account with seven Withings devices, where they
were the only two reaching to_enum's fallback -- 106 warnings across two
days. The account's getdevice response names them directly: model_id 48
is "BPM Vision" and model_id 71 is "BeamO".

Closes joostlek#886, which identified 71 by elimination. That reasoning happens to
have been right, but the raw_model strings settle it without it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@proscar87

Copy link
Copy Markdown
Author

Heads-up: the Verify check is failing only because the PR carries no label, and I don't have permission to add one.

Precedent suggests bugfix#511 "Add more device models" was labelled that way. Happy to be corrected if you'd rather it were enhancement.

Everything else is green.

`getdevice` returns `"Fluid Analyzer"` as the type for the U-Scan, which
DeviceType did not carry, so it resolved to UNKNOWN and warned on every
fetch. Taken verbatim from a live account's log rather than inferred:

    Fluid Analyzer is an unsupported value for <enum 'DeviceType'>

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@proscar87

Copy link
Copy Markdown
Author

Added one more from the same account, and this one needed no inference at all — DeviceType is a str enum, so the log carries the exact value the API returns:

Fluid Analyzer is an unsupported value for <enum 'DeviceType'>

That's the U-Scan. FLUID_ANALYZER = "Fluid Analyzer" added, with a test that it resolves and logs nothing, plus one that an genuinely unknown type still falls back to UNKNOWN and still warns.

Two more unmapped values turned up that I am deliberately not touching here, since I can't establish either the way the raw_model strings established 48 and 71:

Happy to file those separately once I can name them. Suite still 65 passed, ruff clean.

(The label point above still stands, if you'd rather I leave that to you.)

@proscar87

Copy link
Copy Markdown
Author

Correcting an overstatement in the description above before it stands as evidence it isn't.

I wrote that for 71 "the raw_model string removes the need for the reasoning". That's wrong. The diagnostics report model: 0 for any unmapped device — to_enum has already run by then — so the number never arrives next to the name. The table in the description shows 48 and 71 filled in, but those came from the order argument on the line below it, not from reading them beside the names. The mechanism was disclosed; the table presents it as more direct than it was.

What each identification actually rests on:

  • 48 = BPM Vision — independently established in 48 is an unsupported value for <enum 'DeviceModel'> #599 since May 2025, five reporters. Not mine.
  • 71 = BeamOto_enum warns in array order; distinct messages were first seen 48 then 71, matching positions 4 and 6 in the device array. Order matching, plus 48 being fixed independently.

Both still hold. But "confirmed by name" was the wrong way to put it, and I'd rather say so than have you find it.


A third value, which I am not adding to this PR

102 is an unsupported value for <enum 'DeviceModel'> now appears on the same account, after a U-Scan showed up in the device list. Eight devices, three reporting model: 0:

raw_model model device_type
BPM Vision 0 Blood Pressure Monitor
WPA02 0 unknown
BeamO 0 Smart Connected Thermometer

Three unmapped ids (48, 71, 102) and three devices at model: 0 — the count is exact, nothing left over. With 48 and 71 attributed, 102 is WPA02 by elimination.

Which is precisely the reasoning that produced two wrong answers in #729, so I'm reporting it rather than committing it. A wrong mapping is worse than a missing one: the device would be silently mislabelled instead of merely warning.

What is solid here is the Fluid Analyzer type — WPA02 is the only one of the eight whose device_type falls back to unknown, and the log carries the string verbatim. That part is already in this PR.

If you want 102 on this evidence, say so and I'll add it with the reasoning in the commit message. Otherwise the definitive answer is the raw getdevice response with debug logging on, where model_id and model do sit together — I can capture that if it's worth the round trip.

And a fourth, unrelated

11 is an unsupported value for <enum 'MeasurementAttribution'> — first seen once, today. That enum carries 0-5, 7 and 15. Nothing in the payload names it, so it's the same shape as #887: it needs someone who knows what action produced the measurement. Happy to file it separately if you'd like it tracked.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

71 is an unsupported value for <enum 'DeviceModel'> — it is the BeamO

1 participant