Commit 89436aa586d4c8341b076d221911670624743737
1 parent
e6e9828d
- 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%)
Showing
6 changed files
with
286 additions
and
12 deletions
README.md
0 → 100644
1 | +Raspberry Pi Scripts | |
2 | +==================== | |
3 | +This repository contains my collection of scripts and other snippets for the | |
4 | +[Raspberry Pi](https://www.raspberrypi.org). I am publishing these in case they | |
5 | +are of any benefit to other enthusiasts. Use them freely and please let me know | |
6 | +in case you encounter any issues or require changes. | |
7 | + | |
8 | +The latest versions, documentation and bugtracker available on my | |
9 | +[GitLab instance](https://gitlab.lindenaar.net/scripts/raspberrypi) | |
10 | + | |
11 | +Copyright (c) 2019 Frederik Lindenaar. free for distribution under | |
12 | +the GNU General Public License, see [below](#license) | |
13 | + | |
14 | +Contents | |
15 | +======== | |
16 | +This repository contains the following scripts: | |
17 | + * [gpio_trigger.py](#gpio_trigger) | |
18 | + is s script to execute a command when a GPIO input pin changes | |
19 | + * [rpi_no_hdmi.service](#services) | |
20 | + is a systemd service to disable the Raspberry Pi's HDMI port at boot | |
21 | + * [rpi_no_usb.service](#services) | |
22 | + is a systemd service to disable the Raspberry Pi's USB bus at boot | |
23 | + * [rpi_no_wifi.service](#services) | |
24 | + is a systemd service to disable on-board WiFi on Raspberry Pi at boot | |
25 | + * [rpi_poweroff_button.service](#services) | |
26 | + is a systemd service to support a power-off button using [gpio_trigger.py](#gpio_trigger) | |
27 | + | |
28 | + | |
29 | +<a name=gpio_trigger>gpio_trigger.py</a> | |
30 | +---------------------------------------- | |
31 | +This script was initially written to add a power-off button to a Raspberry Pi, | |
32 | +[see this blog post](https://frederik.lindenaar.nl/2019/10/23/raspberry-pi-power-off-button.html) | |
33 | +for the rationale behind it and how to construct and connect a physical button. | |
34 | + | |
35 | +The script itself is a generic solution to monitor a GPIO pin and executes a | |
36 | +command when the input signal on a pin changes. It can run as interactively as | |
37 | +well as in the background and executes a command once or continuously upon any | |
38 | +change or specific transition (e.g. HIGH to LOW). | |
39 | + | |
40 | +The script is written in Python 2 and uses the `RPi.GPIO` library as both are | |
41 | +installed by default on most distributions so should just work. Please note that | |
42 | +by default the script should be started as root to gain access to the GPIO port. | |
43 | + | |
44 | +To implement a simple power-off button, install the script in `/usr/local/sbin`, | |
45 | +connect an NC switch (i.e. one that connects when pressed) between pin 39 (GND) | |
46 | +and pin 40 of the Raspberry Pi and add: | |
47 | + | |
48 | +~~~ | |
49 | +if [ -x /usr/local/sbin/gpio_trigger.py ]; then | |
50 | + /usr/local/sbin/gpio_trigger.py -D -H 5000 poweroff | |
51 | +fi | |
52 | +~~~ | |
53 | + | |
54 | +to the file `/etc/rc.local`. This will start the script in the background (`-D`) | |
55 | +to wait for pin 40 (default pin) to be connected to ground for 5000ms (`-H`) and | |
56 | +then run the command `poweroff` to shutdown the Raspberry Pi. | |
57 | + | |
58 | +Please refer to the output of `gpio_trigger.py -h` for the options supported and | |
59 | +defaults used when no option is specified. | |
60 | + | |
61 | + | |
62 | +<a name=services>Systemd services</a> | |
63 | +------------------------------------- | |
64 | +The repository contains a number of `.service` files, which are systemd service | |
65 | +descriptions to control specific on-board features of the Raspberry Pi (e.g. to | |
66 | +disable unused ports). Their purpose should be pretty clear from their name (and | |
67 | +comments they contain). The rationale of the initial scripts is covered in this | |
68 | +[blog post](https://frederik.lindenaar.nl/2018/05/11/raspberry-pi-power-saving-disable-hdmi-port-and-others-the-systemd-way.html). | |
69 | + | |
70 | +In general, to install these copy them to the directory `/etc/systemd/system/` | |
71 | + | |
72 | +To manually disable the port, 'start' the 'service' with: | |
73 | + | |
74 | +~~~ | |
75 | +service <<filename without .service>> start | |
76 | +~~~ | |
77 | + | |
78 | +To manually enable the port again, 'stop' the 'service' with: | |
79 | + | |
80 | +~~~ | |
81 | +service <<filename without .service>> stop | |
82 | +~~~ | |
83 | + | |
84 | +To enable starting during system boot (to disable the port) run: | |
85 | + | |
86 | +~~~ | |
87 | +systemctl enable service <<filename without .service>> | |
88 | +~~~ | |
89 | + | |
90 | +To disable starting during system boot (to no longer disable the port) run: | |
91 | + | |
92 | +~~~ | |
93 | +systemctl disable service <<filename without .service>> | |
94 | +~~~ | |
95 | + | |
96 | + | |
97 | +<a name="license">License</a> | |
98 | +----------------------------- | |
99 | +These scripts, documentation & configration examples are free software: you can | |
100 | +redistribute and/or modify it under the terms of the GNU General Public License | |
101 | +as published by the Free Software Foundation, either version 3 of the License, | |
102 | +or (at your option) any later version. | |
103 | + | |
104 | +This script, documenatation and configuration examples are distributed in the | |
105 | +hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied | |
106 | +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
107 | +General Public License for more details. | |
108 | + | |
109 | +You should have received a copy of the GNU General Public License along with | |
110 | +this program. If not, download it from <http://www.gnu.org/licenses/>. | |
0 | 111 | \ No newline at end of file |
... | ... |
gpio_trigger.py
1 | 1 | #! /usr/bin/env python |
2 | 2 | |
3 | 3 | # |
4 | -# gpio_trigger.py - execute a command when a GPIO pin is triggered (up or down) | |
4 | +# gpio_trigger.py - execute a command when a GPIO input pin changes | |
5 | 5 | # |
6 | 6 | # Version 1.0, latest version, documentation and bugtracker available at: |
7 | 7 | # https://gitlab.lindenaar.net/scripts/raspberrypi |
... | ... | @@ -24,8 +24,12 @@ from os import fork, system |
24 | 24 | from argparse import ArgumentParser |
25 | 25 | from RPi import GPIO |
26 | 26 | |
27 | -parser = ArgumentParser(description='Run command when a Raspberry Pi pin is' | |
28 | - ' high or low (e.g. a button is pressed)') | |
27 | +parser = ArgumentParser( | |
28 | + description='Run command when a Raspberry Pi pin changes to high or low.', | |
29 | + epilog='(*) use \'--\' to stop argument parsing, arguments can contain the ' | |
30 | + 'following variables: %PIN%=pin number, %STATE%=value (HIGH or LOW)') | |
31 | +parser.add_argument('-D', '--daemon', action='store_true', | |
32 | + help='run in background (as daemon)') | |
29 | 33 | pgroup = parser.add_mutually_exclusive_group(required=False) |
30 | 34 | pgroup.add_argument('-P', '--pcb', action='store_const', dest='mode', |
31 | 35 | const=GPIO.BOARD, default=GPIO.BOARD, |
... | ... | @@ -50,22 +54,22 @@ pgroup.add_argument('-r', '--edge-rising', action='store_const', dest='edge', |
50 | 54 | const=GPIO.RISING, help='respond to pin going up') |
51 | 55 | pgroup.add_argument('-a', '--edge-any', action='store_const', const=GPIO.BOTH, |
52 | 56 | dest='edge', help='respond to any pin change') |
53 | -parser.add_argument('-i', '--ignore-result', action='store_true', default=False, | |
54 | - help='ignore command result code (default: exit if <> 0)') | |
55 | 57 | parser.add_argument('-b', '--debounce', type=int, default=200, |
56 | 58 | help='debounce period (in milliseconds, default=200)') |
59 | +parser.add_argument('-H', '--hold', type=int, default=-1, | |
60 | + help='optional hold time, pin must be held stable for the ' | |
61 | + 'specified time in milliseconds to trigger cmd') | |
57 | 62 | parser.add_argument('-t', '--timeout', type=int, default=-1, |
58 | 63 | help='optional timeout (in milliseconds) to wait') |
64 | +parser.add_argument('-i', '--ignore-result', action='store_true', default=False, | |
65 | + help='ignore command result code (default: exit if <> 0)') | |
59 | 66 | pgroup = parser.add_mutually_exclusive_group(required=False) |
60 | 67 | pgroup.add_argument('-c', '--continuous', default=False, action='store_true', |
61 | 68 | help='continously monitor GPIO pin and run cmd upon change') |
62 | 69 | pgroup.add_argument('-o', '--once', action='store_false', dest='continuous', |
63 | 70 | help='monitor pin and run cmd once, then exit (default)') |
64 | -parser.add_argument('-D', '--daemon', action='store_true', | |
65 | - help='run in background (as daemon)') | |
66 | 71 | parser.add_argument('cmd', help='command to execute when pin goes low') |
67 | -parser.add_argument('arg', nargs='*', help='argument(s) for the command, use --' | |
68 | - ' before first argument to stop parsing parameters') | |
72 | +parser.add_argument('arg', nargs='*', help='argument(s) for the command (*)') | |
69 | 73 | |
70 | 74 | args = parser.parse_args() # parse command line |
71 | 75 | GPIO.setmode(args.mode) # set GPIO number mode |
... | ... | @@ -76,12 +80,21 @@ if args.daemon and fork() != 0: # Fork for daemon mode |
76 | 80 | |
77 | 81 | ret = 0 |
78 | 82 | while args.ignore_result or ret == 0: |
83 | + # wait for GPIO pin to be changed in the right direction | |
79 | 84 | if GPIO.wait_for_edge(args.pin, args.edge, bouncetime=args.debounce, |
80 | 85 | timeout=args.timeout): |
81 | - ret = system(' '.join([ args.cmd ] + args.arg)) # run the command | |
82 | - if not args.continuous: # exit if running once | |
83 | - break | |
86 | + state = GPIO.input(args.pin) | |
87 | + # pin changed, if required check if it is stays the same long enough | |
88 | + if (args.hold < 0) or ( | |
89 | + GPIO.wait_for_edge(args.pin, GPIO.BOTH, bouncetime=args.debounce, | |
90 | + timeout=args.hold - args.debounce) is None): | |
91 | + ret = system(' '.join([ args.cmd ] + [ | |
92 | + [ 'LOW', 'HIGH' ][state] if arg == '%STATE%' else | |
93 | + str(args.pin) if arg == '%PIN%' else arg for arg in args.arg])) | |
94 | + if not args.continuous: # exit if running once | |
95 | + break | |
84 | 96 | else: # exit if timeout |
97 | + ret = -1 | |
85 | 98 | break |
86 | 99 | |
87 | 100 | GPIO.cleanup(args.pin) # cleanup GPIO |
... | ... |
rpi_no_hdmi.service
0 → 100644
1 | +# | |
2 | +# rpi_no_hdmi.service – Systemd service to disable the Raspberry Pi's HDMI port | |
3 | +# | |
4 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
5 | +# https://gitlab.lindenaar.net/scripts/raspberrypi | |
6 | +# | |
7 | +# Copyright (c) 2019 Frederik Lindenaar | |
8 | +# | |
9 | +# This script is free software: you can redistribute and/or modify it under the | |
10 | +# terms of version 3 of the GNU General Public License as published by the Free | |
11 | +# Software Foundation, or (at your option) any later version of the license. | |
12 | +# | |
13 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
14 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
15 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
16 | +# | |
17 | +# You should have received a copy of the GNU General Public License along with | |
18 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
19 | +# | |
20 | + | |
21 | +# To install copy to /etc/systemd/system/rpi_no_hdmi.service | |
22 | +# enable it to start during boot with: systemctl enable rpi_no_hdmi | |
23 | +# temporarily enable with: service rpi_no_hdmi start | |
24 | +# temporarily disable with: service rpi_no_hdmi stop | |
25 | +# disable starting during boot with: systemctl disable rpi_no_hdmi | |
26 | + | |
27 | +[Unit] | |
28 | +Description=Disable Raspberry Pi HDMI port | |
29 | + | |
30 | +[Service] | |
31 | +Type=oneshot | |
32 | +ExecStart=/opt/vc/bin/tvservice -o | |
33 | +ExecStop=/opt/vc/bin/tvservice -p | |
34 | +RemainAfterExit=yes | |
35 | + | |
36 | +[Install] | |
37 | +WantedBy=default.target | |
0 | 38 | \ No newline at end of file |
... | ... |
rpi_no_usb.service
0 → 100644
1 | +# | |
2 | +# rpi_no_usb.service – Systemd service to disable the Raspberry Pi's USB bus | |
3 | +# | |
4 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
5 | +# https://gitlab.lindenaar.net/scripts/raspberrypi | |
6 | +# | |
7 | +# Copyright (c) 2019 Frederik Lindenaar | |
8 | +# | |
9 | +# This script is free software: you can redistribute and/or modify it under the | |
10 | +# terms of version 3 of the GNU General Public License as published by the Free | |
11 | +# Software Foundation, or (at your option) any later version of the license. | |
12 | +# | |
13 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
14 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
15 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
16 | +# | |
17 | +# You should have received a copy of the GNU General Public License along with | |
18 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
19 | +# | |
20 | + | |
21 | +# To install copy to /etc/systemd/system/rpi_no_usb.service | |
22 | +# enable it to start during boot with: systemctl enable rpi_no_usb | |
23 | +# temporarily enable with: service rpi_no_usb start | |
24 | +# temporarily disable with: service rpi_no_usb stop | |
25 | +# disable starting during boot with: systemctl disable rpi_no_usb | |
26 | + | |
27 | +[Unit] | |
28 | +Description=Disable Raspberry Pi USB bus | |
29 | + | |
30 | +[Service] | |
31 | +Type=oneshot | |
32 | +ExecStart=/bin/sh -c "echo 0x0 > /sys/devices/platform/soc/3f980000.usb/buspower" | |
33 | +ExecStop=/bin/sh -c "echo 0x1 > /sys/devices/platform/soc/3f980000.usb/buspower" | |
34 | +RemainAfterExit=yes | |
35 | + | |
36 | +[Install] | |
37 | +WantedBy=default.target | |
0 | 38 | \ No newline at end of file |
... | ... |
rpi_no_wifi.service
0 → 100644
1 | +# | |
2 | +# rpi_no_wifi.service – Systemd service to disable WiFi on Raspberry Pi 3B/ZeroW | |
3 | +# | |
4 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
5 | +# https://gitlab.lindenaar.net/scripts/raspberrypi | |
6 | +# | |
7 | +# Copyright (c) 2019 Frederik Lindenaar | |
8 | +# | |
9 | +# This script is free software: you can redistribute and/or modify it under the | |
10 | +# terms of version 3 of the GNU General Public License as published by the Free | |
11 | +# Software Foundation, or (at your option) any later version of the license. | |
12 | +# | |
13 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
14 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
15 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
16 | +# | |
17 | +# You should have received a copy of the GNU General Public License along with | |
18 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
19 | +# | |
20 | + | |
21 | +# To install copy to /etc/systemd/system/rpi_no_wifi.service | |
22 | +# enable it to start during boot with: systemctl enable rpi_no_wifi | |
23 | +# temporarily enable with: service rpi_no_wifi start | |
24 | +# temporarily disable with: service rpi_no_wifi stop | |
25 | +# disable starting during boot with: systemctl disable rpi_no_wifi | |
26 | + | |
27 | +[Unit] | |
28 | +Description=Disable Raspberry Pi 3B/ZeroW WiFi interface | |
29 | + | |
30 | +[Service] | |
31 | +Type=oneshot | |
32 | +ExecStart=/sbin/ifdown wlan0 | |
33 | +ExecStop=/sbin/ifup wlan0 | |
34 | +RemainAfterExit=yes | |
35 | + | |
36 | +[Install] | |
37 | +WantedBy=default.target | |
0 | 38 | \ No newline at end of file |
... | ... |
rpi_poweroff_button.service
0 → 100644
1 | +# | |
2 | +# rpi_poweroff_button.service – Systemd service to implement a poweroff button | |
3 | +# | |
4 | +# Version 1.0, latest version, documentation and bugtracker available at: | |
5 | +# https://gitlab.lindenaar.net/scripts/raspberrypi | |
6 | +# | |
7 | +# Copyright (c) 2019 Frederik Lindenaar | |
8 | +# | |
9 | +# This script is free software: you can redistribute and/or modify it under the | |
10 | +# terms of version 3 of the GNU General Public License as published by the Free | |
11 | +# Software Foundation, or (at your option) any later version of the license. | |
12 | +# | |
13 | +# This script is distributed in the hope that it will be useful but WITHOUT ANY | |
14 | +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
15 | +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
16 | +# | |
17 | +# You should have received a copy of the GNU General Public License along with | |
18 | +# this program. If not, visit <http://www.gnu.org/licenses/> to download it. | |
19 | +# | |
20 | + | |
21 | +# Please note this requires gpio_trigger.py installed in /usr/local/sbin, see: | |
22 | +# https://frederik.lindenaar.nl/2019/10/23/raspberry-pi-power-off-button.html | |
23 | + | |
24 | +# To install copy to /etc/systemd/system/rpi_poweroff_button.service | |
25 | +# enable it to start during boot with: systemctl enable rpi_poweroff_button | |
26 | +# temporarily enable with: service rpi_poweroff_button start | |
27 | +# temporarily disable with: service rpi_poweroff_button stop | |
28 | +# disable starting during boot with: systemctl disable rpi_poweroff_button | |
29 | + | |
30 | +[Unit] | |
31 | +Description=Power-off button on GPIO | |
32 | + | |
33 | +[Service] | |
34 | +Type=idle | |
35 | +ExecStart=/usr/local/sbin/gpio_trigger.py --hold 5000 poweroff | |
36 | +Restart=always | |
37 | +RestartSec=30 | |
38 | + | |
39 | +[Install] | |
40 | +WantedBy=default.target | |
0 | 41 | \ No newline at end of file |
... | ... |