mirror of
https://github.com/yuelwish/mqtt-bridge.git
synced 2025-10-05 08:06:56 +08:00
fix(mqtt): 解决MQTT重连不重新订阅问题
This commit is contained in:
@@ -2,10 +2,10 @@ package engine
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/YueLWish/mqtt-bridge/pkg/xmqtt"
|
|
||||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
"github.com/panjf2000/ants"
|
"github.com/panjf2000/ants"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/yuelwish/mqtt-bridge/pkg/xmqtt"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -82,9 +82,9 @@ func (e *Engine) handlerMessage(ctx context.Context) {
|
|||||||
if err = gPool.Submit(func() {
|
if err = gPool.Submit(func() {
|
||||||
err := xmqtt.Send(client, msg.Topic, msg.Payload)
|
err := xmqtt.Send(client, msg.Topic, msg.Payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[send message] -- %s ==> %v t:%s failed: %v", msg.FromTag, tTag, msg.Topic, err)
|
log.Printf("[send message] %s ==> %v t:%s failed: %v", msg.FromTag, tTag, msg.Topic, err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[send message] -- %s ==> %v t:%s p:%s", msg.FromTag, tTag, msg.Topic, msg.Payload)
|
log.Printf("[send message] %s ==> %v t:%s p:%s", msg.FromTag, tTag, msg.Topic, msg.Payload)
|
||||||
}
|
}
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Printf("[submit message] failed: %v", err)
|
log.Printf("[submit message] failed: %v", err)
|
||||||
|
4
main.go
4
main.go
@@ -3,9 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/YueLWish/mqtt-bridge/engine"
|
|
||||||
"github.com/YueLWish/mqtt-bridge/pkg/setting"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/yuelwish/mqtt-bridge/engine"
|
||||||
|
"github.com/yuelwish/mqtt-bridge/pkg/setting"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
124
pkg/xmqtt/client.go
Normal file
124
pkg/xmqtt/client.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package xmqtt
|
||||||
|
|
||||||
|
import (
|
||||||
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type subscribed struct {
|
||||||
|
topic string
|
||||||
|
qos byte
|
||||||
|
callback mqtt.MessageHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
mqtt.Client
|
||||||
|
subMap sync.Map
|
||||||
|
status int32 // 1 连接成功 2 断开连接
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
stConned = iota + 1
|
||||||
|
stLost
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewClient(o *mqtt.ClientOptions) mqtt.Client {
|
||||||
|
var (
|
||||||
|
onLostFn mqtt.ConnectionLostHandler
|
||||||
|
onConnFn mqtt.OnConnectHandler
|
||||||
|
)
|
||||||
|
if o.OnConnectionLost != nil {
|
||||||
|
onLostFn = o.OnConnectionLost
|
||||||
|
}
|
||||||
|
if o.OnConnect != nil {
|
||||||
|
onConnFn = o.OnConnect
|
||||||
|
}
|
||||||
|
|
||||||
|
mClient := &Client{}
|
||||||
|
o.SetConnectionLostHandler(func(client mqtt.Client, err error) {
|
||||||
|
atomic.StoreInt32(&mClient.status, stLost)
|
||||||
|
if onLostFn != nil {
|
||||||
|
onLostFn(client, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
o.SetOnConnectHandler(func(client mqtt.Client) {
|
||||||
|
defer atomic.StoreInt32(&mClient.status, stConned)
|
||||||
|
if onConnFn != nil {
|
||||||
|
onConnFn(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
if atomic.LoadInt32(&mClient.status) == stLost {
|
||||||
|
var n int
|
||||||
|
mClient.subMap.Range(func(_, value interface{}) bool {
|
||||||
|
sub := value.(*subscribed)
|
||||||
|
mClient.Client.Subscribe(sub.topic, sub.qos, sub.callback)
|
||||||
|
n++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
mqtt.DEBUG.Printf("[CONN resubscribe %d topic]", n)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
mClient.Client = mqtt.NewClient(o)
|
||||||
|
|
||||||
|
return mClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) SubscribeMultiple(filters map[string]byte, callback mqtt.MessageHandler) mqtt.Token {
|
||||||
|
token := c.Client.SubscribeMultiple(filters, callback)
|
||||||
|
|
||||||
|
if token.Error() == nil {
|
||||||
|
for topic, qos := range filters {
|
||||||
|
sub := subscribed{
|
||||||
|
topic: topic,
|
||||||
|
qos: qos,
|
||||||
|
callback: callback,
|
||||||
|
}
|
||||||
|
c.subMap.Store(sub.topic, &sub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
func (c *Client) Subscribe(topic string, qos byte, callback mqtt.MessageHandler) mqtt.Token {
|
||||||
|
token := c.Client.Subscribe(topic, qos, callback)
|
||||||
|
|
||||||
|
if token.Error() == nil {
|
||||||
|
sub := subscribed{
|
||||||
|
topic: topic,
|
||||||
|
qos: qos,
|
||||||
|
callback: callback,
|
||||||
|
}
|
||||||
|
c.subMap.Store(sub.topic, &sub)
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Unsubscribe(topics ...string) mqtt.Token {
|
||||||
|
token := c.Client.Unsubscribe(topics...)
|
||||||
|
|
||||||
|
if token.Error() == nil {
|
||||||
|
for _, topic := range topics {
|
||||||
|
c.subMap.Delete(topic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) AddRoute(topic string, callback mqtt.MessageHandler) {
|
||||||
|
c.Client.AddRoute(topic, callback)
|
||||||
|
|
||||||
|
c.subMap.Store(topic, &subscribed{
|
||||||
|
topic: topic,
|
||||||
|
qos: 0,
|
||||||
|
callback: callback,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (c *Client) Disconnect(quiesce uint) {
|
||||||
|
c.Client.Disconnect(quiesce)
|
||||||
|
|
||||||
|
c.subMap.Range(func(key, _ interface{}) bool {
|
||||||
|
c.subMap.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
@@ -17,7 +17,8 @@ func Init(clientIdPrefix, addr string, optFns ...func(opt *mqtt.ClientOptions))
|
|||||||
opts := mqtt.NewClientOptions()
|
opts := mqtt.NewClientOptions()
|
||||||
opts.AddBroker(addr)
|
opts.AddBroker(addr)
|
||||||
opts.SetClientID(clientIdPrefix + "-" + strconv.FormatInt(time.Now().UnixNano(), 36))
|
opts.SetClientID(clientIdPrefix + "-" + strconv.FormatInt(time.Now().UnixNano(), 36))
|
||||||
opts.SetKeepAlive(time.Second * time.Duration(10))
|
opts.SetKeepAlive(10 * time.Second)
|
||||||
|
opts.SetMaxReconnectInterval(10 * time.Second)
|
||||||
|
|
||||||
opts.SetOnConnectHandler(func(client mqtt.Client) {
|
opts.SetOnConnectHandler(func(client mqtt.Client) {
|
||||||
r := client.OptionsReader()
|
r := client.OptionsReader()
|
||||||
@@ -51,12 +52,12 @@ func Init(clientIdPrefix, addr string, optFns ...func(opt *mqtt.ClientOptions))
|
|||||||
fn(opts)
|
fn(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := mqtt.NewClient(opts)
|
client := NewClient(opts)
|
||||||
|
|
||||||
token := client.Connect()
|
if token := client.Connect(); token.WaitTimeout(timeoutDuration) && token.Error() != nil {
|
||||||
if token.WaitTimeout(timeoutDuration) && token.Error() != nil {
|
|
||||||
return nil, token.Error()
|
return nil, token.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user