https://www.flickr.com/photos/feuilllu/5553946261/

Réanimation du Karotz en enceinte de bureau autonome

Ça fait bien des années que j’ai acheté ce machin (près de 200€), pour soutenir la seule boite française assez audacieuse pour relancer le Nabaztag. Entre ces deux produits, une évolution majeure : le Karotz embarque un micro-ordinateur sous Linux, dont les fonctions ne seront accessibles qu’au travers d’une pauvre API JavaScript « dans le cloud » durant des années.

Alors qu’il n’a jamais eu la moindre utilité – les applications proposées étant toutes plus nazes les unes que les autres – un développeur prépare dans son coin un firmware appelé OpenKarotz. Ce projet ouvre l’accès aux fonctions principales de l’objet via une simple API en HTTP : lecture de fichier audios, utilisation de tags RFID, couleur de la LED ventrale, orientation des oreilles, prise de photos et même Text-To-Speech (quand ça marche, service en ligne oblige).

Ce projet est constitué d’un installateur web propriétaire et dépendant d’un site abandonné. Alors qu’il se dit « Open », les sources du projet n’ont jamais été publiées, rien n’a été documenté et la communauté est pour ainsi dire morte. À ceux qui se lanceraient, je recommande l’installation sur clé USB car elle est facile à sauvegarder, ce qui sera bien utile le jour où le site aura disparu.

Outils à disposition

OpenKarotz offre un accès console en telnet très pratique. Que trouve t-on à l’intérieur ? Pas grand chose hélas, ni compilateur (gcc/llvm) ni gestionnaire de paquet (apt/yum). Il faudra faire avec ce qui est présent. Au rayon des langages disponibles, deux candidats : Python 2.4.4 (2006) et Bash 4.1.0.

J’ai tout tenté : utiliser des paquets armel de chez Debian, faire tourner le script deboostrap, mettre à jour Python (il n’y a ni easy_install ni pip !). Nada. Le Linux est un Pragmatec, littéralement éventré et proche d’un OpenWRT.

Comme on ne peut rien installer, il faut utiliser des services de Text To Speech en ligne. Les API changent tout le temps, je ne veux plus y toucher à l’avenir et les voix se prêtent très mal à une lecture continue d’actualités. La reconnaissance vocale ne me semble pas faisable sur ce projet.

Karotz Music Player

En résumé, je cherchais à faire une application qui a accès à une enceinte, une clé USB, qui peut faire clignoter une LED et bouger des oreilles de lapin en plastique, sans la moindre interaction.

Le script Python que je vous propose aujourd’hui construit une playlist basée sur le contenu du dossier Music à la racine de la clé USB et la lit. Vous pouvez placer ce dossier parmi les fichiers OpenKarotz de votre installation sur clé. Après la première exécution, il se lancera automatiquement une minute après chaque mise sous tension du Karotz.

La racine du dossier Music est lue en désordre (shuffle) mais le contenu des sous-dossiers est lu dans l’ordre. Le programme lit d’abord le contenu des dossiers avant les fichiers seuls. Je trouve cela pratique car il offre la liberté de lire un ensemble de fichiers mélangés ou dans l’ordre s’ils sont placés dans un sous-dossier. La présence de plusieurs sous-dossiers implique une écoute longue donc variée si proposée au hasard.

Les sous-sous-dossiers sont ignorés. Je rappelle que vous pouvez également jouer des stream et des playlist via l’interface web d’OpenKarotz. Ce script ne nécessite pas de connexion Internet : il tourne théoriquement en mode hors-ligne !

Je n’ai pas encore trouvé comment retirer la dépendance à Internet de manière sûre, un flux de discussion est ouvert à ce sujet.

Lancer un script au démarrage du Karotz, comme un cron @reboot

Les crons sont gérés par le binaire crond de busybox, qui ne supporte pas les raccourcis commençant par @, donc la directive @reboot n’est pas supportée. À la place on peut mettre une ligne de commande dans un script que l’on appelle toutes les minutes, qui veille à créer un fichier dans le dossier /tmp/ (vidé à chaque redémarrage), et qui n’exécute la suite du script que si le fichier n’existe pas. Le cron rappellera le script indéfiniment tant que le lapin est allumé mais ne l’exécutera ainsi qu’une fois. Ça ne consomme pas, c’est simple et ça permet de lister toutes les tâches au même endroit 🙂

Les crons se trouvent dans le fichier /usr/spool/cron/crontabs/root

Je ne connais pas le comportement de cette implémentation de cron, ainsi je recommande de toujours mettre « >/dev/null 2>&1 » en fin de ligne de cron, pour que les sorties n’aillent pas s’entasser quelque part dans un fichier de logs.

Jouer avec les crons pour créer un radio-réveil

