# README
Eclipse hawkBit™ - Client library for Golang
This repository contains the Golang implementation of hawkBit SoftwareUpdatable feature.
The Eclipse Ditto Client for Golang is used for communication.
Table of Contents
- Installation
- Creating and activating a software updatable feature
- Working with software updatable feature
- Logging
Installation
go get github.com/eclipse/hawkbit-clients-golang
Creating and activating a software updatable feature
Each software updatable feature instance requires a ditto.Client and hawkbit.Configuration.
var su *hawkbit.SoftwareUpdatable
// Activate the SoftwareUpdatable feature after Ditto Client is connected.
configDitto := ditto.NewConfiguration().
WithBroker("mqtt-host:1883").
WithConnectHandler(func(dittoClient *ditto.Client) {
if err := su.Activate(); err != nil {
panic(fmt.Errorf("cannot activate software updatable feature: %v", err))
}
})
// Create new Ditto Client instance.
dittoClient := ditto.NewClient(configDitto)
// Create hawkBit SoftwareUpdatable feature configuration.
config := hawkbit.NewConfiguration().
WithDittoClient(dittoClient).
WithThingID(model.NewNamespacedIDFrom("my.namespace:thing.id")).
WithSoftwareType("my-type").
WithInstallHandler(installHandler)
// Create new hawkBit SoftwareUpdatable instance.
su, err = hawkbit.NewSoftwareUpdatable(config)
if err != nil {
panic(fmt.Errorf("failed to create software updatable: %v", err))
}
NOTE: All feature propertires can be modified before the feature activation. This will change the initial feature property values.
After you have configured and created software updatable instance, the Ditto client is ready to be connected.
if err := dittoClient.Connect(); err != nil {
panic(fmt.Errorf("cannot connect to broker: %v", err))
}
It's a good practice to deactivate the feature on client disconnect.
su.Deactivate()
dittoClient.Disconnect()
Working with software updatable feature
Update installed and context dependencies
// Create new DependencyDescription.
dependency := &hawkbit.DependencyDescription{Group: "My Group", Name: "App #1", Version: "1.0.0", Type: "my-type"}
// Update installed dependencies property.
if err := su.SetInstalledDependencies(dependency); err != nil {
fmt.Println(fmt.Errorf("could not update installed dependencies property: %v", err))
}
// Update context dependencies property.
if err := su.SetContextDependencies(dependency); err != nil {
fmt.Println(fmt.Errorf("could not update context dependencies property: %v", err))
}
Handle install operation
func installHandler(update *hawkbit.SoftwareUpdateAction, su *hawkbit.SoftwareUpdatable) {
// Install provided software modules.
for _, module := range update.SoftwareModules {
status := hawkbit.NewOperationStatusUpdate(update.CorrelationID, hawkbit.StatusStarted, module.SoftwareModule).
WithProgress(0).WithMessage("install operation just started")
if err := su.SetLastOperation(status); err != nil {
fmt.Println(fmt.Errorf("could not update the last operation: %v", err))
}
// Do the installation here.
}
// Finally update the installed dependencies.
}
NOTE: The last failed operation will be updated automatically, if needed.
Logging
Various levels of logs are provided by assigning the logging endpoints, ERROR, WARN, INFO and DEBUG. For example:
type LogLevel int
const (
ERROR LogLevel = 1 + iota
WARN
INFO
DEBUG
)
var level = INFO
func init() {
hawkbit.ERROR = &wrapper{level: ERROR, prefix: "ERROR "}
hawkbit.WARN = &wrapper{level: WARN, prefix: "WARN "}
hawkbit.INFO = &wrapper{level: INFO, prefix: "INFO "}
hawkbit.DEBUG = &wrapper{level: DEBUG, prefix: "DEBUG "}
}
type wrapper struct {
level LogLevel
prefix string
}
func (w *wrapper) Println(v ...interface{}) {
if level >= w.level {
fmt.Println(w.prefix, fmt.Sprint(v...))
}
}
func (w *wrapper) Printf(format string, v ...interface{}) {
if level >= w.level {
fmt.Printf(fmt.Sprint(w.prefix, " ", format), v...)
}
}