framework

package module
v0.0.0-...-4db19ce Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2019 License: MIT Imports: 9 Imported by: 1

README

All Interfaces: Build Status

Main Interface: Godoc Go Report Card

REST Interface: Godoc Go Report Card

PubSub Interface: Godoc Go Report Card

Description

This is the Golang User, Device, and Service client library for the OpenChirp framework.

Structure

Top level functions

  • User client interfaces are created using framework.StartUserClient()
  • Device client interfaces are created using framework.StartDeviceClient()
  • Service client interfaces are created using framework.StartServiceClient()

The Client class serves as the parent class of all the above client interfaces and should not be directly used. The purpose of the clients are to provide a single uniform interface for all OpenChirp functionality. The client libraries combine the OpenChirp REST and PubSub protocols into a single abstraction.

REST

The pure http rest interface is exposed as the Golang rest package.

PubSub

The pure pubsub(MQTT) interface is exposed as the Golang pubsub package.

Utilities

The utils package holds functions and data structures commonly used across applications interfacing with OpenChirp.

Godoc

Documentation

Overview

Package framework provides the management interfaces for Users, Devices, and Services. Please use the appropriate top level class for the type of interface you need. The parent class is Client.

Users - StartUserClient()
Device - StartDeviceClient()
Service - StartServiceClientManaged()

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrDeviceUpdatesAlreadyStarted = errors.New("Device updates channel already started")
View Source
var ErrDeviceUpdatesNotStarted = errors.New("Device updates channel not started")
View Source
var ErrMarshalDeviceStatusMessage = errors.New("Failed to marshall device status message into JSON")
View Source
var ErrMarshalStatusMessage = errors.New("Failed to marshall status message into JSON")
View Source
var ErrNotImplemented = errors.New("This method is not implemented yet")
View Source
var MQTTBridgeClient = false

MQTTBridgeClient sets whether the MQTT client will identify itself as a bridge to the broker

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents the context for a single client

func (*Client) FetchDeviceInfo

func (c *Client) FetchDeviceInfo(deviceID string) (rest.DeviceNode, error)

FetchDeviceInfo requests and fetches device information from the REST interface

func (*Client) FetchLocation

func (c *Client) FetchLocation(locationID string) (rest.LocationNode, error)

FetchLocation request the information about locationID

func (*Client) FetchLocationDevices

func (c *Client) FetchLocationDevices(locationID string, recursive bool) ([]rest.NodeDescriptor, error)

FetchLocationDevices fetches the node descriptors for devices at locationID. If recursive is true, all devices at sublocation are included.

type ClientTopicHandler

type ClientTopicHandler func(topic string, payload []byte)

ClientTopicHandler is a function prototype for a subscribed topic callback

type Device

type Device interface {
	// ProcessLink is called once, during the initial setup of a
	// device, and is provided the service config for the linking device.
	// The service is expected to parse the provided config for initial setup.
	// The returned string is used as the device's link status.
	ProcessLink(ctrl *DeviceControl) string
	// ProcessUnlink is called once, when the service has been unlinked from
	// the device.
	ProcessUnlink(ctrl *DeviceControl)
	// ProcessConfigChange is called only when the config has truly changed.
	// The specific config key/values which changed are provided in cchange
	// and the original config is provided in coriginal. Upon successful
	// completion of this call, the device's link status will be updated with
	// the returned string.
	//
	// If you do not want to handle incremental config changes, you may return
	// false. In this case, the service manager will restore the original
	// config, call for the device to be unlinked(ProcessUnlinked), clear the
	// device context, and call ProcessLink with the new config.
	// Note that the new config is accessible through ctrl.Config()
	ProcessConfigChange(ctrl *DeviceControl, cchanges, coriginal map[string]string) (string, bool)
	// ProcessMessage is called upon receiving a pubsub message destined for
	// this device. Along with the standard DeviceControl object, the
	// handler is provided a Message object, which contains the received
	// message's payload, subtopic, and the provided Subscribe key.
	ProcessMessage(ctrl *DeviceControl, msg Message)
}

Device is the interface services will implement

type DeviceClient

type DeviceClient struct {
	Client
	// contains filtered or unexported fields
}

DeviceClient represents the context for a single user device session

func StartDeviceClient

func StartDeviceClient(frameworkuri, brokeruri, id, token string) (*DeviceClient, error)

StartDeviceClient starts the device client management layer

func (*DeviceClient) Publish

func (c *DeviceClient) Publish(subtopic string, payload interface{}) error

Publish publishes a payload to a given mqtt topic

func (*DeviceClient) StopClient

func (c *DeviceClient) StopClient()

StopClient shuts down a started device client

func (*DeviceClient) Subscribe

func (c *DeviceClient) Subscribe(subtopic string, callback ClientTopicHandler) error

Subscribe registers a callback for receiving on a device subtopic

func (*DeviceClient) Unsubscribe

func (c *DeviceClient) Unsubscribe(subtopics ...string) error

Unsubscribe deregisters a callback for a given mqtt topics

type DeviceControl

type DeviceControl struct {
	// contains filtered or unexported fields
}

DeviceControl provides a simplified set of methods for controlling a single device. A DeviceContol object is provided within the context of a single device. The key uses are to Subscribe/Publish/Unsubscribe (pubsub methods) to a device's subtopic and to present the device's current Config and Id. Understand that the pubsub methods will automatically prepend device's topic prefix (ex. openchirp/device/<device_id>/) to the specified subtopic.

Additionally, you should note that the Pubsub methods do not return errors and do not ask you to provide message handler functions. This shifts the responsibility of error handling and message passing to the Managed Service client.

func (*DeviceControl) Config

func (c *DeviceControl) Config() map[string]string

Config returns this device's current config

func (*DeviceControl) Id

func (c *DeviceControl) Id() string

Id returns this device's id

func (*DeviceControl) Publish

func (c *DeviceControl) Publish(subtopic string, payload interface{})

Publish publishes payload to this device's subtopic

func (*DeviceControl) Subscribe

func (c *DeviceControl) Subscribe(subtopic string, key interface{})

Subscribe to a device's subtopic and associate with key.

When receiving a message for this subtopic, the Device's ProcessMessage handler will be invoked with the message and the this key. See

func (*DeviceControl) Unsubscribe

func (c *DeviceControl) Unsubscribe(subtopics ...string)

Unsubscribe unsubscribes from the specified device's subtopics

func (*DeviceControl) UnsubscribeAll

func (c *DeviceControl) UnsubscribeAll()

UnsubscribeAll unsubscribes from all of this device's subtopics

type DeviceUpdate

type DeviceUpdate struct {
	Type   DeviceUpdateType
	Id     string
	Topic  string
	Config map[string]string
}

DeviceUpdate represents a pending service config change for a device

func (DeviceUpdate) Error

func (du DeviceUpdate) Error() string

func (DeviceUpdate) String

func (du DeviceUpdate) String() string

String provides a human parsable string for DeviceUpdates

type DeviceUpdateType

type DeviceUpdateType int

DeviceUpdateType represents enumeration of DeviceUpdate types

const (
	// DeviceUpdateAdd indicates that a new device linked in this service
	DeviceUpdateTypeAdd DeviceUpdateType = iota
	// DeviceUpdateRem indicates a device has unlinked this service
	DeviceUpdateTypeRem
	// DeviceUpdateUpd indicates that a device this service's config
	DeviceUpdateTypeUpd
	// DeviceUpdateTypeErr indicates an error was encountered while receiving
	// a device update event. The error message can be fetched from
	// DeviceUpdate.Error()
	DeviceUpdateTypeErr
)

func (DeviceUpdateType) String

func (dut DeviceUpdateType) String() (s string)

String associates a pretty name with the DeviceUpdateTypes

type Message

type Message struct {
	// contains filtered or unexported fields
}

Message holds a received pubsub payload and topic along with the provided subscription key

func (Message) Key

func (t Message) Key() interface{}

Key returns the provided subscription key for this message

func (Message) Payload

func (t Message) Payload() []byte

Payload returns the pubsub payload of this message

func (Message) String

func (t Message) String() string

String shows all parts of the message as a human readable string

func (Message) Topic

func (t Message) Topic() string

Topic returns the pubsub subtopic which received this message

type ServiceClient

type ServiceClient struct {
	Client
	// contains filtered or unexported fields
}

ServiceClient hold a single ses.Publish(s.)rvice context

func StartServiceClient

func StartServiceClient(frameworkURI, brokerURI, id, token string) (*ServiceClient, error)

StartServiceClient starts the service management layer

func StartServiceClientManaged

func StartServiceClientManaged(
	frameworkURI,
	brokerURI,
	id,
	token,
	statusmsg string,
	newdevice func() Device,
) (*ServiceClient, error)

StartServiceClientManaged starts the service client layer using the fully managed mode

Example (Counter)
package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/openchirp/framework"
)

const (
	// The subscription key used to identify a messages types
	rawRxKey = 0
	rawTxKey = 1
)

// CDevice holds any data you want to keep around for a specific
// device that has linked your service.
//
// In this example, we will keep track of the rawrx and rawtx message counts
type CDevice struct {
	rawRxCount int
	rawTxCount int
}

// NewCDevice is called by the framework when a new device has been linked.
func NewCDevice() framework.Device {
	d := new(CDevice)
	// The following initialization is redundant in Go
	d.rawRxCount = 0
	d.rawTxCount = 0
	// Change type to the Device interface
	return framework.Device(d)
}

// ProcessLink is called once, during the initial setup of a
// device, and is provided the service config for the linking device.
func (d *CDevice) ProcessLink(ctrl *framework.DeviceControl) string {
	// Subscribe to subtopic "rawrx"
	ctrl.Subscribe("rawrx", rawRxKey)
	// Subscribe to subtopic "rawtx"
	ctrl.Subscribe("rawtx", rawTxKey)

	// This message is sent to the service status for the linking device
	return "Success"
}

// ProcessUnlink is called once, when the service has been unlinked from
// the device.
func (d *CDevice) ProcessUnlink(ctrl *framework.DeviceControl) {
	// The framework already handles unsubscribing from all
	// Device associted subtopics, so we don't need to call
	// ctrl.Unsubscribe.
}

// ProcessConfigChange is intended to handle a service config updates.
// If your program does not need to handle incremental config changes,
// simply return false, to indicate the config update was unhandled.
// The framework will then automatically issue a ProcessUnlink and then a
// ProcessLink, instead. Note, NewCDevice is not called.
//
// For more information about this or other Device interface functions,
// please see https://godoc.org/github.com/OpenChirp/framework#Device .
func (d *CDevice) ProcessConfigChange(ctrl *framework.DeviceControl, cchanges, coriginal map[string]string) (string, bool) {
	return "", false

	// If we have processed this config change, we should return the
	// new service status message and true.
	//
	//return "Sucessfully updated", true
}

// ProcessMessage is called upon receiving a pubsub message destined for
// this CDevice.
// Along with the standard DeviceControl object, the handler is provided
// a Message object, which contains the received message's payload,
// subtopic, and the provided Subscribe key.
func (d *CDevice) ProcessMessage(ctrl *framework.DeviceControl, msg framework.Message) {

	if msg.Key().(int) == rawRxKey {
		d.rawRxCount++
		subtopic := "rawrxcount"
		ctrl.Publish(subtopic, fmt.Sprint(d.rawRxCount))
	} else if msg.Key().(int) == rawTxKey {
		d.rawTxCount++
		subtopic := "rawtxcount"
		ctrl.Publish(subtopic, fmt.Sprint(d.rawTxCount))
	} else {
		log.Fatalln("Received unassociated message")
	}
}

func main() {
	// Parse parameters from command line or environment variables
	frameworkServer := "http://localhost:7000"
	mqttServer := "localhost:1883"
	serviceId := "5a1ea73df76abe01c57abfb8"
	serviceToken := "DJpHxwmExGbcYwsEHgQezDVeKS4N"

	c, err := framework.StartServiceClientManaged(
		frameworkServer,
		mqttServer,
		serviceId,
		serviceToken,
		"Unexpected disconnect!",
		NewCDevice)
	if err != nil {
		log.Fatalln("Failed to StartServiceClient: ", err)
	}
	defer c.StopClient()
	log.Println("Started service")

	/* Post service's global status */
	err = c.SetStatus("Started")
	if err != nil {
		log.Fatalln("Failed to publish service status: ", err)
		return
	}
	log.Println("Published Service Status")

	/* Setup signal channel */
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt, syscall.SIGTERM)

	/* Wait on a signal */
	<-signals
	log.Println("Shutting down")

	/* Post service's global status */
	err = c.SetStatus("Shutting down")
	if err != nil {
		log.Fatalln("Failed to publish service status: ", err)
		return
	}
	log.Println("Published Service Status")
}
Output:

Example (Minimal)

ExampleStartServiceClientManaged_minimal demonstates the minimal configuration to use StartServiceClientManaged

package main

import (
	"log"

	"github.com/openchirp/framework"
)

type Device struct {
}

func NewDevice() framework.Device {
	d := new(Device)
	return framework.Device(d)
}
func (d *Device) ProcessLink(ctrl *framework.DeviceControl) string {
	return "Success"
}
func (d *Device) ProcessUnlink(ctrl *framework.DeviceControl) {
}
func (d *Device) ProcessConfigChange(ctrl *framework.DeviceControl, cchanges, coriginal map[string]string) (string, bool) {
	return "", false
}
func (d *Device) ProcessMessage(ctrl *framework.DeviceControl, msg framework.Message) {
}

// ExampleStartServiceClientManaged_minimal demonstates the minimal configuration
// to use StartServiceClientManaged
func main() {
	// Parse parameters from command line or environment variables
	frameworkServer := "http://localhost:7000"
	mqttServer := "localhost:1883"
	serviceId := "5a1ea73df76abe01c57abfb8"
	serviceToken := "DJpHxwmExGbcYwsEHgQezDVeKS4N"

	c, err := framework.StartServiceClientManaged(
		frameworkServer,
		mqttServer,
		serviceId,
		serviceToken,
		"Unexpected disconnect!",
		NewDevice)
	if err != nil {
		log.Fatalln("Failed to StartServiceClient: ", err)
	}
	defer c.StopClient()
	log.Println("Started service")

	/* Post service's global status */
	err = c.SetStatus("Started")
	if err != nil {
		log.Fatalln("Failed to publish service status: ", err)
		return
	}
	log.Println("Published Service Status")
}
Output:

func StartServiceClientStatus

func StartServiceClientStatus(frameworkURI, brokerURI, id, token, statusmsg string) (*ServiceClient, error)

StartServiceClientStatus starts the service management layer with a optional statusmsg if the service disconnects improperly

func (*ServiceClient) FetchDeviceConfigs

func (c *ServiceClient) FetchDeviceConfigs() ([]rest.ServiceDeviceListItem, error)

FetchDeviceConfigs requests all device configs for the current service

func (*ServiceClient) FetchDeviceConfigsAsUpdates

func (c *ServiceClient) FetchDeviceConfigsAsUpdates() ([]DeviceUpdate, error)

FetchDeviceConfigsAsUpdates requests all device configs for the current service and converts them into DeviceUpdate with DeviceUpdateTypeAdd as the type

func (*ServiceClient) GetProperties

func (c *ServiceClient) GetProperties() map[string]string

GetProperties returns the full service properties key/value mapping

func (*ServiceClient) GetProperty

func (c *ServiceClient) GetProperty(key string) string

GetProperty fetches the service property associated with key. If it does not exist the blank string is returned.

func (*ServiceClient) Publish

func (c *ServiceClient) Publish(topic string, payload interface{}) error

Publish publishes a payload to a given mqtt topic

func (*ServiceClient) SetDeviceStatus

