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  }