Skip to content
kernelkitPublic

About

If Input, Then Output

Resources

Stars

3 stars

Watchers

2 watching

Forks

Latest commit

 

History

28 Commits

Folders and files

Repository files navigation

iito - If Input, Then Output

Monitor input sources, and reflect their state on output sinks.

Inputs are things like file attributes (e.g. presence or absence) or device properties (e.g. the online status of a power supply). The canonical output sink is an LED.

Usage

By default, the iito daemon, iitod, will its configuration file iitod.json from the configured --sysconfdir (typically /etc or /usr/local/etc). In this scenario, iitod can be started without any options:

~# iitod

The runtime behavior is wholly determined by the contents of its JSON config file. The top-level object contains one input and one output which, in turn, contain one object per input/output driver. Each driver object then contains all the objects of that type.

In addition to any driver specific config options, output devices also define a list of rules. Each rule defines a condition that must be met in order for the rule to match via its if property. When a matching rule is found, the contents rule's then property is applied to the output device in question.

Example:

Let's say we have a system with 4 pairs of red/green LEDs:

.------------- - - -
| Foobar2000
|
| (@) BOOT
| (@) STAT
|
| (@) PWR1
| (@) PWR2
'------------- - - -

Both BOOT and STAT are fully software controlled. The red channel of each power LED is also software controlled while the green channel is hardwired to the source's power-good signal.

Here is an example iitod configuration for this system:

{
	"input": {
		"path": {
			"here-i-am": { "path": "/run/here-i-am" },
			"panic": { "path": "/run/panic" },
			"boot-ok": { "path": "/run/boot-ok" },
			"mydaemon": { "path": "/run/mydaemon.pid" }
		},
		"udev": {
			"power-1": { "subsystem": "power_supply" },
			"power-2": { "subsystem": "power_supply" }
		}
	},

	"output": {
		"led": {
			"red:boot": {
				"rules": [
					{ "if": "here-i-am", "then": { "brightness": false } },
					{ "if": "panic", "then": { "trigger": "timer" } },
					{ "if": "!boot-ok", "then": { "trigger": "timer" } }
				]
			},
			"green:boot": {
				"rules": [
					{ "if": "here-i-am", "then": { "trigger": "timer" } },
					{ "if": "panic", "then": { "brightness": false } },
					{ "if": "boot-ok", "then": { "brightness": true } }
				]
			},
			"red:status": {
				"rules": [
					{ "if": "here-i-am", "then": { "brightness": false } },
					{ "if": "panic", "then": { "trigger": "timer" } },
					{ "if": "!mydaemon", "then": { "trigger": "timer" } }
				]
			},
			"green:status": {
				"rules": [
					{ "if": "here-i-am", "then": { "trigger": "timer" } },
					{ "if": "panic", "then": { "brightness": false } },
					{ "if": "mydaemon", "then":
						{
							"trigger": "timer",
							"delay_on": 900,
							"delay_off": 100
						}
					}
				]
			},

			"red:power-1": {
				"rules": [
					{ "if": "panic", "then": { "trigger": "timer" } },
					{ "if": "!power-1:online", "then": { "trigger": "timer" } }
				]
			},
			"red:power-2": {
				"rules": [
					{ "if": "panic", "then": { "trigger": "timer" } },
					{ "if": "!power-1:online", "then": { "trigger": "timer" } }
				]
			}
		}
	}
}

In this example, we define a handful of marker file inputs in /run. These are created and destroyed by other components in the system, e.g. /run/mydaemon.pid is likely managed by the mydaemon process, others may be created by init scripts, etc.

Some observations about rules:

  • They are evaluated in-order. The first condition to match is applied to the output.
  • Conditions may be inverted by prepending a ! to it.
  • Input devices may support multiple properties, e.g. online in the case of power supplies. If a condition does not specify any property, the input's default property is used.
  • If no rule matches, the output reverts to a default state determined by the driver.

BOOT and STAT Behavior

There are two global states that control both LEDs in unison:

Cond BOOT & STAT
here-i-am Blink green
panic Blink red

If none of these apply, the BOOT LED is controlled by the boot-ok marker file:

boot-ok BOOT
true Solid green
false Blink red

The STAT LED is tied to the running status of mydaemon:

mydaemon STAT
true Blink green (90% duty cycle)
false Blink red

PWR1 / PWR2 Behavior

In case of a panic condition, both LEDs blink red in unison with BOOT and STAT. Otherwise, a power LED will blink red in the case when their respective power supply is offline (!online). When none of these rules match, the LED will show a solid green, since an LEDs default rule is "off", and the green LEDs are hardwired to "on".

Querying and Controlling iitod

iitod listens on /run/iitod.sock, owned by root:wheel with mode 0660, so members of wheel need no sudo. Use -s PATH to listen on another path.

The iitoctl tool shows each output's rules, with their current value and the active rule marked with *:

~$ iitoctl
Locate: off

INPUT         TYPE     VALUE
true          builtin  true
locate        path     false
startup       path     true
panic         path     false

sys:green:status (led)
    IF         VALUE  THEN
    locate     false  @blink-1hz
    panic      false  @blink-5hz
  * startup    true   @on
    true       true   @blink-1hz

iitoctl locate on creates the file of the configuration's locate path input, until iitoctl locate off, or with iitoctl locate on 60, for 60 seconds. Which LEDs blink, and how, is up to the rules using the locate input, e.g., { "if": "locate", "then": "@blink-5hz" }.

With -j the reply from iitod is printed as JSON. The protocol is one newline terminated JSON request per connection, answered with one JSON reply:

{ "method": "status" }
{ "method": "locate", "params": { "enable": true, "timeout": 60 } }

{ "result": { ... } }
{ "error": "reason" }

locate without params reports the current state. While a timeout is running, the locate and status replies include the remaining seconds.

Building and Installing

iito uses Autotools, so the procdure is hopefully familiar to many.

If you are building from a cloned GIT repo (as opposed to a release tarball), you have to start by generating the configure script:

~/iito$ ./autogen.sh

To build and install with the default settings:

~/iito$ ./configure && make && sudo make install

Testing

As the test suite needs to create virtual LEDs, dummy network device, etc., it requires root privileges to run. A suitable incantation is therefore typically:

~/iito$ sudo make check

About

If Input, Then Output

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages