Remote i3-wm WS : ma télécommande pour bureau Debian GNU/Linux
Il m'arrive d'avoir besoin de prendre le contrôle de ma machine via mon Android (bouger la souris, scroller et taper du texte).
J'ai quasiment toujours utilisé l'application Pointer Host. elle s'appuie sur un serveur Java lancé sur ma machine. Pour bouger la souris et générer des cliques, elle est très efficace. Cependant, l'écriture de caractères a toujours posé problème (chiffres et lettres accentuées erronés).
Depuis quelques semaines, j'ai envie de jouer avec les websockets et réécrire une appli du genre m'a semblé être un bon exercice.
Ce que je vais vous présenter est une POC. Cette application n'est pas sécurisée et est orientée pour mes besoins. Il est cependant très simple de la faire évoluer.
Voici mon cahier des charges :
- aucune application ne doit être installée sur mon téléphone
- utilisation du navigateur web pour le pilotage
- pouvoir bouger la souris
- pouvoir générer des cliques
- pouvoir scroller
- pouvoir taper des mots
- pouvoir lancer des raccouris claviers
- pouvoir gérer le volume du son
- pour Spotify : lancer et mettre en pause la musique, avancer et reculer dans la playlist en cours de lecture
- pouvoir changer de workspace dans mon gestionnaire de fenêtres i3-wm
Les outils pour scripter tout ça sont connus :
xdotool
pour simuler un clavier et une souris (3, 4, 5, 6, 7) :xdotool type "ceci va être tapé"
xdotool key Enter
(toucheEntrée
)xdotool click 1
(clique gauche)
amixer
pour gérer le volume (8) :amixer set Master 50%
(volume à 50%)
playerctl
pour piloter Spotify (9) :playerctl -p spotify next
(titre suivant)
i3-msg
pour piloter i3-wm (10) :i3-msg 'workspace "Foo"'
(affichage du workspaceFoo
)
Websocket est un protocole réseau issu du web qui permet de créer un canal full-duplex entre un client et un serveur. Ils peuvent donc communiquer en temps réel dans une connexion TCP.
Comme à mon habitude et par esprit de contradiction (pas de NodeJS), j'ai décidé d'écrire la partie serveur en PHP 7. La partie cliente est en HTML 5 avec un peu de javascript.
Entre le serveur et le client, ce sont des messages textes qui sont échangés. J'ai décidé de les formater en JSON et seul le client va en envoyer. Ils sont toujours sous cette forme : {"type":"un type de message", [données complémentaires]}
. Voici quelques exemples :
{"type":"workspace","value":"1. IRC"}
{"type":"pointer","click":"left"}
{"type":"media","value":"next"}
{"type":"volume","value":"down"}
{"type":"scroll","value":"up"}
{"type":"pointer","x":"-2","y":"3"}
{"type":"text","value":"Un texte"}
On peut aussi envoyer plusieurs messages dans un seul. Voici un exemple qui va permettre d'ouvrir urxvt
via dmenu
que je lance avec win+d
:
{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"urxvt"},{"type":"key","value":"enter"}]}
Ces messages sont générés par le client et sont interprétés par des messageHandler
une fois transmis au serveur. En voici un exemple :
Le code source de l'application est disponible sur deblan/remote-i3wm-ws et la procédure d'installation est simple :
Pour lancer le serveur websocket, il faut exécuter server/server start
(@see restart
et stop
). Le serveur va écouter sur le port 14598
.
Concernant la partie cliente, vous pouvez créer un vhost Apache/Nginx qui pointera sur client/
ou lancer le serveur web built-in de PHP via php -S 0.0.0.0:15000 -t client/
. Il faudra à présent vous connecter au serveur web depuis un navigateur.
Quelques captures de la partie cliente :
Je vais essayer de faire une vidéo de démonstration. Depuis mon Samsung S8, ça fonctionne du feu de dieu et sur un petit Iphone 4S, c'est tout aussi fonctionnel (à part l'interface web un peu étriquée).
Edit 1
dbus-send
a été remplacé parplayerctl
(merci Thomas L)- le type
messages
a été ajouté et permet d'envoyer plusieurs messages (cf l'exemple avecurxvt
) et les mises à jour du code
Edit 2
- Le code PHP du serveur a été déplacé dans
server/src/resource/server.php
server/server
est à présent un script shell et permet de lancer, relancer et stopper le serveur websocket (server/server start|restart|stop
)