- 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%)
This commit is contained in:
110
README.md
Normal file
110
README.md
Normal file
@@ -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/>.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#! /usr/bin/env python
|
#! /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:
|
# Version 1.0, latest version, documentation and bugtracker available at:
|
||||||
# https://gitlab.lindenaar.net/scripts/raspberrypi
|
# https://gitlab.lindenaar.net/scripts/raspberrypi
|
||||||
@@ -24,8 +24,12 @@ from os import fork, system
|
|||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from RPi import GPIO
|
from RPi import GPIO
|
||||||
|
|
||||||
parser = ArgumentParser(description='Run command when a Raspberry Pi pin is'
|
parser = ArgumentParser(
|
||||||
' high or low (e.g. a button is pressed)')
|
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 = parser.add_mutually_exclusive_group(required=False)
|
||||||
pgroup.add_argument('-P', '--pcb', action='store_const', dest='mode',
|
pgroup.add_argument('-P', '--pcb', action='store_const', dest='mode',
|
||||||
const=GPIO.BOARD, default=GPIO.BOARD,
|
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')
|
const=GPIO.RISING, help='respond to pin going up')
|
||||||
pgroup.add_argument('-a', '--edge-any', action='store_const', const=GPIO.BOTH,
|
pgroup.add_argument('-a', '--edge-any', action='store_const', const=GPIO.BOTH,
|
||||||
dest='edge', help='respond to any pin change')
|
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,
|
parser.add_argument('-b', '--debounce', type=int, default=200,
|
||||||
help='debounce period (in milliseconds, 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,
|
parser.add_argument('-t', '--timeout', type=int, default=-1,
|
||||||
help='optional timeout (in milliseconds) to wait')
|
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 = parser.add_mutually_exclusive_group(required=False)
|
||||||
pgroup.add_argument('-c', '--continuous', default=False, action='store_true',
|
pgroup.add_argument('-c', '--continuous', default=False, action='store_true',
|
||||||
help='continously monitor GPIO pin and run cmd upon change')
|
help='continously monitor GPIO pin and run cmd upon change')
|
||||||
pgroup.add_argument('-o', '--once', action='store_false', dest='continuous',
|
pgroup.add_argument('-o', '--once', action='store_false', dest='continuous',
|
||||||
help='monitor pin and run cmd once, then exit (default)')
|
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('cmd', help='command to execute when pin goes low')
|
||||||
parser.add_argument('arg', nargs='*', help='argument(s) for the command, use --'
|
parser.add_argument('arg', nargs='*', help='argument(s) for the command (*)')
|
||||||
' before first argument to stop parsing parameters')
|
|
||||||
|
|
||||||
args = parser.parse_args() # parse command line
|
args = parser.parse_args() # parse command line
|
||||||
GPIO.setmode(args.mode) # set GPIO number mode
|
GPIO.setmode(args.mode) # set GPIO number mode
|
||||||
@@ -76,12 +80,21 @@ if args.daemon and fork() != 0: # Fork for daemon mode
|
|||||||
|
|
||||||
ret = 0
|
ret = 0
|
||||||
while args.ignore_result or 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,
|
if GPIO.wait_for_edge(args.pin, args.edge, bouncetime=args.debounce,
|
||||||
timeout=args.timeout):
|
timeout=args.timeout):
|
||||||
ret = system(' '.join([ args.cmd ] + args.arg)) # run the command
|
state = GPIO.input(args.pin)
|
||||||
if not args.continuous: # exit if running once
|
# pin changed, if required check if it is stays the same long enough
|
||||||
break
|
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
|
else: # exit if timeout
|
||||||
|
ret = -1
|
||||||
break
|
break
|
||||||
|
|
||||||
GPIO.cleanup(args.pin) # cleanup GPIO
|
GPIO.cleanup(args.pin) # cleanup GPIO
|
||||||
|
|||||||
37
rpi_no_hdmi.service
Normal file
37
rpi_no_hdmi.service
Normal file
@@ -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
|
||||||
37
rpi_no_usb.service
Normal file
37
rpi_no_usb.service
Normal file
@@ -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
|
||||||
37
rpi_no_wifi.service
Normal file
37
rpi_no_wifi.service
Normal file
@@ -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
|
||||||
40
rpi_poweroff_button.service
Normal file
40
rpi_poweroff_button.service
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user