This repository contains the Golang client SDK for Eclipse Ditto.
Currently, Eclipse Hono MQTT is the only one supported transport.
- Installation
- Creating and connecting a client
- Working with features
- Subscribing and handling messages
go get github.com/eclipse/ditto-clients-golang
Each client instance requires a ditto.Configuration object.
config := ditto.NewConfiguration().
WithKeepAlive(30 * time.Second). // default keep alive is 30 seconds
// WithCredentials(&ditto.Credentials{Username: "John", Password: "qwerty"}). if such are available or required
WithBroker("mqtt-host:1883").
WithConnectHandler(connectHandler)
func connectHandler(client ditto.Client) {
// add logic to be executed when the client is connected
}
With this configuration a client instance could be created.
client = ditto.NewClient(config)
NOTE: In some cases an external Paho instance could be provided for the communication. If this is the case, there is a ditto.NewClientMQTT() create function available.
After you have configured and created your client instance, it's ready to be connected.
if err := client.Connect(); err != nil {
panic(fmt.Errorf("cannot connect to broker: %v", err))
}
defer disconnect(client)
Define the feature to be created.
myFeature := &model.Feature{}
myFeature.
WithDefinitionFrom("my.model.namespace:FeatureModel:1.0.0"). // you can provide a semantic definition of your feature
WithProperty("myProperty", "myValue")
Create your Ditto command. Modify acts as an upsert - it either updates or creates features.
command := things.
NewCommand(model.NewNamespacedIDFrom("my.namespace:thing.id")). // specify which thing you will send the command to
Twin().
Feature("MyFeature").
Modify(myFeature) // the payload for the modification - i.e. the feature's JSON representation
Send the Ditto command.
envelope := command.Envelope(protocol.WithResponseRequired(false))
if err := client.Send(envelope); err != nil {
fmt.Printf("could not send Ditto message: %v\n", err)
}
Modify overrides the current feature's property.
command = things.
NewCommand(model.NewNamespacedIDFrom("my.namespace:thing.id")). // specify which thing you will send the command to
Twin().
FeatureProperty("MyFeature", "myProperty").
Modify("myNewValue") // the payload for the modification - i.e. the new property's value JSON representation
Subscribe for incoming Ditto messages.
func connectHandler(client ditto.Client) {
// it's a good practise to subscribe after the client is connected
client.Subscribe(messagesHandler)
}
NOTE: You can add multiple handlers for Ditto messages processing.
It's a good practice to clear all subscriptions on client disconnect.
func disconnect(client ditto.Client) {
// add any resources clearing logic
client.Unsubscribe()
client.Disconnect()
}
NOTE: If no message handler is provided then all would be removed.
Handle and reply to Ditto messages.
func messagesHandler(requestID string, msg *protocol.Envelope) {
if msg.Topic.Namespace == "my.namespace" && msg.Topic.EntityID == "thing.id" &&
msg.Path == "/features/MyFeature/inbox/messages/myCommand" {
// respond to the message by using the outbox
response := things.NewMessage(model.NewNamespacedID(msg.Topic.Namespace, msg.Topic.EntityID)).
Feature("MyFeature").Outbox("myCommand").WithPayload("responsePayload")
responseMsg := response.Envelope(protocol.WithCorrelationID(msg.Headers.CorrelationID()), protocol.WithResponseRequired(false))
responseMsg.Status = 200
if replyErr := client.Reply(requestID, responseMsg); replyErr != nil {
fmt.Printf("failed to send response to request Id %s: %v\n", requestID, replyErr)
}
}
}
A custom logger could be implemented based on ditto.Logger interface. For example:
type logger struct {
prefix string
}
func (l logger) Println(v ...interface{}) {
fmt.Println(l.prefix, fmt.Sprint(v...))
}
func (l logger) Printf(format string, v ...interface{}) {
fmt.Printf(fmt.Sprint(l.prefix, " ", format), v...)
}
Then the Ditto library could be configured to use the logger by assigning the logging endpoints - ERROR, WARN, INFO and DEBUG.
func init() {
ditto.ERROR = logger{prefix: "ERROR "}
ditto.WARN = logger{prefix: "WARN "}
ditto.INFO = logger{prefix: "INFO "}
ditto.DEBUG = logger{prefix: "DEBUG "}
}