Performer and Protocols

A Performer is the entity that binds together an Appliance, its protocol commands and its protocol triggers.

Protocol commands create protocol messages for one or more physical devices realizing the Appliance. Protocol triggers map protocol messages from one or more physical devices to events for the realized Appliance.

Performers translate received protocol messages to events for an Appliance through protocol triggers. When an Appliance has changed its State, Performers translate the transaction from an old Appliance State to a new Appliance State in a list of protocol messages through protocol commands.

Tip

Many commands and triggers can be grouped together inside the same Performer.

When a trigger inside a Performer is triggered then the commands belonging to the same Performer are executed:

- !Performer
  name: "sonos relative volume command up"
  for appliance: "a sound player"
  triggers:
  - !knx_plugin.trigger.dpt_control_dimming.step.up.Trigger {addresses: [0x0C09]}
  commands:
    - !soco_plugin.command.volume.relative.Command {addresses: ["Bath"], fields: {"delta": 10}}

- !Performer
  name: "sonos relative volume command down"
  for appliance: "a sound player"
  triggers:
  - !knx_plugin.trigger.dpt_control_dimming.step.down.Trigger {addresses: [0x0C09]}
  commands:
    - !soco_plugin.command.volume.relative.Command {addresses: ["Bath"], fields: {"delta": -10}}

The above yaml syntax groups together an appliance named a sound player with some KNX protocol triggers and some Sonos protocol commands (using the soco library).

When a KNX push button, with address 0x0C09, is pressed to send a DPT_Control_Dimming step up then the Performer named sonos relative volume command up will create a message to increase volume by 10 for a Sonos device named Bath.

When a KNX push button, with address 0x0C09, is pressed to send a DPT_Control_Dimming step down message then the Performer named sonos relative volume command down will create a message to decrease volume by 10 for a Sonos device named Bath.

Tip

Yaml syntax uses Performers to define Scheduler triggers it is easier to use and re-use a Performer when it has few triggers or commands.

Use multiple Performers instead of grouping together many commands and triggers when the Performers are thought to be used by Scheduler Triggers.

Note

The home package has only an abstract definition for every entity in the home.protocol package.

Implementations are found in external packages, one for every protocol.

Right now, available protocol plugins are:

  • knx_plugin

  • lifx_plugin

  • sonos_plugin

  • home_assistant_plugin

Performer (Class Diagram)

_images/performer_class_diagram.tex.svg

Protocol Triggers

Every time the system receives a message through one of its Protocol Gateways the message is checked against compatible Protocol Triggers.

When a Protocol Trigger is triggered all the Performers which own it will potentially notify related events to their Appliances.

Protocol Triggers can be triggered for many different reasons:

  • a defined kind of protocol message is arrived

  • a number of defined kinds of protocol messages are arrived

  • a mean value for some protocol messages values has been reached

  • a protocol message value is greater than, smaller than or in between some other given value

  • a mix of the above conditions is met

  • and so on

A Protocol Trigger owns a list of Events which are used when it has been triggered.

Returned Events can be obtained applying functions to data collected in the trigger: values in the payload, a mean of multiple messages values, a count of messages and so on.

Performers and Protocol Triggers

_images/performer_protocol_trigger_component_diagram.tex.svg

Update an Appliance state when a protocol message is received

_images/event_from_protocol_sequence_diagram.tex.svg

Lux value changed example

A really simple trigger, which is triggered by any knx received message on address 0xAAAA containing a lux value, can be used to always update the measured value inside an Appliance representing a lux sensor:

- !Performer
  name: "sun lux sensor trigger"
  for appliance: "sun lux sensor"
  commands: []
  triggers:
  - !knx_plugin.trigger.dpt_value_lux.Always {addresses: [0xAAAA]}

The following is a simple, always updating, KNX Trigger:

>>> knx_plugin.trigger.dpt_value_lux.Always.make([0xAAAA, ])
_images/scenario_lux_sensor.tex.svg

