Replacing Mausberry Script with a Python script
-
For those of us using a Mausberry circuit for a hardware power switch (and for anyone considering one), it uses a BASH script that launches at startup and in the background, steadily looping as it waits for a button/switch to trigger a shutdown. When that happens, the BASH script initiates a poweroff command to safely shutdown the Pi. It waits for that to happen, and when it detects the Pi has shut down, it cuts the power.
This is all well and good, but the script that you install if you follow the instructions from the vendor is very general. Some enterprising members of our community have developed an enhanced version of the script for RetroPie that searches for emulators running, shuts them down, and crucially, allows Emulation Station to save metadata before continuing with shutting down the Raspberry Pi. Here is a link to the thread where these enhancements were made.
This solved a problem for many of us who were losing play counts and other details when using the power button/switch. Another problem was identified for when Mausberry users select the QUIT->SHUTDOWN option within ES. In this case, the user is trying to do the right thing by safely shutting down, which works, but it leaves the Mausberry circuit in an odd state. Because the hardware button isn't used, the circuit is not aware of the soft shutdown, so it goes into "limbo" and the power cord has to be removed and restored before the button/switch can be used to power back up. In this thread, we figured out a preliminary way to leverage a third GPIO pin to trigger a transistor wired in parallel with the power switch. This technique makes the Mausberry circuit think the button was pressed and that in turn triggers a proper soft shutdown as designed. It is still a work in progress, but we have a proof of concept.
One of the criticisms of the Mausberry circuit is that it relies on a BASH script looping on a sleep command and polling the value of a GPIO pin. This is apparently not very efficient, as there are better ways to monitor GPIO events that use less CPU. The reason for this post is to take what we have learned and built in a BASH script and convert it to a python script. Python can apparently watch for changes in GPIO values using interrupts instead of constant polling. This starts to get beyond my experience, but I was able to compose the following bit of python code that does exactly what the most basic Mausberry script can do. It is functionally the same as the BASH script, but probably consumes less resources:
#!/usr/bin/env python # Import the RPi.GPIO and OS import RPi.GPIO as GPIO import os # GPIO port setup GPIO.setmode(GPIO.BOARD) # Set pin numbering to BOARD numbering GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Set up pin 16 (23) as an input, pulled down GPIO.setup(18, GPIO.OUT) GPIO.output(18, 1) # Set pin 18 (24) value to 1 # Power button event GPIO.wait_for_edge(16, GPIO.RISING) # Stop script till button released # Power button action os.system('poweroff') # action performed on button press
This can be called from the rc.local just as easily as the BASH script. My challenge is to incorporate the more recent changes in the BASH script from the posts linked above into a better version of the python script. I simply lack the experience with python to know if I am doing it right.
Probably the first order of business is to convert the script so that it uses GPIO pin numbers instead of board numbers as it does now. Then, it is a matter of adding the new set of commands which might be as simple as replacing
os.system('poweroff')
with additions. The result should be a python version of the script for those of us who want to use that instead of BASH. -
@caver01 Yes, thank you for this piece.
That's indeed a much better approach as for the batch script.
I think there is no need to fully integreate the bash into the python code as I would change just the call.... instead of poweroff I would call the script for the POWERBLOCK.So you wait for an interrupt (GPIO button press) and then initiate the call of the bash script. And this one goes straight a line ...
- it checks for an running emulator ... yes/no?
- if yes then end the emulator
- if no end the if-clause
- it checks for an running EmulationStation ... yes/no?
- if yes then end EmulationStation properly and give control back to emulationstation.sh and this initiates a shutdown
- if no end the if-clause
- it initites a shutdown
- it checks for an running emulator ... yes/no?
-
Wow, love these improvements a lot. I own the Mausberry circuit and would love to test when needed!
-
@barrymossel Well the improvement will also be hardware based. As the mausberry dev rather sends the switch signal to the Pie than expects to be received from the Pie it is a bit of soldering to get a full working switch. But as I'm not a circuit designer ... I can't blame anyone. But I never expected that the Mausberry will not really shutdown if you choose a software powerdown as it is also a "everyday" usecase and not specially for the RetroPie.
So this issue could be solved by automatically shutdown if there is no GPIOPin2 feed from the Pie after 30seconds but therefore the Mausberry designer should be informed or read here in the forum ;)
-
@cyperghost Agreed. I too was surprised that it gets stuck the way it does during a soft shutdown.
I seem to recall reading somewhere that a long press (5 seconds?) of the power switch forces it to cut power either way. It doesn't work for me now, but I swear I was able to do it at one point. In any case, I would guess that the designer chose to do it this way. . . ignore the input signal until the hardware button has been pressed.
It seems like the better design would be wait for the input to become a "1", and and then start waiting for it to become zero, regardless of the power switch. Once it sees a "1", it should know that it was generated by the script, so the Pi must be running. If that value drops, the Pi must have shutdown.
In any case, your suggestion about calling the POWERBLOCK script seems like a nice shortcut. Why aren't we doing that with the BASH script?
<EDIT> I realize now that this suggested approach would have the unfortunate effect of converting all reboots into shutdowns.
-
@cyperghost Also, regarding the design, it could not have been built just to receive a signal from the Pi. It has to generate the power on, which the Pi can't do if it has no power. Part of what the mausberry circuit solves is that it completely cuts power to the Pi after the save shutdown.
-
I thought switching the power switch to off and then reset would work when you turn off through the menu. Not sure though. I will never use the menu option anyway, but if someone else in my house does, the reset could work I think.
-
@barrymossel Interesting. I don't even have the reset connected. I see the usefulness of it, but it is also a risk. If someone hits reset instead of power, we have a potential corrupted card. Or, does the reset also do a safe reboot?
-
Oh, and we should probably point out, there is more than one mausberry circuit. I have the DIY button version which is supposed to work with either a toggle or a momentary switch. I use a momentary, so there is no ON or OFF position. It is just a trigger.
-
I have the latest, not DIY. I have a toggle switch attached for on/off and a momentary for reset. The reset will be attached not near the on/off switch, so no (probable) chance that someone presses that by accident. Because it does a hard reset and could potentially corrupt ts sd yes.
-
@caver01 said in Replacing Mausberry Script with a Python script:
@cyperghost Agreed. I too was surprised that it gets stuck the way it does during a soft shutdown.
:D
In any case, your suggestion about calling the POWERBLOCK script seems like a nice shortcut. Why aren't we doing that with the BASH script?
Well, that's a historical thing. I was asked "How can ES be proper shutdown by button switch?" so it was clear to implent the code directly into the mausberry script. Up to v1.2 the script was only able to switch off ES
A few days later the code part to end all emulators that were called via runcommand was also added to the mausberry script mainly by @meleu. A few days later annother one asked for powerdown script for the PowerBlock and this is till now the "bare" form of this script that can be called just one time by any other program.
I think it's easier to tell people... just edit your mausberry shutdown with
sudo nano ....
and add some lines.
To tell them "call annother script" there must be knowledge how the other script must be saved in the right place and it must be made executable and it must be called maybe via sudo.
There are other possibilites. Take a look to gpio-watch. This C written program is also able to use edge detection by button press and will call a script named by gpio button. It looks like it works for input and output events. So the mausberry script will just initiate all GPIOs and at last will call gpio-watch for a triggered event. If there is a trigger the shutdown script will be initiated ;)
EDIT: I bought 2 of the mausberry DIY today ;)
-
@cyperghost so, there are several possible options. I guess I’d like to simply see the last version of the Mausberry script evolve into a self-contained python variant.
-
@cyperghost said
EDIT: I bought 2 of the mausberry DIY today ;)
Did you get a couple of NPN transistors too?
-
@caver01 I have a few of transistors here but don't know what type they are. Have to look into the datasheets first. I would rather use the optofets as I know they work surely.
Your solution is also good and it's much much cheaper ;)
For the sript... I see two approches
- Use the inotify-tool - I have really no practice in this! So an advanced coder should introduce
- A script that checks evidence of "echo 1 > ..."-command within
runcommand.sh
emulationstation.sh
. That's very easy to code with help of thesed
command
-
@cyperghost
I don’t think we need inotify when that wasn’t required for the BASH script.As for number 2, I don’t follow. Why can’t we just borrow the same logic from the excellent updated Mausberry script and use python code instead of BASH? I just don’t know if I can simply embed the commands and reproduce the logic not knowing python myself.
-
@caver01 The main challenge is, that you need the event of quitting ES trapped.
The bash script with the 1 second loop will surly miss that. We are talking about a general solution with usecase for everyone. But now I get why you were confusd. I wroteruncommand.sh
... I ment/opt/retropie/supplementary/emulationstation/emulationstation.sh
So imho for now the best way is to put the echo-command in the
emulationstation.sh
. With help withgrep
-command you can check existance and withsed
-command you can write it in the script. Because this script is executed if ES ends and works flawless but as already mentioned your changes will get lost if ES is updated.I know @meleu is working on a solution for this so keep prepared! But it'll be surly better than simply putting some commands with
sed/grep
I just don’t know if I can simply embed the commands and reproduce the logic not knowing python myself.
That should work. But I'm the wrong person here to ask for.
But python is far better as it uses edge_detection. -
@cyperghost
Agreed. So, next step for me is to start to learn a little python. -
@caver01 So you see.... the solution is there ;) So you can stick on your python script and it's edge detection :)
-
@cyperghost Yes. I may work on this a little bit today. It's great to collaborate! Thanks for your help!
-
@caver01 Here is an very intersting thread https://retropie.org.uk/forum/topic/12930
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.