~chrichri/Librem5-wake-on-IM

Documentation on how to wake a Librem5 via voice call when a new InstantMessage is waiting to be received.
small changes, started ntfy2call section
subscribing on matrix and listing pushers

refs

main
browse  log 

clone

read-only
https://git.sr.ht/~chrichri/Librem5-wake-on-IM
read/write
git@git.sr.ht:~chrichri/Librem5-wake-on-IM

You can also use your local clone with git send-email.

#Wake your phone from suspend on InstantMessage

To save power some phones running mobile linux like Librem5 and Pinephone suspend when not being used.

In suspended state a linux mobile phone can't receive messages via IP.

There are three ways to wake a mobile linux phone from suspend:

  • press a button
  • send a SMS
  • call the phone

I decided it would be worth a try to call my Librem5 when I want it to check for outstanding messages.

Here's a diagram of my setup:

flowchart showing how the matrix server sends a UnifiedPush notification via a ntfy server and how a ntfy client 'ntfy2call' decides when to call the Librem5 to wake it up. The Librem5 receives the same notifications from the ntfy server and confirms their reception to ntfy2call. ntfy2call does not trigger a voice call if the Librem5 confirmed the reception of the notification abot an outstanding message

#Demo

Watch the boring demo video.

  • 0:03 suspend Librem5
  • 0:19 notebook: send im from a VIP matrix account to my account configured on the Librem5
  • 0:41 Librem5 wakes up
  • 0:42 Librem5 shows incoming call (now you know why there is the yellow sticky note on the screen reading )
  • 0:45 Librem5 rejects the call (before it rings)
  • 0:47 Librem5 shows Calls - Missed Call notification
  • (in the upper left corner the symbols for network show that the internet connection is still broken)
  • 1:15 Internet is getting better
  • 1:16 Internet is up
  • 1:19 fractal has already been running before suspend, polled new messages and shows a notification about the new message. On my Librem5 the feedback for this would be a soft .
  • 1:36 my ntfy script jumped in and started an extra feedback for VIPs message playing a long and loud tune

#so what?

I'll put the details of my proof of concept into this repository. An issue tracker will help to improve this if there's interest.

For questions, comments and corrections please use the issue tracker

Until then you can look at my notes taken while setting this up.

#howto

Let's start from the top of the diagram and walk through the branches.

#ntfy server

I'm selfhosting a ntfy server. It is a basic setup and everything I did should work using the public server ntfy.sh as well.

To understand the concept it's good to understand the following terms:

  • Application Servers like Conduit for matrix or mastodon for ActivityPub can be configured to send out notifications to clients on configurable events.
    • the matrix specification names a subscription to get notifications pusher
  • The Push Server receives the notifications from the Application Servers and offers them to clients subscribing to the notifications.
  • A Distributor is installed on the Client Device (e.g. a mobile phone).
    • It subscribes to notification topics on behalf of client applications like Tuba or ElementX.
    • When receiving a notification it knows on behalf of what client it received it and signals the client application to wake up and do whatever needs to be done with the information contained in the push notification.
  • A client application compatible with UnifiedPush does two things to get woken up/started and receive notifications:
    • It tells the Application Server to send notifications to the Push Server
    • It tells the distributor to subscribe to the topic it agreed on with the Application Server
  • A topic is a random name that is needed to subscribe to notifications. It is like a radio channel. The application server needs to tell the push server under which topic to send the notification and the distributor needs to tell the push server which topic it wants to subscribe to.

The context is visualized nicely on the UnifiedPush Webpage.

To get a notification from the notifcation server you'll need to tell you matrix server that it should use a gateway to UnifiedPush. The gateway converts Matrix Push Format to UnifiedPush. Simplifying things I would say that ntfy understands Matrix Push and converts it into UnifiedPush.

#subscribing to notifications

If you use a matrix client that supports UnifiedPush it'd offer you to tell your matrix server to send notifications this way.

Fractal and Chatty do not support UnifiedPush, yet, and anyway for the calling side we'll need to receive notifications.

I used this specification for matrix to subscribe to notifications via requests created by curl.

#authentication

First you'll need to authenticate to the matrix server to get a token used in all other operations.

userid = account name in the form of @account:doma.in

