Feature: MeshCore Companion-Port als eigenständiger Bereich im Dashboard #20

Closed
opened 2026-04-10 09:47:25 +02:00 by ppfeiffer · 0 comments
Owner

Feature Request: MeshCore Companion-Port Integration

Motivation

Neben dem primären Meshtastic-Node soll ein MeshCore Companion-Radio als zweite, vollständig getrennte Datenquelle ins Dashboard eingebunden werden. MeshCore ist eine eigenständige LoRa-Mesh-Firmware und kein Meshtastic – die beiden Systeme sind protokollinkompatibel.

Designentscheidung: Meshtastic- und MeshCore-Daten werden nicht zusammengeführt. Nodes, Nachrichten, Kanäle und Karten beider Systeme werden auf getrennten Unterseiten dargestellt. Die bestehenden Seiten bleiben unverändert.

Referenz-Implementierung: Remote Terminal for MeshCore (FastAPI + React) nutzt dieselbe meshcore Python-Bibliothek und dient als wichtige Orientierung für Datenmodell und UI-Muster.


Protokollunterschiede: Meshtastic vs. MeshCore

Aspekt Meshtastic MeshCore
Datenformat Protobuf Custom Binary (Little-Endian, Length-Prefixed Frames)
TCP-Port 4403 5000
Python-Bibliothek meshtastic (TCPInterface) meshcore (asyncio, PyPI)
Telemetrie Push (periodischer Broadcast) Pull (auf Anfrage)
Node-Identifikation NodeNum + !hex Ed25519 Public Key (32 Byte)
Kanaele Index 0-7, feste Slots Name + SHA-256-Key, beliebig viele
Kontakttypen Einheitlich Client / Repeater / Room / Sensor
Regionen Feste Enum (EU_868, US, ...) Nutzerdefinierte Flood-Scope-Strings

Kontakttypen und ihre Darstellung

Typ Wert Darstellung
Client 1 Kontaktkarte + Direktnachricht-Verlauf
Repeater 2 Eigene Detailseite: Telemetrie, Nachbarn, Funkeinstellungen
Room (Server) 3 Kanal-ähnliche Ansicht, ggf. mit Login
Sensor 4 Telemetrie-Dashboard (CayenneLPP: Temp, GPS, etc.)

Neue Seiten im Webinterface (Übersicht)

Route Inhalt Zugang
/meshcore Übersicht: Verbindungsstatus, eigener Node, Zähler Public
/meshcore/nodes Kontakte nach Typ (Client/Repeater/Room/Sensor) Public
/meshcore/map Leaflet-Karte: Kontakte, Typen-Icons, Pfad-Trace-Overlay Public
/meshcore/messages Direktnachrichten aller Kontakte Public
/meshcore/channels Kanal-Verwaltung inkl. Flood-Scope- und Path-Hash-Mode-Override Admin
/meshcore/channels/{key} Nachrichtenverlauf eines Kanals Public
/meshcore/rf-stats RF-Statistiken: SNR, RSSI, Noise Floor, Airtime, Paketcounter Public
/meshcore/trace Pfad-Trace zu einem Kontakt mit Hop-SNR-Visualisierung Public
/meshcore/config Radio-Konfiguration: Frequenz-Presets, Path Hash Mode, Flood Scope, Loop Detection Admin
/meshcore/scheduler Scheduler mit MeshCore-Kanal-Targeting Admin
/meshcore/nina NINA-Konfiguration für MeshCore-Kanäle Admin
/meshcore/traffic Verkehrsalarm-Konfiguration für MeshCore-Kanäle Admin

Radio-Konfiguration (/meshcore/config) – Kernelement dieses Features

Wichtiger Unterschied zu Meshtastic

