mqtt_client.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package mqttclient
  2. import (
  3. "crypto/tls"
  4. "errors"
  5. "fmt"
  6. mqtt "github.com/eclipse/paho.mqtt.golang"
  7. "log"
  8. "time"
  9. )
  10. // MqttConnectConfig 连接的相关配置
  11. type MqttConnectConfig struct {
  12. Broker string
  13. User string
  14. Password string
  15. Certificate string //证书文件
  16. PrivateKey string //秘钥
  17. ClientId string
  18. WillEnabled bool //遗愿
  19. WillTopic string //遗愿主题
  20. WillPayload string //遗愿消息
  21. WillQos byte //遗愿服务质量
  22. Qos byte //服务质量
  23. Retained bool //保留消息
  24. OnConnect mqtt.OnConnectHandler
  25. OnConnectionLost mqtt.ConnectionLostHandler
  26. }
  27. // MqttClient MQTT客户端,此外也包含了几个参数
  28. type MqttClient struct {
  29. qos byte
  30. retained bool
  31. Client mqtt.Client
  32. topics map[string]mqtt.MessageHandler
  33. }
  34. // 新建证书,也可以不用
  35. func newTLSConfig(certFile string, privateKey string) (*tls.Config, error) {
  36. cert, err := tls.LoadX509KeyPair(certFile, privateKey)
  37. if err != nil {
  38. return nil, err
  39. }
  40. return &tls.Config{
  41. ClientAuth: tls.NoClientCert, //不需要证书
  42. ClientCAs: nil, //不验证证书
  43. InsecureSkipVerify: true, //接受服务器提供的任何证书和该证书中的任何主机名
  44. Certificates: []tls.Certificate{cert},
  45. }, nil
  46. }
  47. func NewMqttClient(config MqttConnectConfig) *MqttClient {
  48. var c MqttClient
  49. opts := mqtt.NewClientOptions().AddBroker(config.Broker).SetClientID(config.ClientId).SetMaxReconnectInterval(time.Second * 5)
  50. if config.WillEnabled {
  51. opts.SetWill(config.WillTopic, config.WillPayload, config.WillQos, config.Retained)
  52. }
  53. //判断是否设置证书
  54. if config.Certificate != "" {
  55. tlsConfig, err := newTLSConfig(config.Certificate, config.PrivateKey)
  56. if err != nil {
  57. log.Panic(err)
  58. return nil
  59. }
  60. opts.SetTLSConfig(tlsConfig)
  61. } else {
  62. opts.SetUsername(config.User).SetPassword(config.Password)
  63. }
  64. //初始化
  65. if config.OnConnect == nil {
  66. config.OnConnect = func(c mqtt.Client) {}
  67. }
  68. if config.OnConnectionLost == nil {
  69. config.OnConnectionLost = func(c mqtt.Client, err error) {}
  70. }
  71. opts.SetOnConnectHandler(c.connectHandler(config.OnConnect)).SetConnectionLostHandler(c.onConnectionLostHandler(config.OnConnectionLost))
  72. c.Client = mqtt.NewClient(opts)
  73. c.qos = config.Qos // qos的级别
  74. c.retained = config.Retained // 保留消息
  75. c.topics = make(map[string]mqtt.MessageHandler) //topic
  76. // 用token的状态判断
  77. if tc := c.Client.Connect(); tc.Wait() && tc.Error() != nil {
  78. log.Panic(tc.Error())
  79. return nil
  80. }
  81. return &c
  82. }
  83. // Publish Mqtt message.
  84. func (mc *MqttClient) Publish(topic string, payload []byte) error {
  85. if mc != nil && mc.Client.IsConnected() {
  86. if tc := mc.Client.Publish(topic, mc.qos, mc.retained, payload); tc.Wait() && tc.Error() != nil {
  87. return tc.Error()
  88. }
  89. return nil
  90. }
  91. return errors.New("mqttClient is nil or disconnected")
  92. }
  93. // Subscribe subscribe a Mqtt topic.
  94. func (mc *MqttClient) Subscribe(topics []string, onMessage mqtt.MessageHandler) error {
  95. for _, topic := range topics {
  96. if tc := mc.Client.Subscribe(topic, mc.qos, onMessage); tc.Wait() && tc.Error() != nil {
  97. return tc.Error()
  98. }
  99. mc.topics[topic] = onMessage
  100. log.Println(fmt.Sprintf("订阅主题[%s]成功", topic))
  101. }
  102. return nil
  103. }
  104. // Unsubscribe unsubscribe a Mqtt topic.
  105. func (mc *MqttClient) Unsubscribe(topics ...string) error {
  106. if tc := mc.Client.Unsubscribe(topics...); tc.Wait() && tc.Error() != nil {
  107. return tc.Error()
  108. }
  109. for _, topic := range topics {
  110. delete(mc.topics, topic)
  111. }
  112. return nil
  113. }
  114. func (mc *MqttClient) Close() {
  115. mc.Client.Disconnect(250) //Millisecond
  116. }
  117. func (mc *MqttClient) connectHandler(handler mqtt.OnConnectHandler) mqtt.OnConnectHandler {
  118. return func(c mqtt.Client) {
  119. for topic, onMessage := range mc.topics {
  120. mc.Client.Subscribe(topic, mc.qos, onMessage)
  121. }
  122. handler(c)
  123. }
  124. }
  125. func (mc *MqttClient) onConnectionLostHandler(handler mqtt.ConnectionLostHandler) mqtt.ConnectionLostHandler {
  126. return func(c mqtt.Client, e error) {
  127. handler(c, e)
  128. }
  129. }