Repository navigation
Friendly entity names with stable unique IDs, numeric signal/battery sensors, diagnostics redaction fixes (refs #284) - #320
Draft
pjordanandrsn wants to merge 2 commits into
Conversation
Ported from pjordanandrsn/ha-generac#4 by @technorat2 (commit 7e3b067 "Improve authentication and entity reporting"), entity and telemetry half, applied unchanged to current upstream: - Friendly display names derived from each entity's technical name, while unique_id keeps using the technical name. - Signal strength reported as a numeric percentage (measurement), plus a device battery percentage sensor and an exercise duration sensor when Mobile Link reports them. - _safe_float() accepts "NN%" strings. - Entity availability also follows coordinator.last_update_success. - Diagnostics: tolerate an unloaded entry, redact e-mail addresses, and detect IPv6 with IPv6Network. The authentication half of binarydev#4 is carried separately. Refs binarydev#284 Co-authored-by: Jordan Anderson <paul.jordan.anderson@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K2RdXuPegztHA1uMG2fbtk
Follow-up to the ported friendly-name change. Registry compatibility: - The port derived each unique_id suffix from the class name. That matched history for every class except LastReadingDateSensor, whose historical suffix is "last_reading". Upgrading would have orphaned the existing propane "last reading" entity and created a new one. Every entity class now declares an explicit entity_key; none is inferred, and unique_ids stay byte-for-byte what they were. - SignalStrengthSensor stays unconditional for generators, so existing entities are never dropped when a device omits the value. It is also added for other device types (propane monitors) when reported. Naming: - _attr_has_entity_name = True, so Home Assistant shows "<device name> <label>" (e.g. "Generator Status") and gives newly created entities device-scoped entity_ids such as sensor.generator_exercise_duration instead of a bare, colliding sensor.status. Existing entity_ids live in the registry and do not change. - Binary sensors and the exercise sensor get explicit labels; GeneracConnectingSensor keeps its connectivity device class. Telemetry/diagnostics: - Fuel level percentages go through _safe_float as well. - Diagnostics: IPv4 and IPv6 were labelled the wrong way round; device data was keyed by apparatusId, which leaked the very ID that the redaction removes; panelId, shortDeviceId and deviceId are now redacted too. Tests: a registry upgrade test seeds every historical unique_id and entity_id for a generator and a propane monitor, sets up the integration from fixture payloads, and asserts every entity is reused with no "_2" duplicates and no restored orphans, and that only the new sensors are added on the right devices. Also: a per-class key inventory, numeric percentage parsing, missing/malformed property payloads, sensor selection per device type, availability, and diagnostics redaction. Refs binarydev#284 Co-authored-by: technorat2 <technorat2@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K2RdXuPegztHA1uMG2fbtk
This was referenced Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #284. Companion PR (independent, no ordering dependency): authentication and reliability, #319.
Problem
#284: entity and friendly names look like
generac_12345678_run_time. The name doubles as the unique_id suffix, so making it readable naively would re-key every entity in users' registries. Separately:"75%", so it can't be graphed;REDACTED_IPV4, never redacted e-mail addresses (theparseaddrcheck was inverted), and keyed the output byapparatusIdeven though that same field is redacted.Behavior changes
_attr_has_entity_name = Truewith a readable label, so Home Assistant shows<device name> <label>, e.g. Generator Status or Propane Tank Last Reading. Newly created entities get device-scoped entity_ids (sensor.generator_exercise_duration), which is thedevice_entityform Friendly Entity Naming #284 asks for.entity_key; nothing is inferred from the class name. unique_ids are byte-for-byte unchanged (<entry_id>_<device_id>_generac_<device_id>_<key>).%value withstate_class: measurement."75%"," 75 % ","75"and75all become75.0, and missing or malformed values become unknown instead of"0%". Still always created for generators; now also created for other device types (propane monitors) when reported.apparatus.properties[].value.batteryLevel, battery %) and Exercise Duration (detail property type 95, minutes)._safe_float, so"45%"no longer breaks the state.coordinator.last_update_success, and aNonecoordinator payload no longer raises.REDACTED_IPV4/REDACTED_IPV6, e-mail addresses becomeREDACTED_EMAIL, devices are keyeddevice_0…,panelId/shortDeviceId/deviceIdare added to the redacted keys, and an entry that isn't loaded returns{"status": "not_loaded"}instead of raisingKeyError.Compatibility: entity registry inventory
Every existing entity across sensor, binary_sensor, weather and image keeps its unique_id, and therefore its entity_id, history, customizations and dashboard references.
StatusSensorgenerac_<id>_status…_statusunchangedDeviceTypeSensorgenerac_<id>_device_type…_device_typeunchangedRunTimeSensorgenerac_<id>_run_time…_run_timeunchangedProtectionTimeSensorgenerac_<id>_protection_time…_protection_timeunchangedActivationDateSensorgenerac_<id>_activation_date…_activation_dateunchangedLastSeenSensorgenerac_<id>_last_seen…_last_seenunchangedConnectionTimeSensorgenerac_<id>_connection_time…_connection_timeunchangedBatteryVoltageSensorgenerac_<id>_battery_voltage…_battery_voltageunchangedOutdoorTemperatureSensorgenerac_<id>_outdoor_temperature…_outdoor_temperatureunchangedSerialNumberSensorgenerac_<id>_serial_number…_serial_numberunchangedModelNumberSensorgenerac_<id>_model_number…_model_numberunchangedDeviceSsidSensorgenerac_<id>_device_ssid…_device_ssidunchangedStatusLabelSensorgenerac_<id>_status_label…_status_labelunchangedStatusTextSensorgenerac_<id>_status_text…_status_textunchangedAddressSensorgenerac_<id>_address…_addressunchangedDealerNameSensorgenerac_<id>_dealer_name…_dealer_nameunchangedDealerEmailSensorgenerac_<id>_dealer_email…_dealer_emailunchangedDealerPhoneSensorgenerac_<id>_dealer_phone…_dealer_phoneunchangedPanelIDSensorgenerac_<id>_panel_id…_panel_idunchangedCapacitySensorgenerac_<id>_capacity…_capacityunchangedFuelTypeSensorgenerac_<id>_fuel_type…_fuel_typeunchangedOrientationSensorgenerac_<id>_orientation…_orientationunchangedBatteryLevelSensorgenerac_<id>_battery_level…_battery_levelunchangedLastReadingDateSensorgenerac_<id>_last_reading…_last_readingpinned (class-name inference giveslast_reading_date)FuelLevelSensorgenerac_<id>_fuel_level…_fuel_levelunchangedSignalStrengthSensorgenerac_<id>_signal_strength…_signal_strengthunchangedExerciseMinutesSensor…_exercise_minutesnewDeviceBatteryLevelSensor…_device_battery_levelnewGeneracConnectedSensorgenerac_<id>_is_connected…_is_connectedunchangedGeneracConnectingSensorgenerac_<id>_is_connecting…_is_connectingunchangedGeneracMaintenanceAlertSensorgenerac_<id>_has_maintenance_alert…_has_maintenance_alertunchangedGeneracWarningSensorgenerac_<id>_show_warning…_show_warningunchangedWeatherSensorgenerac_<id>_weather…_weatherunchangedHeroImageSensorgenerac_<id>_hero_image…_hero_imageunchangedWhat users will notice:
generac_<id>_…to<device> <label>. Names set by the user in the UI still take precedence."75%") to a numeric one (75.0). Automations comparing it to the string"75%"would need updating, and long-term statistics now start recording."0%".sensor.generac_<id>_…apply only to existing installs.Regression tests added
tests/test_entity_registry.py(new), plus additions totest_sensor.py,test_entity.pyandtest_diagnostics.py(+21 tests). Existing name assertions were updated to the new labels.Upgrade test: seeds the registry with every historical unique_id/entity_id for a generator and a propane monitor (39 entities), sets up the integration from dacite-parsed fixture payloads, and asserts:
_2duplicates appear;Run against the original class-name inference, it fails with
Extra items: …_67890_generac_67890_last_reading_date.Inventory: each of the 34 entity classes defines its own
entity_key, with no collisions.Numeric percentage parsing (
"75%"," 75 % ","75",75,"N/A"); missing or unexpectedly typed property payloads (None,[], list value, scalar value); exercise duration including a malformed value; fuel level"45%".Sensor selection for generators vs propane monitors.
Availability after a failed poll; a
Nonecoordinator payload.Diagnostics: no apparatusId in keys, correct IPv4/IPv6 labels, e-mail redaction (bare and
Name <addr>), new identifier keys, an entry that isn't loaded.Validation (run locally, Python 3.14.6,
homeassistant==2026.7.4,pytest-homeassistant-custom-component==0.13.348fromrequirements.txt)pytest: 96 passed (baseline onmain: 75 passed)pre-commit run --all-files(check-yaml, end-of-file, trailing-whitespace, flake8, reorder-python-imports, black 23.3.0, prettier): all passedpython -m compileall custom_components: OK;git diff --check: cleanCommits and attribution
Add friendly entity names and numeric signal/battery sensors: authored by @technorat2, their commit 7e3b067 (entity/telemetry half) applied unchanged to currentmain. It deliberately preserves the original, including the issues fixed in commit 2.Keep entity registry IDs stable; use has_entity_name for friendly names: explicit keys,has_entity_name, keeping the generator signal sensor unconditional, fuel-level parsing, diagnostics fixes and tests (Co-authored-by: technorat2).If you squash-merge, GitHub keeps @technorat2 as a co-author.
Not carried over from the original PR
brand/icon.png(Generac logo): Home Assistant brand assets conventionally go through home-assistant/brands, and this repo's HACS check runs withignore: brands. Adding a third-party trademark is the maintainer's call, so it's left out.session_cookietranslation label removal: already onmain(ff0cc61).device_class: connectivityfrom Connecting: an unrelated UI change, so it's kept as-is.Limitations
translation_key-based. That could be a follow-up if you want the entity names translated.batteryLevelfield come from the original contributor's device payloads. There are no public fixtures for them here, so the sensors appear only when the field is present.tuPropertiesbattery (type 17, existing Battery Level) andapparatusbatteryLevelget both sensors. They come from different API fields, but they may describe the same battery.🤖 Generated with Claude Code