…and these will already wake the phone up without the need of any script.
The good deal! But the main question for me was how to prevent the display to wake up?
Another idea - fail to sleep back in, e.g., 30 sec if the phone has not been unlocked and clear he state in another case.
The answer will probably be hidden within gnome-settings-daemon.
Ideas:
*LED changes color when there is a notification. @dos possible? Maybe then also go back to sleep immediately after recognized notifications.
*IP-adjustable for ping.
*Do not wake up screen during the exam.
*Whitelist or blacklist for wakeup.
@irvinewade Text messages and calls would probably be candidates for a blacklist. I’m talking about notifications that can’t wake up the device. Like signal, or flare, or other messengers, for example.
I did a bit of tinkering.
the monitor stays off while the script is running.
Before the system goes into standby, the rtc is set to a wakeup time that can be configured in minutes.
If this wakeup time is in the quiet hours (at night), it is set to the end of this time.
If there is an alarm clock that lies in the time until the next rtc start, the rtc start is set before the alarm clock start (configurable).
if the system wakes up, it is checked whether it was an rtc wakeup.
if it was an rtc wakeup, it is checked whether there were relevant messages, if not, the system goes back to standby and pulls up the rtc again.
If there were relevant messages (whitelist), the monitor is switched on.
–
i would like to use the led instead of switching on the display, but i haven’t found a way to do this yet.
wakeup-check.conf
# === Allgemeine Einstellungen ===
LOGFILE="/var/log/wakeup-check.log"
WAKE_TIMESTAMP_FILE="/var/log/rtc_wake_timestamp.txt"
# === Wakeup-Logik ===
NEXT_RTC_WAKE_MIN=15 # Regulärer RTC-Wakeup alle X Minuten außerhalb der Quiet Hours
WAKE_BEFORE_ALARM_MINUTES=2 # Minuten vor einem Alarm, zu dem RTC aktiviert wird
# Zeitfenster zur Erkennung eines RTC-Wakeups (Sekunden)
RTC_WAKE_WINDOW_SECONDS=60
# === Quiet Hours ===
QUIET_HOURS_START="23:00"
QUIET_HOURS_END="06:00"
# === Internetverbindung prüfen ===
MAX_WAIT=30 # Sekunden zum Warten auf Internet (über nmcli)
PING_HOST="1.1.1.1" # Fallback Host für Ping
# === Notification-Handling ===
NOTIFICATION_TIMEOUT=20 # Sekunden, um auf neue DBus-Notifications zu warten
APP_WHITELIST="signal flare" # Relevante App-Namen in Kleinbuchstaben
NOTIFICATION_USE_FBCLI=true # Ob fbcli zur Benachrichtigung verwendet wird
NOTIFICATION_TURN_ON_DISPLAY=true # Bildschirm einschalten bei Notification
# === Zielbenutzer ===
TARGET_USER="dein-benutzername" # Benutzername mit aktiver DBus-Session (z. B. der Desktop-User)
wakeup-check-pre.service
[Unit]
Description=Wakeup Check - Pre Suspend
Before=sleep.target
StopWhenUnneeded=true
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wakeup-check.sh pre
[Install]
WantedBy=sleep.target
wakeup-check-post.service
[Unit]
Description=Wakeup Check - Post Suspend
After=suspend.target sleep.target
Requires=suspend.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wakeup-check.sh post
[Install]
WantedBy=suspend.target
/usr/local/bin/wakeup-check.sh
#!/bin/bash
# Konfigurationsdatei laden
CONFIG_FILE="/etc/wakeup-check.conf"
[ ! -f "$CONFIG_FILE" ] && echo "Fehlende Konfigurationsdatei: $CONFIG_FILE" && exit 1
source "$CONFIG_FILE"
# Zielbenutzer UID und DBus-Session prüfen
TARGET_UID=$(id -u "$TARGET_USER")
if [ ! -d "/run/user/${TARGET_UID}" ]; then
echo "DBus-Session für Benutzer ${TARGET_USER} nicht gefunden!"
exit 1
fi
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/${TARGET_UID}/bus"
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOGFILE"
}
turn_off_display() {
log "Turning off display"
sudo -u "$TARGET_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
gdbus call --session --dest org.gnome.ScreenSaver \
--object-path /org/gnome/ScreenSaver \
--method org.gnome.ScreenSaver.SetActive true >/dev/null
}
turn_on_display() {
log "Turning on display"
sudo -u "$TARGET_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
gdbus call --session --dest org.gnome.ScreenSaver \
--object-path /org/gnome/ScreenSaver \
--method org.gnome.ScreenSaver.SetActive false >/dev/null
}
use_fbcli() {
if [ "$NOTIFICATION_USE_FBCLI" == "true" ]; then
log "Using fbcli for notification."
sudo -u "$TARGET_USER" fbcli -E notification-missed-generic
sudo -u "$TARGET_USER" fbcli -E message-new-instant
fi
}
is_rtc_wakeup() {
[ -f "$WAKE_TIMESTAMP_FILE" ] || return 1
last_wake=$(cat "$WAKE_TIMESTAMP_FILE")
now=$(date +%s)
diff=$((now - last_wake))
(( diff >= 0 && diff <= RTC_WAKE_WINDOW_SECONDS ))
}
is_quiet_hours() {
local now time_start time_end
now=$(date +%H:%M)
time_start="$QUIET_HOURS_START"
time_end="$QUIET_HOURS_END"
if [[ "$time_start" < "$time_end" ]]; then
[[ "$now" > "$time_start" && "$now" < "$time_end" ]]
else
[[ "$now" > "$time_start" || "$now" < "$time_end" ]]
fi
}
get_next_alarm_time() {
gdbus call --session \
--dest org.gnome.clocks \
--object-path /org/gnome/clocks/AlarmModel \
--method org.gnome.clocks.AlarmModel.ListAlarms 2>/dev/null |
grep -oP '\d{10}' | sort -n | head -1
}
set_rtc_wakeup() {
local now wake_ts quiet_end_ts next_alarm_ts
now=$(date +%s)
# Quiet hours Ende berechnen
if [[ "$QUIET_HOURS_START" < "$QUIET_HOURS_END" ]]; then
quiet_end_ts=$(date -d "today $QUIET_HOURS_END" +%s)
else
quiet_end_ts=$(date -d "tomorrow $QUIET_HOURS_END" +%s)
fi
next_alarm_ts=$(get_next_alarm_time)
if is_quiet_hours; then
log "Currently in quiet hours."
if [[ "$next_alarm_ts" =~ ^[0-9]+$ && $next_alarm_ts -gt $now && $next_alarm_ts -lt $quiet_end_ts ]]; then
wake_ts=$((next_alarm_ts - (WAKE_BEFORE_ALARM_MINUTES * 60) ))
log "Next alarm during quiet hours. Setting RTC wakeup for $(date -d @$wake_ts)"
else
wake_ts=$quiet_end_ts
log "No alarm during quiet hours. Setting RTC wakeup for end of quiet hours: $(date -d @$wake_ts)"
fi
else
wake_ts=$(( now + (NEXT_RTC_WAKE_MIN * 60) ))
log "Not in quiet hours. Setting RTC wakeup for $(date -d @$wake_ts)"
fi
echo 0 > /sys/class/rtc/rtc0/wakealarm
echo "$wake_ts" > /sys/class/rtc/rtc0/wakealarm
log "RTC wakeup set to $(date -d @$wake_ts)"
}
wait_for_internet() {
log "Waiting up to $MAX_WAIT seconds for internet..."
for ((i=0; i<MAX_WAIT; i++)); do
status=$(nmcli networking connectivity)
log "nmcli: $status"
[[ "$status" == "full" ]] && log "Internet is available." && return 0
sleep 1
done
if ping -q -c 1 -W 2 "$PING_HOST" >/dev/null; then
log "Ping successful – internet likely available."
return 0
fi
log "No internet connection detected."
return 1
}
monitor_notifications() {
local whitelist=($APP_WHITELIST)
timeout "$NOTIFICATION_TIMEOUT" sudo -u "$TARGET_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
dbus-monitor "interface='org.freedesktop.Notifications'" |
while read -r line; do
if echo "$line" | grep -q "member=Notify"; then
buffer=""
for _ in {1..6}; do read -r next && buffer+="$next"$'\n'; done
app=$(echo "$buffer" | grep -oP 'string "\K[^"]+' | head -1 | tr '[:upper:]' '[:lower:]')
log "Notification received from: $app"
for match in "${whitelist[@]}"; do
if [[ "$app" == *"$match"* ]]; then
log "Relevant notification from: $app"
[[ "$NOTIFICATION_TURN_ON_DISPLAY" == "true" ]] && turn_on_display
use_fbcli
echo "NOTIFIED"
return 0
fi
done
log "Unlisted notification from: $app"
fi
done
return 1
}
# --------- MAIN ---------
MODE="$1"
log "===== wakeup-check.sh started (mode: $MODE) ====="
turn_off_display
if [[ "$MODE" == "pre" ]]; then
set_rtc_wakeup
date +%s > "$WAKE_TIMESTAMP_FILE"
log "Pre-mode done. Wake timestamp saved."
log "===== wakeup-check.sh finished ====="
exit 0
fi
if [[ "$MODE" == "post" ]]; then
if is_rtc_wakeup; then
log "RTC wakeup detected."
if is_quiet_hours; then
log "In quiet hours. Suspending again."
set_rtc_wakeup
systemctl suspend
exit 0
fi
if wait_for_internet; then
log "Checking for notifications..."
TMP_NOTIFY_FILE=$(mktemp)
(monitor_notifications > "$TMP_NOTIFY_FILE") &
sleep "$NOTIFICATION_TIMEOUT"
wait
if grep -q "NOTIFIED" "$TMP_NOTIFY_FILE"; then
log "Relevant notification found – staying awake."
else
log "No relevant notification – suspending again."
set_rtc_wakeup
systemctl suspend
fi
rm -f "$TMP_NOTIFY_FILE"
else
log "No internet – suspending again."
set_rtc_wakeup
systemctl suspend
fi
else
log "Non-RTC wakeup – system stays awake."
fi
fi
log "===== wakeup-check.sh finished ====="
I’m still testing a bit then I’ll upload the script.
i am not yet satisfied with deactivating desplay. do you have any ideas?
This might be of use to you:
I think I need to go back to the detection of what woke up the system.
Does anyone have any good ideas?
Plenty of ones!
You could use systemd timers to wake up the phone and check is it expired or not:
$ cat /usr/lib/systemd/system/resume-delay.timer
[Unit]
Description=Resume delay to check IMs
[Timer]
OnActiveSec=1min
AccuracySec=1s
WakeSystem=true
[Install]
WantedBy=timers.target
$ sudo systemctl restart resume-delay.timer
$ sudo systemctl suspend
Resume before the timer expired:
$ systemctl list-timers resume-delay.timer
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri 2025-04-18 10:13:03 +07 31s - - resume-delay.timer resume-delay.service
Resume by the timer:
$ systemctl list-timers resume-delay.timer
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri 2025-04-18 10:14:46 +07 20s - - resume-delay.timer resume-delay.service
There is one strange thing here. The list should look like this:
NEXT LEFT LAST PASSED UNIT ACTIVATES
- - Fri 2025-04-18 10:14:46 +07 5min ago resume-delay.timer resume-delay.service
but in fact I see that the timer did not expire while the phone is already resumed… May be we need to use realtime timers instead of monitonic one, but I can not understand how to set it in a five minutes from now rather that run it each five minutes… Also you should check systemd version. The my one is 254.
basically, the wakeup works very well with the rtc.
However, I have to clearly recognize whether the Librem5 was woken up by a source other than the rtc.
but so far I have not been able to find the wakeup reason in any log.
If it exists somewhere it would be perfect.
$ rtcwake -m show
that only tells me which wakeup time is stored in the rtc, doesn’t it?
This does not tell me whether the rtc has woken up the system or whether someone has pressed the button.
But you could check is alarm expired when you are woken up or not, doesn’t it? I believe this is exactly that you need
p.s. To be honest, I do not remember why I switched to use systemd timers rather that rtcwake
in my previous investigations… Now I see at least one problem - it could conflict if someone else will use the same timer.
i’m looking for some bugs, i’ve broken something. if i’m satisfied, i’ll update it.
Good morning everyone I am almost satisfied. However, somehow I can’t get the name of the app that sent the notification via the dbus monitor.
Any tips?
"$NOTIFICATION_TIMEOUT" sudo -u "$TARGET_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
dbus-monitor "interface='org.freedesktop.Notifications'" |
while read -r line; do
if echo "$line" | grep -q "member=Notify"; then
buffer=""
for _ in {1..6}; do
read -r next && buffer+="$next"$'\n'
done
app=$(echo "$buffer" | grep -oP 'string "\K[^"]+' | head -1 | tr '[:upper:]' '[:lower:]')
summary=$(echo "$buffer" | grep -oP 'string "\K[^"]+' | sed -n '3p')
body=$(echo "$buffer" | grep -oP 'string "\K[^"]+' | sed -n '4p')
log "Notification received from: $app"
log "Title: $summary"
log "Message: $body"
i’ll try using gdbus for the notifications. it’s more consistent with the rest anyway.
Why you need to know the sender?
I don’t need it, I’m just trying to find out what data I can extract. At the end i just want the app name to match it with the whitelist
Did you manage to wake-up the phone without waking the screen?
looks quite good. the screen sometimes wakes up very shortly. but for now i would say it works.
I hope the notification stuff is working now.
I will test it in the next hours.
if you like, here is the project. I look forward to your feedback.