Welcome to Automate’s Documentation!¶
Table of Contents¶
Introduction¶
What is Automate?¶
Automate is a general purpose automatization library for Python. Its objective is to offer convenient and robust object-oriented programming framework for complex state machine systems. Automate can be used to design complex automation systems, yet it is easy to learn and fun to use. It was originally developed with home robotics/automatization projects in mind, but is quite general in nature and one could find applications from various fields that could take advantage of Automate. Automate can be embedded in other Python software as a component, which runs its operations in its own threads.
Highlights¶
- Supported hardware:
- Raspberry Pi GPIO input/output ports (Raspberry Pi GPIO Support for Automate via RPIO library)
- Arduino analog and digital input/output ports (Arduino Support for Automate via pyFirmata library)
- Easy to write extensions to support other hardware, see Making your own Automate Extensions
- System State Saving and Restoring via Serialization
- Intelligent design:
- RPC and Websocket interfaces (provided by Remote Procedure Call Support for Automate and Web User Interface for Automate) to connect between other applications or other Automate systems.
- Comprehensive and customizable Web User Interface via Web User Interface for Automate
- UML graphs can be drawn automaticlaly of the system (as can be seen in the examples of this documentation)
“Hello World” in Automate¶
Let us consider following short Automate program as a first example:
from automate import *
class MySystem(System):
# HW swtich connected Raspberry Pi GPIO port 1
hardware_switch = RpioSensor(port=1)
# Switch that is controllable, for example, from WEB interface
web_switch = UserBoolSensor()
# Lamp relay that switches lamp on/off, connected to GPIO port 2
lamp = RpioActuator(port=2)
# Program that controls the system behaviour
program = Program(
active_condition=Or('web_switch', 'hardware_switch'),
on_activate=SetStatus('lamp', True)
)
my_system = MySystem(
services=[WebService()]
)
This simple example has two sensors hardware_switch
, web_switch
, actuator (lamp
) and a program
that
contains logic what to do and when. Here, lamp
is switched on if either web_switch
or hardware_switch
has
status True. WebService
with default settings is enabled so that user can
monitor system and set
status of web_switch
. The following figure (generated via WebService
interface)
illustrates the system in UML graph:
Original application¶
Automate was originally developed in order to enable simple and robust way of programming home automatization with Raspberry Pi minicomputer, to obtain automatization and automatic monitoring of rather complex planted aquarium safety/controlling system.
How to Install Automate?¶
Automate can be installed like ordinary python package. I recommend installation in within virtual environment (see virtualenv).
(optional): Create and start using virtualenv:
mkvirtualenv automate workon automate
Install from pypi:
pip install automate
Optionally, you can specify some of the extras, i.e. web, rpc, raspberrypi, arduino:
pip install automate[web,rpc,raspberrypi,arduino]
or if you want them all:
pip install automate[all]
Automate Components¶

