Working example
Getting available updates
Use the provided class to enumerate the available update bundles.
client := grpc.NewUpdateClient()
if err := client.Connect(); err != nil {
tools.LogMessage("Error: '%s'", err)
os.Exit(1)
}
if err := client.GetAvailableUpdateBundles(*checkUrlParam); err != nil {
tools.LogMessage("Error: '%s'", err)
os.Exit(1)
}
How to install an update bundle
Use one of the returned update bundle URLs to install the according bundle like this:
client := grpc.NewUpdateClient()
if err := client.Connect(); err != nil {
tools.LogMessage("Error: '%s'", err)
os.Exit(1)
}
if err := client.InstallUpdateBundle(*installUrlParam); err != nil {
tools.LogMessage("Error: '%s'", err)
os.Exit(1)
}
os.Exit(1)
Retrieving device information
The built-in updater, that is started when no user application has been installed, uses this information to open the Display and install an update from the given source without user intervention.
fmt.Println("Getting client information...")
result, _ := uc.updateService.GetClientInformation(uc.mainCtx, &swupdatesvc.Empty{})
fmt.Printf("Product: '%s'\n", result.Product)
fmt.Printf("Customer: '%s'\n", result.Customer)
fmt.Printf("Source: '%s'\n", result.Source)
fmt.Printf("Bootstrap: '%s'\n", result.BootStrap)
fmt.Printf("TmpDir: '%s'\n", result.TmpDir)
for k, v := range result.Infos {
fmt.Printf("Info: '%s' '%s'\n", k, v)
}
Information about the installed bundle
You can retrieve information from the manifest file that has been installed together with the update bundle, that is currently executed on the device.
fmt.Println("Getting installed bundle information...")
result, _ := uc.updateService.GetInstalledBundleInformation(uc.mainCtx, &swupdatesvc.Empty{})
for k, v := range result.ComponentVersions {
fmt.Printf("Component: '%s' Version '%s'\n", k, v)
}
for k, v := range result.UserInformation {
fmt.Printf("User-Key: '%s' Value '%s'\n", k, v)
}
Communication class
package grpc
import (
"context"
"fmt"
"io"
"net"
"github.com/idastroem/swupdatesvc"
grpc "google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type UpdateClient struct {
rootCtx context.Context
mainCtx context.Context
mainCxl context.CancelFunc
updateConnection *grpc.ClientConn
updateService swupdatesvc.UpdaterClient
}
func NewUpdateClient() *UpdateClient {
return &UpdateClient{}
}
func (uc *UpdateClient) Connect() error {
fmt.Print("connecting to update service... ")
// connect to update service
uc.rootCtx = context.Background()
uc.mainCtx, uc.mainCxl = context.WithCancel(uc.rootCtx)
var (
credentials = insecure.NewCredentials() // No SSL/TLS
dialer = func(ctx context.Context, addr string) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, protocol, addr)
}
options = []grpc.DialOption{
grpc.WithTransportCredentials(credentials),
grpc.WithBlock(),
grpc.WithContextDialer(dialer),
}
)
var err error
uc.updateConnection, err = grpc.Dial(sockAddr, options...)
if err != nil {
panic(err)
}
uc.updateService = swupdatesvc.NewUpdaterClient(uc.updateConnection)
fmt.Println("OK")
return nil
}
func (uc *UpdateClient) GetAvailableUpdateBundles(url string) error {
result, _ := uc.updateService.GetAvailableUpdateBundles(uc.mainCtx, &swupdatesvc.GetAvailableUpdateBundlesRequest{
UpdateUrl: url,
})
if result.IsError {
return fmt.Errorf("error: '%s'", result.Message)
}
fmt.Printf("Engine Version: %+v\n", result.EngineVersion)
fmt.Printf("Installed Bundle Version: %+v\n", result.CurrentVersion)
for k, v := range result.InstalledComponents {
fmt.Printf("Installed Component: '%s' Version '%s'\n", k, v)
}
for _, v := range result.AvailableBundles {
fmt.Printf("Available Bundle: %+v\n", v)
}
return nil
}
func (uc *UpdateClient) InstallUpdateBundle(bundleUrl string) error {
stream, _ := uc.updateService.InstallUpdateBundle(uc.mainCtx, &swupdatesvc.InstallUpdateBundleRequest{
BundleUrl: bundleUrl,
})
fmt.Println("Starting update...")
fmt.Println()
for {
resp, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
return err
}
if resp != nil {
if resp.Messsage != "" {
fmt.Println(resp.Messsage)
}
if resp.IsError || resp.IsDone {
fmt.Println()
if resp.IsError {
fmt.Println("Update failed.")
return fmt.Errorf("error: '%s'", resp.Messsage)
}
if resp.IsDone {
fmt.Println("Update successful.")
}
break
} else {
fmt.Printf("\rProgress: %d", int(100*resp.Progress))
}
}
}
return nil
}
func (uc *UpdateClient) GetClientInformation() error {
fmt.Println("Getting client information...")
result, _ := uc.updateService.GetClientInformation(uc.mainCtx, &swupdatesvc.Empty{})
fmt.Printf("Product: '%s'\n", result.Product)
fmt.Printf("Customer: '%s'\n", result.Customer)
fmt.Printf("Source: '%s'\n", result.Source)
fmt.Printf("Bootstrap: '%s'\n", result.BootStrap)
fmt.Printf("TmpDir: '%s'\n", result.TmpDir)
for k, v := range result.Infos {
fmt.Printf("Info: '%s' '%s'\n", k, v)
}
return nil
}
func (uc *UpdateClient) GetInstalledBundleInformation() error {
fmt.Println("Getting installed bundle information...")
result, _ := uc.updateService.GetInstalledBundleInformation(uc.mainCtx, &swupdatesvc.Empty{})
for k, v := range result.ComponentVersions {
fmt.Printf("Component: '%s' Version '%s'\n", k, v)
}
for k, v := range result.UserInformation {
fmt.Printf("User-Key: '%s' Value '%s'\n", k, v)
}
return nil
}