# get token
curl -XPOST   -d '{"type":"m.login.password", "user":"<userid>", "password":"<password>"}'   'https://<matrix server domain name>/_matrix/client/r0/login' | jq .

Note: <matrix server domain name> needs not be the same as the domain in your account name @account:doma.in. doma.in can be different. To find the <matrix server domain name> for the doma.in part of your account you could use curl -X GET 'https://doma.in/.well-known/matrix/server' (replacing doma.in with the actual domain of your account. You'll get something like {"m.server": "matrix.doma.in:443"} telling you that the <matrix server domain name> for your matrix account is matrix.doma.in on tcp port 443.

You'll get an anwer like:

{
  "user_id": "@account:doma.in",
  "access_token": "Q9DaadNCqQvJkeh48KckaleR48KC8902",
  "home_server": "doma.in",
  "device_id": "GYfViNPhJz"
}

You'll need the access_token which in the example is Q9DaadNCqQvJkeh48KckaleR48KC8902 for the following operatoins.

#subscribing

Once you received your token you can tell your matrix server to send notifications to your ntfy server on some topic:

PUSHER='
  "pushkey": "https://<ntfy server>/<topic>?up=1",
  "app_id": "me.myself.noapp",
  "kind": "http",
  "data": {
    "url": "https://<ntfy server>/_matrix/push/v1/notify",
    "format": "event_id_only"
  },
  "app_display_name": "ntfy2call",
  "device_display_name": "some_device",
  "lang": "de"
'

curl -i -X POST "https://<matrix server domain name>/_matrix/client/v3/pushers/set"  \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-d "{${PUSHER}}"

You're free to change the app_id, app_display_name and device_display_name to your likings.

The answer should look like this:

HTTP/2 200 
server: nginx
date: Tue, 15 Oct 2024 06:47:13 GMT
content-type: application/json
content-length: 2
[possibly more headers…]

{}

It is just an empty json. To check if the subscription worked you should look at the registered pushers.

#listing notifications configured for your account
curl -s -X GET 'https://<matrix server domain name>/_matrix/client/v3/pushers?access_token=<access_token>' -H 'Accept: application/json' | jq .

The answer looks something like this:

{
  "pushers": [
    {
      "pushkey": "https://<ntfy server>/<topic>?up=1",
      "app_id": "my.myself.noapp",
      "kind": "http",
      "data": {
        "url": "https://<ntfy server>/_matrix/push/v1/notify",
        "format": "event_id_only"
      },
      "app_display_name": "ntfy2call",
      "device_display_name": "some_device",
      "lang": "de"
    },
    # probably more entries with additional pushers
    # if they've been registered by a client supporting
    # UnifiedPush the topic will start with 'up'
  ]
}
#delete a notification configuration from your account
TODO - if you know please let me know by an issue
#delete an access token
TODO - if you know please let me know by an issue

#testing

To test notifications generated by the matrix server you can open the web gui of ntfy (login if needed) and subscribe to the topic you set on the matrix server for notifications.

Once the matrix server generates a notification you'll get the notification on the web gui.

If this works you completed successfully the configuration of matrix and ntfy.

#ntfy2call

Now that notifications through ntfy are set up and working you'll need to make sure that your phone is woken when a new notification arrives.

I solved this part by making a phone call to my Librem5 to have the modem wake up the CPU from suspend.

The same effect could be achived by sending an SMS. SMS has the advantage that it is clearly within the contract your using. Calling without ever having the intention of picking up the call might be signaling without paying for it. You need to check your situation and decide.

Using SMS costs money, but offers two advantages:

  • it's possible to transmit the content of the notification to the phone which then doesn't need to get it itself via a working internet connection (in case the internet doesen't come up you'll already have the information to decide whether you'd want to take immediate action).
  • I didn't want to get a feedback for every notificiation, but wanted to depend the type of feedback on the content of the notification. This means that signaling for the SMS or call needs to be surpressed. In case of SMS this is already built into chatty. For calls an extra component (Phosh Anti-Spam) is needed.

Furthermore Guido Günther is thinking about a notification distributor build into chatty that would allow acting on behalf of the content of the notification-SMS: start the app that subscribed to the notification topic of the SMS and provide the notification content.

That said: I'll probably change my setup towards SMS once these things work and pay a few €/month to get an SMS flatrate for some SIM to be used to send the notification SMS.

Do not follow this link