tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/examples/net/mqttclient/natiu/main.go (about) 1 // This example is an MQTT client built with the natiu-mqtt package. It sends 2 // machine.CPUFrequency() readings to the broker every second for 10 seconds. 3 // 4 // Note: It may be necessary to increase the stack size when using 5 // paho.mqtt.golang. Use the -stack-size=4KB command line option. 6 7 //go:build ninafw || wioterminal || challenger_rp2040 8 9 package main 10 11 import ( 12 "context" 13 "errors" 14 "fmt" 15 "io" 16 "log" 17 "machine" 18 "math/rand" 19 "net" 20 "time" 21 22 mqtt "github.com/soypat/natiu-mqtt" 23 "tinygo.org/x/drivers/netlink" 24 "tinygo.org/x/drivers/netlink/probe" 25 ) 26 27 var ( 28 ssid string 29 pass string 30 broker string = "test.mosquitto.org:1883" 31 topic string = "cpu/freq" 32 ) 33 34 func main() { 35 waitSerial() 36 37 link, _ := probe.Probe() 38 39 err := link.NetConnect(&netlink.ConnectParams{ 40 Ssid: ssid, 41 Passphrase: pass, 42 }) 43 if err != nil { 44 log.Fatal(err) 45 } 46 47 clientId := "tinygo-client-" + randomString(10) 48 fmt.Printf("ClientId: %s\n", clientId) 49 50 // Get a transport for MQTT packets 51 fmt.Printf("Connecting to MQTT broker at %s\n", broker) 52 conn, err := net.Dial("tcp", broker) 53 if err != nil { 54 log.Fatal(err) 55 } 56 defer conn.Close() 57 58 // Create new client 59 client := mqtt.NewClient(mqtt.ClientConfig{ 60 Decoder: mqtt.DecoderNoAlloc{make([]byte, 1500)}, 61 OnPub: func(_ mqtt.Header, _ mqtt.VariablesPublish, r io.Reader) error { 62 message, _ := io.ReadAll(r) 63 fmt.Printf("Message %s received on topic %s\n", string(message), topic) 64 return nil 65 }, 66 }) 67 68 // Connect client 69 var varconn mqtt.VariablesConnect 70 varconn.SetDefaultMQTT([]byte(clientId)) 71 ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) 72 err = client.Connect(ctx, conn, &varconn) 73 if err != nil { 74 log.Fatal("failed to connect: ", err) 75 } 76 77 // Subscribe to topic 78 ctx, _ = context.WithTimeout(context.Background(), 10*time.Second) 79 err = client.Subscribe(ctx, mqtt.VariablesSubscribe{ 80 PacketIdentifier: 23, 81 TopicFilters: []mqtt.SubscribeRequest{ 82 {TopicFilter: []byte(topic), QoS: mqtt.QoS0}, 83 }, 84 }) 85 if err != nil { 86 log.Fatal("failed to subscribe to", topic, err) 87 } 88 fmt.Printf("Subscribed to topic %s\n", topic) 89 90 // Publish on topic 91 pubFlags, _ := mqtt.NewPublishFlags(mqtt.QoS0, false, false) 92 pubVar := mqtt.VariablesPublish{ 93 TopicName: []byte(topic), 94 } 95 96 for i := 0; i < 10; i++ { 97 if !client.IsConnected() { 98 log.Fatal("client disconnected: ", client.Err()) 99 } 100 101 freq := float32(machine.CPUFrequency()) / 1000000 102 payload := fmt.Sprintf("%.02fMhz", freq) 103 104 pubVar.PacketIdentifier++ 105 err = client.PublishPayload(pubFlags, pubVar, []byte(payload)) 106 if err != nil { 107 log.Fatal("error transmitting message: ", err) 108 } 109 110 time.Sleep(time.Second) 111 112 conn.SetReadDeadline(time.Now().Add(10 * time.Second)) 113 err = client.HandleNext() 114 if err != nil { 115 log.Fatal("handle next: ", err) 116 } 117 118 } 119 120 client.Disconnect(errors.New("disconnected gracefully")) 121 122 for { 123 select {} 124 } 125 } 126 127 // Returns an int >= min, < max 128 func randomInt(min, max int) int { 129 return min + rand.Intn(max-min) 130 } 131 132 // Generate a random string of A-Z chars with len = l 133 func randomString(len int) string { 134 bytes := make([]byte, len) 135 for i := 0; i < len; i++ { 136 bytes[i] = byte(randomInt(65, 90)) 137 } 138 return string(bytes) 139 } 140 141 // Wait for user to open serial console 142 func waitSerial() { 143 for !machine.Serial.DTR() { 144 time.Sleep(100 * time.Millisecond) 145 } 146 }