2015-08-06

Utiliser sa kindle comme écran domotique

* ERRATA 1 : FOR non-frog-speakers : complete journey inside the project and step-by-step instructions to reproduce my video : https://hackaday.io/project/7126-kindle-as-a-home-automation

* ERRATA 2 : all source code (C99, python, energia) are on my GitHub : https://github.com/cekage/kindle-home-automation *

En attendant que l'inspiration Android me revienne, je vous propose une manipulation un peu tarabiscotée pour transformer votre Kindle en écran domotique.

Bien évidemment la kindle possède un navigateur et bien évidemment la manipulation consistera à ne pas le lancer. Sinon c'est trop facile !

* TLDR;  Créér un mobi avec des mots connus du dictionnaire. Rooter la kindle. Diriger les log syslog-ng vers un program. Le "program" doit avoir des triggers pour des requetes http (source plus bas).*


Pré-requis:

Cet article nécessite quelques connaissances pour reproduire la même chose chez vous :
  • une kindle rooté
  • un peu de html et kindlegen 
  • le minimum vital des bases linux : bash, vi, scp, ssh, mount
  • vi (ouais ça se corse à partir de là)
  • syslog-ng
  • savoir compiler un code source avec une toolchain kindle.
Rien d'insurmontable et au pire faites-vous aider.

Objectif:

Nous allons commencer par faire un ebook puis observer en direct dans la KIndle ce qu'il se passe lorsqu'on fait des manipulations.
Ensuite nous allons voir comment canaliser ces informations et les filtrer au besoin.
Enfin nous allons construire un moulin en bout de la canalisation pour faire des requêtes HTTP.

Le mobi

L'opération est toute simple, vous vous procurez kindlegen sur site de amazon et vous faites un .mobi avec.
Le .html que j'ai utilisé pour la démonstration dans la vidéo est sur github.

Visite des coulisses:

Votre kindle est rootée et vous avez ssh ? C'est la manière la plus confortable. Notez que ça  fonctionne aussi avec la liaison série.
k@mbp ~ $ ssh root@192.168.1.110
Welcome to Kindle!

root@192.168.1.110's password: 
#################################################
#  N O T I C E  *  N O T I C E  *  N O T I C E  # 
#################################################
Rootfs is mounted read-only. Invoke mntroot rw to
switch back to a writable rootfs.
#################################################

Première des choses, regardons les syslog:
150806:083005 syslog-ng[29521]: SIGHUP received, restarting syslog-ng
150806:083005 system: I tinyrot:def:Removing  /var/local/log/netlog_00000127_*.gz to save storage space
150806:083005 system: I tinyrot:def::Rotating file /var/log/odotlite with max size 2048
150806:083005 system: I tinyrot:def::No file to rotate: /var/log/odotlite
150806:083005 system: I tinyrot:def::Rotating file /var/log/wpa_supplicant with max size 128
150806:083005 system: I tinyrot:def:Removing  /var/local/log/wpa_supplicant_00000139_*.gz to save storage space
150806:083007 syslog-ng[29521]: new configuration initialized

Rien de bien extraordinaire. Notez la présence de tinyrot, il y a fort à parier qu'il s'agit d'un outil de rotation de log. Nous pouvons oublier tout de suite l'idée de récupérer quoi que soit dans les fichiers logs de /var/log (Race Condition).

