mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-06-28 22:11:36 +02:00
@@ -1,19 +1,18 @@
|
||||
Meshview
|
||||
========
|
||||
|
||||
Now running at https://meshview.bayme.sh
|
||||
# Meshview
|
||||
|
||||
This project watches a MQTT topic for meshtastic messages, imports them to a
|
||||
database and has a web UI to view them.
|
||||
Requires Python 3.12
|
||||
|
||||
Running
|
||||
-------
|
||||
Requires **`python3.12`** and **`graphviz`**.
|
||||
|
||||
## Preparing
|
||||
|
||||
Clone the repo from github with:
|
||||
``` bash
|
||||
git clone --recurse-submodules https://github.com/pablorevilla-meshtastic/meshview.git
|
||||
```
|
||||
It is important to include the `--recurse-submodules` flag or the meshtastic protobufs wont be included
|
||||
> [!NOTE]
|
||||
> It is important to include the `--recurse-submodules` flag or the meshtastic protobufs won't be included.
|
||||
|
||||
Create a python virtual environment:
|
||||
``` bash
|
||||
@@ -28,23 +27,14 @@ You also need to install `graphviz`:
|
||||
``` bash
|
||||
sudo apt-get install graphviz
|
||||
```
|
||||
Edit `config.ini` to change the MQTT server, username, password, and topic(s) as necessary.
|
||||
|
||||
You may also change the web server port from the ***default 8081***.
|
||||
https://github.com/madeofstown/meshview/blob/c9d65a078af5e71a6815c142dbb11e5868f8885b/config.ini#L1-L15
|
||||
|
||||
## Running Meshview
|
||||
|
||||
To run Meshview:
|
||||
``` bash
|
||||
./env/bin/python main.py
|
||||
```
|
||||
Now you can hit http://localhost/
|
||||
|
||||
Other Options:
|
||||
* `--port`
|
||||
|
||||
Web server port, default is `8081`
|
||||
|
||||
* `--mqtt-server`
|
||||
|
||||
MQTT Server, default is `mqtt.bayme.sh`
|
||||
|
||||
* `--topic`
|
||||
|
||||
MQTT Topic, default is `msh/US/bayarea/#`
|
||||
|
||||
Now you can hit http://localhost:8081/
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
[server]
|
||||
bind = *
|
||||
port = 8081
|
||||
tls_cert =
|
||||
acme_challenge =
|
||||
|
||||
[mqtt]
|
||||
server = mqtt.bayme.sh
|
||||
topics = ['msh/US/bayarea/#', 'msh/US/CA/mrymesh/#']
|
||||
port = 1883
|
||||
username = meshdev
|
||||
password = large4cats
|
||||
|
||||
[database]
|
||||
connection_string = sqlite+aiosqlite:///packets.db
|
||||
@@ -1,6 +1,6 @@
|
||||
import asyncio
|
||||
import argparse
|
||||
|
||||
import configparser
|
||||
from meshview import mqtt_reader
|
||||
from meshview import database
|
||||
from meshview import store
|
||||
@@ -8,34 +8,56 @@ from meshview import web
|
||||
from meshview import http
|
||||
|
||||
|
||||
async def load_database_from_mqtt(mqtt_server, topic):
|
||||
async for topic, env in mqtt_reader.get_topic_envelopes(mqtt_server, topic):
|
||||
async def load_database_from_mqtt(mqtt_server: str , mqtt_port: int, topic: str, mqtt_user: str | None = None, mqtt_passwd: str | None = None):
|
||||
async for topic, env in mqtt_reader.get_topic_envelopes(mqtt_server, mqtt_port, topic, mqtt_user, mqtt_passwd):
|
||||
await store.process_envelope(topic, env)
|
||||
|
||||
|
||||
async def main(args):
|
||||
database.init_database(args.database)
|
||||
async def main(config):
|
||||
database.init_database(config["database"]["connection_string"])
|
||||
|
||||
await database.create_tables()
|
||||
mqtt_user = None
|
||||
mqtt_passwd = None
|
||||
if config["mqtt"]["username"] != "":
|
||||
mqtt_user: str = config["mqtt"]["username"]
|
||||
if config["mqtt"]["password"] != "":
|
||||
mqtt_passwd: str = config["mqtt"]["password"]
|
||||
|
||||
async with asyncio.TaskGroup() as tg:
|
||||
tg.create_task(load_database_from_mqtt(args.mqtt_server, args.topic))
|
||||
tg.create_task(web.run_server(args.bind, args.port, args.tls_cert))
|
||||
if args.acme_challenge:
|
||||
tg.create_task(http.run_server(args.bind, args.acme_challenge))
|
||||
tg.create_task(
|
||||
load_database_from_mqtt(config["mqtt"]["server"], int(config["mqtt"]["port"]), config["mqtt"]["topics"], mqtt_user, mqtt_passwd)
|
||||
)
|
||||
tg.create_task(
|
||||
web.run_server(
|
||||
config["server"]["bind"],
|
||||
int(config["server"]["port"]),
|
||||
config["server"].get("tls_cert"),
|
||||
)
|
||||
)
|
||||
if config["server"].get("acme_challenge"):
|
||||
tg.create_task(
|
||||
http.run_server(
|
||||
config["server"]["bind"], config["server"]["acme_challenge"]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def load_config(file_path):
|
||||
"""Load configuration from an INI-style text file."""
|
||||
config_parser = configparser.ConfigParser()
|
||||
config_parser.read(file_path)
|
||||
|
||||
# Convert to a dictionary for easier access
|
||||
config = {section: dict(config_parser.items(section)) for section in config_parser.sections()}
|
||||
return config
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser('meshview')
|
||||
parser.add_argument('--bind', nargs='*', default=['*'])
|
||||
parser.add_argument('--acme-challenge')
|
||||
parser.add_argument('--port', default=8081, type=int)
|
||||
parser.add_argument('--tls-cert')
|
||||
|
||||
parser.add_argument('--mqtt-server', default='mqtt.bayme.sh')
|
||||
parser.add_argument('--topic', nargs='*', default=['msh/US/bayarea/#'])
|
||||
|
||||
parser.add_argument('--database', default='sqlite+aiosqlite:///packets.db')
|
||||
|
||||
parser = argparse.ArgumentParser("meshview")
|
||||
parser.add_argument("--config", help="Path to the configuration file.", default='config.ini')
|
||||
args = parser.parse_args()
|
||||
|
||||
asyncio.run(main(args))
|
||||
config = load_config(args.config)
|
||||
|
||||
asyncio.run(main(config))
|
||||
@@ -25,12 +25,12 @@ def decrypt(packet):
|
||||
pass
|
||||
|
||||
|
||||
async def get_topic_envelopes(mqtt_server, topics):
|
||||
async def get_topic_envelopes(mqtt_server, mqtt_port, topics, mqtt_user, mqtt_passwd):
|
||||
identifier = str(random.getrandbits(16))
|
||||
while True:
|
||||
try:
|
||||
async with aiomqtt.Client(
|
||||
mqtt_server, username="meshdev", password="large4cats" , identifier=identifier,
|
||||
mqtt_server, port=mqtt_port , username=mqtt_user, password=mqtt_passwd , identifier=identifier,
|
||||
) as client:
|
||||
for topic in topics:
|
||||
await client.subscribe(topic)
|
||||
|
||||
Reference in New Issue
Block a user