Skip to content

Instantly share code, notes, and snippets.

@vyamkovyi
Last active April 2, 2024 20:57
Show Gist options
  • Save vyamkovyi/bc14937fd099bd808290f86e200dd800 to your computer and use it in GitHub Desktop.
Save vyamkovyi/bc14937fd099bd808290f86e200dd800 to your computer and use it in GitHub Desktop.
Simple MQTT client application.
// mqttc.go - Simple MQTT client application for testing purposes.
// Copyright (c) 2019 Hexawolf
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package main
import (
"fmt"
"os"
"os/signal"
"flag"
"math/rand"
"time"
"github.com/eclipse/paho.mqtt.golang"
)
const PUB_COMM = "pub"
const SUB_COMM = "sub"
var Data struct {
Broker string
Topic string
Message string
ClientID string
}
var Client mqtt.Client
func printGeneralUsage() {
fmt.Println("Usage:")
fmt.Printf("\t%v <pub|sub> [flags...]\n", os.Args[0])
fmt.Println("Add -h flag to see help for each subcommand.")
}
func main() {
fmt.Println("mqttc.go - Simple MQTT client application for testing purposes.")
fmt.Println("Copyright (c) 2019 Hexawolf (https://hexawolf.dev/)")
if len(os.Args) < 2 {
printGeneralUsage()
return
}
switch os.Args[1] {
case PUB_COMM:
// Publish and exit
pub()
Client.Disconnect(1000)
case SUB_COMM:
sub()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
fmt.Println()
fmt.Println("Signal caught, exiting!")
Client.Disconnect(1000)
default:
printGeneralUsage()
}
}
// genFlagSet generates a flag set for given subcommand name with common
// flags included.
func genFlagSet(name string) *flag.FlagSet {
fset := flag.NewFlagSet(name, flag.ContinueOnError)
fset.StringVar(&Data.Broker, "b", "tcp://localhost:1883", "Broker URI")
fset.StringVar(&Data.Topic, "t", "/test", "Topic name")
fset.StringVar(&Data.ClientID, "c", "random", "Client ID")
return fset
}
// initClient initializes MQTT client in Client variable.
func initClient() {
opts := mqtt.NewClientOptions()
opts.AddBroker(Data.Broker)
if Data.ClientID == "random" {
source := rand.NewSource(time.Now().UnixNano())
random := rand.New(source)
Data.ClientID = fmt.Sprintf("mqttc.go-%d", random.Intn(99999)+1)
fmt.Println("Using ClientID", Data.ClientID)
}
opts.SetClientID(Data.ClientID)
opts.SetDefaultPublishHandler(func(client mqtt.Client, msg mqtt.Message) {
// BUG: not always executed in pub mode.
fmt.Println(string(msg.Payload()))
})
opts.SetOnConnectHandler(func(c mqtt.Client) {
if token := c.Subscribe(Data.Topic, 0, nil); token.Wait() && token.Error() != nil {
panic(token.Error())
}
})
Client = mqtt.NewClient(opts)
if token := Client.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
} else {
fmt.Println("Connected to broker")
}
}
func pub() {
fset := genFlagSet(PUB_COMM)
fset.StringVar(&Data.Message, "m", "Test message.", "Message to publish")
if len(os.Args) < 3 {
fmt.Println("Tip: use -h to view available flags; using defaults")
}
err := fset.Parse(os.Args[2:])
if err != nil {
return
}
initClient()
if token := Client.Publish(Data.Topic, 0, false, Data.Message); token.Wait() && token.Error() != nil {
panic(token.Error())
} else {
fmt.Println("Published")
}
}
func sub() {
fset := genFlagSet(SUB_COMM)
if len(os.Args) < 3 {
fmt.Println("Tip: use -h to view available flags; using defaults")
}
err := fset.Parse(os.Args[2:])
if err != nil {
return
}
initClient()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment