driver

package
v0.0.0-...-9375491 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2022 License: BSD-3-Clause Imports: 18 Imported by: 0

README

XBOS Go Driver Framework

Simple wrapper around the GRPC WAVEMQ bindings for implementing Drivers. A Driver is a persistent process that handles the reporting+actuation to and from one or more devices

Writing a Driver

The virtual light driver is a minimal functional example of how this framework works

package main

import (
	"github.com/gtfierro/xboswave/driver"
	xbospb "github.com/gtfierro/xboswave/proto"
	"time"
)

// a driver struct embeds the driver.Driver struct which provides the API
type virtual_light struct {
	*driver.Driver
	name       string
	state      bool
	brightness int
}

// The configuration contains common parameters for WAVE/WAVEMQ
func newVirtualLight(name string) *virtual_light {
	// perform any specific initialization here
	return &virtual_light{
		state:      true,
		name:       name,
		brightness: 100,
	}
}

// Implement this: Instantiate the driver.Driver using
// driver.NewDriver(cfg) and insert it into your driver struct
func (vl *virtual_light) Init(cfg driver.Config) error {
	d, err := driver.NewDriver(cfg)
	vl.Driver = d
	return err
}

// Implement this:
// add reporting and actuation functions. Block until an error occurs
func (vl *virtual_light) Start() error {
	// each instance of each service reports at the configured interval (driver.Config)
	// AddReport takes the service name, device instance identifier and callback as args
	err := vl.AddReport("virtual_light", vl.name, func() (*xbospb.XBOSIoTDeviceState, error) {
		// read from device, service, etc
		// form and return the device state as xbospb.XBOSIoTDeviceState
		reading := &xbospb.XBOSIoTDeviceState{
			// use this to communicate any device-level error that occurred during reading
			// Error: &xbospb.Error{
			// 	Msg: "Error message (if any)",
			// },
			Light: &xbospb.Light{
				State:      &xbospb.Bool{Value: vl.state},
				Brightness: &xbospb.Int64{Value: int64(vl.brightness)},
			},
		}
		return reading, nil
	})
	if err != nil {
		return err
	}

	err = vl.AddActuationCallback("virtual_light", vl.name, func(msg *xbospb.XBOSIoTDeviceActuation, received time.Time) error {
		// remember to use 'received' to filter out old actuation messages if you want
		if received.Before(time.Now().Add(-1 * time.Minute)) {
			return nil
		}

		// pull the device configuration out of the actuation message
		if msg == nil || msg.Light == nil {
			return nil
		}
		newconfiguration := msg.Light

		// perform the "backend" actuation you need
		if newconfiguration.State != nil {
			vl.state = newconfiguration.State.Value
		}
		if newconfiguration.Brightness != nil {
			value := newconfiguration.Brightness.Value
			if value > 100 {
				value = 100
			} else if value < 0 {
				value = 0
			}
			vl.brightness = int(value)
		}

		// then report the state of the device after the actuation
		reading := &xbospb.XBOSIoTDeviceState{
			Light: &xbospb.Light{
				State:      &xbospb.Bool{Value: vl.state},
				Brightness: &xbospb.Int64{Value: int64(vl.brightness)},
			},
		}
		return vl.Respond("virtual_light", vl.name, uint64(msg.Requestid), reading)
	})
	if err != nil {
		return err
	}

	// blocks until the driver implementation throws an error talking to WAVEMQ
	return vl.BlockUntilError()
}

func main() {
	cfg, err := driver.ReadConfigFromFile("params.toml")
	if err != nil {
		log.Fatal(err)
	}
	vl1 := newVirtualLight("light1")
	vl2 := newVirtualLight("light2")
	driver.Manage(cfg, vl1, vl2)
	select {}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MakeResource

func MakeResource(namespace, service, instance string) *xbospb.Resource

func Manage

func Manage(cfg Config, drivers ...XBOSDriver) error

func ParseResource

func ParseResource(namespace, uri string) *xbospb.Resource

func ResourceToString

func ResourceToString(res *xbospb.Resource) string

Types

type Config

type Config struct {
	// base64 encoded namespace
	Namespace string
	// path to the entity file for this driver
	EntityFile string
	// local site router address
	SiteRouter string
	// default report rate
	ReportRate time.Duration
	Params     map[string]interface{}
}

Driver configuration struct

func ReadConfigFromEnviron

func ReadConfigFromEnviron() (Config, error)

func ReadConfigFromFile

func ReadConfigFromFile(filename string) (Config, error)

func (Config) GetInt

func (cfg Config) GetInt(key string) int

func (Config) GetString

func (cfg Config) GetString(key string) string

func (Config) GetStringSlice

func (cfg Config) GetStringSlice(key string) []string

type Driver

type Driver struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

A Driver is a persistent process that handles the reporting+actuation to and from one or more devices

func NewDriver

func NewDriver(cfg Config) (*Driver, error)

creates a new driver with the given configuration

func (*Driver) AddActuationCallback

func (driver *Driver) AddActuationCallback(service, instance string, cb func(msg *xbospb.XBOSIoTDeviceActuation, received time.Time) error) error

Call the given function whenever the driver receives an actuation request for a given device

func (*Driver) AddReport

func (driver *Driver) AddReport(service, instance string, cb func() (*xbospb.XBOSIoTDeviceState, error)) error

Call the given function at config.ReportRate and publish the returned device state

func (*Driver) AddToContext

func (driver *Driver) AddToContext(triples []Triple)

add triples to the driver's context. These will be deduped automatically so adding triples is idempotent. This method does *not* report any triples; use ReportContext() to do this.

func (*Driver) BlockUntilError

func (driver *Driver) BlockUntilError() error

func (*Driver) ExitWithError

func (driver *Driver) ExitWithError(err error)

func (*Driver) Report

func (driver *Driver) Report(service, instance string, msg *xbospb.XBOSIoTDeviceState) error

This method is called by device drivers to publish a reading, encapsulated in an XBOSIoTDeviceState message. This is called automatically by AddReport(), which uses a regular timer. Respond() is used when publishing in response to the receipt of an actuation message If a time is not provided in msg, Report will add the current timestamp.

func (*Driver) ReportContext

func (driver *Driver) ReportContext(instance string) error

publishes the driver's device context TODO: where is good URI to publish this?

func (*Driver) Respond

func (driver *Driver) Respond(service, instance string, requestid uint64, msg *xbospb.XBOSIoTDeviceState) error

publishes a device's state in response to a Request

type Triple

type Triple struct {
	Subject   URI
	Predicate URI
	Object    URI
}

type URI

type URI struct {
	Namespace string
	Value     string
}

type XBOSDriver

type XBOSDriver interface {
	Init(Config) error
	Start() error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL