igor

package module
v0.0.0-...-56d3bd1 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2020 License: MIT Imports: 9 Imported by: 0

README

Igor Home Automation

Plug and play home automation solution. If a node fails just plug in another one and the system should continue with little to no disruption.

This is achieved through a combination of lansrv and nats-server. When a node starts up, nats-server uses lansrv to find all of the other active nodes on the LAN and join the cluster (or start their own if there are no available nodes). Events are published to the local nats-server, reducers written in Javascript calculate the new state and publish the resulting delta, and finally devices with plugins to control devices subscribe to the resulting state updates.

Architecture

Home automation turns your home into one big user interface. The flux architecture is the best I've seen for managing stateful systems like this and Igor seeks to apply the concepts of flux to home automation. Specifically, it seeks to use the flux architecture as implemented by NGRX which adds the concept of effects which are functions that receive actions and produce 0:n actions as a result.

  1. Igor starts from a base state where no default values initialize the system.
  2. Actions/events are generated
    1. user actions involve changing settings (max/min temperature settings, triggering garage door, etc.)
    2. sensor actions report on how the environment has changed
  3. Effects (updating settings in a file/db, toggle GPIO pin, etc.) run based on the new proposed state and emit new actions
  4. Reducers are run to compute the desired state.
  5. The new state is published to the system.
  6. Controllers read the new state and run the necessary commands to their attached devices and report any errors as events returning to step #2.

Note: since the system communicates via NATS so update broadcasts can be sent specifically so {a: 1, b: {c: 2, d: 3}} where only c is updated can be broadcast on state.b.c with a message of 4 (or whatever the value was updated to).

Reducers are written in Javascript and run via Otto

Roadmap

  • [] security
  • choose serialization format -- JSON

Contributing

Please do! PRs are certainly welcome. Note, this project is intended to be the base for a home automation system and will not house device drivers, user interfaces, etc. Those can exist in their own repositories.

Igor is a home automation system based on the [flux architecture](https://facebook.github.io/flux/).  User commands, sensor readings, 
and system notifications are all marked with a `type` attribute and the event is processed by scripted reducers that take a piece of the current
state of the system and compute a new state based on the event data.  

Communication is handled by [NATS](https://www.nats.io/).  NATS has a number of nice qualities that make it ideal for Igor.  There are queue groups
that send messages to one member of the group at a time so only one node will ever process an event and publish any resulting state updates.
State is persisted on the file system ($IGOR_HOME/state), reducers are javascript scripts run by otto and are read from $IGOR_HOME/reducers (reducers
dictate what gets put into the state).  Components are go plugins.  All designed to be run on Raspberry Pis.

Reducers:
Currently only Javascript with otto.  Would like to support Gentee and possibly arbitrary binaries or maybe even wasm

Documentation

Index

Constants

View Source
const PluginInitSymbol = "Init"

Variables

This section is empty.

Functions

func FilePathToTopic

func FilePathToTopic(filePath string) string

func FilesToJson

func FilesToJson(path string) ([]byte, error)

func FilesToMap

func FilesToMap(path string) (map[string]interface{}, error)

func IsJSON

func IsJSON(data []byte) bool

func JsonToFiles

func JsonToFiles(data []byte, path string, perm os.FileMode) error

func MapToFiles

func MapToFiles(data map[string]interface{}, path string, perm os.FileMode) error

func ParseSubscriptionDirective

func ParseSubscriptionDirective(directive, prefix string) []string

parses a directive line inside of a JS file

func TopicToFilePath

func TopicToFilePath(topic string) string

func TrimStringSlice

func TrimStringSlice(in []string) []string

Types

type AutomationState

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

func NewAutomationState

func NewAutomationState(init []byte) *AutomationState

func (*AutomationState) Mutate

func (as *AutomationState) Mutate(update []byte, updatePath ...string) error

func (*AutomationState) Select

func (as *AutomationState) Select(path ...string) ([]byte, error)

func (*AutomationState) State

func (as *AutomationState) State() []byte

type Event

type Event struct {
	Type      EventType   `json:"type"`
	Timestamp time.Time   `json:"timestamp"`
	Payload   interface{} `json:"payload"`
}

type EventType

type EventType string
const (
	EventWildcard EventType = "*"
)

type IgorPlugin

type IgorPlugin interface {
	// UpdateState is called whenever the state the plugin is listening to changes
	// the state will be in a hierarchical structure like JSON and the path dictates
	// which part of the state the update argument should replace.  An empty path
	// indicates that the entire state for the plugin should be updated
	UpdateState(path []string, update []byte) error
}

type OttoScript

type OttoScript struct {
	Path          string
	Program       *otto.Script
	ResultHandler func(interface{})
}

type PluginInit

type PluginInit func(func(Event), []string) IgorPlugin

PluginInit initializes the plugin with a function to emit events from and the path through the global state that contains the parts this plugin should get it's data from

type Runnable

type Runnable interface {
	Run(args interface{}) interface{}
}

type ScriptManager

type ScriptManager interface {
	HandleEvents(<-chan Event)
}

type ScriptStore

type ScriptStore interface {
	Fetch()
}

type Store

type Store interface {
	Dispatch(Event)
	Subscribe() interface{} // state
}

Directories

Path Synopsis
cmd
igor command
plugin
garageDoor command

Jump to

Keyboard shortcuts

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