MeshCore hat keine Region-Enum (kein EU_868, US etc.). Regionen sind in MeshCore nutzerdefinierte Flood-Scope-Strings (z.B. #europe, #us-ca). Die Funkparameter werden direkt als Frequenz/BW/SF/CR gesetzt. Das Dashboard bietet dafür Preset-Buttons nach Community-Standard:

Preset Frequenz Bandbreite SF CR Hinweis
EU / UK 869.525 MHz 62.5 kHz 8 5 Empfohlen (neu); AF=9 (10% Duty Cycle)
Schweiz 869.618 MHz 62.5 kHz 8 8
USA / Kanada 910.525 MHz 62.5 kHz 7 5 Stand Okt. 2025
Australien 915.800 MHz 250 kHz 10 5 Victoria: 916.575 MHz
Legacy EU 869.525 MHz 250 kHz 11 5 Alte Einstellung

Radio-Parameter (direkt editierbar)

Feld Companion-Kommando Beschreibung
Frequenz (MHz) mc.commands.set_radio(freq=...) z.B. 869.525
Bandbreite (kHz) mc.commands.set_radio(bw=...) 62.5 / 125 / 250
Spreading Factor mc.commands.set_radio(sf=...) 7–12
Coding Rate mc.commands.set_radio(cr=...) 5–8
TX-Power (dBm) mc.commands.set_radio(tx=...) max. 22 dBm (EU)
Airtime Factor set af <n> via CLI 9 = ~10% Duty Cycle (EU Pflicht)
Name mc.commands.set_name() Node-Name im Mesh
GPS-Koordinaten mc.commands.set_coords() Lat/Lon
Batterie / Storage RESP_CODE_BATT_AND_STORAGE Nur Anzeige

Path Hash Mode

Path Hash Mode steuert die Größe des Pfad-Hashes in Repeater-Broadcasts und beeinflusst damit Routing-Kapazität und maximale Hop-Anzahl.

Wert Hash-Größe Eindeutige IDs Max. Hop-Count
0 (Standard) 1 Byte 256 64
1 2 Byte 65.536 32
2 3 Byte 16.777.216 21

Hinweis: Ab Firmware v1.14.0 leiten alle Repeater 1-, 2- und 3-Byte-Pakete weiter, unabhängig von ihrer eigenen Einstellung. Ältere Firmware ignoriert 2- und 3-Byte-Pakete.

Einstellung im Dashboard

Global (Radio-Config-Seite /meshcore/config):

  • Dropdown mit den drei Optionen inkl. Erklärung der Auswirkungen
  • Companion-Kommando: mc.commands.set_path_hash_mode(0|1|2) (Protokoll-Byte: 0x3D)
  • Sichtbar nur wenn path_hash_mode_supported (aus Device-Query, fw_ver >= 10)

Per-Kanal-Override (Kanal-Verwaltung /meshcore/channels):

  • Optionale Überschreibung pro Kanal: 0, 1, 2 oder "Kein Override" (Radio-Standard)
  • Gespeichert in mc_channels.path_hash_mode_override (NULL = kein Override)
  • API: PUT /api/meshcore/channels/{key}/path-hash-mode

Flood Scope

Flood Scope begrenzt die regionale Ausbreitung von Flood-Paketen. Repeater mit Regions-Konfiguration leiten nur Pakete mit passendem Scope weiter.

Werte

Wert Verhalten
"" / "*" / "0" Klassisches Flood (kein Scope, Standard)
"#RegionName" Flood nur innerhalb der genannten Region

Der #-Präfix wird automatisch ergänzt. Der Scope-Key wird wie Kanal-Keys als SHA-256-Hash (erste 16 Bytes) des Namens abgeleitet.

Einstellung im Dashboard

Global (Radio-Config-Seite /meshcore/config):

  • Texteingabe für Scope-String mit Vorschau des abgeleiteten Keys
  • Companion-Kommando: CommandType.SET_FLOOD_SCOPE (0x36), Key = SHA-256(scope)[0:16]
  • Leereingabe oder * = Scope deaktivieren

Per-Kanal-Override (Kanal-Verwaltung /meshcore/channels):

  • Optionaler Scope-Override pro Kanal (überschreibt den globalen Wert beim Senden)
  • Gespeichert in mc_channels.flood_scope_override (NULL = kein Override)
  • API: PUT /api/meshcore/channels/{key}/flood-scope

Loop Detection

Repeater-Einstellung (ab v1.14.0), die Routing-Schleifen erkennt und unterbricht.

Wert Verhalten
off Keine Erkennung (Standard)
minimal Erkennt grobe Schleifen
moderate Moderater Schutz
strict Strenger Schutz (empfohlen für dichte Netze)

Auf der Radio-Config-Seite als Dropdown anzeigen und setzbar machen (nur wenn Firmware >= 1.14.0).


Kanal-Verwaltung (/meshcore/channels) – vollständiges Datenmodell

Jeder Kanal hat folgende einstellbare Parameter:

Feld Typ Beschreibung
name TEXT Kanalname (Key wird automatisch abgeleitet)
key TEXT SHA-256-Präfix (32 Hex), read-only
is_hashtag BOOL Name beginnt mit #
on_radio BOOL Im Radio-Slot geladen (Anzeige, nicht editierbar)
flood_scope_override TEXT|NULL Kanal-spezifischer Flood Scope (überschreibt global)
path_hash_mode_override INT|NULL Kanal-spezifischer Path Hash Mode (0/1/2 oder NULL)
favorite BOOL Favorit (Sidebar oben anzeigen)
last_active REAL Zeitstempel letzte Aktivität
msg_count INT Nachrichtenanzahl gesamt

Kanal-Datenmodell

Key-Ableitung

SHA-256-Hash des Kanalnamens, erste 16 Bytes = 32-stelliger Hex-Key. Hashtag-Kanäle (#name) werden automatisch abgeleitet. Der "Public"-Kanal hat einen festen kanonischen Key.

on_radio-Flag

Kanäle können im Dashboard verfolgt werden, ohne im Radio geladen zu sein. on_radio ist ein separates DB-Feld.

Nachrichten-Format in Kanälen

Kanalnachrichten betten den Absender als "Name: Text" ein. Das Frontend parst den Absender vor dem ersten : (max. 50 Zeichen).


Datenbank (meshbot/database.py)

Neue Tabellen (kein Eingriff in bestehende Tabellen):

CREATE TABLE mc_contacts (
  pubkey       TEXT PRIMARY KEY,
  node_id      TEXT UNIQUE,         -- mc! + erste 4 Bytes Hex
  name         TEXT,
  type         INTEGER DEFAULT 1,   -- 1=client 2=repeater 3=room 4=sensor
  lat          REAL, lon REAL,
  hop_count    INTEGER,
  snr          REAL,
  last_seen    REAL,
  first_seen   REAL,
  on_radio     INTEGER DEFAULT 0,
  favorite     INTEGER DEFAULT 0
);

CREATE TABLE mc_channels (
  key                    TEXT PRIMARY KEY,
  name                   TEXT,
  is_hashtag             INTEGER DEFAULT 0,
  on_radio               INTEGER DEFAULT 0,
  flood_scope_override   TEXT,            -- NULL = kein Override
  path_hash_mode_override INTEGER,        -- NULL = kein Override, 0/1/2
  last_active            REAL,
  msg_count              INTEGER DEFAULT 0,
  favorite               INTEGER DEFAULT 0
);

CREATE TABLE mc_messages (
  id               INTEGER PRIMARY KEY AUTOINCREMENT,
  type             TEXT,             -- 'direct' | 'channel'
  conversation_key TEXT,
  sender_key       TEXT,
  sender_name      TEXT,
  text             TEXT,
  snr              REAL,
  acked            INTEGER DEFAULT 0,
  outgoing         INTEGER DEFAULT 0,
  timestamp        REAL,
  received_at      REAL
);

CREATE TABLE mc_rf_stats (
  ts           REAL PRIMARY KEY,
  noise_floor  REAL,
  last_rssi    REAL,
  last_snr     REAL,
  tx_airtime   INTEGER,
  rx_airtime   INTEGER,
  pkt_recv     INTEGER,
  pkt_sent     INTEGER,
  flood_recv   INTEGER,
  flood_sent   INTEGER,
  direct_recv  INTEGER,
  direct_sent  INTEGER
);

CREATE TABLE mc_trace_results (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  contact_key TEXT,
  timestamp   REAL,
  hops        TEXT    -- JSON: [{node, snr}, ...]
);

Neues Modul meshbot/meshcore_client.py

Klasse MeshCoreClient:

  • Verbindung via await MeshCore.create_tcp(host, port)
  • Unabhängiger Reconnect-Loop, WebSocket-Status mc_status
  • Push-Handler: NEW_ADVERT, MSG_WAITING, SEND_CONFIRMED, TELEMETRY_RESPONSE, TRACE_DATA, PATH_UPDATED
  • Periodischer Poll: Kontakte + RF-Stats alle N Sekunden (CMD_GET_CONTACTS, CMD_GET_STATS)
  • send_to_channel(text, channel_name) als Callback für Bot-Dienste

Web-API – neue Endpunkte

Endpunkt Methode Auth Inhalt
/api/meshcore/status GET Public Verbindungsstatus + eigener Node
/api/meshcore/contacts GET Public Kontakte (filterbar nach type=)
/api/meshcore/messages GET Public Direktnachrichten
/api/meshcore/channels GET Public Alle Kanäle
/api/meshcore/channels POST Admin Kanal hinzufuegen
/api/meshcore/channels/{key} DELETE Admin Kanal entfernen
/api/meshcore/channels/{key}/messages GET Public Nachrichten eines Kanals
/api/meshcore/channels/{key}/send POST User Nachricht senden
/api/meshcore/channels/{key}/flood-scope PUT Admin Flood-Scope-Override setzen
/api/meshcore/channels/{key}/path-hash-mode PUT Admin Path-Hash-Mode-Override setzen
/api/meshcore/rf-stats GET Public RF-Statistik-Zeitreihe
/api/meshcore/trace POST User Pfad-Trace starten
/api/meshcore/trace/{contact_key} GET Public Letztes Trace-Ergebnis
/api/meshcore/config GET Admin Radio-Konfiguration lesen
/api/meshcore/config PUT Admin Radio-Konfiguration schreiben
/api/meshcore/config/preset/{name} POST Admin Frequenz-Preset anwenden

Erweiterung der bestehenden Bot-Dienste

Alle drei Dienste nutzen intern send_callback(text, channel). Diese wird um einen optionalen mc_send_callback(text, channel_name) ergänzt.

NINA → MeshCore (/meshcore/nina)

Erweiterung nina.yaml pro Schweregrad um optionalen meshcore:-Block:

severities:
  Severe:
    send_to_mesh: true
    channel: 0
    meshcore:
      enabled: false
      channel: "Warn"
      resend_interval: 600

Traffic → MeshCore (/meshcore/traffic)

Erweiterung config.yaml:

traffic:
  send_to_mesh: false
  channel: 0
  meshcore:
    enabled: false
    channel: "Verkehr"

Scheduler → MeshCore (/meshcore/scheduler)

Erweiterung scheduler.yaml pro Job:

jobs:
- name: Wetterbericht
  cron: "0 7 * * *"
  command: "?weather"
  channel: 0
  type: command
  meshcore:
    enabled: false
    channel: "General"

Neue Konfiguration (config.yaml)

meshcore:
  enabled: false
  host: 192.168.11.4
  port: 5000
  retry_interval: 30
  poll_interval: 60
  stats_interval: 300

Neue Abhängigkeiten (requirements.txt)

meshcore      # offizielles asyncio Python-SDK (PyPI)
cayennelpp    # CayenneLPP-Telemetrie-Dekodierung

Offene Fragen

  • Scheduler-UI: Eigene Seite /meshcore/scheduler oder erweiterte gemeinsame /scheduler-Seite mit optionaler MeshCore-Spalte?
  • Senden: Sollen Nachrichten aktiv in MeshCore-Kanäle / an Kontakte gesendet werden können?
  • Repeater-Detailseite: Eigene Unterseite für Typ=Repeater mit Telemetrie/Nachbarn?
  • Room-Login: Rooms erfordern Authentifizierung am Room-Server – Scope dieses Features?
  • Airtime Factor (AF): EU-Pflicht (AF=9 ≈ 10% Duty Cycle) – als Pflichtfeld oder Hinweis beim EU-Preset?

Betroffene / neue Dateien

Backend:

  • meshbot/meshcore_client.py – neu
  • meshbot/database.py – neue mc_*-Tabellen
  • meshbot/webserver.py – neue /api/meshcore/*-Endpunkte
  • meshbot/nina.py + meshbot/traffic.py + meshbot/scheduler.py – mc_send_callback
  • config/config.yaml, config/nina.yaml, config/scheduler.yaml
  • requirements.txt, main.py

Frontend (alle neu):

  • static/meshcore.html/js, meshcore-nodes.html/js, meshcore-map.html/js
  • static/meshcore-messages.html/js, meshcore-channels.html/js, meshcore-channel.html/js
  • static/meshcore-rf-stats.html/js, meshcore-trace.html/js
  • static/meshcore-config.html/js (inkl. Preset-Buttons, Path Hash Mode, Flood Scope, Loop Detection)
  • static/meshcore-scheduler.html/js, meshcore-nina.html/js, meshcore-traffic.html/js
  • static/js/app.js – Sidebar-Erweiterung

Referenzen

## Feature Request: MeshCore Companion-Port Integration ### Motivation Neben dem primären Meshtastic-Node soll ein **MeshCore Companion-Radio** als zweite, vollständig **getrennte** Datenquelle ins Dashboard eingebunden werden. MeshCore ist eine eigenständige LoRa-Mesh-Firmware und **kein Meshtastic** – die beiden Systeme sind protokollinkompatibel. **Designentscheidung:** Meshtastic- und MeshCore-Daten werden **nicht zusammengeführt**. Nodes, Nachrichten, Kanäle und Karten beider Systeme werden auf **getrennten Unterseiten** dargestellt. Die bestehenden Seiten bleiben unverändert. > **Referenz-Implementierung:** [Remote Terminal for MeshCore](https://github.com/jkingsman/Remote-Terminal-for-MeshCore) (FastAPI + React) nutzt dieselbe `meshcore` Python-Bibliothek und dient als wichtige Orientierung für Datenmodell und UI-Muster. --- ## Protokollunterschiede: Meshtastic vs. MeshCore | Aspekt | Meshtastic | MeshCore | |---|---|---| | Datenformat | **Protobuf** | **Custom Binary** (Little-Endian, Length-Prefixed Frames) | | TCP-Port | 4403 | **5000** | | Python-Bibliothek | `meshtastic` (TCPInterface) | `meshcore` (asyncio, PyPI) | | Telemetrie | Push (periodischer Broadcast) | Pull (auf Anfrage) | | Node-Identifikation | NodeNum + `!hex` | Ed25519 Public Key (32 Byte) | | Kanaele | Index 0-7, feste Slots | Name + SHA-256-Key, beliebig viele | | Kontakttypen | Einheitlich | Client / Repeater / Room / Sensor | | Regionen | Feste Enum (EU_868, US, ...) | Nutzerdefinierte Flood-Scope-Strings | --- ## Kontakttypen und ihre Darstellung | Typ | Wert | Darstellung | |---|---|---| | Client | 1 | Kontaktkarte + Direktnachricht-Verlauf | | Repeater | 2 | Eigene Detailseite: Telemetrie, Nachbarn, Funkeinstellungen | | Room (Server) | 3 | Kanal-ähnliche Ansicht, ggf. mit Login | | Sensor | 4 | Telemetrie-Dashboard (CayenneLPP: Temp, GPS, etc.) | --- ## Neue Seiten im Webinterface (Übersicht) | Route | Inhalt | Zugang | |---|---|---| | `/meshcore` | Übersicht: Verbindungsstatus, eigener Node, Zähler | Public | | `/meshcore/nodes` | Kontakte nach Typ (Client/Repeater/Room/Sensor) | Public | | `/meshcore/map` | Leaflet-Karte: Kontakte, Typen-Icons, Pfad-Trace-Overlay | Public | | `/meshcore/messages` | Direktnachrichten aller Kontakte | Public | | `/meshcore/channels` | Kanal-Verwaltung inkl. Flood-Scope- und Path-Hash-Mode-Override | Admin | | `/meshcore/channels/{key}` | Nachrichtenverlauf eines Kanals | Public | | `/meshcore/rf-stats` | RF-Statistiken: SNR, RSSI, Noise Floor, Airtime, Paketcounter | Public | | `/meshcore/trace` | Pfad-Trace zu einem Kontakt mit Hop-SNR-Visualisierung | Public | | `/meshcore/config` | Radio-Konfiguration: Frequenz-Presets, Path Hash Mode, Flood Scope, Loop Detection | Admin | | `/meshcore/scheduler` | Scheduler mit MeshCore-Kanal-Targeting | Admin | | `/meshcore/nina` | NINA-Konfiguration für MeshCore-Kanäle | Admin | | `/meshcore/traffic` | Verkehrsalarm-Konfiguration für MeshCore-Kanäle | Admin | --- ## Radio-Konfiguration (`/meshcore/config`) – Kernelement dieses Features ### Wichtiger Unterschied zu Meshtastic MeshCore hat **keine Region-Enum** (kein `EU_868`, `US` etc.). Regionen sind in MeshCore **nutzerdefinierte Flood-Scope-Strings** (z.B. `#europe`, `#us-ca`). Die Funkparameter werden direkt als Frequenz/BW/SF/CR gesetzt. Das Dashboard bietet dafür **Preset-Buttons** nach Community-Standard: | Preset | Frequenz | Bandbreite | SF | CR | Hinweis | |---|---|---|---|---|---| | EU / UK | 869.525 MHz | 62.5 kHz | 8 | 5 | Empfohlen (neu); AF=9 (10% Duty Cycle) | | Schweiz | 869.618 MHz | 62.5 kHz | 8 | 8 | | | USA / Kanada | 910.525 MHz | 62.5 kHz | 7 | 5 | Stand Okt. 2025 | | Australien | 915.800 MHz | 250 kHz | 10 | 5 | Victoria: 916.575 MHz | | Legacy EU | 869.525 MHz | 250 kHz | 11 | 5 | Alte Einstellung | ### Radio-Parameter (direkt editierbar) | Feld | Companion-Kommando | Beschreibung | |---|---|---| | Frequenz (MHz) | `mc.commands.set_radio(freq=...)` | z.B. 869.525 | | Bandbreite (kHz) | `mc.commands.set_radio(bw=...)` | 62.5 / 125 / 250 | | Spreading Factor | `mc.commands.set_radio(sf=...)` | 7–12 | | Coding Rate | `mc.commands.set_radio(cr=...)` | 5–8 | | TX-Power (dBm) | `mc.commands.set_radio(tx=...)` | max. 22 dBm (EU) | | Airtime Factor | `set af <n>` via CLI | 9 = ~10% Duty Cycle (EU Pflicht) | | Name | `mc.commands.set_name()` | Node-Name im Mesh | | GPS-Koordinaten | `mc.commands.set_coords()` | Lat/Lon | | Batterie / Storage | `RESP_CODE_BATT_AND_STORAGE` | Nur Anzeige | --- ## Path Hash Mode Path Hash Mode steuert die Größe des Pfad-Hashes in Repeater-Broadcasts und beeinflusst damit Routing-Kapazität und maximale Hop-Anzahl. | Wert | Hash-Größe | Eindeutige IDs | Max. Hop-Count | |---|---|---|---| | 0 (Standard) | 1 Byte | 256 | 64 | | 1 | 2 Byte | 65.536 | 32 | | 2 | 3 Byte | 16.777.216 | 21 | **Hinweis:** Ab Firmware v1.14.0 leiten alle Repeater 1-, 2- und 3-Byte-Pakete weiter, unabhängig von ihrer eigenen Einstellung. Ältere Firmware ignoriert 2- und 3-Byte-Pakete. ### Einstellung im Dashboard **Global** (Radio-Config-Seite `/meshcore/config`): - Dropdown mit den drei Optionen inkl. Erklärung der Auswirkungen - Companion-Kommando: `mc.commands.set_path_hash_mode(0|1|2)` (Protokoll-Byte: `0x3D`) - Sichtbar nur wenn `path_hash_mode_supported` (aus Device-Query, fw_ver >= 10) **Per-Kanal-Override** (Kanal-Verwaltung `/meshcore/channels`): - Optionale Überschreibung pro Kanal: 0, 1, 2 oder "Kein Override" (Radio-Standard) - Gespeichert in `mc_channels.path_hash_mode_override` (NULL = kein Override) - API: `PUT /api/meshcore/channels/{key}/path-hash-mode` --- ## Flood Scope Flood Scope begrenzt die regionale Ausbreitung von Flood-Paketen. Repeater mit Regions-Konfiguration leiten nur Pakete mit passendem Scope weiter. ### Werte | Wert | Verhalten | |---|---| | `""` / `"*"` / `"0"` | Klassisches Flood (kein Scope, Standard) | | `"#RegionName"` | Flood nur innerhalb der genannten Region | Der `#`-Präfix wird automatisch ergänzt. Der Scope-Key wird wie Kanal-Keys als SHA-256-Hash (erste 16 Bytes) des Namens abgeleitet. ### Einstellung im Dashboard **Global** (Radio-Config-Seite `/meshcore/config`): - Texteingabe für Scope-String mit Vorschau des abgeleiteten Keys - Companion-Kommando: `CommandType.SET_FLOOD_SCOPE` (0x36), Key = SHA-256(scope)[0:16] - Leereingabe oder `*` = Scope deaktivieren **Per-Kanal-Override** (Kanal-Verwaltung `/meshcore/channels`): - Optionaler Scope-Override pro Kanal (überschreibt den globalen Wert beim Senden) - Gespeichert in `mc_channels.flood_scope_override` (NULL = kein Override) - API: `PUT /api/meshcore/channels/{key}/flood-scope` --- ## Loop Detection Repeater-Einstellung (ab v1.14.0), die Routing-Schleifen erkennt und unterbricht. | Wert | Verhalten | |---|---| | `off` | Keine Erkennung (Standard) | | `minimal` | Erkennt grobe Schleifen | | `moderate` | Moderater Schutz | | `strict` | Strenger Schutz (empfohlen für dichte Netze) | Auf der Radio-Config-Seite als Dropdown anzeigen und setzbar machen (nur wenn Firmware >= 1.14.0). --- ## Kanal-Verwaltung (`/meshcore/channels`) – vollständiges Datenmodell Jeder Kanal hat folgende einstellbare Parameter: | Feld | Typ | Beschreibung | |---|---|---| | `name` | TEXT | Kanalname (Key wird automatisch abgeleitet) | | `key` | TEXT | SHA-256-Präfix (32 Hex), read-only | | `is_hashtag` | BOOL | Name beginnt mit `#` | | `on_radio` | BOOL | Im Radio-Slot geladen (Anzeige, nicht editierbar) | | `flood_scope_override` | TEXT\|NULL | Kanal-spezifischer Flood Scope (überschreibt global) | | `path_hash_mode_override` | INT\|NULL | Kanal-spezifischer Path Hash Mode (0/1/2 oder NULL) | | `favorite` | BOOL | Favorit (Sidebar oben anzeigen) | | `last_active` | REAL | Zeitstempel letzte Aktivität | | `msg_count` | INT | Nachrichtenanzahl gesamt | --- ## Kanal-Datenmodell ### Key-Ableitung SHA-256-Hash des Kanalnamens, erste 16 Bytes = 32-stelliger Hex-Key. Hashtag-Kanäle (`#name`) werden automatisch abgeleitet. Der "Public"-Kanal hat einen festen kanonischen Key. ### on_radio-Flag Kanäle können im Dashboard verfolgt werden, **ohne im Radio geladen zu sein**. `on_radio` ist ein separates DB-Feld. ### Nachrichten-Format in Kanälen Kanalnachrichten betten den Absender als `"Name: Text"` ein. Das Frontend parst den Absender vor dem ersten `: ` (max. 50 Zeichen). --- ## Datenbank (meshbot/database.py) Neue Tabellen (kein Eingriff in bestehende Tabellen): ```sql CREATE TABLE mc_contacts ( pubkey TEXT PRIMARY KEY, node_id TEXT UNIQUE, -- mc! + erste 4 Bytes Hex name TEXT, type INTEGER DEFAULT 1, -- 1=client 2=repeater 3=room 4=sensor lat REAL, lon REAL, hop_count INTEGER, snr REAL, last_seen REAL, first_seen REAL, on_radio INTEGER DEFAULT 0, favorite INTEGER DEFAULT 0 ); CREATE TABLE mc_channels ( key TEXT PRIMARY KEY, name TEXT, is_hashtag INTEGER DEFAULT 0, on_radio INTEGER DEFAULT 0, flood_scope_override TEXT, -- NULL = kein Override path_hash_mode_override INTEGER, -- NULL = kein Override, 0/1/2 last_active REAL, msg_count INTEGER DEFAULT 0, favorite INTEGER DEFAULT 0 ); CREATE TABLE mc_messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, -- 'direct' | 'channel' conversation_key TEXT, sender_key TEXT, sender_name TEXT, text TEXT, snr REAL, acked INTEGER DEFAULT 0, outgoing INTEGER DEFAULT 0, timestamp REAL, received_at REAL ); CREATE TABLE mc_rf_stats ( ts REAL PRIMARY KEY, noise_floor REAL, last_rssi REAL, last_snr REAL, tx_airtime INTEGER, rx_airtime INTEGER, pkt_recv INTEGER, pkt_sent INTEGER, flood_recv INTEGER, flood_sent INTEGER, direct_recv INTEGER, direct_sent INTEGER ); CREATE TABLE mc_trace_results ( id INTEGER PRIMARY KEY AUTOINCREMENT, contact_key TEXT, timestamp REAL, hops TEXT -- JSON: [{node, snr}, ...] ); ``` --- ## Neues Modul meshbot/meshcore_client.py Klasse `MeshCoreClient`: - Verbindung via `await MeshCore.create_tcp(host, port)` - Unabhängiger Reconnect-Loop, WebSocket-Status `mc_status` - Push-Handler: NEW_ADVERT, MSG_WAITING, SEND_CONFIRMED, TELEMETRY_RESPONSE, TRACE_DATA, PATH_UPDATED - Periodischer Poll: Kontakte + RF-Stats alle N Sekunden (`CMD_GET_CONTACTS`, `CMD_GET_STATS`) - `send_to_channel(text, channel_name)` als Callback für Bot-Dienste --- ## Web-API – neue Endpunkte | Endpunkt | Methode | Auth | Inhalt | |---|---|---|---| | `/api/meshcore/status` | GET | Public | Verbindungsstatus + eigener Node | | `/api/meshcore/contacts` | GET | Public | Kontakte (filterbar nach type=) | | `/api/meshcore/messages` | GET | Public | Direktnachrichten | | `/api/meshcore/channels` | GET | Public | Alle Kanäle | | `/api/meshcore/channels` | POST | Admin | Kanal hinzufuegen | | `/api/meshcore/channels/{key}` | DELETE | Admin | Kanal entfernen | | `/api/meshcore/channels/{key}/messages` | GET | Public | Nachrichten eines Kanals | | `/api/meshcore/channels/{key}/send` | POST | User | Nachricht senden | | `/api/meshcore/channels/{key}/flood-scope` | PUT | Admin | Flood-Scope-Override setzen | | `/api/meshcore/channels/{key}/path-hash-mode` | PUT | Admin | Path-Hash-Mode-Override setzen | | `/api/meshcore/rf-stats` | GET | Public | RF-Statistik-Zeitreihe | | `/api/meshcore/trace` | POST | User | Pfad-Trace starten | | `/api/meshcore/trace/{contact_key}` | GET | Public | Letztes Trace-Ergebnis | | `/api/meshcore/config` | GET | Admin | Radio-Konfiguration lesen | | `/api/meshcore/config` | PUT | Admin | Radio-Konfiguration schreiben | | `/api/meshcore/config/preset/{name}` | POST | Admin | Frequenz-Preset anwenden | --- ## Erweiterung der bestehenden Bot-Dienste Alle drei Dienste nutzen intern `send_callback(text, channel)`. Diese wird um einen optionalen `mc_send_callback(text, channel_name)` ergänzt. ### NINA → MeshCore (`/meshcore/nina`) Erweiterung `nina.yaml` pro Schweregrad um optionalen `meshcore:`-Block: ```yaml severities: Severe: send_to_mesh: true channel: 0 meshcore: enabled: false channel: "Warn" resend_interval: 600 ``` ### Traffic → MeshCore (`/meshcore/traffic`) Erweiterung `config.yaml`: ```yaml traffic: send_to_mesh: false channel: 0 meshcore: enabled: false channel: "Verkehr" ``` ### Scheduler → MeshCore (`/meshcore/scheduler`) Erweiterung `scheduler.yaml` pro Job: ```yaml jobs: - name: Wetterbericht cron: "0 7 * * *" command: "?weather" channel: 0 type: command meshcore: enabled: false channel: "General" ``` --- ## Neue Konfiguration (config.yaml) ```yaml meshcore: enabled: false host: 192.168.11.4 port: 5000 retry_interval: 30 poll_interval: 60 stats_interval: 300 ``` ## Neue Abhängigkeiten (requirements.txt) ``` meshcore # offizielles asyncio Python-SDK (PyPI) cayennelpp # CayenneLPP-Telemetrie-Dekodierung ``` --- ## Offene Fragen - **Scheduler-UI**: Eigene Seite `/meshcore/scheduler` oder erweiterte gemeinsame `/scheduler`-Seite mit optionaler MeshCore-Spalte? - **Senden**: Sollen Nachrichten aktiv in MeshCore-Kanäle / an Kontakte gesendet werden können? - **Repeater-Detailseite**: Eigene Unterseite für Typ=Repeater mit Telemetrie/Nachbarn? - **Room-Login**: Rooms erfordern Authentifizierung am Room-Server – Scope dieses Features? - **Airtime Factor (AF)**: EU-Pflicht (AF=9 ≈ 10% Duty Cycle) – als Pflichtfeld oder Hinweis beim EU-Preset? --- ## Betroffene / neue Dateien **Backend:** - `meshbot/meshcore_client.py` – neu - `meshbot/database.py` – neue mc_*-Tabellen - `meshbot/webserver.py` – neue `/api/meshcore/*`-Endpunkte - `meshbot/nina.py` + `meshbot/traffic.py` + `meshbot/scheduler.py` – mc_send_callback - `config/config.yaml`, `config/nina.yaml`, `config/scheduler.yaml` - `requirements.txt`, `main.py` **Frontend (alle neu):** - `static/meshcore.html/js`, `meshcore-nodes.html/js`, `meshcore-map.html/js` - `static/meshcore-messages.html/js`, `meshcore-channels.html/js`, `meshcore-channel.html/js` - `static/meshcore-rf-stats.html/js`, `meshcore-trace.html/js` - `static/meshcore-config.html/js` (inkl. Preset-Buttons, Path Hash Mode, Flood Scope, Loop Detection) - `static/meshcore-scheduler.html/js`, `meshcore-nina.html/js`, `meshcore-traffic.html/js` - `static/js/app.js` – Sidebar-Erweiterung --- ## Referenzen - [Remote Terminal for MeshCore (jkingsman)](https://github.com/jkingsman/Remote-Terminal-for-MeshCore) - [MeshCore CLI Commands](https://docs.meshcore.io/cli_commands/) - [MeshCore Companion Protocol](https://docs.meshcore.io/companion_protocol/) - [meshcore Python Library (PyPI)](https://pypi.org/project/meshcore/) - [MeshCore Radio Setting Presets – LetsMesh Forum](https://forum.letsmesh.net/t/meshcore-radio-setting-presets/67) - [path.hash.mode Bug Issue #2154](https://github.com/meshcore-dev/MeshCore/issues/2154)
ppfeiffer changed title from feat: Support for a second MeshCore companion port (multi-interface) to Feature: Unterstützung eines zweiten MeshCore-Companion-Ports (Multi-Interface) 2026-04-10 09:49:10 +02:00
ppfeiffer changed title from Feature: Unterstützung eines zweiten MeshCore-Companion-Ports (Multi-Interface) to Feature: MeshCore Companion-Port als zweite Datenquelle im Dashboard 2026-04-10 10:31:09 +02:00
ppfeiffer changed title from Feature: MeshCore Companion-Port als zweite Datenquelle im Dashboard to Feature: MeshCore Companion-Port als eigenständiger Bereich im Dashboard 2026-04-10 10:42:13 +02:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ppfeiffer/MeshDD-Bot#20
No description provided.