/appdaemon-machine

State machine library for AppDaemon (Home Assistant)

Primary LanguagePythonApache License 2.0Apache-2.0

State machine library for AppDaemon (Home Assistant)

Define and run state machines to drive your automations using AppDaemon with Home Assistant.

Build Status

Installation

  1. Clone the appdaemon-machine repository.
git clone https://github.com/PeWu/appdaemon-machine.git
  1. Copy the machine.py file to your apps directory.
cp appdaemon-machine/machine.py ~/.homeassistant/apps

Example

Simple example:

import appdaemon.plugins.hass.hassapi as hass
from enum import Enum
from machine import Machine, ANY, StateEq, StateNeq, Timeout

class States(Enum):
  HOME = 1
  AWAY = 2
  LEAVING = 3
globals().update(States.__members__) # Make the states accessible without the States. prefix.

class Presence(hass.Hass):
  def initialize(self):
    machine = Machine(self, States)

    machine.add_transitions(ANY, StateEq('device_tracker.my_phone', 'home'), HOME)
    machine.add_transition(HOME, StateNeq('device_tracker.my_phone', 'home'), LEAVING)
    machine.add_transition(LEAVING, Timeout(30), AWAY, on_transition=self.on_away)

    machine.log_graph_link()

  def on_away(self):
    # e.g. turn off the lights.

The log_graph_link() call will log this link on the console.

API

class Machine(hass, states, initial=None, entity=None)

Initializes the state machine.

If both initial and entity are provided:

  • if the entity in Home Assistant contains a valid state, it is used as the initial state
  • otherwise, initial is used as the initial state.

Args

hass: The app inheriting appdaemon.plugins.hass.hassapi.Hass

states: Enum with all possible states.

initial: Initial state of the state machine. Defaults to the first state.

entity: The entity that will mirror the state machine's state.

Machine.add_transition(from_state, trigger, to_state, on_transition=None):

Adds a single transition.

Args

from_state: The state from which the transition is made.

trigger: The trigger causing this transition.

to_state: Destination state of the transition.

on_transition: Optional 0-argument callback to call when performing this transition.

Machine.add_transitions(from_states, triggers, to_state, on_transition=None)

Adds multiple transitions.

Examples:

# 2 transitions, one from STATE1, one from STATE2.
machine.add_transitions([STATE1, STATE2], StateOn('binary_sensor.sensor1'), STATE3)
# 2 transitions for 2 different triggers.
machine.add_transitions(STATE1, [StateOn('binary_sensor.sensor1'), Timeout(5)], STATE3)
# 4 transitions.
machine.add_transitions(
    [STATE1, STATE2],
    [StateOn('binary_sensor.sensor1'), Timeout(5)],
    STATE3)
# One transition from each state to STATE3 (including STATE3->STATE3)
machine.add_transitions(ANY, StateOn('binary_sensor.sensor1'), STATE3)

Args

from_states: A single state or a list of states or ANY.

trigger: A single trigger or multiple triggers.

to_state: A single destination state of the transition.

on_transition: Optional callback to call when performing this transition.

Machine.on_transition(callback)

Sets a callback that will be called on each state transition.

Only one callback can be set. Calls to on_transition() overwrite the previously set callback.

Args

callback: function taking 2 arguments: (from_state, to_state)

Machine.get_dot()

Returns the transition graph in DOT format.

Machine.log_graph_link()

Logs a link to a visualization of the transition graph.

Triggers

Example triggers:

StateOn('binary_sensor.sensor1')
StateOff('binary_sensor.sensor2')
StateEq('device_tracker.device1', 'home')
StateNeq('device_tracker.device2', 'home')
StateIs('sensor.temperature', lambda t: int(t) < 20)
Timeout(10) # seconds

Not supported yet

  • Setting the state explicitly from code, e.g. machine.set_state(HOME).