func (c *ServiceClient) SetDeviceStatus(id string, msgs ...interface{}) error

SetDeviceStatus publishes a device's linked service status message

func (*ServiceClient) SetStatus

func (c *ServiceClient) SetStatus(msgs ...interface{}) error

SetStatus publishes the service status message

func (*ServiceClient) StartDeviceUpdates

func (c *ServiceClient) StartDeviceUpdates() (<-chan DeviceUpdate, error)

StartDeviceUpdates subscribes to the live service events topic and opens a channel to read the updates from. This does not inject the initial configurations into the channel at start like StartDeviceUpdatesSimple.

func (*ServiceClient) StartDeviceUpdatesSimple

func (c *ServiceClient) StartDeviceUpdatesSimple() (<-chan DeviceUpdate, error)

StartDeviceUpdatesSimple subscribes to the live mqtt service news topic and opens a channel to read the updates from. It will automatically fetch the initial configuration and send those as DeviceUpdateTypeAdd updates first. Due to the time between subscribing to live events and requesting the static configuration, there may be redundant DeviceUpdateTypeAdd updates. Your program should account for this.

func (*ServiceClient) StopClient

func (c *ServiceClient) StopClient()

StopClient shuts down a started service

func (*ServiceClient) StopDeviceUpdates

func (c *ServiceClient) StopDeviceUpdates()

StopDeviceUpdates unsubscribes from service news topic and closes the news channel

func (*ServiceClient) Subscribe

func (c *ServiceClient) Subscribe(topic string, callback func(topic string, payload []byte)) error

Subscribe registers a callback for a receiving a given mqtt topic payload

func (*ServiceClient) SubscribeWithClient

func (c *ServiceClient) SubscribeWithClient(topic string, callback ServiceTopicHandler) error

SubscribeWithClient registers a callback for a receiving a given mqtt topic payload and provides the client object

func (*ServiceClient) Unsubscribe

func (c *ServiceClient) Unsubscribe(topics ...string) error

Unsubscribe deregisters a callback for a given mqtt topic

func (*ServiceClient) UpdateConfigParameters

func (c *ServiceClient) UpdateConfigParameters(configParams []rest.ServiceConfigParameter) error

UpdateConfigParameters updates the service's device config template

type ServiceTopicHandler

type ServiceTopicHandler func(client *ServiceClient, topic string, payload []byte)

ServiceTopicHandler is a function prototype for a subscribed topic callback

type UserClient

type UserClient struct {
	Client
}

UserClient represents the context for a single user client session

func StartUserClient

func StartUserClient(frameworkuri, brokeruri, id, token string) (*UserClient, error)

StartUserClient starts the user client management layer

func (*UserClient) Publish

func (c *UserClient) Publish(topic string, payload interface{}) error

Publish publishes a payload to a given mqtt topic

func (*UserClient) StopClient

func (c *UserClient) StopClient()

StopClient shuts down a started user client

func (*UserClient) Subscribe

func (c *UserClient) Subscribe(topic string, callback UserClientTopicHandler) error

Subscribe registers a callback for a receiving a given mqtt topic payload

func (*UserClient) Unsubscribe

func (c *UserClient) Unsubscribe(topics ...string) error

Unsubscribe deregisters a callback for a given mqtt topics

type UserClientTopicHandler

type UserClientTopicHandler func(client *UserClient, topic string, payload []byte)

UserClientTopicHandler is a function prototype for a subscribed topic callback

Directories

Path Synopsis
Package pubsub hold the interfaces and utilities to work with the PubSub side of the OpenChirp framework
Package pubsub hold the interfaces and utilities to work with the PubSub side of the OpenChirp framework
Package rest provides the data structures and primitive mechanisms for representing and communicating framework constructs with the RESTful server.
Package rest provides the data structures and primitive mechanisms for representing and communicating framework constructs with the RESTful server.
Package utils holds common data structures and functions useful for working with OpenChirp.
Package utils holds common data structures and functions useful for working with OpenChirp.

Jump to

Keyboard shortcuts

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