Maintenant ouvrons un ebook en appuyant sur les boutons de la kindle:
150806:083007 syslog-ng[29521]: new configuration initialized
150806:083118 cvm[3363]: I BookletManager:SwitchingBooklets:from=Home,to=Bookworm:
150806:083118 cvm[3363]: I lipc:gsp:prop=orientation, source=com.lab126.system:Get string property
150806:083118 cvm[3363]: I WindowManagerImpl:PageTransitionBehavior:USE_GL16=true:
150806:083118 cvm[3363]: I WindowManagerImpl:NewTemperatureAndPages:temperature=25,pages=5:Updated temperature and pages
150806:083118 cvm[3363]: I Reader:BOOK INFO:book asin=unknown,file size=31022,file last mod date=2015-08-05 11.49.25 -0719,content type=ebook,length=HTMLPosition_ 1354,access=2015-08-06 08.19.41 -0719,last read position=HTMLPosition_ 359,isEncrypted=false,isSample=false,isNew=false,isTTSMetdataPresent=false,isTTSMetadataAllowed=true,fileExtn=mobi:
150806:083118 cvm[3363]: I lipc:gip:prop=userstoreFreeSpace, source=com.lab126.volumd:Get int property

La ligne Reader nous permet donc de savoir quel ebook est ouvert, son format et tout le barda. Notez l'asin, unknown, c'est parce que j'ai utilisé un fichier .mobi. Avec un format en azw3 le fichier aurait un asin de ce type là : 18812ddb-b3de-4ae1-bc3c-538d68b19ad8.
Faites donc des essais et essayer de deviner ce qui va vraiment nous intéresser pour la suite.
Nous avons donc un bout pour commencer : savoir ce que l'utilisateur fait.

Filtrer, raffiner, canaliser

On attaque la partie velue, le syslog, tout d'abord identifions :
[root@kindle root]# ps ax | grep syslog
29521 ?        Ss     0:02 /usr/sbin/syslog-ng

Oh ! Ce familier syslog-ng ! C'est une bonne surprise, nous allons pouvoir lancer arrêter ce daemon très simplement pour tester nos configurations.
Car, et c'est la bonne nouvelle de la bonne surprise : syslog-ng possède des filtres et peut envoyer nos logs à une commande.
Allons au plus rapide, remounter / en rw et modifiez pour obtenir :
[root@kindle root]# grep cvm /etc/syslog-ng/syslog-ng.conf 
destination cvm { program("/tmp/readlog" template("$MSG\n")); };
filter f_cvm { match("cvm"); };
## /var/log/cvm in addition to /var/log/messages,
log { source(src); filter(f_cvm); destination(cvm); };

La destination de la règle cvm sera un programme avec un template minimal, le filter est sur la chaîne "cvm" (vous pouvez l'améliorer) et la règle du log qui reprends la source, le filtre et la destination.
Ok nous savons que l'information que nous cherchons va nous arriver par les log du lecteur, nous avons donc paramétrer le gestionnaire de log pour alimenter un programme nommé readlog qui sera dans /tmp/ (ou ailleurs, peu importe). Il ne reste plus qu'à construire readlog :-)

le code de readlog

Petit rappel, nous sommes sur une système anémique qui n'a pas beaucoup de ram et dont on ne souhaite pas épuiser la batterie en le faisant lagger.
Donc on oublie les scripts bash avec sed/grep/curl, c'est pas beau, ça mange de la ram et ça tue les chatons.
ON OUBLIE LE SCRIPT BASH !!!!
Vous trouverez les fichiers sources sur mon repo github.
git clone https://github.com/cekage/kindle-home-automation

Conclusion

C'était un défi fun, il n'y avait qu'une seule manière pour passer une valeur du lecteur d'ebook à un logiciel sous-jacent. L'utilisation du dictionnaire est rustre mais efficace.
L'expression régulière clef est "SupplementarInfoBox:QUICK_LOOKUP:asin=.*,word=[A-Z]+:", comprenez qu'en utilisant un azw3 (avec calibre ?) vous pouvez bloquer la clef ASIN à une valeur connue et ainsi limiter les interférences avec les autres ebooks.

En ce qui concerne la partie LED, elle n'a pas beaucoup d'intérêt. C'est un simple blink avec un test sur la ligne série. Si "1" on toggle LED1 si "0" on toggle LED0… le tout est piloté avec un script python qui écoute sur mbp:8080 (en dur dans le code source) et écrit sur /dev/msp430 (la launchpad).