Initial commit
authorBenjamin Braatz <bb@bbraatz.eu>
Wed, 13 Apr 2022 00:31:00 +0000 (02:31 +0200)
committerBenjamin Braatz <bb@bbraatz.eu>
Wed, 13 Apr 2022 00:31:00 +0000 (02:31 +0200)
README [new file with mode: 0644]
etc/hostname [new file with mode: 0644]
etc/localtime [new symlink]
etc/sudoers.d/wheel [new file with mode: 0644]
etc/systemd/system/controlpi.service [new file with mode: 0644]
etc/systemd/system/multi-user.target.wants/controlpi.service [new symlink]
etc/systemd/system/multi-user.target.wants/pigpiod.service [new symlink]
etc/systemd/system/pigpiod.service.d/override.conf [new file with mode: 0644]
home/pi/conf-init.json [new file with mode: 0644]
home/pi/conf-test.json [new file with mode: 0644]
home/pi/conf.json [new file with mode: 0644]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..7399221
--- /dev/null
+++ b/README
@@ -0,0 +1,179 @@
+Install statically linked qemu to allow chroot to ARM:
+$ aur sync --chroot qemu-arm-static
+$ sudo pacman -Sy
+$ sudo pacman -S qemu-arm-static
+
+Get and unpack Arch Linux ARM for Pi 2/3:
+$ cd /tmp
+$ wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz
+$ sudo mkdir controlpi 
+$ sudo mount -t tmpfs none controlpi/
+$ sudo tar -xpf ArchLinuxARM-rpi-2-latest.tar.gz -C controlpi/
+
+First upgrade:
+$ TERM=xterm sudo arch-chroot controlpi/
+# pacman-key --init
+# pacman-key --populate archlinuxarm
+# pacman -Syu
+
+Package management until:
+# pacman -Q --explicit
+base
+binutils
+fakeroot
+gcc
+git
+linux-rpi
+make
+openssh
+pacman-contrib
+parted
+python
+raspberrypi-bootloader-x
+raspberrypi-firmware
+sudo
+vim
+# pacman -Q --deps --unrequired --unrequired
+Nothing
+
+Clean up /etc/systemd/system/:
+# rm /etc/systemd/system/multi-user.target.wants/remote-fs.target
+# rm /etc/systemd/system/sysinit.target.wants/haveged.service
+
+Clean up /var/log:
+# rm -r /var/log/journal  # Makes journal volatile
+# rm /var/log/lastlog
+
+Change timezone to Europe/Berlin:
+# ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime
+
+Rename standard user:
+# mv /home/alarm /home/pi
+# sed -i 's/alarm/pi/g' /etc/passwd /etc/shadow /etc/group /etc/gshadow
+
+Change passwords to well-known password:
+# passwd
+# passwd pi
+
+Enable sudo for standard user (all in group 'wheel'):
+# echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel
+# chmod o-r etc/sudoers.d/wheel
+
+Safe settings for sshd:
+# sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/g' /etc/ssh/sshd_config
+# sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
+
+Install ssh keys:
+# su - pi
+$ mkdir .ssh
+Put accompanying authorized_keys file in /home/pi/.ssh/authorized_keys.
+$ chmod -R go-rx .ssh/
+$ exit
+
+Script for resizing to full SD card:
+# su - pi
+$ cat << EOF > resize-fs.sh
+#!/bin/sh
+sudo parted /dev/mmcblk0 resizepart 2 100%
+sudo partprobe /dev/mmcblk0
+sudo resize2fs /dev/mmcblk0p2
+EOF
+$ chmod +x resize-fs.sh
+$ exit
+
+Enable I2C:
+# echo 'dtparam=i2c_arm=on' >> /boot/config.txt
+# echo 'i2c-dev' >> /etc/modules-load.d/raspberrypi.conf
+
+Install pigpio from the AUR:
+# su - pi
+$ git clone https://aur.archlinux.org/pigpio.git
+$ cd pigpio/
+$ makepkg -s
+$ exit
+# pacman -U /home/pi/pigpio/pigpio-XX-X-armv7h.pkg.tar.xz
+# ln -s /usr/lib/systemd/system/pigpiod.service /etc/systemd/system/multi-user.target.wants/
+# mkdir /etc/systemd/system/pigpiod.service.d
+# cat << EOF > /etc/systemd/system/pigpiod.service.d/override.conf
+[Service]
+ExecStart=
+ExecStart=/usr/bin/pigpiod -l
+EOF
+
+Clear package cache:
+# paccache -rk0
+
+Install ControlPi system:
+# su - pi
+$ python -m venv controlpi-venv
+$ source controlpi-venv/bin/activate
+$ pip install -U pip setuptools wheel
+$ pip install git+git://git.graph-it.com/graphit/controlpi.git
+$ pip install git+git://git.graph-it.com/graphit/controlpi-pinio.git
+$ pip install git+git://git.graph-it.com/graphit/controlpi-modbus.git
+$ pip install git+git://git.graph-it.com/graphit/controlpi-wsclient.git
+$ pip install git+git://git.graph-it.com/graphit/controlpi-wsserver.git
+$ pip install git+git://git.graph-it.com/graphit/controlpi-statemachine.git
+$ exit
+# cat << EOF > /etc/systemd/system/controlpi.service
+[Unit]
+Description=ControlPi Service
+Wants=network-online.target
+After=network-online.target
+After=pigpiod.service
+StartLimitIntervalSec=300
+StartLimitBurst=5
+
+[Service]
+WorkingDirectory=/home/pi
+Environment=PYTHONUNBUFFERED=1
+ExecStart=/home/pi/controlpi-venv/bin/python -m controlpi conf.json
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+# ln -s /etc/systemd/system/controlpi.service /etc/systemd/system/multi-user.target.wants/
+
+Change hostname to '<whatever>pi':
+# sed -i 's/alarmpi/<whatever>pi/g' /etc/hostname
+
+Create <Whatever>-specific conf.json
+# su - pi
+$ cat << EOF > conf.json
+{
+    "<Whatever>Pi-Master": {
+        "plugin": "WSClient",
+        "url": "ws://graph.example.com:8080",
+        "interface": "eth0",
+        "up filter": [ ],
+        "down filter": [ { "target": { "const": "" } } ]
+    }
+}
+EOF
+$ exit
+
+Exit chroot and build archive:
+# exit
+$ sudo tar -czf <whatever>pi.tar.gz -C controlpi/ .
+
+Create image:
+$ fallocate -l 2G 20YY-MM-DD-<whatever>pi-arch-controlpi.img
+$ sudo losetup --find --show 20YY-MM-DD-<whatever>pi-arch-controlpi.img
+$ sudo parted --script /dev/loop0 mklabel msdos
+$ sudo parted --script /dev/loop0 mkpart primary fat32 0% 100M
+$ sudo parted --script /dev/loop0 mkpart primary ext4 100M 100%
+$ sudo mkfs.vfat -F32 /dev/loop0p1
+$ sudo mkfs.ext4 -F /dev/loop0p2
+$ sudo mount /dev/loop0p2 /mnt
+$ sudo mkdir /mnt/boot
+$ sudo mount /dev/loop0p1 /mnt/boot
+$ sudo tar -xpf <whatever>pi.tar.gz -C /mnt/
+$ sudo umount /mnt/boot
+$ sudo umount /mnt
+$ sudo losetup --detach /dev/loop0
+$ scp 20YY-MM-DD-<whatever>pi-arch-controlpi.img root@graph-de-screwerk-com.castle:sdimages/
+
+Flash image to SD card:
+$ sudo dd if=20YY-MM-DD-<whatever>pi-arch-controlpi.img of=/dev/mmcblk0 bs=1M
diff --git a/etc/hostname b/etc/hostname
new file mode 100644 (file)
index 0000000..a74be41
--- /dev/null
@@ -0,0 +1 @@
+controlpi
diff --git a/etc/localtime b/etc/localtime
new file mode 120000 (symlink)
index 0000000..622b45b
--- /dev/null
@@ -0,0 +1 @@
+/usr/share/zoneinfo/Europe/Berlin
\ No newline at end of file
diff --git a/etc/sudoers.d/wheel b/etc/sudoers.d/wheel
new file mode 100644 (file)
index 0000000..7c499c2
--- /dev/null
@@ -0,0 +1 @@
+%wheel ALL=(ALL) NOPASSWD: ALL
diff --git a/etc/systemd/system/controlpi.service b/etc/systemd/system/controlpi.service
new file mode 100644 (file)
index 0000000..6402fa4
--- /dev/null
@@ -0,0 +1,17 @@
+[Unit]
+Description=ControlPi Service
+Wants=network-online.target
+After=network-online.target
+After=pigpiod.service
+StartLimitIntervalSec=300
+StartLimitBurst=5
+
+[Service]
+WorkingDirectory=/home/pi
+Environment=PYTHONUNBUFFERED=1
+ExecStart=/home/pi/controlpi-venv/bin/python -m controlpi conf.json
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
diff --git a/etc/systemd/system/multi-user.target.wants/controlpi.service b/etc/systemd/system/multi-user.target.wants/controlpi.service
new file mode 120000 (symlink)
index 0000000..dcb81bd
--- /dev/null
@@ -0,0 +1 @@
+/etc/systemd/system/controlpi.service
\ No newline at end of file
diff --git a/etc/systemd/system/multi-user.target.wants/pigpiod.service b/etc/systemd/system/multi-user.target.wants/pigpiod.service
new file mode 120000 (symlink)
index 0000000..5df2d0f
--- /dev/null
@@ -0,0 +1 @@
+/usr/lib/systemd/system/pigpiod.service
\ No newline at end of file
diff --git a/etc/systemd/system/pigpiod.service.d/override.conf b/etc/systemd/system/pigpiod.service.d/override.conf
new file mode 100644 (file)
index 0000000..fb0b252
--- /dev/null
@@ -0,0 +1,3 @@
+[Service]
+ExecStart=
+ExecStart=/usr/bin/pigpiod -l
diff --git a/home/pi/conf-init.json b/home/pi/conf-init.json
new file mode 100644 (file)
index 0000000..dac7db3
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "ControlPi-Master": {
+        "plugin": "WSClient",
+        "url": "ws://graph-hsv-hsrobotics-com.castle:8080",
+        "interface": "eth0",
+        "up filter": [ ],
+        "down filter": [ { "target": { "const": "" } } ]
+    }
+}
diff --git a/home/pi/conf-test.json b/home/pi/conf-test.json
new file mode 100644 (file)
index 0000000..0eeae26
--- /dev/null
@@ -0,0 +1,489 @@
+{
+    "Debug": {
+        "plugin": "WSServer",
+        "web": {
+            "/": {
+                "module": "controlpi_plugins.wsserver",
+                "location": "Debug"
+            }
+        }
+    },
+    "Log": {
+        "plugin": "Log",
+        "filter": [{}]
+    },
+    "Output Card 1": {
+        "plugin": "OutputCard",
+        "address": 56,
+        "pins": {
+            "A1-1": 0, "A1-2": 1, "A1-3": 2, "A1-4": 3,
+            "A1-5": 4, "A1-6": 5, "A1-7": 6, "A1-8": 7
+        }
+    },
+    "Output Card 2": {
+        "plugin": "OutputCard",
+        "address": 57,
+        "pins": {
+            "A2-1": 0, "A2-2": 1, "A2-3": 2, "A2-4": 3,
+            "A2-5": 4, "A2-6": 5, "A2-7": 6, "A2-8": 7
+        }
+    },
+    "Input Card 1": {
+        "plugin": "InputCard",
+        "address": 32,
+        "interrupt pin": 4,
+        "pins": {
+            "E1-1": 0, "E1-2": 1, "E1-3": 2, "E1-4": 3,
+            "E1-5": 4, "E1-6": 5, "E1-7": 6, "E1-8": 7
+        }
+    },
+    "Input Card 2": {
+        "plugin": "InputCard",
+        "address": 33,
+        "interrupt pin": 17,
+        "pins": {
+            "E2-1": 0, "E2-2": 1, "E2-3": 2, "E2-4": 3,
+            "E2-5": 4, "E2-6": 5, "E2-7": 6, "E2-8": 7
+        }
+    },
+    "Input Card 3": {
+        "plugin": "InputCard",
+        "address": 34,
+        "interrupt pin": 27,
+        "pins": {
+            "E3-1": 0, "E3-2": 1, "E3-3": 2, "E3-4": 3,
+            "E3-5": 4, "E3-6": 5, "E3-7": 6, "E3-8": 7
+        }
+    },
+    "Input Card 4": {
+        "plugin": "InputCard",
+        "address": 35,
+        "interrupt pin": 22,
+        "pins": {
+            "E4-1": 0, "E4-2": 1, "E4-3": 2, "E4-4": 3,
+            "E4-5": 4, "E4-6": 5, "E4-7": 6, "E4-8": 7
+        }
+    },
+    "Test Init": {
+        "plugin": "Init",
+        "messages": [{ "target": "Test On", "command": "start" }]
+    },
+    "Test Wait": {
+        "plugin": "GenericWait"
+    },
+    "Test A1-1 On": {
+        "plugin": "Alias",
+        "from": {
+            "target": { "const": "Test On" },
+            "command": { "const": "start" }
+        },
+        "to": [
+            { "target": "A1-1", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-1 On" }
+        ]
+    },
+    "Test A1-1 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-1 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-1", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-1 Off" }
+        ]
+    },
+    "Test A1-2 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-1 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-2", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-2 On" }
+        ]
+    },
+    "Test A1-2 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-2 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-2", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-2 Off" }
+        ]
+    },
+    "Test A1-3 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-2 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-3", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-3 On" }
+        ]
+    },
+    "Test A1-3 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-3 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-3", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-3 Off" }
+        ]
+    },
+    "Test A1-4 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-3 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-4", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-4 On" }
+        ]
+    },
+    "Test A1-4 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-4 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-4", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-4 Off" }
+        ]
+    },
+    "Test A1-5 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-4 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-5", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-5 On" }
+        ]
+    },
+    "Test A1-5 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-5 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-5", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-5 Off" }
+        ]
+    },
+    "Test A1-6 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-5 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-6", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-6 On" }
+        ]
+    },
+    "Test A1-6 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-6 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-6", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-6 Off" }
+        ]
+    },
+    "Test A1-7 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-6 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-7", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-7 On" }
+        ]
+    },
+    "Test A1-7 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-7 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-7", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-7 Off" }
+        ]
+    },
+    "Test A1-8 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-7 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-8", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-8 On" }
+        ]
+    },
+    "Test A1-8 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-8 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A1-8", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A1-8 Off" }
+        ]
+    },
+    "Test A2-1 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A1-8 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-1", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-1 On" }
+        ]
+    },
+    "Test A2-1 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-1 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-1", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-1 Off" }
+        ]
+    },
+    "Test A2-2 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-1 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-2", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-2 On" }
+        ]
+    },
+    "Test A2-2 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-2 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-2", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-2 Off" }
+        ]
+    },
+    "Test A2-3 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-2 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-3", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-3 On" }
+        ]
+    },
+    "Test A2-3 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-3 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-3", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-3 Off" }
+        ]
+    },
+    "Test A2-4 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-3 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-4", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-4 On" }
+        ]
+    },
+    "Test A2-4 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-4 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-4", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-4 Off" }
+        ]
+    },
+    "Test A2-5 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-4 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-5", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-5 On" }
+        ]
+    },
+    "Test A2-5 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-5 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-5", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-5 Off" }
+        ]
+    },
+    "Test A2-6 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-5 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-6", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-6 On" }
+        ]
+    },
+    "Test A2-6 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-6 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-6", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-6 Off" }
+        ]
+    },
+    "Test A2-7 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-6 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-7", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-7 On" }
+        ]
+    },
+    "Test A2-7 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-7 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-7", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-7 Off" }
+        ]
+    },
+    "Test A2-8 On": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-7 Off" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-8", "command": "set state", "new state": true },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-8 On" }
+        ]
+    },
+    "Test A2-8 Off": {
+        "plugin": "Alias",
+        "from": {
+            "sender": { "const": "Test Wait" },
+            "id": { "const": "A2-8 On" },
+            "event": { "const": "finished" }
+        },
+        "to": [
+            { "target": "A2-8", "command": "set state", "new state": false },
+            { "target": "Test Wait", "command": "wait",
+              "seconds": 0.1, "id": "A2-8 Off" }
+        ]
+    }
+}
diff --git a/home/pi/conf.json b/home/pi/conf.json
new file mode 100644 (file)
index 0000000..dac7db3
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "ControlPi-Master": {
+        "plugin": "WSClient",
+        "url": "ws://graph-hsv-hsrobotics-com.castle:8080",
+        "interface": "eth0",
+        "up filter": [ ],
+        "down filter": [ { "target": { "const": "" } } ]
+    }
+}