mirror of
https://github.com/l5yth/potato-mesh.git
synced 2026-08-10 19:03:28 +02:00
Ensure node numeric aliases are derived from canonical IDs (#101)
* Derive node numeric aliases when missing * Preserve raw message senders when storing payloads * Normalize packet message sender ids when available * run rufo
This commit is contained in:
+64
-3
@@ -236,6 +236,48 @@ get "/api/messages" do
|
||||
query_messages(limit).to_json
|
||||
end
|
||||
|
||||
# Determine the numeric node reference for a canonical node identifier.
|
||||
#
|
||||
# The Meshtastic protobuf encodes the node ID as a hexadecimal string prefixed
|
||||
# with an exclamation mark (for example ``!4ed36bd0``). Many payloads also
|
||||
# include a decimal ``num`` alias, but some integrations omit it. When the
|
||||
# alias is missing we can reconstruct it from the canonical identifier so that
|
||||
# later joins using ``nodes.num`` continue to work.
|
||||
#
|
||||
# @param node_id [String, nil] canonical node identifier (e.g. ``!4ed36bd0``).
|
||||
# @param payload [Hash] raw node payload provided by the data daemon.
|
||||
# @return [Integer, nil] numeric node reference if it can be determined.
|
||||
def resolve_node_num(node_id, payload)
|
||||
raw = payload["num"]
|
||||
|
||||
case raw
|
||||
when Integer
|
||||
return raw
|
||||
when Numeric
|
||||
return raw.to_i
|
||||
when String
|
||||
trimmed = raw.strip
|
||||
return nil if trimmed.empty?
|
||||
return Integer(trimmed, 10) if trimmed.match?(/\A[0-9]+\z/)
|
||||
return Integer(trimmed.delete_prefix("0x").delete_prefix("0X"), 16) if trimmed.match?(/\A0[xX][0-9A-Fa-f]+\z/)
|
||||
if trimmed.match?(/\A[0-9A-Fa-f]+\z/)
|
||||
canonical = node_id.is_a?(String) ? node_id.strip : ""
|
||||
return Integer(trimmed, 16) if canonical.match?(/\A!?[0-9A-Fa-f]+\z/)
|
||||
end
|
||||
end
|
||||
|
||||
return nil unless node_id.is_a?(String)
|
||||
|
||||
hex = node_id.strip
|
||||
return nil if hex.empty?
|
||||
hex = hex.delete_prefix("!")
|
||||
return nil unless hex.match?(/\A[0-9A-Fa-f]+\z/)
|
||||
|
||||
Integer(hex, 16)
|
||||
rescue ArgumentError
|
||||
nil
|
||||
end
|
||||
|
||||
# Insert or update a node row with the most recent metrics.
|
||||
#
|
||||
# @param db [SQLite3::Database] open database handle.
|
||||
@@ -259,9 +301,11 @@ def upsert_node(db, node_id, n)
|
||||
else v
|
||||
end
|
||||
}
|
||||
node_num = resolve_node_num(node_id, n)
|
||||
|
||||
row = [
|
||||
node_id,
|
||||
n["num"],
|
||||
node_num,
|
||||
user["shortName"],
|
||||
user["longName"],
|
||||
user["macaddr"],
|
||||
@@ -314,6 +358,15 @@ def require_token!
|
||||
halt 403, { error: "Forbidden" }.to_json unless token && !token.empty? && provided == token
|
||||
end
|
||||
|
||||
# Determine whether the canonical node identifier should replace the provided
|
||||
# sender reference for a message payload.
|
||||
#
|
||||
# @param message [Object] raw request payload element.
|
||||
# @return [Boolean]
|
||||
def prefer_canonical_sender?(message)
|
||||
message.is_a?(Hash) && message.key?("packet_id") && !message.key?("id")
|
||||
end
|
||||
|
||||
# Insert a text message if it does not already exist.
|
||||
#
|
||||
# @param db [SQLite3::Database] open database handle.
|
||||
@@ -323,8 +376,16 @@ def insert_message(db, m)
|
||||
return unless msg_id
|
||||
rx_time = m["rx_time"]&.to_i || Time.now.to_i
|
||||
rx_iso = m["rx_iso"] || Time.at(rx_time).utc.iso8601
|
||||
from_id = normalize_node_id(db, m["from_id"]) || m["from_id"]
|
||||
from_id = from_id.to_s.strip unless from_id.nil?
|
||||
raw_from_id = m["from_id"]
|
||||
trimmed_from_id = raw_from_id.nil? ? nil : raw_from_id.to_s.strip
|
||||
trimmed_from_id = nil if trimmed_from_id&.empty?
|
||||
canonical_from_id = normalize_node_id(db, raw_from_id)
|
||||
use_canonical = canonical_from_id && (trimmed_from_id.nil? || prefer_canonical_sender?(m))
|
||||
from_id = if use_canonical
|
||||
canonical_from_id.to_s.strip
|
||||
else
|
||||
trimmed_from_id
|
||||
end
|
||||
from_id = nil if from_id&.empty?
|
||||
row = [
|
||||
msg_id,
|
||||
|
||||
Reference in New Issue
Block a user