Skip to content

Implement entity merge strategy for Meshtastic mesh nodes#78

Merged
d3mocide merged 2 commits into
mainfrom
claude/mesh-network-normalize-ZSEDM
May 22, 2026
Merged

Implement entity merge strategy for Meshtastic mesh nodes#78
d3mocide merged 2 commits into
mainfrom
claude/mesh-network-normalize-ZSEDM

Conversation

@d3mocide
Copy link
Copy Markdown
Owner

Summary

Adds a merge mode to entity publishing that preserves existing entity data while selectively updating fields with new values. This enables incremental updates to mesh node entities from multiple Meshtastic message types (position, nodeinfo, telemetry) without losing previously-observed attributes.

Key Changes

  • poller/bus.py: Added merge parameter to publish_entity() that performs intelligent field merging:

    • Skips None values (only non-null fields update)
    • Deep-merges identity dicts (new non-None keys win, existing keys preserved)
    • Falls back to full replacement on merge errors
  • poller/normalizers/meshtastic_mqtt.py: Updated all three mesh node handlers to use merge=True:

    • _handle_position(): Removed hardcoded display_name field; now merges position data
    • _handle_nodeinfo(): Enabled merge mode for identity updates
    • _handle_telemetry(): Removed redundant display_name, lat, lon fields; enabled merge mode
  • poller/db.py: Updated write_entity_observation() SQL to preserve existing data:

    • display_name: Uses COALESCE() to keep existing value if new is NULL
    • identity: Uses PostgreSQL || operator for JSONB merge instead of replacement
  • poller/pollers/meshcore_pymc.py: Added altitude and status fields to contact entity template for consistency with other mesh node sources

Implementation Details

The merge strategy allows Meshtastic handlers to publish partial entity updates without clobbering data from other message types. For example:

  • Position updates contribute lat/lon/altitude/signal_quality
  • Nodeinfo updates contribute display_name/identity/hardware info
  • Telemetry updates contribute battery/environment metrics

All updates flow through the same entity_id, and the merge logic ensures each handler's contribution is preserved across multiple publishes.

https://claude.ai/code/session_01C1LWuAM16EChKffhfZvAWd

claude added 2 commits May 22, 2026 13:17
… and position

Meshtastic sends position, nodeinfo, and telemetry as separate MQTT messages.
Because publish_entity did a full Redis SET and the DB ON CONFLICT clause fully
replaced display_name and identity, a position update would overwrite the human
name set by nodeinfo (e.g. "K5ABC" → "!12345678"), and nodeinfo would wipe the
lat/lon set by position.

- bus.py: add merge=True option to publish_entity; performs a Redis GET+merge
  before writing, deep-merging the identity dict so partial updates only
  update the fields they provide
- db.py: use COALESCE for display_name (NULL doesn't overwrite a good name)
  and the PostgreSQL || operator to merge the identity JSONB column instead
  of replacing it wholesale
- meshtastic_mqtt.py: position and telemetry handlers drop display_name (not
  authoritative for names) and use merge=True; nodeinfo uses merge=True so it
  preserves existing lat/lon while setting the human name
- meshcore_pymc.py: add altitude, status, and last_seen fields to entity dict
  for consistency with the other two mesh sources

https://claude.ai/code/session_01C1LWuAM16EChKffhfZvAWd
… sources

- mesh_node.py: add shared snr_to_quality() export so the formula is defined
  once; fix hw_model to emit None instead of "" when the model is unknown
- meshtastic_mqtt.py: import snr_to_quality from the shared normalizer,
  removing the duplicate private copy
- meshcore.py: import snr_to_quality; stamp signal_quality on the sending
  node's entity on every throttled packet event (merge=True so only that
  field changes); replace the hardcoded "local" node_a sentinel with the
  actual local node entity_id from _local_node_ids

https://claude.ai/code/session_01C1LWuAM16EChKffhfZvAWd
@d3mocide d3mocide merged commit bc2847a into main May 22, 2026
6 checks passed
@d3mocide d3mocide deleted the claude/mesh-network-normalize-ZSEDM branch May 22, 2026 20:05
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.

2 participants