From 937580e24fc03d404b7654ec433c7157be95f59c Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 19 Jun 2026 16:21:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(mqtt):=20console=5Flog.mqtt=20=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E8=BF=9E=E6=8E=A5/=E6=96=AD=E5=BC=80/=E8=AE=A2?= =?UTF-8?q?=E9=98=85/=E5=8F=96=E6=B6=88=E8=AE=A2=E9=98=85=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为 meshtasticFilterHook 增加 consoleLog 字段;当 console_log.mqtt=true 时 向 stderr 输出 4 类事件(带 client_id、username、remote IP:port): - OnSessionEstablished → [mqtt] connect ... (认证后才打,避开被 IP 屏蔽拒掉的客户端) - OnDisconnect → [mqtt] disconnect ... (含 expire 和 mochi 上报的断开原因) - OnSubscribed → [mqtt] subscribe ... (每个 filter 一行) - OnUnsubscribed → [mqtt] unsubscribe ... (每个 filter 一行) Provides() 同步多声明这 4 个事件类型;关闭开关时各 handler 立即返回。 Co-Authored-By: Claude --- main.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index fff149a..bcf684a 100644 --- a/main.go +++ b/main.go @@ -53,6 +53,7 @@ type meshtasticFilterHook struct { settings *rspkg.Cache pkiResolver func(toNodeNum, fromNodeNum uint32) ([]byte, []byte, bool) autoAcker func(record map[string]any) + consoleLog bool // 控制台是否打印 MQTT 连接/订阅事件 } // ID 返回用于识别 Meshtastic payload 过滤器的 hook 名称。 @@ -60,9 +61,14 @@ func (h *meshtasticFilterHook) ID() string { return "meshtastic-filter" } -// Provides 声明该 hook 只处理客户端发布消息。 +// Provides 声明该 hook 处理客户端连接、订阅与发布事件。 func (h *meshtasticFilterHook) Provides(b byte) bool { - return b == mqtt.OnConnect || b == mqtt.OnPublish + return b == mqtt.OnConnect || + b == mqtt.OnPublish || + b == mqtt.OnSessionEstablished || + b == mqtt.OnDisconnect || + b == mqtt.OnSubscribed || + b == mqtt.OnUnsubscribed } // OnConnect 在 MQTT 会话建立前拒绝命中 IP 屏蔽表的客户端。 @@ -75,6 +81,54 @@ func (h *meshtasticFilterHook) OnConnect(cl *mqtt.Client, pk packets.Packet) err return nil } +// OnSessionEstablished 在客户端通过认证、会话建立后打印连接日志。 +func (h *meshtasticFilterHook) OnSessionEstablished(cl *mqtt.Client, pk packets.Packet) { + if !h.consoleLog { + return + } + info := mqttClientInfoFromClient(cl) + fmt.Fprintf(os.Stderr, "[mqtt] connect client_id=%s username=%s remote=%s:%s\n", + info.ClientID, info.Username, info.RemoteHost, info.RemotePort) +} + +// OnDisconnect 在客户端断开时打印日志,含触发原因。 +func (h *meshtasticFilterHook) OnDisconnect(cl *mqtt.Client, err error, expire bool) { + if !h.consoleLog { + return + } + info := mqttClientInfoFromClient(cl) + reason := "client closed" + if err != nil { + reason = err.Error() + } + fmt.Fprintf(os.Stderr, "[mqtt] disconnect client_id=%s username=%s remote=%s:%s expire=%t reason=%s\n", + info.ClientID, info.Username, info.RemoteHost, info.RemotePort, expire, reason) +} + +// OnSubscribed 客户端订阅成功后打印订阅的 topic filter 列表。 +func (h *meshtasticFilterHook) OnSubscribed(cl *mqtt.Client, pk packets.Packet, reasonCodes []byte) { + if !h.consoleLog { + return + } + info := mqttClientInfoFromClient(cl) + for _, sub := range pk.Filters { + fmt.Fprintf(os.Stderr, "[mqtt] subscribe client_id=%s username=%s remote=%s:%s topic=%s\n", + info.ClientID, info.Username, info.RemoteHost, info.RemotePort, sub.Filter) + } +} + +// OnUnsubscribed 客户端取消订阅后打印日志。 +func (h *meshtasticFilterHook) OnUnsubscribed(cl *mqtt.Client, pk packets.Packet) { + if !h.consoleLog { + return + } + info := mqttClientInfoFromClient(cl) + for _, sub := range pk.Filters { + fmt.Fprintf(os.Stderr, "[mqtt] unsubscribe client_id=%s username=%s remote=%s:%s topic=%s\n", + info.ClientID, info.Username, info.RemoteHost, info.RemotePort, sub.Filter) + } +} + // OnPublish 在 broker 转发消息前校验 payload;无效消息会被拒绝并丢弃。 func (h *meshtasticFilterHook) OnPublish(cl *mqtt.Client, pk packets.Packet) (packets.Packet, error) { valid, _, record := mqtpp.MQTTPP(pk.TopicName, pk.Payload, h.key, mqtpp.Options{ @@ -398,6 +452,7 @@ func startMQTTServer(cfg *configpkg.Config, store *storepkg.Store, dbQueue *stor blocking: blocking, settings: settings, pkiResolver: botpkg.NewPKIKeyResolver(store), + consoleLog: cfg.ConsoleLog.MQTT, } if err := server.AddHook(hook, nil); err != nil { return nil, nil, "", err