diff --git a/plugin/hermes_meshtastic/adapter.py b/plugin/hermes_meshtastic/adapter.py index f902b60..5f8fefa 100644 --- a/plugin/hermes_meshtastic/adapter.py +++ b/plugin/hermes_meshtastic/adapter.py @@ -14,13 +14,24 @@ import time from typing import Any, Dict, List, Optional try: - from gateway.platforms.base import BasePlatformAdapter, SendResult - from gateway.platforms.event import MessageEvent, MessageType + from gateway.platforms.base import ( + BasePlatformAdapter, + MessageEvent, + MessageType, + SendResult, + ) except ImportError: # Allow importing and testing utility functions without gateway in environment class BasePlatformAdapter: # type: ignore[no-redef] - def __init__(self, config: Any): + def __init__(self, config: Any, platform: Any = "meshtastic"): self.config = config + self.platform = platform + + def build_source(self, **kwargs): + return kwargs + + async def handle_message(self, event: Any) -> None: + pass class SendResult: # type: ignore[no-redef] def __init__(self, success: bool, message_id: Optional[str] = None, error: Optional[str] = None): @@ -107,7 +118,7 @@ class MeshtasticAdapter(BasePlatformAdapter): """Hermes gateway adapter for Meshtastic LoRa radios over TCP.""" def __init__(self, config: Any): - super().__init__(config) + super().__init__(config, platform="meshtastic") self.extra = getattr(config, "extra", {}) or {} self.host = self.extra.get("host", "meshtastic.local") self.port = int(self.extra.get("port", 4403)) @@ -191,24 +202,32 @@ class MeshtasticAdapter(BasePlatformAdapter): to_id = packet.get("toId") is_dm = to_id != "^all" and packet.get("to") == my_node_num chat_id = from_id if is_dm else f"channel_{ch}" + chat_type = "dm" if is_dm else "channel" rx_snr = packet.get("rxSnr", 0.0) - hop_limit = packet.get("hopLimit", 0) logger.info( "[Meshtastic] Inbound message from %s on ch=%s (is_dm=%s, SNR=%.1fdB): %s", from_id, ch, is_dm, rx_snr, text ) - # Build Hermes MessageEvent - event = MessageEvent( - platform="meshtastic", - message_type=MessageType.TEXT, - text=text, - sender_id=from_id, - sender_name=from_id, + # Build Hermes SessionSource and MessageEvent + source = self.build_source( chat_id=chat_id, + chat_name=f"Meshtastic {chat_id}", + chat_type=chat_type, + user_id=from_id, + user_name=from_id, + message_id=str(packet.get("id", int(time.time()))), + ) + + event = MessageEvent( + text=text, + message_type=MessageType.TEXT, + user_id=from_id, + user_name=from_id, + source=source, + raw_message=packet, message_id=str(packet.get("id", int(time.time()))), - raw_event=packet, ) if self._loop and self._loop.is_running(): @@ -217,18 +236,18 @@ class MeshtasticAdapter(BasePlatformAdapter): except Exception as exc: logger.exception("[Meshtastic] Error processing received packet: %s", exc) - async def send_message( + async def send( self, chat_id: str, - message: str, - reply_to_id: Optional[str] = None, - **kwargs: Any, + content: str, + reply_to: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, ) -> SendResult: - """Send a message out over LoRa.""" + """Send a message out over LoRa (implements BasePlatformAdapter.send).""" if not self._connected or not self._iface: return SendResult(success=False, error="Meshtastic radio not connected") - clean_text = strip_markdown(message) + clean_text = strip_markdown(content) chunks = chunk_text(clean_text, MAX_LORA_MESSAGE_LENGTH) # Destination: if chat_id starts with '!', it is a direct node ID @@ -265,6 +284,14 @@ class MeshtasticAdapter(BasePlatformAdapter): logger.exception("[Meshtastic] Failed to send message: %s", exc) return SendResult(success=False, error=str(exc)) + async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: + """Get chat/channel info (implements BasePlatformAdapter.get_chat_info).""" + is_dm = chat_id.startswith("!") + return { + "name": f"Node {chat_id}" if is_dm else f"Channel {chat_id}", + "type": "dm" if is_dm else "channel", + } + async def disconnect(self) -> None: """Disconnect and clean up resources.""" self._running = False diff --git a/plugin/pyproject.toml b/plugin/pyproject.toml index 68b02b0..e5f95f4 100644 --- a/plugin/pyproject.toml +++ b/plugin/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "hermes-meshtastic" -version = "0.1.1" +version = "0.1.2" description = "Meshtastic LoRa mesh gateway adapter plugin for Hermes Agent" readme = "README.md" requires-python = ">=3.10"