mqttclient.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "time"
  7. "github.com/sirupsen/logrus"
  8. "lc/common/mqtt"
  9. )
  10. type BaseMqttOnline interface {
  11. GetOnlineMsg() (string, string)
  12. GetWillMsg() (string, string)
  13. }
  14. type EmptyMqttOnline struct {
  15. }
  16. func (o *EmptyMqttOnline) GetOnlineMsg() (string, string) {
  17. return "", ""
  18. }
  19. func (o *EmptyMqttOnline) GetWillMsg() (string, string) {
  20. return "", ""
  21. }
  22. type MqttClient struct {
  23. mqtt *mqtt.Client //
  24. mu sync.Mutex //保护mapTopics
  25. mapTopics map[string]mqtt.QOS //订阅的主题
  26. timeout uint //超时时间,毫秒为单位
  27. MqttOnline BaseMqttOnline //是否发布上线消息&遗嘱消息
  28. }
  29. func NewMqttClient(server, clientid, user, password string, timeout uint, mqttOnline BaseMqttOnline) *MqttClient {
  30. o := MqttClient{
  31. mapTopics: make(map[string]mqtt.QOS),
  32. timeout: timeout,
  33. MqttOnline: mqttOnline,
  34. }
  35. client, err := mqtt.NewClient(mqtt.ClientOptions{
  36. Servers: []string{server},
  37. ClientID: clientid,
  38. Username: user,
  39. Password: password,
  40. AutoReconnect: true,
  41. }, &o)
  42. if err != nil {
  43. panic(fmt.Sprintln("MQTT错误:", err.Error()))
  44. return nil
  45. }
  46. o.mqtt = client
  47. ctx, cancel := o.Ctx()
  48. defer cancel()
  49. err = client.Connect(ctx)
  50. return &o
  51. }
  52. func (o *MqttClient) ConnectionLostHandler(err error) {
  53. logrus.Errorln("MqttClient.ConnectionLostHandler:MQTT连接已经断开,原因:", err)
  54. }
  55. func (o *MqttClient) OnConnectHandler() {
  56. logrus.Infoln("MqttClient.OnConnectHandler:MQTT连接成功")
  57. //连接成功则订阅主题
  58. for k, v := range o.mapTopics {
  59. o.Subscribe(k, v)
  60. }
  61. topic, str := o.MqttOnline.GetOnlineMsg()
  62. if topic != "" {
  63. o.PublishString(topic, str, 0)
  64. }
  65. }
  66. func (o *MqttClient) GetWill() (topic string, payload string) {
  67. return o.MqttOnline.GetWillMsg()
  68. }
  69. func (o *MqttClient) Connect() error {
  70. if !o.mqtt.IsConnected() {
  71. ctx, cancel := o.Ctx()
  72. defer cancel()
  73. return o.mqtt.Connect(ctx)
  74. }
  75. return nil
  76. }
  77. func (o *MqttClient) IsConnected() bool {
  78. return o.mqtt.IsConnected()
  79. }
  80. func (o *MqttClient) Publish(topic string, payload []byte, qos mqtt.QOS) error {
  81. ctx, cancel := o.Ctx()
  82. defer cancel()
  83. return o.mqtt.Publish(ctx, topic, payload, qos)
  84. }
  85. func (o *MqttClient) PublishString(topic string, payload string, qos mqtt.QOS) error {
  86. ctx, cancel := o.Ctx()
  87. defer cancel()
  88. return o.mqtt.PublishString(ctx, topic, payload, qos)
  89. }
  90. func (o *MqttClient) PublishJSON(topic string, payload interface{}, qos mqtt.QOS) error {
  91. ctx, cancel := o.Ctx()
  92. defer cancel()
  93. return o.mqtt.PublishJSON(ctx, topic, payload, qos)
  94. }
  95. func (o *MqttClient) Subscribe(topic string, qos mqtt.QOS) error {
  96. o.mu.Lock()
  97. defer o.mu.Unlock()
  98. if _, ok := o.mapTopics[topic]; !ok {
  99. o.mapTopics[topic] = qos
  100. }
  101. ctx, cancel := o.Ctx()
  102. defer cancel()
  103. return o.mqtt.Subscribe(ctx, topic, qos)
  104. }
  105. func (o *MqttClient) Unsubscribe(topic string) error {
  106. o.mu.Lock()
  107. defer o.mu.Unlock()
  108. if _, ok := o.mapTopics[topic]; ok {
  109. delete(o.mapTopics, topic)
  110. }
  111. ctx, cancel := o.Ctx()
  112. defer cancel()
  113. return o.mqtt.Unsubscribe(ctx, topic)
  114. }
  115. func (o *MqttClient) Handle(topic string, handler mqtt.MessageHandler) mqtt.Route {
  116. return o.mqtt.Handle(topic, handler)
  117. }
  118. func (o *MqttClient) Ctx() (context.Context, context.CancelFunc) {
  119. return context.WithTimeout(context.Background(), time.Millisecond*time.Duration(o.timeout))
  120. }