Pinephone

20/06/2022 : code is now on GitLab

A lot of improvements have been made since the last update, so enjoy !"

Picture

Main window of Echo (in devel.)

Firefox OS prooved, a long time ago, that we don't need huge librairies like Gnome or KDE to build powerful webapps, handling phone, SMS, email, etc. And in fact, it's a lot easier to build rich interfaces, using HTML5/CSS3/JS standards, than spending hours building static UIs, giving especially bad results when rotating the device, or when the size of the device change.

Its another big mistake to think that native apps are the future, and the only way to build a powerful phone, when datas sleep in the clouds, and should be accessible on mobile & static devices... Following the android or ios jails are not the solution : they are the problem, because they limit the amount of devs capable to build apps, they tax devs, they force them to use closed tools and formats, etc. They are exactly the 1984 nightmare, with a telecran in the pocket, and people too "limited" to understand the world of slaves that the GAFAM are currently building around them.

Fortunaly, with the pinephone (from Pine64), we can definitively offer something other, something rich, something easy to use, something really different, like Firefox OS does :

  • using the usual web tools to build powerful webapps, easy to maintain
  • using a single websocket to transfert datas beetween clients/server, with an easy route/args/status/callback style
  • using node.js and DBus handlers to read/write device infos, and transfer them through the websocket to clients
  • using the same websocket to save or recall data, using open standards like XML

I already translated my old Cactus (calendar) and Cockatoo (contacts) webapps to this new device, using node.js to establish a client/server websocket.

Picture

Picture

Picture

Picture

Cockatoo (for contacts)

I finally decide to build my own phone application (Echo), using mmcli and dbus, to get all the options i was looking for, especially dedicated music with a decent level of sound on incoming calls ! It works pretty well, thanks to callaudiod and its easy to use phone mode. This application is not finished yet. I need now to find a way to bypass the screen login, and wake up the screen when the phone is in sleeping mode. I you know how to do it, please share.

Don't forget to stop gnome-calls when using Echo, to avoid conflicts on incoming calls !

P.S.: "Echo" doesn't integrate yet held, multiparty and forwarding calls. That's not my priority at this time. I prefer concentrate myself to improve and simplify stability and ergonomy for usual calls (in fact 100% of my own use), then write a SMS webapp.

How to use it ?

I strongly recommand Firefox, because epiphany suffers from two major problems : a vertical scrolling not so smooth than Firefox, and the fact that epiphany doesn't remember when you authorize a self signed certificate (Firefox does).

In fact, certificates are one of the major headeach when you use webapps. Browsers become all very (too?) restrictive, even with https://localhost or https://127.0.0.1. You had no choices but to point first on the URL of the socket (https://localhost:2020), then you can access the webapps with https://localhost/ffox/.

These restrictions are rather stupid on my point of view, because authorizations should cover a domain one's for all, and not be restrictive on wss://. In fact, you should even be able to build a white list of sites/ports to bypass browsers protections - it will be a lot easier for everyone : users & devs !

For the moment, i follow the advices of Let's encrypt, but it doesn't solves the issue.

Future improvements ? Writing handlers on server side to:

  • call a contact (made !)
  • open a known contact file on incoming call (made !)
  • get/send SMS (incoming)
  • open an external email application
  • ...

Client installation

You should already have a working apache HTTPS server on the pinephone. There are enough how-to on the web if you don't know the procedure.

On the pinephone as root :

	
mkdir -p /var/www/html/pinephone
cd /var/www/html/pinephone
wget "https://alsatux/dev/pinephone/webapps.latest.tgz"
tar zxvf webapps.latest.tgz
chown -R www-data:www-data /var/www/html/pinephone
adduser mobian www-data
find /var/www/html/pinephone -type d -print0|xargs -0iX chmod 775 X
find /var/www/html/pinephone -type f -print0|xargs -0iX chmod 664 X
	
	

The client archive provides Cactus, Cockatoo, Echo & all common files.

The first time, on the pinephone, you have to point Epiphany or Firefox to https://mobian:2020, to override self certificate signing protection in the browser, then you can point to https://mobian/pinephone/webapps/cactus or https://mobian/pinephone/webapps/cockatoo.

Don't forget to fix the settings on startup.

When the phone is connected on a computer with USB, its default IP is 10.66.0.1, which means you can use Firefox (or any other browser) on your desktop to access Cactus or Cockatoo on the phone. Just change mobian hostname with 10.66.0.1, and fix the new settings.

Server installation

