diff --git a/database.py b/database.py index 7ab9369..11a7427 100644 --- a/database.py +++ b/database.py @@ -3,7 +3,7 @@ from datetime import datetime, timezone from peewee import * from playhouse.migrate import migrate as migrate_database, SqliteMigrator -latest_version = 4 # increment each time new database migrations are added +latest_version = 5 # increment each time new database migrations are added database = DatabaseProxy() # use a proxy object, as we will init real db client inside meshchat.py migrator = SqliteMigrator(database) @@ -32,6 +32,14 @@ def migrate(current_version): migrator.add_column("lxmf_messages", 'method', LxmfMessage.method), ) + # migrate to version 5 + if current_version < 5: + migrate_database( + migrator.add_column("announces", 'rssi', Announce.rssi), + migrator.add_column("announces", 'snr', Announce.snr), + migrator.add_column("announces", 'quality', Announce.quality), + ) + return latest_version @@ -61,6 +69,9 @@ class Announce(BaseModel): identity_hash = CharField(index=True) # identity hash that announced the destination identity_public_key = CharField() # base64 encoded public key, incase we want to recreate the identity manually app_data = TextField(null=True) # base64 encoded app data bytes + rssi = IntegerField(null=True) + snr = FloatField(null=True) + quality = FloatField(null=True) created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) diff --git a/meshchat.py b/meshchat.py index 14844d8..6c0428d 100644 --- a/meshchat.py +++ b/meshchat.py @@ -2019,6 +2019,9 @@ class ReticulumMeshChat: "background_colour": db_lxmf_user_icon.background_colour, } + # get current hops away + hops = RNS.Transport.hops_to(bytes.fromhex(announce.destination_hash)) + return { "id": announce.id, "destination_hash": announce.destination_hash, @@ -2026,6 +2029,10 @@ class ReticulumMeshChat: "identity_hash": announce.identity_hash, "identity_public_key": announce.identity_public_key, "app_data": announce.app_data, + "hops": hops, + "rssi": announce.rssi, + "snr": announce.snr, + "quality": announce.quality, "display_name": display_name, "custom_display_name": self.get_custom_destination_display_name(announce.destination_hash), "lxmf_user_icon": lxmf_user_icon, @@ -2186,7 +2193,12 @@ class ReticulumMeshChat: query.execute() # upserts the provided announce to the database - def db_upsert_announce(self, identity: RNS.Identity, destination_hash: bytes, aspect: str, app_data: bytes): + def db_upsert_announce(self, identity: RNS.Identity, destination_hash: bytes, aspect: str, app_data: bytes, announce_packet_hash: bytes): + + # get rssi, snr and signal quality if available + rssi = self.reticulum.get_packet_rssi(announce_packet_hash) + snr = self.reticulum.get_packet_snr(announce_packet_hash) + quality = self.reticulum.get_packet_q(announce_packet_hash) # prepare data to insert or update data = { @@ -2194,6 +2206,9 @@ class ReticulumMeshChat: "aspect": aspect, "identity_hash": identity.hash.hex(), "identity_public_key": base64.b64encode(identity.get_public_key()).decode("utf-8"), + "rssi": rssi, + "snr": snr, + "quality": quality, "updated_at": datetime.now(timezone.utc), } @@ -2377,13 +2392,13 @@ class ReticulumMeshChat: # handle an announce received from reticulum, for an audio call address # NOTE: cant be async, as Reticulum doesn't await it - def on_audio_call_announce_received(self, aspect, destination_hash, announced_identity, app_data): + def on_audio_call_announce_received(self, aspect, destination_hash, announced_identity, app_data, announce_packet_hash): # log received announce print("Received an announce from " + RNS.prettyhexrep(destination_hash) + " for [call.audio]") # upsert announce to database - self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data) + self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data, announce_packet_hash) # find announce from database announce = database.Announce.get_or_none(database.Announce.destination_hash == destination_hash.hex()) @@ -2398,13 +2413,13 @@ class ReticulumMeshChat: # handle an announce received from reticulum, for an lxmf address # NOTE: cant be async, as Reticulum doesn't await it - def on_lxmf_announce_received(self, aspect, destination_hash, announced_identity, app_data): + def on_lxmf_announce_received(self, aspect, destination_hash, announced_identity, app_data, announce_packet_hash): # log received announce print("Received an announce from " + RNS.prettyhexrep(destination_hash) + " for [lxmf.delivery]") # upsert announce to database - self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data) + self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data, announce_packet_hash) # find announce from database announce = database.Announce.get_or_none(database.Announce.destination_hash == destination_hash.hex()) @@ -2423,13 +2438,13 @@ class ReticulumMeshChat: # handle an announce received from reticulum, for an lxmf propagation node address # NOTE: cant be async, as Reticulum doesn't await it - def on_lxmf_propagation_announce_received(self, aspect, destination_hash, announced_identity, app_data): + def on_lxmf_propagation_announce_received(self, aspect, destination_hash, announced_identity, app_data, announce_packet_hash): # log received announce print("Received an announce from " + RNS.prettyhexrep(destination_hash) + " for [lxmf.propagation]") # upsert announce to database - self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data) + self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data, announce_packet_hash) # find announce from database announce = database.Announce.get_or_none(database.Announce.destination_hash == destination_hash.hex()) @@ -2507,13 +2522,13 @@ class ReticulumMeshChat: # handle an announce received from reticulum, for a nomadnet node # NOTE: cant be async, as Reticulum doesn't await it - def on_nomadnet_node_announce_received(self, aspect, destination_hash, announced_identity, app_data): + def on_nomadnet_node_announce_received(self, aspect, destination_hash, announced_identity, app_data, announce_packet_hash): # log received announce print("Received an announce from " + RNS.prettyhexrep(destination_hash) + " for [nomadnetwork.node]") # upsert announce to database - self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data) + self.db_upsert_announce(announced_identity, destination_hash, aspect, app_data, announce_packet_hash) # find announce from database announce = database.Announce.get_or_none(database.Announce.destination_hash == destination_hash.hex()) diff --git a/src/backend/announce_handler.py b/src/backend/announce_handler.py index 5d2cd3a..c322d47 100644 --- a/src/backend/announce_handler.py +++ b/src/backend/announce_handler.py @@ -7,10 +7,10 @@ class AnnounceHandler: self.received_announce_callback = received_announce_callback # we will just pass the received announce back to the provided callback - def received_announce(self, destination_hash, announced_identity, app_data): + def received_announce(self, destination_hash, announced_identity, app_data, announce_packet_hash): try: # handle received announce - self.received_announce_callback(self.aspect_filter, destination_hash, announced_identity, app_data) + self.received_announce_callback(self.aspect_filter, destination_hash, announced_identity, app_data, announce_packet_hash) except: # ignore failure to handle received announce pass diff --git a/src/frontend/components/messages/MessagesSidebar.vue b/src/frontend/components/messages/MessagesSidebar.vue index 0b88061..75e0b91 100644 --- a/src/frontend/components/messages/MessagesSidebar.vue +++ b/src/frontend/components/messages/MessagesSidebar.vue @@ -90,7 +90,20 @@