Files
meshtastic_firmware/mcp-server/src/meshtastic_mcp/registry.py
T
Ben MeadorsGitHubCopilotcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
c8dac10348 Add MCP server for interacting with meshtastic devices and testing framework / TUI (#10194)
* Start of MCP server and test suite

* Add MCP server for interacting with meshtastic devices and testing framework / TUI

* Update mcp-server/README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix mcp-server review feedback from thread

Agent-Logs-Url: https://github.com/meshtastic/firmware/sessions/91dc128a-ed50-4d07-8bb2-3dc6623a05f7

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* Enhance StreamAPI and PhoneAPI for improved log record handling and concurrency control

* Semgrep fixes

* Trunk and semgrep fixes

* optimize pio streaming tee file writes

Agent-Logs-Url: https://github.com/meshtastic/firmware/sessions/04e26c6b-6a2b-45be-bbeb-79ae4d0be633

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* chore: remove redundant log handle assignment

Agent-Logs-Url: https://github.com/meshtastic/firmware/sessions/04e26c6b-6a2b-45be-bbeb-79ae4d0be633

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* Consolidate type imports and remove placeholder test files

* Add tests for config persistence and more exchange messages

* Refactor position test to validate on-demand request/reply behavior

* Remove  position request/reply test and update README for telemetry behavior

* Fix transmit history file to get removed on factory reset

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-04-18 08:17:44 -05:00

99 lines
2.7 KiB
Python

"""In-memory registry of active serial monitor sessions and port locks.
Two things live here so the rest of the package has a single place to reach
them:
1. `sessions`: `{session_id: SerialSession}` for pio device monitor subprocs.
2. `port_locks`: `{port: threading.Lock}` so admin/info tools can fail fast
when a serial monitor or another meshtastic client already owns a port.
"""
from __future__ import annotations
import threading
from typing import Any
from .serial_session import SerialSession, close_session
_LOCK = threading.Lock()
_sessions: dict[str, SerialSession] = {}
_port_locks: dict[str, threading.Lock] = {}
def register_session(session: SerialSession) -> None:
with _LOCK:
_sessions[session.id] = session
def get_session(session_id: str) -> SerialSession:
with _LOCK:
session = _sessions.get(session_id)
if session is None:
raise KeyError(f"Unknown session_id: {session_id!r}")
return session
def remove_session(session_id: str) -> SerialSession | None:
with _LOCK:
return _sessions.pop(session_id, None)
def active_session_for_port(port: str) -> SerialSession | None:
"""Find any active (non-eof) session owning `port`."""
sweep_dead()
with _LOCK:
for s in _sessions.values():
if s.port == port and s.proc.poll() is None:
return s
return None
def all_sessions() -> list[SerialSession]:
with _LOCK:
return list(_sessions.values())
def sweep_dead() -> int:
"""Remove sessions whose subprocess has exited. Returns count removed."""
removed_sessions: list[SerialSession] = []
with _LOCK:
for sid, s in list(_sessions.items()):
if s.proc.poll() is not None:
removed_sessions.append(_sessions.pop(sid))
for session in removed_sessions:
try:
close_session(session)
except Exception:
pass
return len(removed_sessions)
def shutdown_all() -> None:
"""Close every live session (called on server exit)."""
with _LOCK:
items = list(_sessions.items())
_sessions.clear()
for _sid, session in items:
try:
close_session(session)
except Exception:
pass
def port_lock(port: str) -> threading.Lock:
"""Per-port lock for SerialInterface / admin tool serialization."""
with _LOCK:
lock = _port_locks.get(port)
if lock is None:
lock = threading.Lock()
_port_locks[port] = lock
return lock
def snapshot() -> dict[str, Any]:
"""Debug dump: session count, port lock count."""
with _LOCK:
return {
"sessions": len(_sessions),
"port_locks": len(_port_locks),
}