On the pinephone as root :

	
# server installation
apt update
apt install nodejs
cd /usr/local/src
mkdir pinephone
cd pinephone
npm install ws wscat bufferutil file-system utf-8-validate utils-extend path dbus-native
wget "https://alsatux/dev/pinephone/node.server.latest.tgz"
tar zxvf node.server.latest.tgz
cp pinephone.service /etc/systemd/system
# default storage dir
install -o 1000 -g 1000 -m 775 -d /home/mobian/sdcard
	
	

Then modify the pinephone.config.js and the storage.config.js files. In this last file, fix the "sdcard1" parameter to the path you want to read/write your datas.

My advice is to run manually the server side with "node pinephone.js" as root, check if all is ok with the webapps (read/write), and finaly enable the systemd unit pinephone.service with :

	
systemctl start pinephone.service
systemctl enable pinephone.service
	
	

Download sources

Version notes

  • 1.41
    • Use dbus-native against mmcli, except to find the modem number.
    • Adding DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus to pkexec commands.
    • Adding a contact module apart.
    • Correction of several little bugs (and one big !).
  • 1.4
    • Adding keypad sounds + DTMF.
    • Rewrite the homepage.
    • Add the new logo of Echo.
    • Correct little HTML mistakes.
  • 1.3
    • Bye bye gnome-calls - our love was impossible, because you are too retricted for me.
    • Hello "Echo", to get/pass calls using a web browser, local or distant... Yes : you can already dialing and call from the Firefox on your desktop ! And in a short future, activate the speaker or mute the micro ! Enjoy !
  • 1.2
    • Open contact file on incoming calls.
    • Change calls to gnome-calls, according to the new mobian stable release 20201113 from Awai.
  • 1.1
    • Add phone out-calling using gnome-calls.
  • 1.0
    • Initial public release.

Hacker's fest

For all of my friends...

SMS part

I'm currently trying to decode modem data, so i partially translate the mmsdecoder.php from Jonatan Heyman to javascript.

You can try decoding your own datas using node.js. First get the datas from CLI or from DBUS :


root@mobian ~ # mmcli -m 0 --messaging-list-sms
    /org/freedesktop/ModemManager1/SMS/4 (received)
root@mobian ~ # mmcli -s 4
  -----------------------
  General    | dbus path: /org/freedesktop/ModemManager1/SMS/4
  -----------------------
  Content    |    number: +33654321012
             |      data: 00060401BEAF848C829850356F6F787A46714565755376345350615767676B41008D928918802B33333635343332313031312F545950453D504C4D4E0086818A808F818E0305D6DB83687474703A2F2F3231332E3232382E332E36302F6D6D732E7068703F50356F6F787A46714565755376345350615767676B41008805810303F480
  -----------------------
  Properties |  pdu type: deliver
             |     state: received
             |   storage: me
             |      smsc: +336XXXXXXXX
             | timestamp: 2020-11-28T12:09:56+01:00

Then download mmsdecoder.js, edit the file, copy the "data" string at the end, then run the script with node mmsdecode.js.

Result of the previous command :


{ BBC: null,
  CC: null,
  CONTENTLOCATION: 'http://213.228.3.60/mms.php?P5ooxzFqEeuSv4SPaWggkA',
  CONTENTTYPE: null,
  DATE: null,
  DELIVERYREPORT: 0,
  DELIVERYTIME: null,
  EXPIRY: { type: 'seconds', value: 259200 },
  FROM: '+33654321012/TYPE=PLMN',
  MESSAGECLASS: 'Personal',
  MESSAGEID: null,
  MESSAGETYPE: 'm-notification-ind',
  MMSVERSIONMAJOR: 1,
  MMSVERSIONMINOR: 2,
  MESSAGESIZE: 382683,
  PRIORITY: 'Normal',
  READREPLY: null,
  REPORTALLOWED: null,
  RESPONSESTATUS: null,
  RESPONSETEXT: null,
  SENDERVISIBILITY: null,
  STATUS: null,
  SUBJECT: null,
  TO: null,
  TRANSACTIONID: 'P5ooxzFqEeuSv4SPaWggkA',
  MMSVERSIONRAW: '92',
  CONTENTTYPE_PARAMS: null }

The script searched for the "AF 84" signature, marking the user header, and ignore previous bytes. I haven't found yet a full and easy to use description to decode the previous header, so if you have something, please share.

I plan to integrate MMS reception to a new webapp (surprise !). But i need a lot of SMS/MMS to do so and my bad : i only have a single SIM.

Voice part

Disable gnome-calls, then try the following... Big thanks to d-feet !

Making a call

NMCLI GDBUS
	