On peut facilement ajouter quelques crons pour que le lapin s’anime tout seul :
# S'endort à 21h00 chaque jour
0 21 * * * /usr/www/cgi-bin/sleep
# S'éveille à 7h00 du lundi au vendredi
0 7 * * 1-5 /usr/www/cgi-bin/wakeup
# S'éveille à 8h00 le samedi
0 8 * * 6 /usr/www/cgi-bin/wakeup
# S'éveille à 10h00 le dimanche
0 10 * * 0 /usr/www/cgi-bin/wakeup

Utilisation du bouton

L’API HTTP OpenKarotz est complète, en revanche je ne vois pas comment utiliser le bouton en haut de la tête .

La commande dbus-monitor –system affiche de nouvelles entrées à chaque pression du bouton, j’en déduis qu’il doit être possible d’intercepter ces évènements dbus en Python, mais la version est si vieille que les exemples de code pompés dans la doc de l’époque ne fonctionnent pas. J’y ai passé des heures.

Les périphériques du Karotz sont gérés par des démons situés dans /usr/karotz/bin/ et lancés par /www/cgi-bin/start_ok (d’ailleurs si le son de démarrage vous énerve, commentez PlaySound $CNF_DATADIR/Sounds/ready.mp3).

Il faut donc commencer par désactiver le bout de script surveillant l’utilisation du bouton dans /www/cgi-bin/dbus_events en commentant toute la section BUTTON HANDLER (tous les types de clics). Je n’ai pas réussi à aller plus loin.

Liens utiles

– quelques apps supplémentaires (sans offense, toujours aussi nazes)
tous les liens qu’il faut pour développer (vraiment)

3 commentaires sur “Réanimation du Karotz en enceinte de bureau autonome

  1. super,
    openkarotz etait un beau projet, dommage qu’il ai ete abandonnée,
    mon lapin est en veille,
    je vais donc essayer de le reconvertir en lecteur enceinte de bureau,

  2. Dans le fichier /karotz/OkSetup/yaffs_start.sh, ligne 41 on peut lire :

    /usr/bin/python /usr/scripts/wait_until_connected.py

    J’ai été très surpris de voir le contenu du script wait_until_connected.py, car l’API HTTP peut être appelée depuis le lapin lui même via des scripts en Python. Le lapin peut être parfaitement autonome et finir sa vie bloqué si vous l’emportez dans un autre batiment (!) loin de votre wifi.

    J’ai rendu ce script non-bloquant en modifiant cette section comme il suit :

    # Tout en haut
    import threading

    # …
    # …
    # …

    #main

    def retry_connexion():
    if len(sys.argv) > 1 and sys.argv[1] == « –quiet »:
    wait_until_connected(False)
    else:
    wait_until_connected(True)

    connexion_thread = threading.Thread(None, retry_connexion)
    connexion_thread.start()
    connexion_thread._Thread__stop()

    Mon Karotz s’allume désormais quoi qu’il arrive MAIS même dans des conditions normales je ne parviens plus à m’y connecter (je ne trouve plus son ip sur le réseau).

    On m’a proposé un dernier code que je n’ai pas pu tester (je n’avais pas envie de formater) :

    retrycount=0
    while retrycount < 3:
    os.system("logger -s \"[START] loading wifi config\"")
    if not ethernet and wifi:
    config.load_wifi()
    if not network.wait_wifi_status(10):
    retrycount+=1
    continue

    if ethernet: config.load_ip("eth0")
    if wifi: config.load_ip("wlan0")

    os.system("logger -s \"[START] asking for ip\"")
    if not network.wait_ip(300):
    continue
    os.system("logger -s \"[START] network is ready to go\"")
    break

  3. Pour que le lapin démarre correctement, j’ai du commenter dans le fichier /usr/scripts/wait_until_connected.py les 3 lignes ci-dessous:

    while 1:
    os.system(« logger -s \ »[START] loading wifi config\ » »)
    if not ethernet and wifi:
    config.load_wifi()
    if not network.wait_wifi_status(300):
    continue

    if ethernet: config.load_ip(« eth0 »)
    if wifi: config.load_ip(« wlan0 »)

    #os.system(« logger -s \ »[START] asking for ip\ » »)
    #if not network.wait_ip(300):
    # continue
    os.system(« logger -s \ »[START] network is ready to go\ » »)
    break

    Et pour utiliser le bouton avec openkarotz il faut modifier le script /www/cgi-bin/dbus_events

    par exemple pour appeler une url sur simple clic:

    # ———————
    # Single Click Detected
    # User Defined Action
    # ———————
    echo $line | grep « member=click »
    if [ $? -eq 0 ]; then
    curl -s ‘http://myurl’ > /dev/null
    fi

    j’espère que ça te fera avancer 😉

L'espace de discussion de cet article est désormais fermé.