This is a copy from the HomeAutomation project documentation PDF.
To get an overview of the different components in the HomeAutomation system and their functionality, this section will follow a user action through the HA stack with reasonable detail: A user presses an in-wall switch to turn on the light in a room.
This explanation will neccessarily include more technical details than are discussed on these web pages, for example message identifiers exchanged on the bus, and hardware component details. If required, these can be looked up in the PDF documentation..
A digital input controller frequently checks its connected inputs for state
changes. As long as the user presses the pushbutton light switch, this
causes one of the controller's input lines to read a high level, which is a
change from the default low level. Therefore, the controller sends an
INDIGPULSE message on the CAN bus, informing the HACS about that
change in state.
This message is read from the bus by the CAN/USB interface attached to the
HACS, and converted into a serial line message. This in turn is read by
ha_iod on the HACS, and dispatched to its TCP clients.
One receiving TCP client is
ha_control's iodclt thread, which is now
responsible for generating an event message from this datagram, and placing
it on the queues of other
ha_control threads that have registered for
notification about such events. For compatibility with the user-centric
configuration file, the CAN-bus identifier (bus number, DID and channel
number) is converted to the room.number identifier when creating the event
notice. As layer of abstraction on the input side, the
notice is translated to a
At least the actor thread is then notified about this event.
The actor thread has a table of possible events and the associated actions
as configured through the
actions.xml configuration and associated
configuration files, in particular macros and group configurations. As a
single light is to be switched, macros and groups do not apply for this
example, though, so the action to cause is just the immediate switching of a
single device. This device is identified by its device identificator
(room.number type), and the matching Device instance (in this case, a
relayoutputclass Device instance) is looked up.
The actor thread has been configured by the user to create an
output_toggle action when a
switch_toggled event is received for the
respective light switch device, so it calls the
method with the
Device.action_trigger() method creates from this an action
command as a CAN datagram (actually, a list of CAN datagrams containing only
a single datagram). The
Device class knows its own address in
both room.number and bus+DID+channel forms. The created datagram is
addressed to the CAN address of the digital output controller to which the
actor for the lamp is connected, the MTID is set as
data to the channel number.
data is set to 3, the
toggle command. The completed datagram is then handed to the iodclt
thread for transmission down the stream.
The iodclt thread sends the datagram through its TCP connection to
ha_iod, which in turn reformats it and sends it through the USB-serial
line to the CAN/USB controller. This device creates an actual CAN message
from it, identifies the bus number to use, places it in the respective CAN
controller's transmission buffer, and initiates the transmission. As soon
as the bus is free to be used (or the HACS' CAN interface wins the bus
arbitration process), the datagram will be transmitted to the actor bus
On the actor bus device, the message is received and evaluated, resulting in the identification of the I/O port for which a newly set state is desired. First, the current state of the port is measured through the actor's feedback line. Because the toggle command was received, this state is inverted to get the actually desired new state. The respective I/O port control signal is asserted to switch the actor, and the feedback line is monitored until the desired state has been entered, or a timeout has been reached. Then, the I/O port control signal is deactivated again, and a final measurement is done on the feedback line. If all components work, this measurement gives the desired new port state, and the respective room is illuminated now.
If the I/O port is found to be in the desired state, the bus device sends a
SYSM_LO_C, CI=S_IOSTATE CAN message for the respective channel number and
including the new state value to signal either
off. If the final
feedback line measurement did not confirm the desired state, a
CI=S_OFAIL message is sent instead, and the I/O port is marked as failed in
non-volatile memory in the bus device. If a timeout has occurred while
driving the actor, but the final measurement confirms that the new state has
been activated on the actor, a
SYSM_LO_C, CI=S_ODEGRAD message is sent,
and the I/O port is not registered as failed. In that case, operator
interaction would still be expected to mitigate the imminent risk of the
output device terminally failing.
SYSM_LO_C message sent by the bus device is received by
ha_control as detailed above, and handed to the Device instance which
commanded the change in state by calling
with the respective event message as parameter. There, the internal state
of the bus device is updated accordingly (Device.currentstate is set to
reflect the new state of the actor).
If an error indicator (
SYSM_LO_C, CI=S_OFAIL or
was received instead, appropriate error reporting would be initiated by
ha_control on request of the Device instance.