Automatic Startup and Shutdown of your Onboard Computers

Background

This solution is applicable to any Linux or PC based small form factor computers you wish to automate startup and safe shutdown for.

I recently found myself wanting to set up an MMDVM hotspot and a WIRES-X PC Stick style computer in my car -- as a permanent configuration. Having only DMR repeaters in the area, this would allow me to dive into other modes.

I carried a hotspot around for some time, but then I also became interested in using WIRES-X PDN mode on the go. Things were getting complicated and cumbersome, and I'd frequently forget to safely shutdown the hotspot and PC, which often resulted in frustratingly long bootup times while the filesystem was scanned for errors. Windows was a particular PITA in that sense. Remembering this every time was no longer an option for me. It's just not a burden worth taking on, but I felt it was a fight worth fighting. So I starting thinking thru a way to solve this by somehow triggering an automatic 'safe shutdown'.

Objectives

  • Automatic power-up and shutdown of mobile computers
  • Mobile WIRES-X node, "direct" while driving, with the option of a timer-based "access point" mode while parked.

Description

The solution involves two timer-relays that assist in a two-stage shutdown event, along with a dedicated Raspberry Pi Zero (or full size). The first stage notifies all the computers to initiate shutdown, and the second stage cuts power to the devices. The second stage is ideal for devices that support automated boot on power up.

Sequence of Events

Startup

The timer-relays are always powered on, but the signal line is tied to a fuse slot that is on only when your ignition is on. When you turn your ignition on, the relay closes the circuit on your mobile computing power bus, and boot-up occurs.

Shutdown

Upon shutting your ignition off, the signal line is lowered, causing both timer-relays to initiate countdown. The shorter of the two timers expires, triggering a GPIO on the Raspberry Pi Zero which then broadcasts a message on the network telling all other computers to shutdown. This is done via a small Python script that monitors this event. All other computers are running a Python script listening for said message. These scripts are described in the following sections.

And finally, the second timer-relay fires, cutting power to the power bus.

Parts Used

Total cost ~$50

Interconnect

Please note the way you connect your fuse tap. Connecting it in the wrong direction circumvents the fuse and very bad things will happen. Read the instruction manual for your fuse tap.

Connections

Software

Server (Raspberry Pi)

We'll use the gpiozero Python package so we can monitor our GPIO pin.

sudo apt-get update

sudo apt-get install python3-gpiozero

We can now create our relay-trigger.py script with the following contents:

from gpiozero import Button
from signal import pause
from time import sleep
import socket
import subprocess

DEST_PORT = 17473
DEST_IP = "255.255.255.255"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

def doShutdown():
  print("GPIO Change Detected")
  for i in range(3):
    sock.sendto(b'\x01\x01', (DEST_IP, DEST_PORT))
    sleep(0.5)
  subprocess.Popen(['sudo', 'shutdown', '-h', 'now'])

# GPIO where relay is connected
button = Button(21)

button.when_released = doShutdown

pause()

The above script will detect GPIO #21 when our first relay is triggered. The script then broadcasts a UDP message telling all other listening computers to shut down. Finally, the script tells the Raspberry Pi to shut down.

Our script is ready for execution, but we'll want this script to automatically start every time the Raspberry Pi boots up. We'll achieve this by creating a systemd service.

Create the following file, as sudo: /lib/systemd/system/relay-trigger.service with the following contents:

[Unit]
Description=Relay trigger upon GPIO 2
After=network-online.target

[Service]
ExecStart=/usr/bin/python3 /home/pi/relay-trigger.py

[Install]
WantedBy=network-online.target

We can now tell systemd to load the new service:

sudo systemctl daemon-reload

And we enable it:

sudo systemctl enable relay-trigger.service

Upon rebooting our Raspberry Pi, the new service should launch automatically:

sudo reboot

We can verify that our new service is up and running with the following command:

sudo systemctl | grep relay

Clients

Our client/daemon can run on any Windows or Linux device. This example shows how to set it up to auto-start in a Windows environment. For Linux, you can create a similar service to the one we created in the previous section.

We create our script titled client.py and place it wherever you wish to keep it. The contents of this script are:

import subprocess
import socket
import platform

UDP_PORT = 17473

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind(('',UDP_PORT))

sysname = platform.system()

while True:
    data, addr = sock.recvfrom(1024)
    if data == b'\x01\x01':
        if sysname == 'Windows':
          subprocess.run(["shutdown", "/p", "/f"])
        elif sysname == 'Linux':
          subprocess.Popen(['sudo', 'shutdown', '-h', 'now'])

Create a shortcut to this script in the current user's Windows Startup Folder, which is found at the following path:

C:\Users\USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

Finally, install Python 3 if you don't already have it.

Rebooting your Windows device will now automatically start the daemon.

Assembled

Other Suggestions

You can use a mesh VPN solution to gain easy access to your mobile computers. I like to use ZeroTier as it is free and very simple to use.