All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.8.3 - 2026-09-09
- Date-of-birth based user profiles: the user profile stores an optional
date_of_birthinstead of collecting an age; the current age is derived from it with a birthday-aware calculation, so it never needs a manual yearly update. The handshake and body-composition math receive the derived age (HA-local date, no UTC off-by-one around birthdays), and derived sensors refresh once per HA-local day. - Safe migration for existing profiles: profiles created before DOB support keep their stored age and load unchanged; no DOB is ever fabricated. Enter a date of birth once through Options → Edit user and it becomes the source of truth (the age key is dropped on save). A blank DOB stays allowed for legacy profiles while they keep using their stored age.
- DOB input validation: invalid dates and future dates are rejected with
clear UI errors (
YYYY-MM-DD, year 1900+). - Unit tests: birthday-aware age math (including leap days), DOB
validation, legacy profile loading, serialization round-trips, handshake
age byte and multi-user independence (
tests/test_dob.py).
- Options/Config flow user forms: "Age" replaced by "Date of birth" with an explanatory note ("your age is calculated automatically from this date"). No stable ids, device/entity relationships, Person links, measurement history or deletion behavior changed.
0.8.2 - 2026-09-09
- README redesigned for HACS and general readability: release/HACS/ license/CI badges, grouped feature blocks, dedicated hardware and requirements sections, HACS-first installation, clearer multi-user and configuration guidance, and an accurate description of the offline last-known-value behavior introduced in v0.8.1.
- Privacy sanitization pass across the whole repository: no personal
names, addresses, e-mail addresses, phone numbers, real Bluetooth MACs,
private IPs/hostnames, or credentials are present in any tracked file.
Protocol UUIDs and documentation placeholders
(
AA:BB:CC:DD:EE:FF,user@example.invalid) are kept.
0.8.1 - 2026-09-08
- Sensor state persistence across BLE disconnects: user measurement and
derived sensors no longer gate availability on the BLE connection state.
Once a valid measurement exists, entities keep their last known value
(and stay
available) while the scale sleeps/disconnects, so history graphs keep a continuous line instead of showing a gap. The scale-levelConnectedbinary sensor still reports link state independently.
0.8.0 - 2026-09-08
- Device branding: physical scale device friendly name is now the
canonical
Realme Smart Scale(MAC no longer part of the primary name; model metadata isRMH2011). User devices are named by the person only (no repeated "Realme Smart Scale - ..." prefix) under the scale viavia_device. Stable device identifiers are unchanged. - Entity metadata:
Last Measuredis now categorizedDIAGNOSTIC; icons aligned (Muscle->mdi:arm-flex,BMI->mdi:human,Ideal Weight->mdi:target); entity unique ids/entity ids are untouched. - Handshake-profile select shows the person's name (no internal user id) unless names collide.
- Options flow copy: Remove-user screens now clearly state that removal permanently deletes the user's measurements, sensors and device (matching v0.7 deletion); "Home Assistant person (optional)" labels. No flow logic or deletion implementation changed.
- Static UI-metadata tests (
tests/test_ui_metadata.py).
0.7.0 - 2026-09-08
-
Complete user deletion:
coordinator.async_remove_user(user_id)(invoked only from Options → Remove User → Save & Close) now removes everything belonging to the user, keyed on the stableuser_id:- the user's HA entities (entity registry),
- the user's virtual device (device registry, stable
(DOMAIN, f"{address}_{user_id}")identifier), - the user's persisted measurement records (store deletion),
- all runtime state (
users,_user_by_id,latest_by_user,_identity_state,last_measurement, active fallback).
The physical scale device, other users, HA Person links and dashboard configuration are never touched. Deletion is idempotent and works with or without a Person link.
-
Deletion only on explicit Options-Flow action: setup/reload never call the removal path, so HACS updates and restarts can never erase users or data. Users live in
config_entry.options; measurements live in Home Assistant's.storageviaStore(never the source directory).
- Regression tests: full-cleanup implementation, registry API usage, deletion never invoked during startup/reload, save-close-only invocation, and persistent-storage-outside-source-dir guarantees.
0.6.3 - 2026-09-08
- Save & Close "a coroutine was expected, got None": the config-entry
options update listener
_async_options_updatedwas a synchronous@callbackfunction returningNone, but HA awaits the listener. It is now anasync defthat directlyawaitsconfig_entries.async_reload(noasync_create_task), keeping the no-change/no-coordinator early returns.@callbackremains only where it is actually used (_register_services_once).
0.6.2 - 2026-09-08
- Options menu displayed internal ids (e.g.
add_user) instead of the human-readable labels:async_show_menutreats a dict as explicit labels, so_build_menu()now returns a list of step ids, letting Home Assistant resolve each entry through themenu_optionstranslations. Action constants andasync_step_*handlers are unchanged; strings.json/en.json labels are untouched.
0.6.1 - 2026-09-08
- Options → Reassign menu UnknownStep:
ACTION_REASSIGNnow resolves toreassign_pick(canonical step), matchingasync_step_reassign_pick; the stalereassign_measurementmenu key/label reference was removed from code and both translation files.assign_pickremains the canonical assign step. - Save & Close while the scale is asleep/offline no longer fails:
async_setup_entry()no longer refuses to start when the scale is not currently reachable (async_resolve_ble_device()gate removed). The coordinator keeps its background BLE retry loop, so config saves/reloads always persist and the scale reconnects when it becomes available.
- Regression/structure tests:
ACTION_REASSIGN == reassign_pick, every menu option maps to an implementedasync_step_*handler, no staleassign_unknown/reassign_measurementnavigation references remain, andasync_setup_entryis not gated on BLE reachability while the coordinator retry loop is preserved.
0.6.0 - 2026-09-08
- Separated concepts: handshake profile (BLE), configured user (profile), detected user (owner of a measurement) are distinct; "Active user" UI is renamed Scale handshake profile everywhere and documented as not being the detected person.
- Identity baseline is separate from latest measurement. Baselines are rebuilt only from identity-valid stored records. With an expected weight configured, an out-of-range assignment (e.g. 52 kg handed to a 73 kg user) can never poison the identity range - the next ~52 kg reading still identifies the correct lighter user.
- Per-user identity fields: Expected weight (kg), Identification tolerance (kg), Impedance tolerance (Ohm); 0 falls back to the global automatic-identification defaults.
- User devices show only identity-valid measurements as their "latest".
- Identity-range gating (expected +/- tolerance), impedance as secondary tie-breaker, no-match/ambiguous stay unassigned, single-user easy mode.
- Returns
method(automatic_weight,automatic_weight_impedance,none) andconfidence; both persist on records and are included in the measurement event payload.
- Canonical flow step name
assign_pickeverywhere; the staleassign_unknownmenu key/step reference is gone (menu key, Python action, strings and translations now all useassign_pick). - Manual assignment returns a friendly "measurement no longer available" message instead of a raw traceback for stale records.
0.5.1 - 2026-09-08
- Options Flow follows the current HA API:
async_get_options_flowis a@staticmethod @callbacksynchronous hook returning a no-argumentRealmeScaleOptionsFlow(); the flow reads the entry from the parentOptionsFlow.config_entryproperty. - Bluetooth metadata per current guidance: manifest depends on
bluetooth_adapters(notbluetooth) and only advertises connectable discovery matchers (service UUID + scale-like names) — noconnectable: falseentries, since the RMH2011 needs an active GATT session. - Discovery rejects non-connectable sources (
not_connectableabort with a clear message/translation) instead of half-configuring a scale it cannot connect to. - Menu wording: Add User / Edit User / Remove User / Active User / Assignment Settings / Assign Unknown Measurement / Reassign Measurement / Save & Close, first screen shows "Configured users: {count} / Unknown measurements: {pending}".
- README: "Adding additional users" section + Active User vs Assigned User explanation.
- Regression/structure tests for the options flow:
tests/test_user_management.py(step & hook presence, translation coverage for every menu action/step/error/abort, and the full add → edit → remove → zero-users storage journey).
0.5.0 - 2026-09-08
- Multi-user management spec: the scale stays a single config entry with users as profiles inside it (stable UUID ids, shared BLE coordinator, per-user devices under the scale). Add/edit/delete users from the entry's Options → Users & measurements.
- Zero-user support: the last user may now be deleted; the scale remains configured and measurements arrive as unassigned until a user is added.
- Delete confirmation: deleting a user now asks for explicit confirmation.
- History preserved on delete: a deleted user's stored measurements are kept and become unassigned records (re-attributable later), instead of being dropped.
- Wording aligned with the spec: Users / Add user / Edit user / Delete user throughout the options flow (no per-user "devices" language).
parse_user_optionsno longer invents a fallback user when the storeduserslist is explicitly empty (previously blocked zero-user mode).
0.4.4 - 2026-09-08
- Opening entry Options returned "500 / Config flow could not be
loaded":
async_get_options_flowwas declaredasync def, but Home Assistant invokes it synchronously and expects the flow instance; an un-awaited coroutine caused the 500. The hook is now a plain (non-async) static method, so the Users & measurements menu opens.
0.4.3 - 2026-09-08
- Entry "Options" menu (Users & measurements) was missing entirely:
RealmeScaleConfigFlownever registeredasync_get_options_flow, so Home Assistant did not expose the entry's Options at all. The hook is now wired andRealmeScaleOptionsFlowaccepts the config entry it is constructed with. Add / edit / remove users now works from the entry card.
0.4.2 - 2026-09-08
- "Add Integration → Realme Smart Scale" reported
not_implemented: a refactor had leftasync_step_user/async_step_profiledefined outside theRealmeScaleConfigFlowclass, so Home Assistant could not find the starting step. The steps are proper class methods again. - The address step now always uses a plain, universally serializable MAC text field (discovered scales are shown as a hint instead of a dropdown that some Home Assistant versions cannot render).
0.4.1 - 2026-09-07
- Repository branding: realme logo added as repo-root
icon.png/logo.png(HACS) and as component brand assetscustom_components/realme_scale/brand/{icon,logo}{,@2x}.pngfor Home Assistant 2026.3+. - README: contributor credits section.
- Integration Help link now points to this repository's documentation (was the upstream openScale repo).
- Options-flow Back navigation no longer raises
not_implemented(missingasync_step_menuhandler for the menu step).
0.4.0 - 2026-09-07
- Derived metric sensors per user (computed on the fly): BMI, body fat mass (kg), BMR (Schofield/WHO), ideal weight (Devine), protein % (Wang).
- Interpretation text sensors per user: BMI category (WHO), body-fat category (Gallagher age/sex bands), body-water level, visceral-fat rating and a simple body-type heuristic.
realme_scale_measurementevents for unassigned readings now also carrycandidate_user_ids(parallel tocandidate_users).- Interactive confirm blueprint (
blueprints/ realme_scale_confirm_measurement.yaml): push notification with one quick action per likely user; tapping assigns the measurement. - README: derived-metrics reference table, medical disclaimer and formula sources.
- Unit tests for the metrics module (
tests/test_metrics.py).
0.3.0 - 2026-09-07
- CI: GitHub Actions workflow runs the pure-python test suite on push/PR.
- HA People integration: user setup/edit forms offer a dropdown of
existing
person.*entities; picking one auto-fills the profile name and links the profile (every sensor of that user then exposesperson/person_entity_idattributes). - Discovery filtering: only devices advertising the scale service UUID
(
0000a602) or a scale-like name token are offered by the integration — other realme BLE devices (e.g. "realme Buds Air7") are no longer detected as a scale. - Multi-user support: every scale entry now holds a list of user profiles; users can be added / edited / removed after install from a menu-driven options flow.
- One HA device per user: each user's latest attributed measurement is exposed as its own device with the full sensor set.
- Active-user select entity plus options action to pick which profile is written into the scale handshake (reconnects to apply).
- Two-signal auto-attribution (weight + impedance fingerprints, both with configurable tolerances): measurements are matched to the user whose last reading is consistent with the new one.
- Confirm-before-assign semantics: readings that match nobody - or match
several users - are not silently attributed; they stay unassigned and
the event reports
candidate_users(nearest first) for a confirm prompt. - Persistent measurement store (per entry): every packet is recorded
with a
measurement_id; the bounded unassigned queue survives restarts. - Assign unassigned measurements to a user later from Options →
Assign unassigned measurements or via the new
realme_scale.assign_measurementservice; BIA figures are recomputed under the assigned user's profile. - Reassign already-assigned records (Options → Reassign a recent measurement, or the same service) to fix wrong auto-assignments; the affected users' "latest" sensors are refreshed from the store.
realme_scale_measurementevents now carrymeasurement_idandstatus(assigned|unknown), pluscandidate_usersfor ambiguous readings.- README: per-user dashboard guide with example YAML and entity ids.
- Unit tests for attribution, record serialization and user-options
parsing/migration (
tests/test_assignment.py,test_records.py,test_options.py).
- Config flow 500 on current Home Assistant: the manual MAC field no
longer uses
cv.matches_regex(newer schema serializers reject it); the MAC is validated in code instead. - Discovery no longer matches unrelated realme BLE devices (see "Discovery filtering" above).
- Import of the measurement-id constant in
store.pytidied up.
- Old single-profile entries migrate transparently: the flat profile becomes a one-user registry with the legacy user id.
- Sensor unique ids are now user-scoped
(
<unique>_user_<user_id>_<metric>). After upgrading, previously configured sensors appear as separate per-user entities; orphaned v0.1 entities may need to be removed from the entity registry.
0.1.1 - 2026-02-09
hacs.json(HACS-ready metadata for the custom component).CHANGELOG.md.- GitHub Actions CI (
pytestfor the protocol/BIA unit tests).
- GATT write type now mirrors openScale's
GattScaleAdapter: write-with-response is used unless the characteristic only advertisesPROPERTY_WRITE_NO_RESPONSE.
0.1.0 - 2026-02-09
- Initial release.
- Home Assistant custom integration for the realme Smart Scale RMH2011.
- Byte-faithful port of the openScale
RealmeSmartScaleHandlerprotocol:- service
0000a602, characteristicsa621(notify),a622(keep-alive),a624(handshake),a625(notify); - 6-step handshake to
a624with MAC-keyed XOR (MAC[i % 6]) body cipher; - keep-alive
00 01 D9toa622every 1 s; - live measurement stream on
a621(weightu16BE/100, scale timeu32BE, impedanceu16BE).
- service
- Local body-composition engine ported from openScale
YunmaiLib(body fat, water, muscle, bone mass, lean body mass, visceral fat). - Config flow with BLE discovery and a user profile step (sex / age / height / activity level / initial weight), plus options flow.
- Nine sensors and a connectivity binary sensor.
realme_scale_measurementHA event andrealme_scale.reconnectservice.- Unit tests + hardware-free protocol smoke test (
tests/).