Add first_heard timestamp (#23)

This commit is contained in:
l5y
2025-09-14 09:12:57 +02:00
committed by GitHub
parent c67b18c657
commit 62b096c601
5 changed files with 71 additions and 8 deletions
+47
View File
@@ -0,0 +1,47 @@
-- Add first_heard column to nodes table and backfill with last_heard
BEGIN TRANSACTION;
CREATE TABLE nodes_new (
node_id TEXT PRIMARY KEY,
num INTEGER,
short_name TEXT,
long_name TEXT,
macaddr TEXT,
hw_model TEXT,
role TEXT,
public_key TEXT,
is_unmessagable BOOLEAN,
is_favorite BOOLEAN,
hops_away INTEGER,
snr REAL,
last_heard INTEGER,
first_heard INTEGER NOT NULL,
battery_level REAL,
voltage REAL,
channel_utilization REAL,
air_util_tx REAL,
uptime_seconds INTEGER,
position_time INTEGER,
location_source TEXT,
latitude REAL,
longitude REAL,
altitude REAL
);
INSERT INTO nodes_new(node_id,num,short_name,long_name,macaddr,hw_model,role,public_key,is_unmessagable,is_favorite,
hops_away,snr,last_heard,first_heard,battery_level,voltage,channel_utilization,air_util_tx,uptime_seconds,
position_time,location_source,latitude,longitude,altitude)
SELECT node_id,num,short_name,long_name,macaddr,hw_model,role,public_key,is_unmessagable,is_favorite,
hops_away,snr,last_heard,last_heard,battery_level,voltage,channel_utilization,air_util_tx,uptime_seconds,
position_time,location_source,latitude,longitude,altitude
FROM nodes;
DROP TABLE nodes;
ALTER TABLE nodes_new RENAME TO nodes;
CREATE INDEX IF NOT EXISTS idx_nodes_last_heard ON nodes(last_heard);
CREATE INDEX IF NOT EXISTS idx_nodes_hw_model ON nodes(hw_model);
CREATE INDEX IF NOT EXISTS idx_nodes_latlon ON nodes(latitude, longitude);
COMMIT;
+5 -3
View File
@@ -27,6 +27,7 @@ def upsert_node(node_id, n):
user = _get(n, "user") or {}
met = _get(n, "deviceMetrics") or {}
pos = _get(n, "position") or {}
lh = _get(n, "lastHeard")
row = (
node_id,
_get(n, "num"),
@@ -40,7 +41,8 @@ def upsert_node(node_id, n):
_get(n, "isFavorite"),
_get(n, "hopsAway"),
_get(n, "snr"),
_get(n, "lastHeard"),
lh,
lh,
_get(met, "batteryLevel"),
_get(met, "voltage"),
_get(met, "channelUtilization"),
@@ -55,9 +57,9 @@ def upsert_node(node_id, n):
conn.execute(
"""
INSERT INTO nodes(node_id,num,short_name,long_name,macaddr,hw_model,role,public_key,is_unmessagable,is_favorite,
hops_away,snr,last_heard,battery_level,voltage,channel_utilization,air_util_tx,uptime_seconds,
hops_away,snr,last_heard,first_heard,battery_level,voltage,channel_utilization,air_util_tx,uptime_seconds,
position_time,location_source,latitude,longitude,altitude)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
ON CONFLICT(node_id) DO UPDATE SET
num=excluded.num, short_name=excluded.short_name, long_name=excluded.long_name, macaddr=excluded.macaddr,
hw_model=excluded.hw_model, role=excluded.role, public_key=excluded.public_key, is_unmessagable=excluded.is_unmessagable,
+1
View File
@@ -15,6 +15,7 @@ CREATE TABLE IF NOT EXISTS nodes (
hops_away INTEGER,
snr REAL,
last_heard INTEGER, -- unix seconds
first_heard INTEGER NOT NULL, -- first time we saw node
battery_level REAL,
voltage REAL,
channel_utilization REAL,
+13 -2
View File
@@ -42,13 +42,24 @@ def test_upsert_node_handles_position(tmp_path):
longitude: float = 13.4
altitude: float = 34.0
n = {"num": 7, "position": Position()}
n = {"num": 7, "position": Position(), "lastHeard": 100}
nodes.upsert_node("node1", n)
nodes.conn.commit()
row = nodes.conn.execute(
"SELECT latitude FROM nodes WHERE node_id=?", ("node1",)
"SELECT latitude, first_heard, last_heard FROM nodes WHERE node_id=?",
("node1",),
).fetchone()
assert row is not None
assert row[0] == 52.5
assert row[1] == 100
assert row[2] == 100
n["lastHeard"] = 200
nodes.upsert_node("node1", n)
nodes.conn.commit()
row2 = nodes.conn.execute(
"SELECT first_heard, last_heard FROM nodes WHERE node_id=?", ("node1",)
).fetchone()
assert row2 == (100, 200)
finally:
os.chdir(cwd)
+5 -3
View File
@@ -44,6 +44,7 @@ def upsert_node(db, node_id, n)
met = n["deviceMetrics"] || {}
pos = n["position"] || {}
role = user["role"] || "CLIENT"
lh = n["lastHeard"]
row = [
node_id,
n["num"],
@@ -57,7 +58,8 @@ def upsert_node(db, node_id, n)
n["isFavorite"],
n["hopsAway"],
n["snr"],
n["lastHeard"],
lh,
lh,
met["batteryLevel"],
met["voltage"],
met["channelUtilization"],
@@ -71,9 +73,9 @@ def upsert_node(db, node_id, n)
]
db.execute <<~SQL, row
INSERT INTO nodes(node_id,num,short_name,long_name,macaddr,hw_model,role,public_key,is_unmessagable,is_favorite,
hops_away,snr,last_heard,battery_level,voltage,channel_utilization,air_util_tx,uptime_seconds,
hops_away,snr,last_heard,first_heard,battery_level,voltage,channel_utilization,air_util_tx,uptime_seconds,
position_time,location_source,latitude,longitude,altitude)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
ON CONFLICT(node_id) DO UPDATE SET
num=excluded.num, short_name=excluded.short_name, long_name=excluded.long_name, macaddr=excluded.macaddr,
hw_model=excluded.hw_model, role=excluded.role, public_key=excluded.public_key, is_unmessagable=excluded.is_unmessagable,