Sun brightness is high example

A slightly more complex trigger that can be used to notify a sun is bright event to some Appliance sensible to a home.event.sun.Bright event:

>>> knx_plugin.trigger.dpt_value_lux.Bright.make([0xAAAA, ])

Light is forced on example

When a button is pressed by the user to turn on the light then the user is saying to the system:

hei, I want the light to stay turned on, do not touch it.

The following is a simple KNX Trigger with a forcing on event notified every time a on message on address 0xBBBB through the knx protocol is received:

>>> knx_plugin.trigger.dpt_switch.On.make([0xBBBB, ], [home.appliance.light.event.forced.Event.On,])
_images/scenario_light_trigger.tex.svg

Protocol Commands

The Protocol Commands are those entities which translate the Abstract Appliance State in a protocol message which is able, for example, to turn on or off a device.

A Performer asks to its Protocol Commands to create, if needed, the protocol messages suited to be sent through the Protocol Gateways every time the Appliance state is changed by the system.

Performer and Protocol Commands

_images/performer_protocol_command_component_diagram.tex.svg

Adjust lifx bulb color when knx switch is turned on example

Protocol Commands inside a Performer are always executed when the Appliance State is changed by a Protocol Trigger in the same Performer:

- !Performer
  name: "adjust lifx bulb color when turned on"
  for appliance: "a lifx bulb"
  triggers:
  - !knx_plugin.trigger.dpt_switch.On.make([0xBBBB, ], [home.appliance.light.event.forced.Event.On,])
  commands:
    - !lifx_plugin.command.SetColor {addresses: [["172.31.10.245", 56700]]}
_images/scenario_lifx_command_one_performer.tex.svg

Adjust lifx bulb color a few seconds later the knx switch is turned on example

A Performer Command will send a message to bus few seconds later a Protocol Trigger is triggered if a Scheduler Trigger owning the Performer Trigger has been scheduled with the Performer Command as a target:

 - !Performer
   name: "force on a lifx bulb"
   for appliance: "a lifx bulb"
   triggers:
   - !knx_plugin.trigger.dpt_switch.On.make([0xBBBB, ], [home.appliance.light.event.forced.Event.On,])
   commands: []
 - !Performer
   name: "set color for a lifx bulb"
   for appliance: "a lifx bulb"
   triggers: []
   commands:
   - !lifx_plugin.command.SetColor {addresses: [["172.31.10.245", 56700]]}
- !protocol.delay.Trigger
  name: "adjust lifx bulb color"
  notify more events: []
  when triggered performers: "force on a lifx bulb"
  and timeout expires: 3
- !schedule
  trigger: "adjust lifx bulb color"
  for performers: "set color for a lifx bulb"
_images/scenario_lifx_command_multiple_performers.tex.svg

Appliances and Performers reusability

When an Appliance model has been defined together with the Performers that can change its state then both the Appliance and the Performers can be easily reused simply changing Protocol Triggers and Protocol Commands and, if needed, customizing Appliance and Performers names.

Performer Class

class home.Performer(name: str, appliance: home.Appliance, commands: Iterable[home.protocol.Command], triggers: Iterable[home.protocol.Trigger])

The entity which links together an Appliance, its protocol commands and its protocol triggers.

Through a Performer the physical devices are linked with their abstract Appliance. A Performer keep synchronized physical devices states and Appliance states.

has(description: home.protocol.Description) bool

The Performer has a trigger or command for the given protocol message description?

Parameters

description – A protocol message description

Returns

bool

is_for(appliance: home.Appliance) bool

The Performer is for the given Appliance?

Parameters

appliance – An Appliance to look for

Returns

bool

execute(old_state: home.appliance.State, new_state: home.appliance.State) Iterable[Any]

For every command in Performer make them create messages given old and new Appliance State.

Parameters
  • old_state – the old Appliance State

  • new_state – the new Appliance State

Returns

a list of protocol messages to be send through the Gateway