# use {u"number":GLib.Variant("s", "0389768566")} in d-feet
$ mmcli -m 0 --voice-create-call="number=0389768566"
Successfully created new call: /org/freedesktop/ModemManager1/Call/1
$ mmcli -m 0 --voice-list-calls
    /org/freedesktop/ModemManager1/Call/1 outgoing (unknown)
	
	
	
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Modem/0 --method org.freedesktop.ModemManager1.Modem.Voice.CreateCall "{'number':<'0389768566'>}"
(objectpath '/org/freedesktop/ModemManager1/Call/1',)
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Modem/0 --method org.freedesktop.ModemManager1.Modem.Voice.ListCalls
([objectpath '/org/freedesktop/ModemManager1/Call/1'],)
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Call/1 --method org.freedesktop.DBus.Properties.Get "org.freedesktop.ModemManager1.Call" "Direction"
(<2>,)
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Call/1 --method org.freedesktop.DBus.Properties.Get "org.freedesktop.ModemManager1.Call" "State"
(<0>,)
	
	
	
$ mmcli -m 0 -o "/org/freedesktop/ModemManager1/Call/1" --start
successfully started the call
$ mmcli -m 0 --voice-list-calls
    /org/freedesktop/ModemManager1/Call/1 outgoing (dialing)
	
	
	
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Call/1 --method org.freedesktop.ModemManager1.Call.Start
()
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Call/1 --method org.freedesktop.DBus.Properties.Get "org.freedesktop.ModemManager1.Call" "Direction"
(<2>,)
$ gdbus call --system --dest org.freedesktop.ModemManager1 --object-path /org/freedesktop/ModemManager1/Call/1 --method org.freedesktop.DBus.Properties.Get "org.freedesktop.ModemManager1.Call" "State"
(<1>,)
	
	
	
$ dbus-send --dest=org.mobian_project.CallAudio --type=method_call /org/mobian_project/CallAudio org.mobian_project.CallAudio.MuteMic boolean:false
$ dbus-send --dest=org.mobian_project.CallAudio --type=method_call /org/mobian_project/CallAudio org.mobian_project.CallAudio.SelectMode uint32:1
	
	

Hangup

	
$ mmcli -m 0 -o "/org/freedesktop/ModemManager1/Call/1" --hangup
successfully hung up the call
$ mmcli -m 0 --voice-list-calls
    /org/freedesktop/ModemManager1/Call/1 outgoing (terminated)
$ mmcli -m 0 --voice-delete-call "/org/freedesktop/ModemManager1/Call/1"
successfully deleted call from modem
dbus-send --dest=org.mobian_project.CallAudio --type=method_call /org/mobian_project/CallAudio org.mobian_project.CallAudio.SelectMode uint32:0
dbus-send --dest=org.mobian_project.CallAudio --type=method_call /org/mobian_project/CallAudio org.mobian_project.CallAudio.MuteMic boolean:true
	
	

Options for the method SelectMode (from source code project)

	
@CALL_AUDIO_MODE_DEFAULT: Default mode (used for music, alarms, ringtones...)  * 
@CALL_AUDIO_MODE_CALL: Voice call mode
	
	

Incoming call

	
#!/bin/sh

OLDTIMER=0
dbus-monitor --system "interface='org.freedesktop.ModemManager1.Modem.Voice',type='signal',member='CallAdded'" | while read -r; do
	TIMER="$(date +%s)"
	DIFF="$(expr $TIMER - $OLDTIMER)"
	# Avoid multi-lines from DBUS
	if [ $DIFF -gt 2 ]; then
		CALLID=$(mmcli -m 0 --voice-list-calls -a | grep -Eo '[0-9]+ incoming \(ringing-in\)' | grep -Eo '[0-9]+')
		if [ -n "$CALLID" ]; then
			CALLER=$(mmcli -m 0 --voice-list-calls -o "/org/freedesktop/ModemManager1/Call/$CALLID" -K | grep call.properties.number | cut -d ":" -f 2 | tr -d " ")
			echo $CALLER;
			mmcli -m 0 -o "/org/freedesktop/ModemManager1/Call/$CALLID" --accept
			dbus-send --dest=org.mobian_project.CallAudio --type=method_call /org/mobian_project/CallAudio org.mobian_project.CallAudio.MuteMic boolean:false
			dbus-send --dest=org.mobian_project.CallAudio --type=method_call /org/mobian_project/CallAudio org.mobian_project.CallAudio.SelectMode uint32:1
		fi
	fi
	OLDTIMER="$TIMER"
done