Compare commits

...

5 Commits

Author SHA1 Message Date
Xavier Del Campo Romero 4911e89749
Fork 2023-03-13 02:52:46 +01:00
Xavier Del Campo Romero fe0369e835 README.md: add information on suspend inhibitors 2022-03-04 23:18:52 +01:00
Xavier Del Campo Romero 312bc6955a Do not suspend on active inhibitors 2022-03-04 22:31:09 +01:00
milky-sway b24bfb10c7
Create sleepwalk.service 2022-01-04 21:43:51 +01:00
milky-sway 1040cf1045
Create sleepwalk 2022-01-04 21:43:20 +01:00
3 changed files with 206 additions and 3 deletions

View File

@ -6,13 +6,13 @@ Helper scripts for PinePhone and PinePhone Pro users
By default, the script will make the phone sleep within 60 seconds, when the screen is turned off (sleep mode will not apply while the screen is on) and will make the phone sleep for 10 minutes (if not interrrupted by pressing the power button to wake the phone). It will then keep the phone awake for 30 seconds and put the phone immediately back to sleep mode for another 10 minutes and so on. You can change the durations directly at the top of the script. While the phone is sleeping, the RGB LED will light up constantly green and when it is awake for the short period of time, it will be a blinking red. The LED will be turned off, when the phone screen is enabled (for example by pressing the power button).
Any active suspend inhibitors (e.g.: some music players) will keep the phone awake until the inhibitor is deactivated.
Howto install and use:
- Save the 'sleepwalk' script to /usr/local/bin and the systemd service file 'sleepwalk.service' to '/etc/systemd/system/'
- Disable deep sleep in your desktop managers settings such as phosh
- Execute 'systemctl enable sleepwalk.service' and 'systemcl start sleepwalk.service' to enable and start the service
Known issues:
- Phone will go to sleep even if apps like for example a music player is playing in the background while the screen is turned off. It will however not sleep, if you are making a call.
Dependencies:
- rtcwake
- systemd

191
sleepwalk Normal file
View File

@ -0,0 +1,191 @@
#!/bin/bash
SLEEP_SECS_INIT=30
SLEEP_SECS=$SLEEP_SECS_INIT
SLEEP_STEP=180
SLEEP_MAX_SECS=600
WAKE_SECS=35
LOCK_DIR="/tmp/sleepwalk"
CPU_STATE=1
set_cpu_offline() {
if [ $CPU_STATE -eq 1 ]; then
echo "Powering off all CPU cores except cpu0"
for i in $(seq 2); do
echo 0 > /sys/devices/system/cpu/cpu$i/online
done
CPU_STATE=0
fi
}
set_cpu_online() {
SLEEP_SECS=$SLEEP_SECS_INIT
if [ $CPU_STATE -eq 0 ]; then
echo "Powering on all CPU cores except cpu0"
for i in $(seq 2); do
echo 1 > /sys/devices/system/cpu/cpu$i/online
done
CPU_STATE=1
fi
}
start_deep_sleep() {
led_sleep
if [ $((SLEEP_SECS + $SLEEP_STEP)) -lt $SLEEP_MAX_SECS ]; then
SLEEP_SECS=$((SLEEP_SECS + SLEEP_STEP))
else
SLEEP_SECS=$SLEEP_MAX_SECS
fi
sleep 5 # Give some extra time for pending output data
if [ can_suspend ]; then
echo mem > /sys/power/state 2>/dev/null
fi
return $?
}
wait_for_notifications() {
secs=$WAKE_SECS
is_led_on=0
while [ $secs -ge 0 ]; do
sleep 1
if [ $is_led_on == 0 ]; then
led_wake
is_led_on=1
else
led_disable
is_led_on=0
fi
if is_screen_on; then
if is_charging; then
cpufreq-set -g conservative
else
cpufreq-set -g powersave
fi
set_cpu_online
break
fi
set_cpu_offline
secs=$(($secs-1))
done
led_disable
}
schedule_wake_time() {
echo "Sleeping for ${SLEEP_SECS}s"
rtcwake -m no --date "+${SLEEP_SECS}s" 2>&1 >/dev/null
}
reset_wake_time() {
led_wake
> /sys/class/rtc/rtc0/wakealarm
}
is_charging() {
[ "$(cat /sys/class/power_supply/axp20x-usb/online)" = "1" ]
}
is_inhibitor_active() {
# INHIBITORS=$(sudo -u "$(cat /proc/$(pidof -s gnome-session-ctl)/environ | grep -z USER | sed 's,\x0,,;s,USER=,,')" DBUS_SESSION_BUS_ADDRESS=$(cat /proc/$(pidof -s gnome-session-ctl)/environ | grep -z DBUS_SESSION_BUS_ADDRESS | sed "s,\x0,,;s,DBUS_SESSION_BUS_ADDRESS=,,") gnome-session-inhibit --list)
# printf "%s\n" "$INHIBITORS"
INHIBITORS=$(systemd-inhibit --list --what=sleep --mode=block --no-legend \
| grep -e 'sleep')
[ -n "$INHIBITORS" ]
# if [ "$INHIBITORS" = "No inhibitors" ]; then
# return 1
# fi
# return 0
}
is_screen_on() {
return "$(cat /sys/class/backlight/backlight/bl_power)"
}
can_suspend() {
! ( is_inhibitor_active || is_screen_on || is_charging )
}
led_sleep() {
:
# echo 1 > /sys/class/leds/green\:indicator/brightness
# echo 0 > /sys/class/leds/red\:indicator/brightness
# echo 0 > /sys/class/leds/blue\:indicator/brightness
}
led_wake() {
:
# echo 0 > /sys/class/leds/green\:indicator/brightness
# echo 1 > /sys/class/leds/red\:indicator/brightness
# echo 0 > /sys/class/leds/blue\:indicator/brightness
}
led_disable() {
:
# echo 0 > /sys/class/leds/green\:indicator/brightness
# echo 0 > /sys/class/leds/red\:indicator/brightness
# echo 0 > /sys/class/leds/blue\:indicator/brightness
}
if [ $EUID -ne 0 ]; then
echo "Needs root" >&2
exit 1
fi
if [ -z "$1" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
cat <<-EOF >&2
Usage: sleepwalk [start/stop]
Commands:
start Start sleep cycle
stop Stop sleep cycle
EOF
exit
fi
if [ "$1" == "start" ]; then
if [ -d "$LOCK_DIR" ] || ! mkdir "$LOCK_DIR"; then
echo "sleepwalk is already running - run 'sleepwalk stop' to stop it" >&2
exit 1
fi
trap "$0 stop" EXIT
while [ -d "$LOCK_DIR" ]; do
while ! can_suspend; do
set_cpu_online
if is_charging && is_screen_on; then
cpufreq-set -g conservative
else
cpufreq-set -g powersave
fi
sleep 10
done
reset_wake_time
schedule_wake_time
while ! start_deep_sleep; do
reset_wake_time
echo "Failed going to sleep, try again in $WAKE_SECS seconds ..." >&2
wait_for_notifications
schedule_wake_time
if ! can_suspend; then
break
fi
done
wait_for_notifications
done
elif [ "$1" == "stop" ]; then
reset_wake_time
led_disable
rmdir "$LOCK_DIR" 2>/dev/null
else
echo "Unknown command: $1" >&2
exit 1
fi

12
sleepwalk.service Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=Deep-Sleep-Service for PinePhone with support for periodic wake-ups to get notifications
[Service]
User=root
WorkingDirectory=/
ExecStart=sleepwalk start
ExecStop=sleepwalk stop
Restart=always
[Install]
WantedBy=multi-user.target