added a random id to each recived message to make duplicate detection easier, also added a delete message endpoint
This commit is contained in:
parent
70f0599c63
commit
6c8c969b67
|
@ -58,6 +58,10 @@ This will start the server locally. To expose it to the internet, it's recommend
|
||||||
|
|
||||||
- `/api/mesh/get_last_messages`: GET endpoint to retrieve the last cached messages.
|
- `/api/mesh/get_last_messages`: GET endpoint to retrieve the last cached messages.
|
||||||
|
|
||||||
|
- `/api/mesh/delete_message`: POST endpoint to delete a message from the local cache.
|
||||||
|
- Parameters:
|
||||||
|
- `message_id` (str): The messageid to be deleted.
|
||||||
|
|
||||||
- `/api/mesh/nodes`: GET endpoint to list all seen nodes.
|
- `/api/mesh/nodes`: GET endpoint to list all seen nodes.
|
||||||
|
|
||||||
- `/api/mesh/status`: GET endpoint to check connection status.
|
- `/api/mesh/status`: GET endpoint to check connection status.
|
||||||
|
|
70
meshttpd.py
70
meshttpd.py
|
@ -6,6 +6,8 @@ import meshtastic
|
||||||
import meshtastic.tcp_interface
|
import meshtastic.tcp_interface
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import random
|
||||||
|
|
||||||
class MeshAPI(object):
|
class MeshAPI(object):
|
||||||
def __init__(self, hostname='meshtastic.local'):
|
def __init__(self, hostname='meshtastic.local'):
|
||||||
|
@ -17,12 +19,12 @@ class MeshAPI(object):
|
||||||
"""
|
"""
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.iface = None
|
self.iface = None
|
||||||
self.device_telemetry_cache = {}
|
self.device_telemetry_cache = {} # Cache to store device telemetry data
|
||||||
self.environment_telemetry_cache = {}
|
self.environment_telemetry_cache = {} # Cache to store environment telemetry data
|
||||||
self.message_cache = []
|
self.message_cache = {} # Cache to store messages
|
||||||
self.seen_nodes = {}
|
self.seen_nodes = {} # Dictionary to store information about seen nodes
|
||||||
self.connection_attempts = 0
|
self.connection_attempts = 0 # Number of connection attempts made
|
||||||
self.last_connection_time = None
|
self.last_connection_time = None # Time of the last successful connection
|
||||||
self.connection_thread = threading.Thread(target=self.connect_to_mesh, daemon=True)
|
self.connection_thread = threading.Thread(target=self.connect_to_mesh, daemon=True)
|
||||||
|
|
||||||
def on_receive(self, packet, interface):
|
def on_receive(self, packet, interface):
|
||||||
|
@ -64,7 +66,8 @@ class MeshAPI(object):
|
||||||
if 'decoded' in packet and 'text' in packet['decoded']:
|
if 'decoded' in packet and 'text' in packet['decoded']:
|
||||||
node_id = packet['from']
|
node_id = packet['from']
|
||||||
message_data = packet['decoded']['text']
|
message_data = packet['decoded']['text']
|
||||||
self.message_cache.append({"node_id": node_id, "message": message_data})
|
internal_message_id = self.generate_internal_message_id(node_id, message_data)
|
||||||
|
self.message_cache[internal_message_id] = {"node_id": node_id, "message": message_data}
|
||||||
if len(self.message_cache) > 100:
|
if len(self.message_cache) > 100:
|
||||||
self.message_cache.pop(0)
|
self.message_cache.pop(0)
|
||||||
|
|
||||||
|
@ -78,7 +81,6 @@ class MeshAPI(object):
|
||||||
def on_connection(self, interface, topic=pub.AUTO_TOPIC):
|
def on_connection(self, interface, topic=pub.AUTO_TOPIC):
|
||||||
"""
|
"""
|
||||||
Callback function called when we (re)connect to the radio.
|
Callback function called when we (re)connect to the radio.
|
||||||
If you have poor wifi coverage like in my case this is essential.
|
|
||||||
"""
|
"""
|
||||||
self.last_connection_time = time.time()
|
self.last_connection_time = time.time()
|
||||||
self.connection_attempts += 1
|
self.connection_attempts += 1
|
||||||
|
@ -87,7 +89,7 @@ class MeshAPI(object):
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def index(self):
|
def index(self):
|
||||||
"""
|
"""
|
||||||
Exposed endpoint for the poors man swagger!
|
Exposed endpoint for the index page.
|
||||||
"""
|
"""
|
||||||
html = """
|
html = """
|
||||||
<html>
|
<html>
|
||||||
|
@ -140,6 +142,16 @@ class MeshAPI(object):
|
||||||
<li>
|
<li>
|
||||||
<a href="/api/mesh/get_last_messages">/api/mesh/get_last_messages</a>: GET endpoint to retrieve the last cached messages
|
<a href="/api/mesh/get_last_messages">/api/mesh/get_last_messages</a>: GET endpoint to retrieve the last cached messages
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/api/mesh/delete_message">/api/mesh/delete_message</a>: POST endpoint to delete a message from the cache
|
||||||
|
<ul>
|
||||||
|
<li>Parameters:
|
||||||
|
<ul>
|
||||||
|
<li><b>message_id</b> (str): The ID of the message to be deleted.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/api/mesh/nodes">/api/mesh/nodes</a>: GET endpoint to list all seen nodes
|
<a href="/api/mesh/nodes">/api/mesh/nodes</a>: GET endpoint to list all seen nodes
|
||||||
</li>
|
</li>
|
||||||
|
@ -212,6 +224,30 @@ class MeshAPI(object):
|
||||||
"""
|
"""
|
||||||
return self.message_cache
|
return self.message_cache
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
@cherrypy.tools.json_out()
|
||||||
|
def delete_message(self, message_id=None):
|
||||||
|
"""
|
||||||
|
Exposed endpoint for deleting a message from the cache.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message_id (str): The ID of the message to be deleted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A JSON object containing the status of the operation.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
404 (Missing parameters): If the `message_id` parameter is missing.
|
||||||
|
400 (Invalid message ID): If the specified message ID is invalid.
|
||||||
|
"""
|
||||||
|
if message_id is None:
|
||||||
|
cherrypy.response.status = 404
|
||||||
|
return {"error": "Missing parameters: message_id"}
|
||||||
|
if message_id not in self.message_cache:
|
||||||
|
raise cherrypy.HTTPError(400, "Invalid message ID")
|
||||||
|
del self.message_cache[message_id]
|
||||||
|
return {"status": "success", "message": "Message deleted successfully"}
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_out()
|
@cherrypy.tools.json_out()
|
||||||
def nodes(self):
|
def nodes(self):
|
||||||
|
@ -244,6 +280,22 @@ class MeshAPI(object):
|
||||||
print(f"Error: Could not connect to {self.hostname} {ex}")
|
print(f"Error: Could not connect to {self.hostname} {ex}")
|
||||||
time.sleep(1) # Wait for 1 second before attempting to reconnect
|
time.sleep(1) # Wait for 1 second before attempting to reconnect
|
||||||
|
|
||||||
|
def generate_internal_message_id(self, node_id, message):
|
||||||
|
"""
|
||||||
|
Function to generate an internal message ID using MD5 hashing of random data, node ID, and message.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node_id (str): The ID of the node.
|
||||||
|
message (str): The message.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The generated internal message ID.
|
||||||
|
"""
|
||||||
|
random_data = str(random.random()).encode()
|
||||||
|
hash_input = random_data + node_id.encode() + message.encode()
|
||||||
|
hash_object = hashlib.md5(hash_input)
|
||||||
|
return hash_object.hexdigest()[:10]
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""
|
"""
|
||||||
Function to start the connection thread.
|
Function to start the connection thread.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user