lights

package
v0.2024.5 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2024 License: GPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package lights provides automated control of lighting. Information is read from sensors, occupancy and/or brightness, that then informs decisions about whether lights should be on and at what brightness.

This package provides these automatic lighting functions:

  1. Lights in occupied spaces are on, lights in unoccupied spaces are off
  2. Lights that are on are dimmer if it's bright outside

Implementation approach

The core automation logic can be found in the processState function in logic.go. This code receives the combined knowledge of the system and works out what needs to be done to satisfy the automatic outcomes we desire. Here you'll find the code that says "if any sensor reports a state of OCCUPIED, then the lights should be on".

Collecting and updating the shared knowledge is a process we call patching, inspired by version control systems. ReadState holds all the information we can know and it is updated by a sequence of Patcher.Patch calls. These Patcher instances come from the different sensors and are applied to the shared state one at a time in state.go#readStateChanges.

Invoking the logic when the state changes happens in processStateChanges which takes care to avoid unnecessary work by skipping analysing state that has already been superseded by more state changes.

Implementation finer details

To avoid duplicating commands and to provide some sense of determinism the logic function is allowed to complete before being called again, even if more state changes are available. The context passed to the func is only cancelled if the automation as a whole is stopped. This means that we shouldn't get into a state where the logic has turns some lights on but not others because a new version of the state is available. Actions successfully performed by the logic are recorded in WriteState which is consulted before new actions are performed. If the logic wants to turn the lights on, then it can check WriteState to see if the light has already been asked to turn on, the action can then be skipped as needed.

One of the clauses for the logic is to wait a configured time after a space becomes unoccupied before turning the lights off. To accomplish this the logic could use time.After but that would cause the logic to block for a long time, during which the automation is not reacting to new information. Instead the logic returns a TTL value that indicates to the calling func that the analysis of the state and the subsequent actions are only correct until TTL expires, at which point the logic should be rerun.

Index

Constants

View Source
const (
	ModeAuto     = "auto"
	ModeDefault  = "default"
	ModeValueKey = "lighting.mode"
)
View Source
const AutoType = "lights"

Variables

View Source
var Factory = auto.FactoryFunc(func(services auto.Services) service.Lifecycle {
	logger := services.Logger.Named("lights")
	impl := PirsTurnLightsOn(services.Node, logger)
	return autoToService(impl, logger)
})

Functions

This section is empty.

Types

type BrightnessAutomation

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

BrightnessAutomation implements turning lights on or off based on occupancy readings from PIRs and other devices.

func PirsTurnLightsOn

func PirsTurnLightsOn(clients node.Clienter, logger *zap.Logger) *BrightnessAutomation

PirsTurnLightsOn creates an automation that controls light brightness based on PIR occupancy status.

func (*BrightnessAutomation) Configure

func (b *BrightnessAutomation) Configure(configData []byte) error

Configure updates the configured devices and settings this automation uses.

func (*BrightnessAutomation) Start

Start implements Starter and initialises this automation. Start may be called before or after Configure.

func (*BrightnessAutomation) Stop

func (b *BrightnessAutomation) Stop() error

Stop stops the automation from running. You must call Start to have automated action occur again.

type BrightnessSensorPatches

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

BrightnessSensorPatches contributes patches for changing the state based on brightness sensor readings.

func (*BrightnessSensorPatches) Poll

func (o *BrightnessSensorPatches) Poll(ctx context.Context, changes chan<- Patcher) error

func (*BrightnessSensorPatches) Pull

func (o *BrightnessSensorPatches) Pull(ctx context.Context, changes chan<- Patcher) error

func (*BrightnessSensorPatches) Subscribe

func (o *BrightnessSensorPatches) Subscribe(ctx context.Context, changes chan<- Patcher) error

type BrightnessWriteState

type BrightnessWriteState struct {
	WriteTime  time.Time
	Brightness *traits.Brightness
}

type ButtonPatches

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

func (*ButtonPatches) Poll

func (p *ButtonPatches) Poll(ctx context.Context, changes chan<- Patcher) error

func (*ButtonPatches) Pull

func (p *ButtonPatches) Pull(ctx context.Context, changes chan<- Patcher) error

func (*ButtonPatches) Subscribe

func (p *ButtonPatches) Subscribe(ctx context.Context, changes chan<- Patcher) error

type ButtonType

type ButtonType int
const (
	UndefinedButton ButtonType = iota
	OnButton
	OffButton
	ToggleButton
)

func (ButtonType) String

func (s ButtonType) String() string

type ModePatches

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

ModePatches contributes patches for changing the state based on mode changes.

func (*ModePatches) Poll

func (o *ModePatches) Poll(ctx context.Context, changes chan<- Patcher) error

func (*ModePatches) Pull

func (o *ModePatches) Pull(ctx context.Context, changes chan<- Patcher) error

func (*ModePatches) Subscribe

func (o *ModePatches) Subscribe(ctx context.Context, changes chan<- Patcher) error

type OccupancySensorPatches

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

OccupancySensorPatches contributes patches for changing the state based on occupancy sensor readings.

func (*OccupancySensorPatches) Poll

func (o *OccupancySensorPatches) Poll(ctx context.Context, changes chan<- Patcher) error

func (*OccupancySensorPatches) Pull

func (o *OccupancySensorPatches) Pull(ctx context.Context, changes chan<- Patcher) error

func (*OccupancySensorPatches) Subscribe

func (o *OccupancySensorPatches) Subscribe(ctx context.Context, changes chan<- Patcher) error

type PatchFunc

type PatchFunc func(s *ReadState)

func (PatchFunc) Patch

func (p PatchFunc) Patch(s *ReadState)

type Patcher

type Patcher interface {
	Patch(s *ReadState)
}

Patcher represents a single patch that adjusts ReadState.

type ReadState

type ReadState struct {
	Config config.Root

	AutoStartTime time.Time // time that the automation started up
	Occupancy     map[string]*traits.Occupancy
	// used for daylight dimming
	AmbientBrightness map[string]*traits.AmbientBrightness
	Buttons           map[string]*gen.ButtonState
	// used for selecting the run modes, aka "modes" config property
	Modes *traits.ModeValues
}

ReadState models everything we have read from the system. For example if we PullBrightness, then the responses will be recoded here.

func NewReadState

func NewReadState(t time.Time) *ReadState

func (*ReadState) Clone

func (s *ReadState) Clone() *ReadState

func (*ReadState) Now

func (s *ReadState) Now() time.Time

type WriteState

type WriteState struct {
	Brightness       map[string]BrightnessWriteState
	LastButtonAction time.Time // used for button press deduplication, the last time we did anything due to a button press
	LastButtonOnTime time.Time // used for occupancy related darkness, the last time lights were turned on due to button press
	ActiveMode       string
}

WriteState models the state of the system based on the changes we've made to it. For example if we UpdateBrightness, then the response to that call is recorded in this state.

func NewWriteState

func NewWriteState(startTime time.Time) *WriteState

func (*WriteState) MergeFrom

func (s *WriteState) MergeFrom(other *WriteState)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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