github.com/gkstretton/dark/services/goo@v0.0.0-20231114224855-2d1a2074d446/mqtt/mqtt.go (about) 1 package mqtt 2 3 import ( 4 "flag" 5 "fmt" 6 "sync" 7 "time" 8 9 paho "github.com/eclipse/paho.mqtt.golang" 10 ) 11 12 var ( 13 host = flag.String("host", "DEPTH", "the hostname of the mqtt broker") 14 ) 15 16 const QOS = 1 17 18 var client paho.Client 19 20 type Callback func(topic string, payload []byte) 21 type subscriptions map[string][]Callback 22 23 var lock = &sync.Mutex{} 24 25 var subs = subscriptions{} 26 27 const timeout = time.Millisecond * time.Duration(250) 28 29 func Start() { 30 _ = paho.CRITICAL 31 client = paho.NewClient(paho.NewClientOptions(). 32 AddBroker(fmt.Sprintf("%s:1883", *host)). 33 SetOnConnectHandler(on_connect). 34 SetAutoReconnect(true). 35 SetConnectionLostHandler(on_disconnect), 36 ) 37 token := client.Connect() 38 if !token.WaitTimeout(time.Second * time.Duration(2)) { 39 panic("mqtt client connect timed out") 40 } 41 if token.Error() != nil { 42 panic(token.Error()) 43 } 44 45 client.AddRoute("#", on_message) 46 } 47 48 func on_message(client paho.Client, msg paho.Message) { 49 // fmt.Printf("Received mqtt message on '%s': %v\n", msg.Topic(), string(msg.Payload())) 50 } 51 52 func on_disconnect(client paho.Client, err error) { 53 fmt.Printf("Disconnected from broker: %v\n", err) 54 } 55 56 func on_connect(client paho.Client) { 57 lock.Lock() 58 defer lock.Unlock() 59 for topic, cbs := range subs { 60 for _, cb := range cbs { 61 fmt.Printf("subscribing to %s\n", topic) 62 t := client.Subscribe(topic, QOS, func(c paho.Client, m paho.Message) { 63 cb(m.Topic(), m.Payload()) 64 }) 65 if !t.WaitTimeout(timeout) { 66 fmt.Printf("subscribe to %s timed out\n", topic) 67 } 68 if t.Error() != nil { 69 fmt.Printf("error subscribing to %s: %v", topic, t.Error()) 70 } 71 } 72 } 73 fmt.Println("Connected to broker") 74 } 75 76 func Publish(topic string, payload interface{}) error { 77 if client == nil { 78 return fmt.Errorf("mqtt client not initialised") 79 } 80 token := client.Publish(topic, QOS, false, payload) 81 if !token.WaitTimeout(timeout) { 82 return fmt.Errorf("publish to %s timed out", topic) 83 } 84 if token.Error() != nil { 85 return fmt.Errorf("error publishing to %s: %v", topic, token.Error()) 86 } 87 return nil 88 } 89 90 func Subscribe(topic string, cb Callback) { 91 lock.Lock() 92 defer lock.Unlock() 93 if client == nil { 94 fmt.Println("mqtt client not initialised") 95 } 96 subs[topic] = append(subs[topic], cb) 97 if client != nil && client.IsConnectionOpen() { 98 client.Subscribe(topic, QOS, func(c paho.Client, m paho.Message) { 99 cb(m.Topic(), m.Payload()) 100 }) 101 } 102 } 103 104 func Unsubscribe(topic string) { 105 lock.Lock() 106 defer lock.Unlock() 107 delete(subs, topic) 108 }