TCP/JSON I2C relay control service targeting Raspberry Pi 4 (Debian Trixie) with a
Sequent Microsystems 16-relay HAT,
Sequent Microsystems 8-relay HAT, or
Sequent Microsystems 4-relay HAT.
Board type is selected via the board config key; a single binary supports all three.
Specifically for use with PgTgBridge built-in plugin PgTg PiGpio. Can be used as a smart
wrapper to the relay board that is accessible using JSON strings such as from Node-Red.
Commands are newline-delimited JSON sent over TCP. The connection remains open between commands.
| Direction | Example |
|---|---|
| Set ON | {"cmd":"set","output":"output1","value":1} |
| Set OFF | {"cmd":"set","output":"output2","value":0} |
| Timed ON (30s) | {"cmd":"set","output":"output1","value":30} |
| Read all outputs | {"cmd":"read"} |
| Read all inputs | {"cmd":"read_inputs"} |
| OK (set) | {"status":"ok","output":"output1","value":1} |
| OK (read) | {"status":"ok","outputs":{"output1":1,"output2":0}} |
| OK (read_inputs) | {"status":"ok","inputs":{"input1":0,"input2":1,"input3":0,"input4":1}} |
| Error | {"status":"error","message":"unknown output: output5"} |
| Error (no inputs) | {"status":"error","message":"board does not support inputs"} |
| Value | Behaviour |
|---|---|
0 |
Static OFF — cancels any running timer |
1 |
Static ON — cancels any running timer |
2–999 |
Drives output ON; auto-forces OFF after that many seconds. A new value ≥ 2 before expiry resets the timer. |
On expiry the server sends {"status":"ok","output":"<name>","value":0} on the open connection if a client is connected.
When the PgTgBridge GPIO plugin is configured with an Amp PTT output, it sends value: 15
(not 1) whenever the amplifier PTT is keyed. This starts a 15-second channel watchdog timer on
the service side. PgTgBridge then re-sends value: 15 every 10 seconds to keep the watchdog
alive for the duration of the transmission. When PTT is released the PgTgBridge sends value: 0.
If the PgTgBridge loses connectivity, the watchdog expires after 15 seconds and the PTT output is automatically deactivated — preventing a stuck transmitter if the connectivity to the host machine is lost.
If the PgTgBridge service is stopped, PgTg sends value: 0 to all configured channels before halting.
Enable I2C on the Raspberry Pi (required once):
sudo raspi-config
# Interface Options → I2C → EnableOr add to /boot/firmware/config.txt:
dtparam=i2c_arm=on
Verify the relay board is detected (stack 0 appears at address 0x27):
i2cdetect -y 1Location: /etc/PgTgPiSequent/PgTgPiSequent.conf
# PgTgPiSequent configuration file
# TCP port for the JSON command interface
port = 5556
# Board type: 16relay (default), 8relay, or 4relay
board = 16relay
# Sequent Microsystems relay board stack level (0-7, default 0)
# Stack 0 = I2C address 0x27 (formula: (stack + 0x20) ^ 0x07)
# Verify with: i2cdetect -y 1
stack = 0
# Relay output mappings: output<N> = relay channel number
# 16relay board: channels 1-16
# 8relay board: channels 1-8
# 4relay board: channels 1-4
output1 = 1
output2 = 2
output3 = 3
output4 = 4| Key | Description |
|---|---|
port |
TCP port for the JSON command interface |
board |
16relay (default), 8relay, or 4relay — selects the Sequent HAT |
stack |
Board stack level 0–7 (physical jumper); each stacked board gets a unique level |
output<N> |
Maps logical output N to a relay channel on the board (1–16 for 16relay, 1–8 for 8relay, 1–4 for 4relay) |
input<N> |
(4relay only) Maps logical input N to a digital input channel (1–4) |
The live conf file is created from the package template on first install and is preserved on upgrade and removal. Edit it directly on the Pi; it is never overwritten by apt.
port = 5556
board = 8relay
stack = 0
output1 = 1
output2 = 2
output3 = 3
output4 = 4
output5 = 5
output6 = 6
output7 = 7
output8 = 8port = 5556
board = 4relay
stack = 0
output1 = 1
output2 = 2
output3 = 3
output4 = 4
input1 = 1
input2 = 2
input3 = 3
input4 = 4The service runs as the dedicated system user PgTgPiSequent (member of the i2c group) — no root required.
[Unit]
Description=PgTgPiSequent TCP/JSON I2C relay control service
After=network.target
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/bin/PgTgPiSequent /etc/PgTgPiSequent/PgTgPiSequent.conf
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=PgTgPiSequent
User=PgTgPiSequent
Group=i2c
[Install]
WantedBy=multi-user.targetThe service file is installed and enabled automatically by the Debian package.
Two build workflows are available — cross-compile from a WSL2 host, or build natively on the Pi. If building under WSL2, a deb package is created.
Prerequisites (install once on the Pi):
sudo apt install cmake ninja-build./build
# Produces: build-native/PgTgPiSequentYou will be responsible for copying the PgTgPiSequent binary to /usr/bin/PgTgPiSequent:
sudo cp build-native/PgTgPiSequent /usr/bin/PgTgPiSequent
sudo chmod +x /usr/bin/PgTgPiSequentAnd creating the configuration file at /etc/PgTgPiSequent/PgTgPiSequent.conf.
(you need to setup the cross-compiler yourself)
Prerequisites (install once in WSL2):
sudo apt install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu cmake ninja-buildrm -rf build-aarch64 && mkdir build-aarch64
./build-with-cross-compiler
# Produces: build-aarch64/PgTgPiSequent (ELF aarch64)./package
# Produces: PgTgPiSequent_1.0.2_arm64.deb
# Sources binary from build-aarch64/PgTgPiSequent./deploy
# SCPs PgTgPiSequent_1.0.2_arm64.deb to pi@<yourPiIpaddress>:/home/pi/sudo apt install /home/pi/PgTgPiSequent_1.0.2_arm64.debThe package installer:
- Creates the
PgTgPiSequentsystem user and adds it to thei2cgroup - Copies the factory-default config to
/etc/PgTgPiSequent/PgTgPiSequent.conf(first install only) - Copies the daemon binary to
/usr/bin - Installs and starts the systemd service
# Upgrade (live config is preserved)
sudo apt install /home/pi/PgTgPiSequent_1.0.2_arm64.deb
# Remove (binary and service removed; config kept)
sudo apt remove PgTgPiSequent
# Full purge (config and system user also removed)
sudo apt purge PgTgPiSequent# Set output1 ON
echo '{"cmd":"set","output":"output1","value":1}' | nc localhost 5556
# Read all output states
echo '{"cmd":"read"}' | nc localhost 5556
# Set output1 OFF
echo '{"cmd":"set","output":"output1","value":0}' | nc localhost 5556
# Timed ON — output1 goes ON, forces OFF after 30 seconds
echo '{"cmd":"set","output":"output1","value":30}' | nc localhost 5556
# Monitor in journald
journalctl -f -u PgTgPiSequent# Start and follow logs
sudo systemctl start PgTgPiSequent && journalctl -u PgTgPiSequent -f
# Stop (triggers clean I2C release — verify in journal)
sudo systemctl stop PgTgPiSequent
# Confirm service is running as PgTgPiSequent (not root)
ps aux | grep PgTgPiSequent
# See user and group
ps -eo user,group,cmd | grep PgTgPiSequent