mirror of
https://github.com/tcivie/meshtastic-metrics-exporter.git
synced 2025-01-03 09:57:49 -08:00
255 lines
8.3 KiB
Python
255 lines
8.3 KiB
Python
from abc import ABC, abstractmethod
|
|
from venv import logger
|
|
|
|
import redis
|
|
import unishox2
|
|
from meshtastic.admin_pb2 import AdminMessage
|
|
from meshtastic.mesh_pb2 import Position, User, Routing, Waypoint, RouteDiscovery, NeighborInfo
|
|
from meshtastic.mqtt_pb2 import MapReport
|
|
from meshtastic.paxcount_pb2 import Paxcount
|
|
from meshtastic.portnums_pb2 import PortNum
|
|
from meshtastic.remote_hardware_pb2 import HardwareMessage
|
|
from meshtastic.storeforward_pb2 import StoreAndForward
|
|
from meshtastic.telemetry_pb2 import Telemetry
|
|
from prometheus_client import CollectorRegistry
|
|
|
|
|
|
class Processor(ABC):
|
|
def __init__(self, registry: CollectorRegistry, redis_client: redis.Redis):
|
|
self.registry = registry
|
|
self.redis_client = redis_client
|
|
|
|
@abstractmethod
|
|
def process(self, payload):
|
|
pass
|
|
|
|
|
|
class ProcessorRegistry:
|
|
_registry = {}
|
|
|
|
@classmethod
|
|
def register_processor(cls, portnum):
|
|
def inner_wrapper(wrapped_class):
|
|
cls._registry[portnum] = wrapped_class()
|
|
return wrapped_class
|
|
|
|
return inner_wrapper
|
|
|
|
@classmethod
|
|
def get_processor(cls, portnum):
|
|
return cls._registry.get(portnum, UnknownAppProcessor())
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.UNKNOWN_APP)
|
|
class UnknownAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received UNKNOWN_APP packet")
|
|
return None
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.TEXT_MESSAGE_APP)
|
|
class TextMessageAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received TEXT_MESSAGE_APP packet")
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.REMOTE_HARDWARE_APP)
|
|
class RemoteHardwareAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received REMOTE_HARDWARE_APP packet")
|
|
hardware_message = HardwareMessage()
|
|
hardware_message.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.POSITION_APP)
|
|
class PositionAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received POSITION_APP packet")
|
|
position = Position()
|
|
position.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.NODEINFO_APP)
|
|
class NodeInfoAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received NODEINFO_APP packet")
|
|
user = User()
|
|
user.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.ROUTING_APP)
|
|
class RoutingAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received ROUTING_APP packet")
|
|
routing = Routing()
|
|
routing.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.ADMIN_APP)
|
|
class AdminAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received ADMIN_APP packet")
|
|
admin_message = AdminMessage()
|
|
admin_message.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.TEXT_MESSAGE_COMPRESSED_APP)
|
|
class TextMessageCompressedAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received TEXT_MESSAGE_COMPRESSED_APP packet")
|
|
decompressed_payload = unishox2.decompress(payload, len(payload))
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.WAYPOINT_APP)
|
|
class WaypointAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received WAYPOINT_APP packet")
|
|
waypoint = Waypoint()
|
|
waypoint.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.AUDIO_APP)
|
|
class AudioAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received AUDIO_APP packet")
|
|
pass # NOTE: Audio packet. should probably be processed
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.DETECTION_SENSOR_APP)
|
|
class DetectionSensorAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received DETECTION_SENSOR_APP packet")
|
|
pass # NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.REPLY_APP)
|
|
class ReplyAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received REPLY_APP packet")
|
|
pass # NOTE: Provides a 'ping' service that replies to any packet it receives. This is useful for testing.
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.IP_TUNNEL_APP)
|
|
class IpTunnelAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received IP_TUNNEL_APP packet")
|
|
pass # NOTE: IP Packet. Handled by the python API, firmware ignores this one and passes it on.
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.PAXCOUNTER_APP)
|
|
class PaxCounterAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received PAXCOUNTER_APP packet")
|
|
paxcounter = Paxcount()
|
|
paxcounter.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.SERIAL_APP)
|
|
class SerialAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received SERIAL_APP packet")
|
|
pass # NOTE: Provides a hardware serial interface to send and receive from the Meshtastic network.
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.STORE_FORWARD_APP)
|
|
class StoreForwardAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received STORE_FORWARD_APP packet")
|
|
store_and_forward = StoreAndForward()
|
|
store_and_forward.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.RANGE_TEST_APP)
|
|
class RangeTestAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received RANGE_TEST_APP packet")
|
|
pass # NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.TELEMETRY_APP)
|
|
class TelemetryAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received TELEMETRY_APP packet")
|
|
telemetry = Telemetry()
|
|
telemetry.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.ZPS_APP)
|
|
class ZpsAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received ZPS_APP packet")
|
|
pass # NOTE: Experimental tools for estimating node position without a GPS
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.SIMULATOR_APP)
|
|
class SimulatorAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received SIMULATOR_APP packet")
|
|
pass # NOTE: Used to let multiple instances of Linux native applications communicate as if they did using their LoRa chip.
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.TRACEROUTE_APP)
|
|
class TraceRouteAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received TRACEROUTE_APP packet")
|
|
traceroute = RouteDiscovery()
|
|
traceroute.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.NEIGHBORINFO_APP)
|
|
class NeighborInfoAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received NEIGHBORINFO_APP packet")
|
|
neighbor_info = NeighborInfo()
|
|
neighbor_info.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.ATAK_PLUGIN)
|
|
class AtakPluginProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received ATAK_PLUGIN packet")
|
|
pass # NOTE: ATAK Plugin
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.MAP_REPORT_APP)
|
|
class MapReportAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received MAP_REPORT_APP packet")
|
|
map_report = MapReport()
|
|
map_report.ParseFromString(payload)
|
|
pass
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.PRIVATE_APP)
|
|
class PrivateAppProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received PRIVATE_APP packet")
|
|
pass # NOTE: Private application portnum
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.ATAK_FORWARDER)
|
|
class AtakForwarderProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received ATAK_FORWARDER packet")
|
|
pass # NOTE: ATAK Forwarder
|
|
|
|
|
|
@ProcessorRegistry.register_processor(PortNum.MAX)
|
|
class MaxProcessor(Processor):
|
|
def process(self, payload):
|
|
logger.debug("Received MAX packet")
|
|
pass # NOTE: Maximum portnum value
|