From 89436aa586d4c8341b076d221911670624743737 Mon Sep 17 00:00:00 2001 From: Frederik Lindenaar <frederik@lindenaar.nl> Date: Wed, 23 Oct 2019 22:05:48 +0200 Subject: [PATCH] - added README.md - added systemd service descriptors - new features in gpio_trigger.py: - support waiting for a hold period (-H) - added option to ignore command's result code (-i) - added variable subtitution in the arguments (%PIN% and %STATE%) --- README.md | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gpio_trigger.py | 37 +++++++++++++++++++++++++------------ rpi_no_hdmi.service | 37 +++++++++++++++++++++++++++++++++++++ rpi_no_usb.service | 37 +++++++++++++++++++++++++++++++++++++ rpi_no_wifi.service | 37 +++++++++++++++++++++++++++++++++++++ rpi_poweroff_button.service | 40 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 286 insertions(+), 12 deletions(-) create mode 100644 README.md create mode 100644 rpi_no_hdmi.service create mode 100644 rpi_no_usb.service create mode 100644 rpi_no_wifi.service create mode 100644 rpi_poweroff_button.service diff --git a/README.md b/README.md new file mode 100644 index 0000000..b81ac65 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +Raspberry Pi Scripts +==================== +This repository contains my collection of scripts and other snippets for the +[Raspberry Pi](https://www.raspberrypi.org). I am publishing these in case they +are of any benefit to other enthusiasts. Use them freely and please let me know +in case you encounter any issues or require changes. + +The latest versions, documentation and bugtracker available on my +[GitLab instance](https://gitlab.lindenaar.net/scripts/raspberrypi) + +Copyright (c) 2019 Frederik Lindenaar. free for distribution under +the GNU General Public License, see [below](#license) + +Contents +======== +This repository contains the following scripts: + * [gpio_trigger.py](#gpio_trigger) + is s script to execute a command when a GPIO input pin changes + * [rpi_no_hdmi.service](#services) + is a systemd service to disable the Raspberry Pi's HDMI port at boot + * [rpi_no_usb.service](#services) + is a systemd service to disable the Raspberry Pi's USB bus at boot + * [rpi_no_wifi.service](#services) + is a systemd service to disable on-board WiFi on Raspberry Pi at boot + * [rpi_poweroff_button.service](#services) + is a systemd service to support a power-off button using [gpio_trigger.py](#gpio_trigger) + + +<a name=gpio_trigger>gpio_trigger.py</a> +---------------------------------------- +This script was initially written to add a power-off button to a Raspberry Pi, +[see this blog post](https://frederik.lindenaar.nl/2019/10/23/raspberry-pi-power-off-button.html) +for the rationale behind it and how to construct and connect a physical button. + +The script itself is a generic solution to monitor a GPIO pin and executes a +command when the input signal on a pin changes. It can run as interactively as +well as in the background and executes a command once or continuously upon any +change or specific transition (e.g. HIGH to LOW). + +The script is written in Python 2 and uses the `RPi.GPIO` library as both are +installed by default on most distributions so should just work. Please note that +by default the script should be started as root to gain access to the GPIO port. + +To implement a simple power-off button, install the script in `/usr/local/sbin`, +connect an NC switch (i.e. one that connects when pressed) between pin 39 (GND) +and pin 40 of the Raspberry Pi and add: + +~~~ +if [ -x /usr/local/sbin/gpio_trigger.py ]; then + /usr/local/sbin/gpio_trigger.py -D -H 5000 poweroff +fi +~~~ + +to the file `/etc/rc.local`. This will start the script in the background (`-D`) +to wait for pin 40 (default pin) to be connected to ground for 5000ms (`-H`) and +then run the command `poweroff` to shutdown the Raspberry Pi. + +Please refer to the output of `gpio_trigger.py -h` for the options supported and +defaults used when no option is specified. + + +<a name=services>Systemd services</a> +------------------------------------- +The repository contains a number of `.service` files, which are systemd service +descriptions to control specific on-board features of the Raspberry Pi (e.g. to +disable unused ports). Their purpose should be pretty clear from their name (and +comments they contain). The rationale of the initial scripts is covered in this +[blog post](https://frederik.lindenaar.nl/2018/05/11/raspberry-pi-power-saving-disable-hdmi-port-and-others-the-systemd-way.html). + +In general, to install these copy them to the directory `/etc/systemd/system/` + +To manually disable the port, 'start' the 'service' with: + +~~~ +service <<filename without .service>> start +~~~ + +To manually enable the port again, 'stop' the 'service' with: + +~~~ +service <<filename without .service>> stop +~~~ + +To enable starting during system boot (to disable the port) run: + +~~~ +systemctl enable service <<filename without .service>> +~~~ + +To disable starting during system boot (to no longer disable the port) run: + +~~~ +systemctl disable service <<filename without .service>> +~~~ + + +<a name="license">License</a> +----------------------------- +These scripts, documentation & configration examples are free software: you can +redistribute and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +This script, documenatation and configuration examples are distributed in the +hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, download it from <http://www.gnu.org/licenses/>. \ No newline at end of file diff --git a/gpio_trigger.py b/gpio_trigger.py index 02f46de..8369149 100755 --- a/gpio_trigger.py +++ b/gpio_trigger.py @@ -1,7 +1,7 @@ #! /usr/bin/env python # -# gpio_trigger.py - execute a command when a GPIO pin is triggered (up or down) +# gpio_trigger.py - execute a command when a GPIO input pin changes # # Version 1.0, latest version, documentation and bugtracker available at: # https://gitlab.lindenaar.net/scripts/raspberrypi @@ -24,8 +24,12 @@ from os import fork, system from argparse import ArgumentParser from RPi import GPIO -parser = ArgumentParser(description='Run command when a Raspberry Pi pin is' - ' high or low (e.g. a button is pressed)') +parser = ArgumentParser( + description='Run command when a Raspberry Pi pin changes to high or low.', + epilog='(*) use \'--\' to stop argument parsing, arguments can contain the ' + 'following variables: %PIN%=pin number, %STATE%=value (HIGH or LOW)') +parser.add_argument('-D', '--daemon', action='store_true', + help='run in background (as daemon)') pgroup = parser.add_mutually_exclusive_group(required=False) pgroup.add_argument('-P', '--pcb', action='store_const', dest='mode', const=GPIO.BOARD, default=GPIO.BOARD, @@ -50,22 +54,22 @@ pgroup.add_argument('-r', '--edge-rising', action='store_const', dest='edge', const=GPIO.RISING, help='respond to pin going up') pgroup.add_argument('-a', '--edge-any', action='store_const', const=GPIO.BOTH, dest='edge', help='respond to any pin change') -parser.add_argument('-i', '--ignore-result', action='store_true', default=False, - help='ignore command result code (default: exit if <> 0)') parser.add_argument('-b', '--debounce', type=int, default=200, help='debounce period (in milliseconds, default=200)') +parser.add_argument('-H', '--hold', type=int, default=-1, + help='optional hold time, pin must be held stable for the ' + 'specified time in milliseconds to trigger cmd') parser.add_argument('-t', '--timeout', type=int, default=-1, help='optional timeout (in milliseconds) to wait') +parser.add_argument('-i', '--ignore-result', action='store_true', default=False, + help='ignore command result code (default: exit if <> 0)') pgroup = parser.add_mutually_exclusive_group(required=False) pgroup.add_argument('-c', '--continuous', default=False, action='store_true', help='continously monitor GPIO pin and run cmd upon change') pgroup.add_argument('-o', '--once', action='store_false', dest='continuous', help='monitor pin and run cmd once, then exit (default)') -parser.add_argument('-D', '--daemon', action='store_true', - help='run in background (as daemon)') parser.add_argument('cmd', help='command to execute when pin goes low') -parser.add_argument('arg', nargs='*', help='argument(s) for the command, use --' - ' before first argument to stop parsing parameters') +parser.add_argument('arg', nargs='*', help='argument(s) for the command (*)') args = parser.parse_args() # parse command line GPIO.setmode(args.mode) # set GPIO number mode @@ -76,12 +80,21 @@ if args.daemon and fork() != 0: # Fork for daemon mode ret = 0 while args.ignore_result or ret == 0: + # wait for GPIO pin to be changed in the right direction if GPIO.wait_for_edge(args.pin, args.edge, bouncetime=args.debounce, timeout=args.timeout): - ret = system(' '.join([ args.cmd ] + args.arg)) # run the command - if not args.continuous: # exit if running once - break + state = GPIO.input(args.pin) + # pin changed, if required check if it is stays the same long enough + if (args.hold < 0) or ( + GPIO.wait_for_edge(args.pin, GPIO.BOTH, bouncetime=args.debounce, + timeout=args.hold - args.debounce) is None): + ret = system(' '.join([ args.cmd ] + [ + [ 'LOW', 'HIGH' ][state] if arg == '%STATE%' else + str(args.pin) if arg == '%PIN%' else arg for arg in args.arg])) + if not args.continuous: # exit if running once + break else: # exit if timeout + ret = -1 break GPIO.cleanup(args.pin) # cleanup GPIO diff --git a/rpi_no_hdmi.service b/rpi_no_hdmi.service new file mode 100644 index 0000000..504db08 --- /dev/null +++ b/rpi_no_hdmi.service @@ -0,0 +1,37 @@ +# +# rpi_no_hdmi.service – Systemd service to disable the Raspberry Pi's HDMI port +# +# Version 1.0, latest version, documentation and bugtracker available at: +# https://gitlab.lindenaar.net/scripts/raspberrypi +# +# Copyright (c) 2019 Frederik Lindenaar +# +# This script is free software: you can redistribute and/or modify it under the +# terms of version 3 of the GNU General Public License as published by the Free +# Software Foundation, or (at your option) any later version of the license. +# +# This script is distributed in the hope that it will be useful but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. +# + +# To install copy to /etc/systemd/system/rpi_no_hdmi.service +# enable it to start during boot with: systemctl enable rpi_no_hdmi +# temporarily enable with: service rpi_no_hdmi start +# temporarily disable with: service rpi_no_hdmi stop +# disable starting during boot with: systemctl disable rpi_no_hdmi + +[Unit] +Description=Disable Raspberry Pi HDMI port + +[Service] +Type=oneshot +ExecStart=/opt/vc/bin/tvservice -o +ExecStop=/opt/vc/bin/tvservice -p +RemainAfterExit=yes + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/rpi_no_usb.service b/rpi_no_usb.service new file mode 100644 index 0000000..aa82d25 --- /dev/null +++ b/rpi_no_usb.service @@ -0,0 +1,37 @@ +# +# rpi_no_usb.service – Systemd service to disable the Raspberry Pi's USB bus +# +# Version 1.0, latest version, documentation and bugtracker available at: +# https://gitlab.lindenaar.net/scripts/raspberrypi +# +# Copyright (c) 2019 Frederik Lindenaar +# +# This script is free software: you can redistribute and/or modify it under the +# terms of version 3 of the GNU General Public License as published by the Free +# Software Foundation, or (at your option) any later version of the license. +# +# This script is distributed in the hope that it will be useful but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. +# + +# To install copy to /etc/systemd/system/rpi_no_usb.service +# enable it to start during boot with: systemctl enable rpi_no_usb +# temporarily enable with: service rpi_no_usb start +# temporarily disable with: service rpi_no_usb stop +# disable starting during boot with: systemctl disable rpi_no_usb + +[Unit] +Description=Disable Raspberry Pi USB bus + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "echo 0x0 > /sys/devices/platform/soc/3f980000.usb/buspower" +ExecStop=/bin/sh -c "echo 0x1 > /sys/devices/platform/soc/3f980000.usb/buspower" +RemainAfterExit=yes + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/rpi_no_wifi.service b/rpi_no_wifi.service new file mode 100644 index 0000000..33d86ae --- /dev/null +++ b/rpi_no_wifi.service @@ -0,0 +1,37 @@ +# +# rpi_no_wifi.service – Systemd service to disable WiFi on Raspberry Pi 3B/ZeroW +# +# Version 1.0, latest version, documentation and bugtracker available at: +# https://gitlab.lindenaar.net/scripts/raspberrypi +# +# Copyright (c) 2019 Frederik Lindenaar +# +# This script is free software: you can redistribute and/or modify it under the +# terms of version 3 of the GNU General Public License as published by the Free +# Software Foundation, or (at your option) any later version of the license. +# +# This script is distributed in the hope that it will be useful but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. +# + +# To install copy to /etc/systemd/system/rpi_no_wifi.service +# enable it to start during boot with: systemctl enable rpi_no_wifi +# temporarily enable with: service rpi_no_wifi start +# temporarily disable with: service rpi_no_wifi stop +# disable starting during boot with: systemctl disable rpi_no_wifi + +[Unit] +Description=Disable Raspberry Pi 3B/ZeroW WiFi interface + +[Service] +Type=oneshot +ExecStart=/sbin/ifdown wlan0 +ExecStop=/sbin/ifup wlan0 +RemainAfterExit=yes + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/rpi_poweroff_button.service b/rpi_poweroff_button.service new file mode 100644 index 0000000..7c7d0c2 --- /dev/null +++ b/rpi_poweroff_button.service @@ -0,0 +1,40 @@ +# +# rpi_poweroff_button.service – Systemd service to implement a poweroff button +# +# Version 1.0, latest version, documentation and bugtracker available at: +# https://gitlab.lindenaar.net/scripts/raspberrypi +# +# Copyright (c) 2019 Frederik Lindenaar +# +# This script is free software: you can redistribute and/or modify it under the +# terms of version 3 of the GNU General Public License as published by the Free +# Software Foundation, or (at your option) any later version of the license. +# +# This script is distributed in the hope that it will be useful but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. +# + +# Please note this requires gpio_trigger.py installed in /usr/local/sbin, see: +# https://frederik.lindenaar.nl/2019/10/23/raspberry-pi-power-off-button.html + +# To install copy to /etc/systemd/system/rpi_poweroff_button.service +# enable it to start during boot with: systemctl enable rpi_poweroff_button +# temporarily enable with: service rpi_poweroff_button start +# temporarily disable with: service rpi_poweroff_button stop +# disable starting during boot with: systemctl disable rpi_poweroff_button + +[Unit] +Description=Power-off button on GPIO + +[Service] +Type=idle +ExecStart=/usr/local/sbin/gpio_trigger.py --hold 5000 poweroff +Restart=always +RestartSec=30 + +[Install] +WantedBy=default.target \ No newline at end of file -- libgit2 0.22.2