Automate system is built of the following components:
- System (derived by user from
System
) binds all parts together into a single state machine - Services (subclassed of
AbstractService
) provide programming interfaces with user and devices that can be used by SystemObjects. - SystemObjects (subclassed of
SystemObject
orProgrammableSystemObject
):- Sensors (subclassed on
AbstractSensor
) are used as an interface to the (usually read-only) state of device or software. - Actuators (subclassed on
AbstractActuator
) are used as an interface to set/write the state of device or software. - Programs (subclassed on
ProgrammableSystemObject
) define the logic between Sensors and Actuators. They are used to control statuses of Actuators, by rules that are programmed by using special Callables (subclasses ofAbstractCallable
) objects that depend on statuses of Sensors and other components. Also Sensors and Actuators are often subclassed fromProgrammableSystemObject
so they also have similar features by themselves. Depending on the application, however, it might (or might not) improve readability if plainProgram
component is used.
- Sensors (subclassed on
All Automate components are derived from HasTraits
, provided by
Traits library, which provides automatic notification of attribute changes, which is used
extensively in Automate. Due to traits, all Automate components are configured by passing
attribute names as keyword arguments in object initialization (see for example attributes
pin
and
dev
traits of
ArduinoDigitalActuator
in the example below).
Automate system is written by subclassing System
and adding there desired
SystemObject
as its attributes, such as in the following example:
from automate import *
class MySystem(System):
mysensor = FloatSensor()
myactuator = ArduinoDigitalActuator(pin=13, dev=0)
myprogram = Program()
...
After defining the system, it can be instantiated. There, services with their necessary arguments can be explicitly defined as follows:
mysys = MySystem(services=[WebService(http_port=8080), ArduinoService(dev='/dev/ttyS0')])
Some services (those that have autoload
atribute set to True)
do not need to be explicitly defined. For example,
ArduinoService
would be used automatically
loaded because of the usage of ArduinoDigitalActuator
,
with default settings (dev='/dev/ttyUSB0'
). Instantiating
System will launch IPython shell to access the system internals from the command line. This can be prevented, if
necessary, by defining keyword argument exclude_services
as
['TextUIService']
, which disables autoloading of
TextUIService
. For further information about services, see Services.
Programming Automate Objects¶
Programs¶
Program features are defined in ProgrammableSystemObject
class.
Program
, DefaultProgram
and
StatusObject
classes are subclassed
from ProgrammableSystemObject
, as can be seen in the following
inheritance diagram.

Programs are used to define the logic on which system operates. Program behavior is determined by the conditions
(active_condition
,
update_condition
) and actions
(on_activate
,
on_update
,
on_deactivate
),
that are of AbstractCallable
type. Callables are special objects that are used to implement the actual programming of Automate program objects
(see Callables). There are many special Callable classes to perform different operations
(see Builtin Callables) and it is also easy to develop your own Callables
(see Deriving Custom Callables).
All Sensors and Actuators that affect the return value of a condition callable,
are triggers
of a Callable. All actuators (and writeable sensors) that
a callable may change, are targets
. Whenever any of the
triggers status change, programs
conditions are automatically updated and actions are taken if appropriate condition evaluates
as True
.
Actions and conditions are used as follows. Programs can be either active or inactive depending on
active_condition
. When program actives
(i.e. active_condition changes to True
),
on_activate
action is called. When program deactivates,
on_deactivate
,
action is called, correspondingly.
When program is active, its targets can be continuously manipulated by
on_update
callable, which
is called whenever update_condition evaluates as True
.
Actuator Status Manipulation¶
Program can control status of one or more actuators. Programs manipulate Actuator statuses the following way:
- One or more programs can control state of the same Actuator. Each program has
priority
(floating point number), so that the actual status of Actuator is determined by program with highest priority - If highest priority program deactivates, the control of Actuator status is moved to the the second-highest priority active program.
- If there are no other Program, each Actuator has also one DefaultProgram, which then takes over Actuator control.
The following example application illustrates the priorities:
from automate import *
class MySystem(System):
low_prio_prg = UserBoolSensor(priority=-5,
active_condition=Value('low_prio_prg'),
on_activate=SetStatus('actuator', 1.0),
default=True,
)
med_prio_prg = UserBoolSensor(priority=1,
active_condition=Value('med_prio_prg'),
on_activate=SetStatus('actuator', 2.0),
default=True,
)
high_prio_prg = UserBoolSensor(priority=5,
active_condition=Value('high_prio_prg'),
on_activate=SetStatus('actuator', 3.0),
default=True,
)
inactive_high_prio_prg = UserBoolSensor(priority=6,
active_condition=Value('inactive_high_prio_prg'),
on_activate=SetStatus('actuator', 4.0),
default=False,
)
actuator = FloatActuator()
ms = MySystem(services=[WebService()])
In this application, four programs (three manually defined programs and DefaultProgram
dp_actuator
) are active for actuator.
The actual status of actuator (now: 3.0
) is determined by highest priority program.
If high_prio_prog
goes inactive (i.e. if its
status is changed to False
):
high_prio_prg.status = False
the status is then determined by med_prio_prg
(=> 2.0
). And so on. All the active programs
for actuator are visible in UML diagram.
Red arrow shows the dominating program, blue arrows show the other non-dominating active programs and gray arrows
show the inactive programs that have the actuator as a target (i.e. if they are activated, they will manipulate
the status of the actuator). low_prio_prg
can never manipulate actuator status as its priority is lower than
default program dp_actuator
priority.
Program Features¶
Program features are defined in ProgrammableSystemObject
class. Its definition is as follows:
Note
Unfortunately, due to current Sphinx autodoc limitation, all trait types are displayed in this
documentation as None
. For the real trait types, please see the source fode.
-
class
automate.program.
ProgrammableSystemObject
(*args, **kwargs)[source]¶ System object with standard program features (i.e. conditions & actions).
-
active_condition
= None¶ A condition Callable which determines the condition, when the program is activated. Program deactivates, when condition turns to False. When program is activated, on_activate action is executed. When program deactivates. on_deactivate is executed.
-
on_activate
= None¶ An action Callable to be executed when Program actives.
-
on_deactivate
= None¶ An action Callable to be executed when Program deactivates.
-
update_condition
= None¶ When program is active, this is the condition Callable that must equal to
True
in order to on_update action to be executed. Whenever a trigger is changed, this condition is checked and ifTrue
, on_update is executed.
-
on_update
= None¶ Action Callable to be executed if Program is active and update_condition is
True
.
-
priority
= None¶ When programs sets Actuator status, the actual status of Actuator is determined by a program that has highest priority. Lower priority programs are stacked and used only if higher priority programs are deactivated.
-
active
= None¶ Is program active? Automatically changed. In UIs you can fake the program active status by changing this. Normally do not change manually.
-
status
= None¶ Status property is introduced to have interface compability with Status objects. For plain Programs, status equals to the result of its active condition Callable.
-
actual_triggers
= None¶ (read-only property) Set of triggers, that cause this Program conditions to be checked (and actions to be executed). This data is updated from custom triggers list, conditions and actions.
-
actual_targets
= None¶ (read-only property) Set of targets that this Program might touch. This data is updated from custom targets list and actions.
-
triggers
= None¶ Custom set of additional triggers, whose status change will trigger this Program conditions/actions
-
exclude_triggers
= None¶ Triggers in this set do not trigger the program actions/conditions even if they are introduced by Callables etc.
-
targets
= None¶ Additional targets. Not usually needed, but if you want to set status for some reason by some custom function, for example, then you need to use this.
-
StatusObjects¶

Actuators (AbstractActuator
) and
sensors (AbstractSensor
)
are subclassed of StatusObject
.
The most important property is status
,
which may be of various data types, depending of the implementation defined in subclasses.
Type of status is determined by _status
trait.
There are couple of useful features in StatusObjects that may be used to affect when status is really changed. These are accessible via the following attributes:
safety_delay
andsafety_mode
can be used to define a minimum delay between status changes (“safety” ~ some devices might break if changed with big frequency)change_delay
andchange_mode
can be used to define a delay which (always) takes place before status is changed.
Here, modes are one of 'rising'
, 'falling'
, 'both'
, default being 'rising'
. To disable
functionality completely, set corresponding delay parameter to zero. Functions are
described below.
Creating Custom Sensors and Actuators¶
Custom actuators and sensors can be easiliy written based on
AbstractActuator
and AbstractSensor
classes, respectively.
As an example, we will define one of each:
# imports from your own library that you are using to define your sensor & actuator
from mylibrary import (setup_data_changed_callback,
fetch_data_from_my_datasource,
initialize_my_actuator_device,
change_status_in_my_actuator_device)
class MySensor(AbstractSensor):
"""
Let us assume that you have your own library which has a status that you
want to track in your Automate program.
"""
# define your status data type
_status = CBool
def setup(self):
setup_my_datasource()
# we tell our library that update_status need to be called when status is
# changed. We could use self.set_status directly, if library can pass
# new status as an argument.
setup_data_changed_callback(self.update_status)
def update_status(self):
# fetch new status from your datasource (this function is called by
# your library)
self.status = fetch_data_from_your_datasource()
def cleanup(self):
# define this if you need to clean things up when program is stopped
pass
class MyActuator(AbstractActuator):
# define your status data type. Transient=True is a good idea because
# actuator status is normally determined by other values (sensors & programs etc)
_status = CFloat(transient=True)
def setup(self):
initialize_my_actuator_device()
def _status_changed(self):
chagnge_status_in_my_actuator_device(self.status)
For more examples, look
builtin_sensors
and
builtin_actuators
. For more examples, see also Extensions,
especially support modules for Arduino and Raspberry Pi IO devices)
StatusObject Definition¶
-
class
automate.statusobject.
StatusObject
(*args, **kwargs)[source]¶ Baseclass for Sensors and Actuators
-
safety_delay
= None¶ Determines minimum time required for switching. State change is then delayed if necessary.
-
safety_mode
= None¶ Determines when
safety_delay
needs to be taken into account: when status is rising, falling or both.
-
change_delay
= None¶ Similar to
safety_delay
, but just delays change to make sure that events shorter than change_delay are not taken into account
-
change_mode
= None¶ As
safety_mode
, but forchange_delay
-
silent
= None¶ Do not emit actuator status changes into logs
-
debug
= None¶ Print more debugging information into logs
-
changing
= None¶ (property) Is delayed change taking place at the moment?
-
is_program
¶ A property which can be used to check if StatusObject uses program features or not.
-
status
= None¶ Status of the object.
-
set_status
(new_status, origin=None, force=False)[source]¶ For sensors, this is synonymous to:
sensor.status = new_status
For (non-slave) actuators, origin argument (i.e. is the program that is changing the status) need to be given,
-
update_status
()[source]¶ In sensors: implement particular value reading from device etc. here (this calls set_status(value)). In actuators: set value in particular device. Implement in subclasses.
-
activate_program
(program)[source]¶ When program controlling this object activates, it calls this function.
-
Sensor Baseclass Definition¶

-
class
automate.statusobject.
AbstractSensor
(*args, **kwargs)[source]¶ Base class for all sensors
-
user_editable
= None¶ Is sensor user-editable in UIs. This variable is meant for per-instance tuning for Sensors, whereas
editable
is for per-class adjustment.
-
default
= None¶ Default value for status
-
reset_delay
= None¶ If non-zero, Sensor status will be reset to default after defined time (in seconds).
-
silent
= None¶ Do not log status changes
-
Actuator Baseclass Definition¶