notify(events: Iterable[home.Event]) Tuple[Iterable[Any], home.appliance.State, home.appliance.State]

Notify to the contained Appliance the given Events. Create the protocol messages with old and new Appliance state.

Parameters

events – Events to be notified to the Appliance

Returns

protocol messages to be sent through the Gateway, old Appliance State and new Appliance State

is_notified(event: home.Event) bool

The given Event is already inside the Appliance State?

Parameters

event – an Event to look for

Returns

bool

update_by(description: home.protocol.Description) Tuple[home.appliance.State, home.appliance.State]

Update the contained Appliance State through the given protocol message description.

Parameters

description – a protocol message description

Returns

(old Appliance State, new Appliance State)

protocol.Description Class

class home.protocol.Description(description)

An abstract Description for a protocol message

property type: str
Returns

a protocol identifier

property label: str
Returns

the label attached to this protocol description

classmethod make(*args, **kwargs) home.protocol.Description

Make a protocol message Description given the arguments.

Parameters
  • args

  • kwargs

Returns

a protocol message Description

classmethod make_from_yaml(*args, **kwargs) home.protocol.Description

Make a protocol message Description given the yaml arguments.

Parameters
  • args

  • kwargs

Returns

a protocol message Description

classmethod make_from(msg: Any) home.protocol.Description

Make a protocol message Description given the protocol message

Parameters

msg – a protocol message

Returns

a protocol message Description

protocol.Trigger Class

class home.protocol.Trigger(description: Any, events: List[home.Event] = None)

An abstract Trigger for a protocol message.

abstract is_triggered(another_description: home.protocol.Description) bool

This trigger is triggered by the given protocol message Description?

Parameters

another_description – a protocol message description

Returns

bool

property events: List[home.Event]

Events to be notified when this Trigger is triggered.

Returns

a list of Events to be notified

make_new_state_from(another_description: home.protocol.Description, old_state: home.appliance.State) home.appliance.State

Given the protocol message Description, if this Trigger is triggered, notify Trigger’s Events to the given state and return new state.

Parameters
  • another_description – a protocol message Description

  • old_state – an Appliance State to be updated

Returns

an updated Appliance State

protocol.Command Class

class home.protocol.Command(description)

An abstract Command for a protocol.

abstract execute()

Build one or more messages for the protocol Gateway, using the internal protocol message representation

Returns

a list of protocol messages

abstract make_msgs_from(old_state: home.appliance.State, new_state: home.appliance.State) List[Any]

Update the internal protocol message representation and call execute to build one or more messages for the protocol Gateway

Parameters
  • old_state – the old Appliance State

  • new_state – the new Appliance State

Returns

a list of protocol messages

protocol.Gateway Class

class home.protocol.Gateway

An Abstract Protocol Gateway.

The entity which can send and receive protocol messages to/from the protocol bus.

abstract associate_commands(descriptions: home.protocol.Description) Any

Connect the Protocol Commands with the Gateway, if needed.

Only connected commands should go through the Gateway to the bus.

Parameters

descriptions – a protocol message description

Returns

an association object, if any

abstract associate_triggers(descriptions: home.protocol.Description)

Connect the Protocol Triggers with the Gateway, if needed.

Only connected triggers should go through the Gateway from the bus.

Parameters

descriptions – a protocol message description

Returns

an association object, if any

abstract async run(tasks: Iterable[Callable])

Create an asynchronous task capable of receiving messages from the bus.

Every received message becomes a Protocol Trigger.

Every created Protocol Trigger goes through given tasks to be processed.

Parameters

tasks – a function capable of process a Protocol Trigger

abstract async writer(msgs: Iterable[Any], *args)

A function capable of sending protocol messages to the bus.

Parameters
  • msgs – a protocol messages

  • args

static make_trigger(msg: Any) home.protocol.Trigger

Make a Protocol Trigger from a protocol message.

Parameters

msg – a protocol message

Returns

a Protocol Trigger