From a54c2d7020400bbd6a86a1099fa527ddf0b04f74 Mon Sep 17 00:00:00 2001 From: Volkor <me@volkor.me> Date: Sun, 2 Feb 2025 01:39:03 +1100 Subject: [PATCH] better ui, meshpacket logging Although I might want to redo some meshpackets into their own tables (for stuff like telemetry and such) --- Cargo.lock | 81 +++++++++++++-- Cargo.toml | 6 +- README.md | 4 + config.toml | 8 +- db/migrations/0001_initial.sql | 29 ++++++ src/config.rs | 18 +++- src/db.rs | 173 ++++++++++++++++++++++++++++++++- src/gui.rs | 118 +++++++++++++++++++--- src/packets.rs | 26 +++-- yamm.db | Bin 139264 -> 176128 bytes 10 files changed, 427 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9dcb688..4fa3848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -832,6 +838,29 @@ dependencies = [ "libc", ] +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "chrono-humanize" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799627e6b4d27827a814e837b9d8a504832086081806d45b1afa34dc982b023b" +dependencies = [ + "chrono", +] + [[package]] name = "clipboard-win" version = "5.4.0" @@ -2026,12 +2055,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.32" @@ -2070,6 +2093,29 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" version = "1.5.0" @@ -2550,6 +2596,16 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "longitude" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287771e9700a56b8ee1c12188e67e551daf66980b9fde697e9551d74db19cc0e" +dependencies = [ + "lazy_static", + "libm", +] + [[package]] name = "loop9" version = "0.1.5" @@ -5493,6 +5549,15 @@ dependencies = [ "windows-targets 0.53.0", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.57.0" @@ -6094,15 +6159,17 @@ name = "yamm" version = "0.1.0" dependencies = [ "bincode", + "chrono", + "chrono-humanize", "eframe", "egui", "egui_extras", "fern", "figment", - "humantime", "image", "lazy_static", "log", + "longitude", "meshtastic", "rusqlite", "rusqlite_migration", diff --git a/Cargo.toml b/Cargo.toml index 185eca2..54b538c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] fern = "0.7.1" -humantime = "2.1.0" log = "0.4.22" meshtastic = "0.1.6" tokio = "1.42.0" @@ -17,10 +16,13 @@ lazy_static = "1.5.0" figment = {version = "0.10.19", features = ["toml", "env"]} serde = "1.0.217" bincode = "1.3.3" +chrono-humanize = "0.2.3" # gui eframe = { version = "0.30.0", features = ["wgpu"] } egui = "0.30.0" walkers = "0.33.0" egui_extras = { version = "0.30.0", features = ["all_loaders"] } -image = { version = "0.25", features = ["jpeg", "png", "webp"] } \ No newline at end of file +image = { version = "0.25", features = ["jpeg", "png", "webp"] } +chrono = "0.4.39" +longitude = "0.2.1" diff --git a/README.md b/README.md index e59b673..5faa14c 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,9 @@ Rough order of how much I want to add support. - [ ] Shows Historical Data as a nice graph - [ ] SNR (both individual neighbours and overall) + - RSSI is done per packet, instead of in nodeinfo. this seems... clunky. + - We're gonna have to log packets coming directly from neighbours, and store the rssi. it seems like that might be the only way to actually get neighbours? + - potentially show helpful guides on why each node is bad quality. (https://sensing-labs.com/f-a-q/a-good-radio-level/) ? - [ ] Messages per day? - [ ] Number of Nodes seen - [ ] Channel Util @@ -41,6 +44,7 @@ Rough order of how much I want to add support. - [ ] Can we show the potential nodes that don't have GPS? - [ ] Can we use heard traceroutes to map out neighbours in the mesh? - Can we send out some traceroutes every few hours to map it if we don't? (some people don't like meshsense for this reason) +- [ ] calculate distance to 'collector node' - [ ] Generates a nice public dashboard (static http, once every hour?) - Supports anything other than TCP Connection. - [ ] Bluetooth (how? wtf? i hate bluetooth!) diff --git a/config.toml b/config.toml index 5f3fd30..f9a5b73 100644 --- a/config.toml +++ b/config.toml @@ -17,4 +17,10 @@ serial_port = "Set this from whatever 'available ports' says." ## If connection_type is TCP or MQTT, use this ip & port combo to connect ip = "192.168.1.11" -port = 4403 \ No newline at end of file +port = 4403 + + +[gui] +# Should we show units in metric, or idiot american? +# Supported: Centimeters, Meters, Kilometers, Inches, Feet, Yards, Miles, +units = "Kilometers" \ No newline at end of file diff --git a/db/migrations/0001_initial.sql b/db/migrations/0001_initial.sql index 468616b..cb045e8 100644 --- a/db/migrations/0001_initial.sql +++ b/db/migrations/0001_initial.sql @@ -342,4 +342,33 @@ CREATE TABLE DetectionSensorConfig ( CREATE TABLE PaxcounterConfig ( enabled INTEGER, paxcounter_update_interval INTEGER +); + +-- MeshPacket tables +-- This table stores every single MeshPacket sent over the radio. +-- Since this can contain a Payload_variant, we need to handle all of the following types +-- https://docs.rs/meshtastic/latest/meshtastic/protobufs/enum.PortNum.html +CREATE TABLE MeshPacket ( + primary_id INTEGER PRIMARY KEY AUTOINCREMENT, -- internal db packet number + packet_from INTEGER, -- sending node number + packet_to INTEGER, -- the (immediate) destination + channel INTEGER, -- what channel was this sent on, however it's a device specific set + id INTEGER, -- 'unique' id for the packet, only unique per sender, and for ~10 mins + rx_time INTEGER, -- unixtime packet was received, not sent over radio + rx_snr INTEGER, -- radio quality @ time of rx, not sent over radio + hop_limt INTEGER, -- n hops allowed, 0 is direct neighbours only + want_ack INTEGER, -- does the sender want ack on arrival of destination? + priority INTEGER, -- how important it is in the network + rx_rssi INTEGER, -- rssi of packet, not sent over radio + via_mqtt INTEGER, -- did it pass over mqtt at any point? + hop_start INTEGER, -- what was the hop limit at tx? + pv_status INTEGER, -- NULL = No payload, 1 = decoded, 2 = encrypted + pv_portnum INTEGER, -- what type of data we're sending + pv_data BLOB, -- the data we're sending. + pv_want_response INTEGER, -- ask the reipient to respond + pv_dest INTEGER, -- the addr of the destination + pv_source INTEGER, -- the original sender node, only used for reliable multihop pkt + pv_request_id INTEGER, -- used for routing or responses, original msg id + pv_reply_id INTEGER, -- is the payload a reply to a previous message? + pv_emoji INTEGER -- is the payload an emoji? ); \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 5edec01..1ec1691 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,4 @@ +use longitude::DistanceUnit; use serde::Deserialize; /// Holds the individual config segments. @@ -7,6 +8,7 @@ pub struct AppConfig { pub database: DatabaseConfig, pub logging: LoggingConfig, pub meshconfig: MeshConfig, + pub gui: GuiConfig, } #[derive(Debug, Clone, Deserialize)] @@ -46,6 +48,12 @@ pub enum ConnectionType { } +/// Holds the config for the GUI +#[derive(Debug, Clone, Deserialize)] +pub struct GuiConfig { + pub units: String +} + // Defaults impl Default for ServerConfig { @@ -82,4 +90,12 @@ impl Default for MeshConfig { port: 4403, } } -} \ No newline at end of file +} + +impl Default for GuiConfig { + fn default() -> Self { + Self { + units: "Kilometers".to_string() + } + } +} diff --git a/src/db.rs b/src/db.rs index 4851ec0..0acdbed 100644 --- a/src/db.rs +++ b/src/db.rs @@ -9,7 +9,7 @@ use rusqlite_migration::{Migrations, M}; use serde::{Deserialize, Serialize}; use tracing::{debug, error, info}; use lazy_static::lazy_static; -use meshtastic::protobufs::{Channel, DeviceMetrics, MyNodeInfo, NodeInfo, Position, User}; +use meshtastic::protobufs::{Channel, Data, DeviceMetrics, MeshPacket, MyNodeInfo, NodeInfo, Position, User}; use crate::CONFIG; @@ -828,4 +828,175 @@ impl Database { nodes } + pub fn read_home_node() -> Result<NodeInfo, rusqlite::Error> { + let db = Database::open().expect("Failure to open database for reading"); + + let mut stmt = db.conn.prepare("SELECT num, user_id, user_lname, user_sname, + hw_model, is_licensed, role, battery_level, + voltage, latitude_i, longitude_i, altitude, + location_source, gps_timestamp, altitude_source, + pdop, hdop, vdop, gps_accuracy, ground_speed, + ground_track, fix_quality, fix_type, sats_in_view, + sensor_id, next_update, seq_number, precision_bits, + snr, last_heard, channel_utilization, air_util_tx, + channel, via_mqtt, hops_away + FROM Node + WHERE num = (SELECT my_node_num FROM MyNodeInfo)")?; + + + + // If needed, handle the result using pattern matching or further processing + stmt.query_row([], |row| { + Ok(NodeInfo { + num: row.get(0)?, + user: Some(User { + id: row.get(1).unwrap_or("NULL".to_owned()), + long_name: row.get(2).unwrap_or("NULL".to_owned()), + short_name: row.get(3).unwrap_or("NULL".to_owned()), + macaddr: vec![], + hw_model: row.get(4).unwrap_or_default(), + is_licensed: row.get(5).unwrap_or(false), + role: row.get(6).unwrap_or_default(), + }), + position: Some(Position { + latitude_i: row.get(9).unwrap_or(0), + longitude_i: row.get(10).unwrap_or(0), + altitude: row.get(11).unwrap_or(0), + time: 0, + location_source: row.get(12).unwrap_or_default(), + altitude_source: row.get(14).unwrap_or_default(), + timestamp: row.get(13).unwrap_or(0), + timestamp_millis_adjust: 0, + altitude_hae: 0, + altitude_geoidal_separation: 0, + pdop: row.get(15).unwrap_or(0), + hdop: row.get(16).unwrap_or(0), + vdop: row.get(17).unwrap_or(0), + gps_accuracy: row.get(18).unwrap_or(0), + ground_speed: row.get(19).unwrap_or(0), + ground_track: row.get(20).unwrap_or(0), + fix_quality: row.get(21).unwrap_or(0), + fix_type: row.get(22).unwrap_or(0), + sats_in_view: row.get(23).unwrap_or(0), + sensor_id: row.get(24).unwrap_or(0), + next_update: row.get(25).unwrap_or(0), + seq_number: row.get(26).unwrap_or(0), + precision_bits: row.get(27).unwrap_or(0), + }), + snr: row.get(28)?, + last_heard: row.get(29)?, + device_metrics: Some(DeviceMetrics { + battery_level: row.get(7).unwrap_or(101), + voltage: row.get(8).unwrap_or(0.0), + channel_utilization: row.get(30).unwrap_or(0.0), + air_util_tx: row.get(31).unwrap_or(0.0), + }), + channel: row.get(32)?, + via_mqtt: row.get(33)?, + hops_away: row.get(34)?, + }) + }) + } + + /// Check for the existence of a MeshPacket with the same data + pub fn check_meshpacket_dupe(pv_data: &Option<Vec<u8>>) -> Result<bool> { + let db = Database::open().expect("Failure to open database"); + let mut stmt = db.conn.prepare("SELECT COUNT(1) + FROM MeshPacket + WHERE data = ?1")?; + let exists = stmt.query_row([&pv_data], |row| row.get::<_, i64>(0))? > 0; + Ok(exists) + } + + /// Add a new meshpacket entry into the db. + pub fn add_meshpacket(packet: &MeshPacket) -> Result<bool> { + let db = Database::open().expect("Failure to open database"); + + // Initialise default pv's + let mut pv_status: Option<i32> = None; + let mut pv_portnum: Option<i32> = None; + let mut pv_data: Option<Vec<u8>> = None; + let mut pv_want_response: Option<bool> = None; + let mut pv_dest: Option<u32> = None; + let mut pv_source: Option<u32> = None; + let mut pv_request_id: Option<u32> = None; + let mut pv_reply_id: Option<u32> = None; + let mut pv_emoji: Option<u32> = None; + + // Can we handle the payload variant? is it empty? encrypted? decoded? + if packet.payload_variant.is_none() { + // if None, use defaults we set above! + } + + if packet.payload_variant.is_some() { + match packet.payload_variant.clone().unwrap() { + meshtastic::protobufs::mesh_packet::PayloadVariant::Decoded(data) => { + // decoded packet, update pv values + pv_status = Some(1); + pv_portnum = Some(data.portnum); + pv_data = Some(data.payload); + pv_want_response = Some(data.want_response); + pv_dest = Some(data.dest); + pv_source = Some(data.source); + pv_request_id = Some(data.request_id); + pv_reply_id = Some(data.reply_id); + pv_emoji = Some(data.emoji); + }, + meshtastic::protobufs::mesh_packet::PayloadVariant::Encrypted(items) => { + // encrypted packet, update some pv values + pv_status = Some(2); + pv_data = Some(items); + }, + } + } + + // WAIT! hold on! have we heard this packet before? + // Unfortunately there's no "original sender" thing that I can see, so fuck it + // check the db for duplicate pv_data's + if Self::check_meshpacket_dupe(&pv_data).unwrap_or(false) { + // Packet is a duplicate, lets skip it! + debug!("Skipping duplicate MeshPacket {}", packet.from); + Ok(false) + } else { + // Add MeshPacket + db.conn.execute( + "INSERT INTO MeshPacket ( + packet_from, packet_to, channel, id, + rx_time, rx_snr, hop_limt, want_ack, + priority, rx_rssi, via_mqtt, hop_start, + pv_status, pv_portnum, pv_data, pv_want_response, + pv_dest, pv_source, pv_request_id, pv_reply_id, + pv_emoji + ) VALUES ( + ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, + ?15, ?16, ?17, ?18, ?19, ?20, ?21 + )", + rusqlite::params![ + packet.from, + packet.to, // 4294967295 = 0xFFFFFFFF = Everyone / Unknown + packet.channel, + packet.id, + packet.rx_time, + packet.rx_snr, + packet.hop_limit, + packet.want_ack, + packet.priority, + packet.rx_rssi, + packet.via_mqtt, + packet.hop_start, + pv_status, + pv_portnum, + pv_data, + pv_want_response, + pv_dest, + pv_source, + pv_request_id, + pv_reply_id, + pv_emoji + ] + )?; + debug!("Added new MeshPacket from {}", packet.from); + Ok(true) + } + } } \ No newline at end of file diff --git a/src/gui.rs b/src/gui.rs index a19f7d2..38824fc 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,7 +1,40 @@ +use std::str::FromStr; + +use chrono::DateTime; use egui_extras::{Column, TableBuilder}; +use meshtastic::protobufs::{config::device_config::Role, HardwareModel}; use tracing::debug; +use chrono_humanize::{self, HumanTime}; +use longitude::{Distance, DistanceUnit, Location}; +use meshtastic::protobufs::Position; + +use crate::{db::Database, CONFIG}; -use crate::db::Database; +/// Calculates the distance betwen 2 coordinate points. +fn calc_distance_to_node(away: Position) -> Option<f64> { + let home_pos = Database::read_home_node().expect("Failed to find Home Node").position.unwrap(); + + let distance = Location { + // Home Base + latitude: home_pos.latitude_i as f64 * 1e-7, + longitude: home_pos.longitude_i as f64 * 1e-7, + }.distance(&Location { + // Away + latitude: away.latitude_i as f64 * 1e-7, + longitude: away.longitude_i as f64 * 1e-7, + }); + // convert to the right distance depending on settings + match CONFIG.gui.units.as_ref() { + "Centimeters" => Some(distance.in_unit(DistanceUnit::Centimeters)), + "Meters" => Some(distance.in_unit(DistanceUnit::Meters)), + "Kilometers" => Some(distance.in_unit(DistanceUnit::Kilometers)), + "Inches" => Some(distance.in_unit(DistanceUnit::Inches)), + "Feet" => Some(distance.in_unit(DistanceUnit::Feet)), + "Yards" => Some(distance.in_unit(DistanceUnit::Yards)), + "Miles" => Some(distance.in_unit(DistanceUnit::Miles)), + _ => Some(distance.in_unit(DistanceUnit::Kilometers)), // if you can't type, force km. + } +} pub(crate) async fn run_gui() { debug!("Running in GUI Mode!"); @@ -14,16 +47,28 @@ pub(crate) async fn run_gui() { // Table Panel, showing nodes in a list. egui::CentralPanel::default().show(ctx, |ui| { // Get nodes from DB - let nodes = Database::read_node_list().expect("Failed to read nodes"); + let mut nodes = Database::read_node_list().expect("Failed to read nodes"); + + // Sort nodes by `last_heard` in descending order + nodes.sort_by(|a, b| b.last_heard.cmp(&a.last_heard)); + TableBuilder::new(ui) - .column(Column::auto().resizable(true)) - .column(Column::remainder()) - .column(Column::remainder()) - .column(Column::remainder()) - .column(Column::remainder()) - .column(Column::remainder()) - .column(Column::remainder()) - .header(20.0, |mut header| { + // TODO for the table: + // - Clickable Table Sorting + // - Add more info + // - Auto hide/show scrollbar on smaller devices + // - Add to a panel that we can move around / shitty windowing. + .column(Column::remainder()) // node id + .column(Column::remainder().clip(true)) // node name + .column(Column::remainder()) // snr + .column(Column::remainder()) // dist + .column(Column::remainder()) // hops + .column(Column::remainder().clip(true)) // hw model + .column(Column::remainder()) // role + .column(Column::remainder()) // battery + .column(Column::remainder().clip(true)) // last heard + .striped(true) + .header(15.0, |mut header| { header.col(|ui| { ui.heading("Node ID"); }); @@ -33,6 +78,22 @@ pub(crate) async fn run_gui() { header.col(|ui| { ui.heading("SNR"); }); + header.col(|ui| { + + // Get distance units + let unit = match CONFIG.gui.units.as_ref() { + "Centimeters" => "cm", + "Meters" => "m", + "Kilometers" => "km", + "Inches" => "in", + "Feet" => "ft", + "Yards" => "yd", + "Miles" => "mi", + _ => "km", // Default to km if no match found. + }; + + ui.heading(format!("Distance ({})", unit)); + }); header.col(|ui| { ui.heading("Hops Away"); }); @@ -43,14 +104,27 @@ pub(crate) async fn run_gui() { ui.heading("Role"); }); header.col(|ui| { - ui.heading("Battery Level"); + ui.heading("Battery"); + }); + header.col(|ui| { + ui.heading("Last Heard"); }); }) .body(|mut body| { for node in nodes { let user = node.user.unwrap(); let device = node.device_metrics.unwrap(); - body.row(10.0, |mut row| { + // Convert the last heard to a time, then make it nice to read. + let now = chrono::Local::now().to_utc(); + let humanised = if node.last_heard == 0 { + String::from("Unknown") + } else { + let last_heard = DateTime::from_timestamp(node.last_heard.into(), 0).unwrap(); + let duration = last_heard - now; + HumanTime::from(duration).to_string() + }; + + body.row(15.0, |mut row| { row.col(|ui| { ui.label(user.id); }); @@ -60,18 +134,34 @@ pub(crate) async fn run_gui() { row.col(|ui| { ui.label(node.snr.to_string()); }); + row.col(|ui| { + if let Some(distance) = calc_distance_to_node(node.position.unwrap()) { + if distance.is_nan() { + ui.label("-"); + } else { + ui.label(format!("{:.2}", distance)); + } + } else { + ui.label("-"); + } + }); row.col(|ui| { ui.label(node.hops_away.to_string()); }); row.col(|ui| { - ui.label(user.hw_model.to_string()); + // Convert the i32 to a HardwareModel object, then convert to string + ui.label(HardwareModel::from_i32(user.hw_model).unwrap_or_default().as_str_name()); }); row.col(|ui| { - ui.label(user.role.to_string()); + // Convert the i32 to a Role object, convert to string. + ui.label(Role::from_i32(user.role).unwrap_or_default().as_str_name()); }); row.col(|ui| { ui.label(device.battery_level.to_string()); }); + row.col(|ui| { + ui.label(humanised); + }); }); } }); diff --git a/src/packets.rs b/src/packets.rs index a12c4b4..d5fd3a0 100644 --- a/src/packets.rs +++ b/src/packets.rs @@ -2,7 +2,8 @@ use std::path::Path; use config::device_config; use from_radio::PayloadVariant; -use meshtastic::protobufs::*; +use log::info; +use meshtastic::protobufs::{config::device_config::Role, *}; use tracing::{debug, error}; use crate::db::Database; @@ -15,8 +16,8 @@ pub fn parse(message: &FromRadio) -> bool { match message.payload_variant { // A normal message Some(PayloadVariant::Packet(ref packet)) => { - debug!("New Message Packet!"); - parse_packet(packet); + debug!("New MeshPacket!"); + parse_meshpacket(packet); }, // Information about the local node Some(PayloadVariant::MyInfo(ref info)) => { @@ -59,14 +60,19 @@ pub fn parse(message: &FromRadio) -> bool { true } -fn parse_packet(packet: &MeshPacket) { +fn parse_meshpacket(packet: &MeshPacket) { // Handle packet data - error!("Unhandled MeshPacket Packet: {:#?}", &packet); - + debug!("Parsing MeshPacket Packet: {:?}", &packet); + let _ = Database::add_meshpacket(packet); + + // I don't think we can, but imagine if meshtastic added the "last hop node" + // so we can figure out at least who im actively receiving from, and figure out their + // signal strength without brute forcing and sending/waiting for other packets. + // because I'd love to be able to update 0 hop nodes snr/rssi from here, but I have to let it g } fn parse_myinfo(packet: &MyNodeInfo) { - debug!("Parsing MyNodeInfo Packet: {:#?}", &packet); + debug!("Parsing MyNodeInfo Packet: {:?}", &packet); let _ = Database::update_mynodeinfo(packet); } @@ -82,7 +88,7 @@ fn parse_nodeinfo(node_info: &NodeInfo) { fn parse_config(config: &Config) { // Handle Config data - debug!("Parsing Config Packet: {:#?}", &config); + debug!("Parsing Config Packet: {:?}", &config); // Match and destructure the payload_variant if let Some(payload_variant) = config.payload_variant.clone() { @@ -113,7 +119,7 @@ fn parse_config(config: &Config) { } fn parse_module_config(module_config: &ModuleConfig) { - debug!("Parsing Module Packet: {:#?}", &module_config); + debug!("Parsing Module Packet: {:?}", &module_config); // Handle ModuleConfig data // Match and destructure the payload_variant if let Some(payload_variant) = module_config.payload_variant.clone() { @@ -162,7 +168,7 @@ fn parse_module_config(module_config: &ModuleConfig) { } fn parse_channel_info(channel_info: &Channel) { - debug!("Parsing Channel Packet: {:#?}", &channel_info); + debug!("Parsing Channel Packet: {:?}", &channel_info); // Handle ChannelInfo data let _ = Database::update_channel(channel_info); } diff --git a/yamm.db b/yamm.db index ba450ab0817c9ed872df41b1eae021433714cba9..f77f5dcf23bda7fb3a2dd839ba13f9be42b95f22 100644 GIT binary patch literal 176128 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 l$8fS%+!8a&yhkr4jK$1Wd}>F_kymY˵Otk(~k{|8*xd<Fmj delta 8325 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 G<UavT8X!Xe -- GitLab