-
class
automate.statusobject.
AbstractActuator
(*args, **kwargs)[source]¶ Base class for all actuators.
-
default
= None¶ Default value for status. For actuators, this is set by automatically created
DefaultProgram
dp_actuatorname
-
slave
= None¶ If
True
, actual status can be set by any program anytime without restrictions.
-
program
= None¶ A property giving current program governing the status of this actuator (program that has the highest priority)
-
priorities
= None¶ This dictionary can be used to override program priorities.
Note
Keys here must be program names, (not
Program
instances).
-
default_program
= None¶ Reference to actuators
DefaultProgram
-
set_status
(status, origin=None, force=False)[source]¶ For programs, to set current status of the actuator. Each active program has its status in
program_stack
dictionary and the highest priority is realized in the actuator
-
activate_program
(program)[source]¶ Called by program which desires to manipulate this actuator, when it is activated.
-
update_program_stack
()[source]¶ Update
program_stack
. Used by programs_priority_changed
attribute to reset ordering.
-
program_stack
= None¶ Program stack of current programs, sorted automatically by program priority.
-
program_status
= None¶ Dictionary containing statuses set by each active program
-
Builtin Statusobject Types¶
Here are the definitions for the builtin statusobject types (sensors and actuators). More types are available in Extensions.
Builtin Sensors¶
Module for various Sensor classes.
-
class
automate.sensors.builtin_sensors.
UserAnySensor
(*args, **kwargs)[source]¶ User editable sensor type that accepts values of any types
-
class
automate.sensors.builtin_sensors.
UserBoolSensor
(*args, **kwargs)[source]¶ Boolean-valued user-editable sensor
-
class
automate.sensors.builtin_sensors.
UserEventSensor
(*args, **kwargs)[source]¶ Boolean-valued user-editable sensor suitable for using for singular events.
After status has been changed to
True
, it changes automatically its status back toFalse
.
-
class
automate.sensors.builtin_sensors.
AbstractNumericSensor
(*args, **kwargs)[source]¶ Abstract class for numeric sensor types, that allows limiting value within a specific range.
If limiting values (
value_min
,value_max
) are used, value that exceeds these limits, is clipped to the range.-
value_min
= None¶ Minimum allowed value for status
-
value_max
= None¶ Maximum allowed value for status
-
-
class
automate.sensors.builtin_sensors.
UserIntSensor
(*args, **kwargs)[source]¶ Integer-valued user-editable sensor
-
class
automate.sensors.builtin_sensors.
UserFloatSensor
(*args, **kwargs)[source]¶ Float-valued user-editable sensor
-
class
automate.sensors.builtin_sensors.
UserStrSensor
(*args, **kwargs)[source]¶ String-valued user-editable sensor
-
class
automate.sensors.builtin_sensors.
CronTimerSensor
(*args, **kwargs)[source]¶ Scheduled start/stop timer. Both start and stop times are configured by cron-type string (see man 5 crontab for description of the definition format).
-
timer_on
= None¶ Semicolon separated lists of cron-compatible strings that indicate when to switch status to
True
-
timer_off
= None¶ Semicolon separated lists of cron-compatible strings that indicate when to switch status to
False
-
-
class
automate.sensors.builtin_sensors.
FileChangeSensor
(*args, **kwargs)[source]¶ Sensor that detects file changes on filesystem. Integer valued status is incremented by each change.
-
filename
= None¶ Name of file or directory to monitor
-
watch_flags
= None¶ PyInotify flags to configure what file change events to monitor
-
-
class
automate.sensors.builtin_sensors.
AbstractPollingSensor
(*args, **kwargs)[source]¶ Abstract baseclass for sensor that polls periodically its status
-
interval
= None¶ How often to do polling
-
poll_active
= None¶ This can be used to enable/disable polling
-
-
class
automate.sensors.builtin_sensors.
PollingSensor
(*args, **kwargs)[source]¶ Polling sensor that uses a Callable when setting the status of the sensor.
-
status_updater
= None¶ Return value of this Callable is used to set the status of the sensor when polling
-
type
= None¶ If set, typeconversion to this is used. Can be any function or type.
-
-
class
automate.sensors.builtin_sensors.
SimplePollingSensor
(*args, **kwargs)[source]¶ Polling sensor that calls on_update periodically.
-
class
automate.sensors.builtin_sensors.
IntervalTimerSensor
(*args, **kwargs)[source]¶ Sensor that switches status between True and False periodically.
-
class
automate.sensors.builtin_sensors.
SocketSensor
(*args, **kwargs)[source]¶ Sensor that reads a TCP socket.
Over TCP port, it reads data per lines and tries to set the status of the sensor to the value specified by the line. If content of the line is ‘close’, then connection is dropped.
-
host
= None¶ Hostname/IP to listen. Use
'0.0.0.0'
to listen all interfaces.
-
port
= None¶ Port to listen
-
stop
= None¶ set to
True
to tell SocketSensor to stop listening to port
-
-
class
automate.sensors.builtin_sensors.
ShellSensor
(*args, **kwargs)[source]¶ Run a shell command and follow its output. Status is set according to output, which is filtered through custome filter function.
-
cmd
= None¶ Command can be, for example, ‘tail -f logfile.log’, which is convenient approach to follow log files.
-
caller
= None¶ If this is set to true, caller object is passed to the filter function as second argument
-
filter
= None¶ Filter function, which must be a generator, such as for example:
def filter(queue): while True: line = queue.get() if line == 'EOF': break yield line
or a simple line-by-line filter:
def filter(line): return processed(line)
-
Builtin Actuators¶
Module for builtin Actuator classes
-
class
automate.actuators.builtin_actuators.
BoolActuator
(*args, **kwargs)[source]¶ Boolean valued actuator
-
class
automate.actuators.builtin_actuators.
IntActuator
(*args, **kwargs)[source]¶ Integer valued actuator
-
class
automate.actuators.builtin_actuators.
FloatActuator
(*args, **kwargs)[source]¶ Floating point valued actuator
-
class
automate.actuators.builtin_actuators.
AbstractInterpolatingActuator
(*args, **kwargs)[source]¶ Abstract base class for interpolating actuators.
-
change_frequency
= None¶ How often to update status (as frequency)
-
slave_actuator
= None¶ Slave actuator, that does the actual work (set .slave attribute to True in slave actuator)
-
Callables¶
Introduction¶
Callables are used like a small programming language to define the programming logic within the
Automate system. All classes derived from ProgrammableSystemObject
have five
attributes that accept Callable type objects:
- Conditions
- Actions
Conditions determine when and actions, correspondingly, what to do.
Actions are triggered by triggers that are Sensors and Actuators. Triggers are collected
from Callables (conditions and actions) automatically, and their status changes are subscribed and followed
automatically by a
ProgrammableSystemObject
. Thus, condition statuses are evaluated automatically, and
actions are executed based on condition statuses.
Let us take a look at a small example that uses conditions and actions:
from automate import *
class CounterClock(System):
active_switch = UserBoolSensor()
periodical = IntervalTimerSensor(interval=1)
target_actuator = IntActuator()
prog = Program(
active_condition = Value(active_switch),
on_activate = SetStatus(target_actuator, 0),
on_update = SetStatus(target_actuator,
target_actuator + 1),
triggers = [periodical],
exclude_triggers = [target_actuator],
)
s = CounterClock(services=[WebService(read_only=False)])
When user has switched active_switch
sensor to True
, this simple program will start adding +1 to target_actuator value every
second. Because periodical
is not used as a trigger in any action/condition, we need to explicitly define it as a
trigger with triggers attribute. Correspondingly, target_actuator
is automatically collected as prog’s trigger (because
it is the second argument of SetStatus), so we need to explicitly exclude it with exclude_triggers
attribute.
Tip
Try the code yourself! Just cpaste the code into your IPython shell and go to http://localhost:8080 in your browser! Screenshot:

