Docs / Contact / sdks/go/examples

Go SDK: Examples

Practical examples for common use cases with the Tendrl Go SDK.

Periodic Data Collection with Tether

The Tether method calls a function on a schedule and publishes its return value:

go

// Collect and publish system metrics every 30 seconds
stop := client.Tether("system-metrics", func() (interface{}, error) {
    return map[string]interface{}{
        "cpu_usage":  getCPUUsage(),
        "mem_usage":  getMemUsage(),
        "goroutines": runtime.NumGoroutine(),
    }, nil
}, []string{"system", "metrics"}, 30*time.Second)

// Stop when done
defer stop()

Return an error to skip publishing that cycle without stopping the tether:

go

stop := client.Tether("sensor", func() (interface{}, error) {
    value, err := readSensor()
    if err != nil {
        return nil, err // Skips this cycle, tries again next interval
    }
    return map[string]interface{}{"value": value}, nil
}, []string{"sensor"}, 5*time.Second)

Synchronous Publish with Response

Wait for the server to acknowledge a message:

go

messageID, err := client.Publish(
    map[string]interface{}{
        "action":  "provision",
        "device":  "sensor-042",
    },
    []string{"provisioning"},
    "",    // entity (empty = self)
    true,  // waitResponse
    10,    // timeout seconds
)
if err != nil {
    log.Printf("Failed: %v", err)
} else {
    log.Printf("Confirmed: %s", messageID)
}

Inbound Message Routing

Route incoming messages by tag with client.On():

go

client.On(tendrl.MessageRoute{
    Tag: "diagnostic",
    Handler: func(msg tendrl.IncomingMessage) error {
        log.Println("Diagnostic:", msg.Data)
        return nil
    },
})

client.On(tendrl.MessageRoute{
    Tag: "ai-response",
    Handler: func(msg tendrl.IncomingMessage) error {
        log.Println("AI:", msg.Data)
        return nil
    },
})

client.On(tendrl.MessageRoute{
    Tags: []string{"alert", "anomaly"},
    Handler: func(msg tendrl.IncomingMessage) error {
        log.Println("Alert:", msg.Data)
        return nil
    },
})
client.SetMessageCheckRate(2 * time.Second)
client.SetMessageCheckLimit(10)

Cross-Account Messaging

Send messages to entities in other accounts:

go

err := client.PublishCrossAccount(
    map[string]interface{}{
        "command": "status_request",
    },
    "account123:us-west:entity:device-001",
    []string{"query"},
)

State Table Management

Persist device state that survives restarts:

go

// Read current state
state, err := client.GetState()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Current state: %v\n", state)

// Merge new data (PATCH; existing keys preserved)
err = client.UpdateState(map[string]interface{}{
    "firmware":  "2.1.0",
    "last_boot": time.Now().Format(time.RFC3339),
}, nil)

// Merge with tags to trigger flows
err = client.UpdateState(map[string]interface{}{
    "status": "active",
}, []string{"device", "status-change"})

// Replace entire state (PUT; removes all previous keys)
err = client.ReplaceState(map[string]interface{}{
    "firmware": "2.1.0",
    "status":   "active",
}, nil)

Connectivity Monitoring

Check network status and react to changes:

go

if client.IsOnline() {
    // Send queued data
    client.PublishAsync(data, tags)
} else {
    log.Println("Offline; message will be stored")
}

// Get detailed connectivity state
connState := client.GetConnectivityState()
fmt.Printf("Online: %v, Last check: %s\n",
    connState.Online, connState.LastCheck)

Flexible Data Types

The SDK accepts any JSON-serializable type:

go

// Maps
client.PublishAsync(map[string]interface{}{"key": "value"}, tags)

// Structs
type SensorReading struct {
    ID    string  `json:"id"`
    Value float64 `json:"value"`
    Unit  string  `json:"unit"`
}
client.PublishAsync(SensorReading{
    ID: "temp-1", Value: 23.5, Unit: "celsius",
}, tags)

// Slices
client.PublishAsync([]int{1, 2, 3}, tags)

// Strings (auto-wrapped as {"data": "..."})
client.PublishAsync("simple message", tags)

// Primitives
client.PublishAsync(42, tags)
client.PublishAsync(3.14, tags)
client.PublishAsync(true, tags)

Custom Heartbeat

Send a manual heartbeat with specific metrics:

go

err := client.PublishHeartbeat(tendrl.HeartbeatData{
    MemFree:  getMemFree(),
    MemTotal: getMemTotal(),
    DiskFree: getDiskFree(),
    DiskSize: getDiskTotal(),
})