Deriving Custom Callables¶
A collection of useful Callables is provided by builtin_callables
module.
It is also easy to derive custom callables from AbstractCallable
baseclass.
For most cases it is enough to re-define call()
method.
If Callable utilizes threads (like
Delay
,
WaitUntil
and
While
)
and continues as an background process after returning from call method, it is also necessary
to define cancel()
that notifies threads that their processing
must be stopped. These threaded Callables can store their threads and other information in
state
dictionary, which stores information per
caller Program. Per-caller state information is fetched via
get_state()
. After data is no longer needed, it must be cleared with
del_state()
method.
Arguments given to Callable are stored in
_args
and keyword arguments in
_kwargs
. There are the following shortcuts that may
be used:
obj
,
value
and
objects
. When accessing these, it is necessary (almost) always
to use call_eval()
method, which evaluates concurrent status value
out of Callable, StatusObject, or string that represents name of an object residing in System namespace.
See more in the following section.
Trigger and Target Collection¶
Triggers and targets are automatically collected from Callables recursively.
All Callable types can specify which arguments are considered as triggers and which
are considered as targets, by defining
_give_triggers()
and
_give_targets()
, correspondingly.
As a general rule, Callable should not consider criteria conditions as triggers
(for example the conditions of
If
,
Switch
etc).
Referring to Other Objects in Callables¶
Various system objects can be referred either by name (string), or by object references. Name is preferred, because it allows to refer to objects that are defined in different scopes (i.e. those that are defined either in Groups or later in the code).
If desired, automatic name referencing can be also disabled by setting
allow_name_referencing
False. Then it is possible
to refer to other objects by using special construct Object(‘name’).
All variables passed to Callables are/must be evaluated through
call_eval()
method, i.e.
if Callables are used as arguments, they are evaluated by their
call()
method
and StatusObject
‘s status attribute is used, respectively.
Callable Abstract Base Class definition¶
Callable classes are are subclassed of AbstractCallable
.
-
class
automate.callable.
AbstractCallable
(*args, **kwargs)[source]¶ A base class for subclassing Callables that are used in Program conditions and action attributes.
Callables are configured by giving them arguments and keyword arguments.They must always define
call()
method which defines their functionality.-
triggers
= None¶ Property that gives set of all triggers of this callable and it’s children callables. Triggers are all those StatusObjects that alter the status (return value of
call()
) of Callable.
-
targets
= None¶ Property that gives set of all targets of this callable and it’s children callables. Targets are all those StatusObjects of which status the callable might alter in
call()
.
-
status
= None¶ Read-only status property of the callable. Usefull only when callable is used as a condition. This automatically depends on all the StatusObjects below the Callable tree.
-
state
= None¶ State dictionary that is used by
call()
andcancel()
if some state variables are needed to be saved Remember to clean data in subclasses when it is no longer needed.
-
on_setup_callable
= None¶ Event that can be used to execute code right after callable setup. See
OfType
. Something that needs to be done manually this way, because Traits does not allow defining the order of subscribed function calls.
-
call_eval
(value, caller, return_value=True, **kwargs)[source]¶ Value might be either name registered in System namespace, or object, either StatusObject or Callable. If Callable, evaluate
call()
method. If StatusObject, return status.
-
setup_callable_system
(system, init=False)[source]¶ This function basically sets up
system
, if it is not yet set up. After that, other Callable initialization actions are performed.Parameters: init – value True
is given when running this at the initialization phase. Then system attribute is set already, but callable needs to be initialized otherwise.
-
call
(*args, **kwargs)[source]¶ The basic functionality of the Callable is implemented in this function. Needs to be defined in derived subclasses.
If callable is used as a Program condition, this must return the value of the condition (see for example conditions
And
,Sum
etc.), otherwise return value is optional.
-
objects
¶ Shortcut to
_args
.
-
obj
¶ Shortcut property to the first stored object.
-
value
¶ Shortcut property to the second stored object.
-
collect
(target)[source]¶ Recursively collect all potential triggers/targets in this node and its children. Define targets and triggers of this particular callable in
_give_triggers()
and_give_targets()
.Parameters: target (str) – valid values: 'targets'
and'triggers'
-
children
¶ A property giving a generator that goes through all the children of this Callable (not recursive)
-
cancel
(caller)[source]¶ Recursively cancel all threaded background processes of this Callable. This is called automatically for actions if program deactivates.
-
give_str_indented
(tags=False)[source]¶ Give indented string representation of the callable. This is used in Web User Interface for Automate.
-
Builtin Callables¶
Module builtin_callables
provides classes that may be used to various purposes
in Automate Program
, in condition and action attributes.
They are loaded automatically into automate.callables
along with callables from possible installed extensions.
Builtin Callable Types¶
-
class
automate.callables.builtin_callables.
Empty
(*args, **kwargs)[source]¶ Do nothing but return None. Default action in Programs.
Usage:
Empty()
-
class
automate.callables.builtin_callables.
AbstractAction
(*args, **kwargs)[source]¶ Abstract base class for actions (i.e. callables that do something but do not necessarily return anything.
-
class
automate.callables.builtin_callables.
Attrib
(*args, **kwargs)[source]¶ Give specified attribute of a object.
Parameters: bool (no_eval) – if True, evaluation of object is skipped – use this to access attributes of SystemObjects Usage & example:
Attrib(obj, 'attributename') Attrib(sensor_name, 'status', no_eval=True)
-
class
automate.callables.builtin_callables.
Method
(*args, **kwargs)[source]¶ Call method in an object with specified args
Usage:
Method(obj, 'methodname')
-
class
automate.callables.builtin_callables.
Func
(*args, **kwargs)[source]¶ Call function with given arguments.
Usage & example:
Func(function, *args, **kwargs) Func(time.sleep, 2)
Parameters: add_caller (bool) – if True, then caller program is passed as first argument.
-
class
automate.callables.builtin_callables.
OnlyTriggers
(*args, **kwargs)[source]¶ Baseclass for actions that do not have any targets (i.e. almost all actions).
-
class
automate.callables.builtin_callables.
Log
(*args, **kwargs)[source]¶ Print callable argument outputs / other arguments to the log.
Usage:
Log(object1, object2, 'string1'...)
Parameters: log_level (str) – Log level (i.e. logging function name) (default ‘info’)
-
class
automate.callables.builtin_callables.
Debug
(*args, **kwargs)[source]¶ Same as
Log
but with debug logging level.
-
class
automate.callables.builtin_callables.
ToStr
(*args, **kwargs)[source]¶ Return string representation of given arguments evaluated. Usage:
ToStr('formatstring {} {}', callable1, statusobject1)
Parameters: no_sub (bool) – if True, removes format string from argument list. Then usage is simply: ToStr(callable1, statusobject1, no_sub=True)
-
class
automate.callables.builtin_callables.
Eval
(*args, **kwargs)[source]¶ Execute python command given as a string with eval (or exec).
Usage:
Eval("print time.{param}()", pre_exec="import time", param="time")
First argument: python command to be evaluated. If it can be evaluated by eval() then return value is the evaluated value. Otherwise, exec() is used and True is returned.
Parameters: - pre_exec (str) – pre-execution string. For example necessary import commands.
- namespace (dict) – Namespace. Defaults to locals() in
builtin_callables
.
Optionally, other keyword arguments can be given, and they are replaced in the first argument by format().
See also (and prefer using):
Func
-
class
automate.callables.builtin_callables.
GetService
(*args, **kwargs)[source]¶ Get service by name and number.
Usage:
GetService(name) GetService(name, number)
Usage examples:
GetService('WebService') GetService('WebService', 1)
-
class
automate.callables.builtin_callables.
ReloadService
(*args, **kwargs)[source]¶ Reload given service.
Usage:
ReloadService(name, number) ReloadService(name)
Usage examples:
ReloadService('WebService', 0) ReloadService('ArduinoService')
-
class
automate.callables.builtin_callables.
Shell
(*args, **kwargs)[source]¶ Execute shell command and return string value
Parameters: Usage examples:
Shell('/bin/echo test', output=True) # returns 'test' Shell('mplayer something.mp3', no_wait=True) # returns PID of mplayer # process that keeps running Shell('/bin/cat', input='test', output=True) # returns 'test'.
-
class
automate.callables.builtin_callables.
SetStatus
(*args, **kwargs)[source]¶ Set sensor or actuator value
Usage:
SetStatus(target, source) # sets status of target to the status of source. SetStatus(target, source, Force=True) # sets status to hardware level even if it is not changed SetStatus([actuator1, actuator2], [sensor1, sensor2]) # sets status of actuator 1 to status of sensor1 and # status of actuator2 to status of sensor2.
-
class
automate.callables.builtin_callables.
SetAttr
(obj, **kwargs)[source]¶ Set object’s attributes
Usage:
SetAttr(obj, attr=value, attr2=value2) # performs setattr(obj, attr, value) and setattr(obj, attr2, value2).
-
class
automate.callables.builtin_callables.
Changed
(*args, **kwargs)[source]¶ Is value changed since evaluated last time? If this is the first time this Callable is called (i.e. comparison to last value cannot be made), return True.
Usage:
Changed(sensor1)
-
class
automate.callables.builtin_callables.
Swap
(*args, **kwargs)[source]¶ Swap sensor or BinaryActuator status (False to True and True to False)
Usage:
Swap(actuator1)
-
class
automate.callables.builtin_callables.
AbstractRunner
(*args, **kwargs)[source]¶ Abstract baseclass for Callables that are used primarily to run other Actions
-
class
automate.callables.builtin_callables.
Run
(*args, **kwargs)[source]¶ Run specified Callables one at time. Return always True.
Usage:
Run(callable1, callable2, ...)
-
class
automate.callables.builtin_callables.
Delay
(*args, **kwargs)[source]¶ Execute commands delayed by time (in seconds) in separate thread
Usage:
Delay(delay_in_seconds, action)
-
class
automate.callables.builtin_callables.
Threaded
(*args, **kwargs)[source]¶ Execute commands in a single thread (in order)
Usage:
Threaded(action)
-
class
automate.callables.builtin_callables.
If
(*args, **kwargs)[source]¶ Basic If statement
Usage:
If(x, y, z) # if x, then run y, z, where x, y, and z are Callables or StatusObjects If(x, y)
-
class
automate.callables.builtin_callables.
IfElse
(*args, **kwargs)[source]¶ Basic if - then - else statement
Usage:
IfElse(x, y, z) # if x, then run y, else run z, where x, y, # and z are Callables or StatusObjects IfElse(x, y)
-
class
automate.callables.builtin_callables.
Switch
(*args, **kwargs)[source]¶ Basic switch - case statement.
Two alternative usages:
- First argument switch criterion (integer-valued) and others are cases OR
- First argument is switch criterion and second argument is dictionary that contains all possible cases as keys and related actions as their values.
Usage:
Switch(criterion, choice1, choice2...) # where criteria is integer-valued # (Callable or StatusObject etc.) # and choice1, 2... are Callables. Switch(criterion, {'value1': callable1, 'value2': 'callable2'})
-
class
automate.callables.builtin_callables.
TryExcept
(*args, **kwargs)[source]¶ Try returning x, but if exception occurs in the value evaluation, then return y.
Usage:
Try(x, y) # where x and y are Callables or StatusObjects etc.
-
class
automate.callables.builtin_callables.
Min
(*args, **kwargs)[source]¶ Give minimum number of given objects.
Usage:
Min(x, y, z...) # where x,y,z are anything that can be # evaluated as number (Callables, Statusobjects etc).
-
class
automate.callables.builtin_callables.
Max
(*args, **kwargs)[source]¶ Give maximum number of given objects
Usage:
Max(x, y, z...) # where x,y,z are anything that can be # evaluated as number (Callables, Statusobjects etc).
-
class
automate.callables.builtin_callables.
Sum
(*args, **kwargs)[source]¶ Give sum of given objects
Usage:
Sum(x, y, z...) # where x,y,z are anything that can be # evaluated as number (Callables, Statusobjects etc).
-
class
automate.callables.builtin_callables.
Product
(*args, **kwargs)[source]¶ Give product of given objects
Usage:
Product(x, y, z...) # where x,y,z are anything that can be # evaluated as number (Callables, Statusobjects etc).
-
class
automate.callables.builtin_callables.
Division
(*args, **kwargs)[source]¶ Give division of given objects
Usage:
Division(x, y) # where x,y are anything that can be # evaluated as number (Callables, Statusobjects etc).
-
class
automate.callables.builtin_callables.
Anything
(*args, **kwargs)[source]¶ Condition which gives True always
Usage:
Anything(x,y,z...)
-
class
automate.callables.builtin_callables.
Or
(*args, **kwargs)[source]¶ Or condition
Usage:
Or(x,y,z...) # gives truth value of x or y or z or ,,,
-
class
automate.callables.builtin_callables.
And
(*args, **kwargs)[source]¶ And condition
Usage:
And(x,y,z...) # gives truth value of x and y and z and ...
-
class
automate.callables.builtin_callables.
Neg
(*args, **kwargs)[source]¶ Give negative of specified callable (minus sign)
Usage:
Neg(x) # returns -x
-
class
automate.callables.builtin_callables.
Inverse
(*args, **kwargs)[source]¶ Give inverse of specified callable (1/something)
Usage:
Inv(x) # returns 1/x
-
class
automate.callables.builtin_callables.
Not
(*args, **kwargs)[source]¶ Give negation of specified object
Usage:
Not(x) # returns not x
-
class
automate.callables.builtin_callables.
Equal
(*args, **kwargs)[source]¶ Equality condition, i.e. is x == y
Usage:
Equal(x, y) # returns truth value of x == y
-
class
automate.callables.builtin_callables.
Less
(*args, **kwargs)[source]¶ Condition: is x < y
Usage:
Less(x,y) # returns truth value of x < y
-
class
automate.callables.builtin_callables.
More
(*args, **kwargs)[source]¶ Condition: is x > y
Usage:
More(x,y) # returns truth value of x > y
-
class
automate.callables.builtin_callables.
Value
(*args, **kwargs)[source]¶ Give specified value
Usage:
Value(x) # returns value of x. Used to convert StatusObject into Callable, # for example, if StatusObject status needs to be used directly # as a condition of Program condition attributes.
-
class
automate.callables.builtin_callables.
AbstractQuery
(*args, **kwargs)[source]¶ Baseclass for query type of Callables, i.e. those that return set of objects from system based on given conditions.
-
class
automate.callables.builtin_callables.
OfType
(*args, **kwargs)[source]¶ Gives all objects of given type that are found in System
Usage & example:
OfType(type, **kwargs) OfType(AbstractActuator, exclude=['actuator1', 'actuator2']) # returns all actuators in system, except those named 'actuator1' and 'actuator2'.
Parameters: exclude (list) – list of instances to be excluded from the returned list.
-
class
automate.callables.builtin_callables.
RegexSearch
(*args, **kwargs)[source]¶ Scan through string looking for a match to the pattern. Return matched parts of string by
re.search()
.Parameters: group (int) – Match group can be chosen by group number. Usage & examples:
RegexSearch(match_string, content_to_search, **kwargs) RegexSearch(r'(\d*)(\w*)', '12test') # returns '12' RegexSearch(r'(\d*)(\w*)', '12test', group=2) # returns 'test' RegexSearch(r'testasfd', 'test') # returns ''
Tip
More examples in unit tests
-
class
automate.callables.builtin_callables.
RegexMatch
(*args, **kwargs)[source]¶ Try to apply the pattern at the start of the string. Return matched parts of string by
re.match()
.Parameters: group (int) – Match group can be chosen by group number. Usage & examples from unit tests:
RegexMatch(match_string, content_to_search, **kwargs) RegexMatch(r'heptest', 'heptest') # returns 'heptest' RegexMatch(r'heptest1', 'heptest') # returns '' RegexMatch(r'(hep)te(st1)', 'heptest1', group=1) # returns 'hep' RegexMatch(r'(hep)te(st1)', 'heptest1', group=2) # returns 'st1'
Tip
More examples in unit tests
-
class
automate.callables.builtin_callables.
RemoteFunc
(*args, **kwargs)[source]¶ Evaluate remote function via XMLRPC.
Usage:
RemoteFunc('host', 'funcname', *args, **kwargs)
-
class
automate.callables.builtin_callables.
WaitUntil
(*args, **kwargs)[source]¶ Wait until sensor/actuator/callable status changes to True and then execute commands. WaitUntil will return immediately and only execute specified actions after criteria is fullfilled.
Usage:
WaitUntil(sensor_or_callable, Action1, Action2, etc)
Note
No triggers are collected from WaitUntil
-
class
automate.callables.builtin_callables.
While
(*args, **kwargs)[source]¶ Executes commands (in thread) as long as criteria (sensor, actuator, callable status) remains true. Flushes worker queue between each iteration such that criteria is updated, if executed actions alter it.
Parameters: do_after (Callable) – given Callable is executed after while loop is finished. Usage & example:
While(criteria, action1, action2, do_after=action3) # Example loop that runs actions 10 times. Assumes s=UserIntSensor() Run( SetStatus(s, 0), While(s < 10, SetStatus(s, s+1), other_actions ) )
Note
While execution is performed in separate thread
Note
No triggers are collected from While
-
class
automate.callables.builtin_callables.
TriggeredBy
(*args, **kwargs)[source]¶ Return whether action was triggered by one of specified triggers or not
If no arguments, return the trigger.
Usage:
TriggeredBy() # -> returns the trigger TriggeredBy(trig1, trig2...) #-> Returns if trigger is one of arguments
Other Callable-like utilities¶
-
class
automate.tools.
PushOver
(name='', **traits)[source]¶ Send push notifications to android/IOS phones (see http://pushover.net).
Use this as you would use a Callable.
-
api_key
= None¶ Pushover.net application/API token
-
user_key
= None¶ Pushover.net user key
-
priority
= None¶ Pushover.net message priority
-
device
= None¶ Device name (empty to send to all devices)
-
sound
= None¶ Sound name in device
-
-
class
automate.tools.
EmailSender
(name='', **traits)[source]¶ Send email notification of the current status of the system
-
to_email
= None¶ Email address where email is to be sent
-
smtp_hostname
= None¶ Smtp server
-
smtp_username
= None¶ SMTP username
-
smtp_password
= None¶ SMTP password
-
smtp_fromname
= None¶ Name that appears in From: field
-
smtp_fromemail
= None¶ Email that appears in From: field
-
Automate System¶
Introduction¶
automate.system.System
encapsulates the state machine parts into single object. It has already been
explained how to use System. Here we will go further into some details.
Groups¶
In Automate system, it is possible to group objects by putting them to Groups. Grouping helps organizing objects in code level as well as in GUIs (Web User Interface for Automate etc.).
Here is an example:
class MySystem(System):
class group1(Group):
sensor1 = UserBoolSensor()
sensor2 = UserBoolSensor()
class group2(Group):
sensor3 = UserBoolSensor()
sensor4 = UserBoolSensor()
By adding SystemObject to a group, will assign it a tag corresponding to its groups class name. I.e. here,
sensor1
and sensor2
will get tag group:group1 and sensor3
and sensor4
will get tag group:group2.
System has single namespace dictionary that contains names of all objects. That implies that objects in different groups may not have same name.
System State Saving and Restoring via Serialization¶
If System state is desired to be loaded later from periodically auto-saved state dumps,
system can be instantiated via load_or_create()
as follows:
my_system_instance = MySystem.load_or_create('my_statedump.dmp')
Then system state will be saved periodically (by default, once per 30 minutes) by
StatusSaverService
, which is automatically loaded
service (see Services). If you desire to change
interval, you need to explicitly define
dump_interval
as follows:
status_saver = StatusSaverService(dump_interval=10) # interval in seconds
my_system_instance = MySystem.load_or_create('my_statedump.dmp', services=[status_saver])
SystemObject¶

SystemObject
is baseclass for all objects that may be used within
System
(most importantly,
Sensors, Actuators and Programs).
Due to multiple inheritance, many SystemObjects,
such as Sensors (AbstractSensor
),
Actuators (AbstractActuator
), and
Programs (Program
) can act in multiple roles,
in addition to their primary role, as follows:
- Sensors and actuators can always be used also as a program i.e. they may have conditions
and action callables defined, because they derive from
ProgrammableSystemObject
. - Both Actuators and Sensors can be used as triggers in Callables and via them in Programs
- Also plain Programs can be used as a Sensor. Then its activation status (boolean) serves as Sensor status.
Sensors and Programs do not have Actuator properties (i.e. per-program statuses), but
Sensor status can still be set/written by a Program, similarly to actuators with
slave
attribute set to True.
System Class Definition¶
-
class
automate.system.
System
(loadstate=None, **traits)[source]¶ -
allow_name_referencing
= None¶ Allow referencing objects by their names in Callables. If disabled, you can still refer to objects by names by Object(‘name’)
-
filename
= None¶ Filename to where to dump the system state
-
logfile
= None¶ Name of the file where logs are stored
-
print_level
= None¶ Log level for the handler that writes to stdout
-
logger
= None¶ Reference to logger instance (read-only)
-
raven_dsn
= None¶ Sentry: Raven DSN configuration (see http://sentry.io)
-
log_handler
= None¶ Instance to the log handler that writes to stdout
-
log_format
= None¶ Format string of the log handler that writes to stdout
-
print_handler
= None¶ Instance to the log handler that writes to logfile (read-only)
-
logfile_format
= None¶ Format string of the log handler that writes to logfile
-
log_level
= None¶ Log level of the handler that writes to logfile
-
default_services
= None¶ Add here services that you want to be added automatically. This is meant to be re-defined in subclass.
-
services
= None¶ List of services that are loaded in the initialization of the System.
-
exclude_services
= None¶ List of servicenames that are desired to be avoided (even if normally autoloaded).
-
namespace
= None¶ System namespace (read-only)
-
objects_sorted
= None¶ Property giving objects sorted alphabetically (read-only)
-
sensors
= None¶ Read-only property giving all sensors of the system
-
actuators
= None¶ Read-only property giving all actuator of the system
-
programs
= None¶ Read-only property giving all objects that have program features in use
-
ordinary_programs
= None¶ Read-only property giving all
Program
objects
-
worker_autostart
= None¶ Start worker thread automatically after system is initialized
-
pre_exit_trigger
= None¶ Trigger which is triggered before quiting (used by Services)
Read-only property that gives list of all object tags
-
two_phase_queue
= None¶ Enable experimental two-phase queue handling technique (not recommended)
-
classmethod
load_or_create
(filename=None, no_input=False, **kwargs)[source]¶ Load system from a dump, if dump file exists, or create a new system if it does not exist.
-
cmd_namespace
¶ A read-only property that gives the namespace of the system for evaluating commands.
-
get_unique_name
(obj, name='', name_from_system='')[source]¶ Give unique name for an Sensor/Program/Actuator object
-
services_by_name
¶ A property that gives a dictionary that contains services as values and their names as keys.
-
service_names
¶ A property that gives the names of services as a list
-
eval_in_system_namespace
(exec_str)[source]¶ Get Callable for specified string (for GUI-based editing)
-
register_service_functions
(*funcs)[source]¶ Register function in the system namespace. Called by Services.
-
request_service
(type, id=0)[source]¶ Used by Sensors/Actuators/other services that need to use other services for their operations.
-
name
= None¶ Name of the system (shown in WEB UI for example)
-
worker_thread
= None¶ Reference to the worker thread (read-only)
-
raven_client
= None¶ Raven client (is created automatically if raven_dsn is set and this is left empty)
-
post_init_trigger
= None¶ Trigger which is triggered after initialization is ready (used by Services)
-
SystemObjects Class Definition¶
-
class
automate.systemobject.
SystemObject
(name='', **traits)[source]¶ Baseclass for Programs, Sensor, Actuators
-
callables
= []¶ Names of attributes that accept Callables. If there are custom callables being used, they must be added here. The purpose of this list is that these Callables will be initialized properly.
ProgrammableSystemObject
introduces 5 basic callables (see also Programs).
-
get_default_callables
()[source]¶ Get a dictionary of default callables, in form {name:callable}. Re-defined in subclasses.
-
system
= None¶ Reference to System object
-
description
= None¶ Description of the object (shown in WEB interface)
Tags are used for (for example) grouping objects. See Groups.
-
name
= None¶ Name property is determined by System namespace. Can be read/written.
-
hide_in_uml
= None¶ If set to True, current SystemObject is hidden in the UML diagram of WEB interface.
-
view
= ['hide_in_uml']¶ Attributes that can be edited by user in WEB interface
-
data_type
= ''¶ The data type name (as string) of the object. This is written in the initialization, and is used by WEB interface Django templates.
-
editable
= False¶ If editable=True, a quick edit widget will appear in the web interface. Define in subclasses.
-
object_type
¶ A read-only property that gives the object type as string; sensor, actuator, program, other. Used by WEB interface templates.
-
logger
= None¶ Python Logger instance for this object. System creates each object its own logger instance.
-
get_status_display
(**kwargs)[source]¶ Redefine this in subclasses if status can be represented in human-readable way (units etc.)
-
get_as_datadict
()[source]¶ Get information about this object as a dictionary. Used by WebSocket interface to pass some relevant information to client applications.
-
Services¶
Introduction¶
There are two kinds of Services in Automate: UserServices and SystemServices.
SystemServices are mainly designed to implement a practical way of writing an interface between your
custom SystemObjects and their corresponding resources (devices for example). For example,
RpioService
provide access to Raspberry Pi GPIO pins for
RpioActuator
and
RpioSensor
objects,
and ArduinoService, correspondingly, provides access to Arduino devices for ArduinoActuator and ArduinoSensors.
(Arduino and RPIO support are provided by extensions, see Extensions).
UserServices, on the other hand, provide user interfaces to the system. For example,
WebService
provides access to the system via web browser,
TextUIService
via IPython shell and
RpcService
via XmlRPC (remote procedure call) interface for other applications.
If not automatically loaded (services with autoload
set to True
),
they need to be instantiated (contrary to SystemObject
)
outside the System, and given in the initialization of the system (services
).
For example of initialization and configuring of
WebService
, see “Hello World” in Automate.
Services Class Definitions¶
-
class
automate.service.
AbstractService
[source]¶ Base class for System and UserServices
-
autoload
= False¶ If set to True, service is loaded automatically (if not explicitly prevented in
automate.system.System.exclude_services
). Overwrite this in subclasses,
-
Builtin Services¶
-
class
automate.services.logstore.
LogStoreService
[source]¶ Provides interface to log output. Used by WebService.
-
log_level
= None¶ Log level
-
log_length
= None¶ Log length
-
most_recent_line
= None¶ The most recent log line is always updated here. t Subscription to this attribute can be used to follow new log entries.
-
-
class
automate.services.statussaver.
StatusSaverService
[source]¶ Service which is responsible for scheduling dumping system into file periodically.
-
dump_interval
= None¶ Dump saving interval, in seconds. Default 30 minutes.
-
-
class
automate.services.plantumlserv.
PlantUMLService
[source]¶ Provides UML diagrams of the system as SVG images. Used by WebService.
PLantUMLService requires either PlantUML software (which is opensource software written in Java) to be installed locally (see http://plantuml.sourceforge.net/) or it is possible to use online service of plantuml.com In addition you need python package
plantuml
(available via PYPI).-
url
= None¶ URL of PlantUML Java Service. To use PlantUML online service, set this to ‘http://www.plantuml.com/plantuml/svg/‘
-
arrow_colors
= None¶ Arrow colors as HTML codes stored as a dictionary with keys: controlled_target, active_target, inactive_target, trigger
-
background_colors
= None¶ Background colors as HTML codes, stored as a dictionary with keys: program, actuator, sensor
-
-
class
automate.services.textui.
TextUIService
[source]¶ Provides interactive Python shell frontend to the System. Uses IPython if it is installed. Provides couple of functions to the System namespace.
Extensions¶
Automate functionality can be easily extended by various extension modules, and it is also possible to make your own Automate extensions, for details see Making your own Automate Extensions. The following extensions are included in Automate:
Web User Interface for Automate¶
Introduction¶
Automate Web UI extension provides easy to use approach to monitoring and modifying Automate system and its components. Features:
- Displayed data updated in real time via Websocket
- Responsive design (using Bootstrap CSS & JS library), suitable for mobile and desktop use.
- Optional authentication
- Read-only and read-write modes.
- Read-only mode allows only monitoring (default)
- Read-write mode allows modifying the System by:
- adding new Actuators / Sensors / Programs
- modifying existing Actuators / Sensors / Programs
- Quick editing of user-editable sensors from main views
- HTTP and secured HTTPS servers supported (powered by built in Tornado Web Server)
Main features are illustrated with a few screenshots:
Installation¶
Install extras:
pip install automate[web]
Main view¶
In main view you can observe actuator and sensor statuses in real time, and also easily access user-editable sensor statuses. Clicking object name will give more details of the selected item as well as ‘edit’ button. (only in read-write mode).

Edit view¶
In edit view you can edit almost all the attributes of the objects that are in the system. You can also create new ones.

UML view¶
In UML view you can see nice UML diagram of the whole system. To enable UML diagram, you need to set
up PlantUMLService
.

Console view¶
In console view you can see the log as well as type commands same way as in IPython shell.

Example application using Web UI¶
This is extended example of the “Hello World” in Automate, that opens two web services, one for port 8085 and another
in 8086. It will go to UML view by default and in “User defined” -view you will see only web_switch
.
from automate import *
class MySystem(System):
# HW swtich connected Raspberry Pi GPIO port 1
hardware_switch = RpioSensor(port=1)
# Switch that is controllable, for example, from WEB interface
web_switch = UserBoolSensor(tags=['user'])
# Lamp relay that switches lamp on/off, connected to GPIO port 2
lamp = RpioActuator(port=2)
# Program that controls the system behaviour
program = Program(
active_condition = Or('web_switch', 'hardware_switch'),
on_activate = SetStatus('lamp', True)
)
# To view UML diagram, we need to set up PlantUMLService. Here we will use
# plantuml.com online service to render the UML graphics.
plantuml_service = PlantUMLService(url='http://www.plantuml.com/plantuml/svg/')
web_service = WebService(
read_only=False,
default_view='plantuml',
http_port=8085,
http_auth = ('myusername', 'mypassword'),
user_tags = ['user'],
)
# Just to give example of slave feature, let's open another server instance
# at port 8086.
slave = WebService(
http_port=8086,
slave=True,
)
my_system = MySystem(services=[plantuml_service, web_service, slave])
Tip
Try to run the code in your IPython shell by copying & pasting it with cpaste
command!
WebService class definition¶
-
class
automate.extensions.webui.
WebService
[source]¶ Web User Interface Service for Automate
-
read_only
= None¶ Restrict usage to only monitoring statuses (default:
True
). If WebService is not in read_only mode, it is possible to run arbitrary Python commands through eval/exec via web browser. This is, of course, a severe security issue. Secure SSL configuration HIGHLY recommended, if not operating inread_only
mode.
-
default_view
= None¶ Default view that is displayed when entering the server. Can be the name of any view in views.py
-
show_actuator_details
= None¶ Below Actuator row, show active Programs that are controlling Actuator
-
http_port
= None¶ HTTP port to listen
-
http_auth
= None¶ Authentication for logging into web server. (user,password) pairs in a tuple.
-
websocket_timeout
= None¶ Let websocket connection die after
websocket_timeout
time of no ping reply from client.
Tags that are shown in user defined view
-
debug
= None¶ Django debugging mode (slower, more info shown when error occurs)
-
custom_pages
= None¶ User-defined custom pages as a dictionary of form
{name: template_content}
-
slave
= None¶ set to True, if you want to launch multiple servers with same system. Authentication and other settings are then taken from master service. Only web server settings (http host/port) are used from slave.
-
django_settings
= None¶ In this dictionary you can define your custom Django settings which will override the default ones
-
redirect_from_setters
= None¶ From /set/object/value and /toggle/object, redirect to /set_ready/object/value after after executing action
Show hidden objects in web UI (those prefixed with _)
-
server_url
= None¶ Full exposed url root
-
WSGI Support for Automate¶
This extension provides Web server for WSGI-aware extensions, such as Remote Procedure Call Support for Automate, Web User Interface for Automate. It is of no use alone.
Class definition¶
-
class
automate.extensions.wsgi.
TornadoService
[source]¶ Abstract service that provides HTTP server for WSGI applications.
-
http_ipaddr
= None¶ Which ip address to listen. Use
0.0.0.0
(default) to listen to all local networking interfaces.
-
http_port
= None¶ HTTP (or HTTPS if using SSL) port to listen
-
ssl_certificate
= None¶ Path to ssl certificate file. If set, SSL will be used.
Tip
You may use script scripts/generate_selfsigned_certificate.sh to generate a self-signed openssl certificate.
-
ssl_private_key
= None¶ Path to ssl private key file
-
num_threads
= None¶ Number of listener threads to spawn
-
static_dirs
= None¶ Extra static dirs you want to serve. Example:
static_dirs = {'/my_static/(.*)': '/path/to/my_static'}
-
Remote Procedure Call Support for Automate¶
Introduction¶
This extension provides XmlRPC API for external applications. Exported API is by default defined by
automate.extensions.rpc.rpc.ExternalApi
.
Class definitions¶
-
class
automate.extensions.rpc.
RpcService
[source]¶ Tags that are displayed via get_websensors RPC function
-
api
= None¶ If you want to define custom api (similar to, or derived from
ExternalApi
, it can be given here.
Arduino Support for Automate¶
Introduction¶
This extension provides interface to Arduino devices via pyFirmata library.
Example application¶
This example application sets up couple of analog and digital Arduino Sensors and Actuators.
It also introduces Servo actuator with ConstantTimeActuator
,
which functions such a way that if value of a1
changes, the value of servo
will change smoothly
within given time interval.
from automate import *
class MySystem(System):
a1 = ArduinoAnalogSensor(dev=0, pin=0)
d12 = ArduinoDigitalSensor(dev=0, pin=12)
d13 = ArduinoDigitalActuator(dev=0, pin=13) # LED on Arduino board
servo = ArduinoServoActuator(min_pulse=200,
max_pulse=8000,
dev=0,
pin=3,
default=50,
slave=True)
interp = ConstantTimeActuator(change_time=2.,
change_frequency=20.,
slave_actuator=servo)
prog = Program(
on_update=Run(Log("Value: %s", Value(a1)),
SetStatus(d13, d12),
SetStatus(interp, Value(180) * Value(a1)))
)
my_arduino = ArduinoService(
arduino_devs=["/dev/ttyUSB0"],
arduino_dev_types=["Arduino"],
arduino_dev_sampling=[500])
s = MySystem(services=[my_arduino, WebService()])
Class definitions¶
Service¶
-
class
automate.extensions.arduino.
ArduinoService
[source]¶ Service that provides interface to Arduino devices via pyFirmata library.
-
arduino_devs
= None¶ Arduino devices to use, as a list
-
arduino_dev_types
= None¶ Arduino device board types, as a list of strings. Choices are defined by pyFirmata board class names, i.e. allowed values are “Arduino”, “ArduinoMega”, “ArduinoDue”.
-
arduino_dev_sampling
= None¶ Arduino device sampling rates, as a list (in milliseconds).
-
Sensors¶
-
class
automate.extensions.arduino.
AbstractArduinoSensor
(*args, **kwargs)[source]¶ Abstract base class for Arduino sensors
-
dev
= None¶ Arduino device number (specify, if more than 1 devices configured in ArduinoService)
-
pin
= None¶ Arduino pin number
-
Actuators¶
-
class
automate.extensions.arduino.
AbstractArduinoActuator
(*args, **kwargs)[source]¶ Abstract base class for Arduino actuators
-
dev
= None¶ Arduino device number (specify, if more than 1 devices configured in ArduinoService)
-
pin
= None¶ Arduino pin number
-
-
class
automate.extensions.arduino.
ArduinoDigitalActuator
(*args, **kwargs)[source]¶ Boolean-valued actuator object for digital Arduino output pins
-
class
automate.extensions.arduino.
ArduinoPWMActuator
(*args, **kwargs)[source]¶ Float-valued actuator object for Arduino output pins that can be configured in PWM mode Status is float between 0.0 and 1.0.
-
class
automate.extensions.arduino.
ArduinoServoActuator
(*args, **kwargs)[source]¶ Float-valued actuator object for Arduino output pins that can be configured in Servo mode Status is servo angle (0-360).
-
min_pulse
= None¶ Minimum pulse time (in microseconds)
-
max_pulse
= None¶ Maximum pulse time (in microseconds)
-
Raspberry Pi GPIO Support for Automate¶
Introduction¶
This extension provides interface to Raspberry Pi GPIO via RPIO library. RPIO library.
Example application¶
This simple example application sets up simple relation between input pin button
in port 22 and
output pin light
in port 23. If for a button is attached in button
, pushing it down
will light the led, that is attached to light
.
from automate import *
from automate.extensions.rpio import RpioSensor, RpioActuator
class MySystem(System):
button = RpioSensor(port=22, button_type='down')
light = RpioActuator(port=23, change_delay=2)
myprog = Program(active_condition=Value('mysensor'),
on_activate=SetStatus('myactuator', True))
mysystem = MySystem()
Class definitions¶
Service¶
-
class
automate.extensions.rpio.
RpioService
[source]¶ Service that provides interface to Raspberry Pi GPIO via RPIO library.
-
gpio_cleanup
= None¶ Perform GPIO cleanup when exiting (default: False).
-
rpio
= None¶ Use RPIO instead of RPI.GPIO
-
Sensors¶
-
class
automate.extensions.rpio.
RpioSensor
(*args, **kwargs)[source]¶ Boolean-valued sensor object that reads Raspberry Pi GPIO input pins.
-
port
= None¶ GPIO port
-
inverted
= None¶ Set to True to have inversed status value
Button setup: “down”: pushdown resistor, “up”: pushup resistor, or “none”: no resistor set up.
-
-
class
automate.extensions.rpio.
RpioSensor
(*args, **kwargs)[source] Boolean-valued sensor object that reads Raspberry Pi GPIO input pins.
-
port
= None GPIO port
-
inverted
= None Set to True to have inversed status value
-
button_type
= None Button setup: “down”: pushdown resistor, “up”: pushup resistor, or “none”: no resistor set up.
-
Actuators¶
-
class
automate.extensions.rpio.
RpioActuator
(*args, **kwargs)[source]¶ Boolean-valued actuator for setting Raspberry Pi GPIO port statuses (on/off).
-
port
= None¶ GPIO port id
-
inverted
= None¶ Set to True to have inversed status value
-
-
class
automate.extensions.rpio.
TemperatureSensor
(*args, **kwargs)[source]¶ W1 interface (on Raspberry Pi board) that polls polling temperature. (kernel modules w1-gpio and w1-therm required). Not using RPIO, but placed this here, since this is also Raspberry Pi related sensor.
-
addr
= None¶ Address of W1 temperature sensor (something like
"28-00000558263c"
), see what you have in/sys/bus/w1/devices/
-
max_jump
= None¶ Maximum jump in temperature, between measurements. These temperature sensors tend to give sometimes erroneous results.
-
max_errors
= None¶ Maximum number of erroneous measurements, until value is really set
-
-
class
automate.extensions.rpio.
RpioPWMActuator
(*args, **kwargs)[source]¶ Actuator to control PWM (pulse-width-modulation) ports on Raspberry pi GPIO.
Status range 0...1
This is not recommended to be used because RPIO PWM implementation is not very well behaving. I recommend to use ArduinoPWMActuator with an Arduino loaded with StandardFirmata. It’s much more stable and robust solution.
-
port
= None¶ GPIO port number
-
dma_channel
= None¶ RPIO PWM DMA channel
-
frequency
= None¶ PWM frequency (Hz)
-
Making your own Automate Extensions¶
Extension Development¶
Automate extensions allow extending Automate functionalities by writing external libraries that may consist of new Service, Sensor, Actuator, or Callable classes.
To start developing automate extensions, it is recommended to use cookiecutter template. This is how it works:
Install
cookiecutter
1.0.0 or newer:pip install cookiecutter
Generate a Automate extension project:
cookiecutter https://github.com/tuomas2/cookiecutter-automate-ext-template.git
Cookiecutter asks few questions and you have great basis for starting your template development. There will be created Python files where you may add your new custom Automate classes.
For your classes to be exported to the Automate, make sure that they are listed in
extension_classes
list in __init__.py
of the extension module.
All installed Automate Extensions are available from Automate applications and are imported to automate namespace.
Tip
You can install your extension in editable mode by running pip install -e .
in your extension root directory.
Tip
You can look at Extensions for examples.