# Boîte COF de l'AGB

_Maurice, Sel, catvayor. Octobre 2024_


Pour l'AG budget d'octobre 2024, HackENS a produit un contrôleur
de projecteur pour [le site de l'AGB](http://agb.hackens.org)
à mettre entre les mains (responsables, voyons) du COF.

Le COF avait donc accès à la configuration d'un projecteur (motorisation,
luminosité, couleur) et à un effet "color bump".

![Boîte en octobre 2024](boite_oct24.jpg)


## Réalisation

L'idée de départ est la suivante : un panneau de contrôle sans fil pour le COF,
relié via l'API de Maurice aux projecteurs de l'AGB. Maurice a fourni une
batterie (108 Wh !!) et via BiBi HackENS a récupéré des Raspberry Pi Zero,
qui sont idéales pour ce genre de projet.

On a identifié 3 domaines lors du développement (on était 3, quel hasard) :

- la mécanique/électronique : une boîte qui tient, avec joystick
et boutons;

- le software sur le contrôleur : comment programmer la Raspi et comment on
communique avec l'API de l'AGB;

- les hooks dans l'API de l'AGB, notamment rajouter le contrôle du projecteur
dans les services offerts, ainsi que le système d'autorisation.

La distinction n'était pas toujours très claire toutefois : est-ce que la soudure,
la détermination des pinout relève du point 1 ou 2 ? Est-ce que la trigo pour
contrôler le projecteur de manière intuitive relève du contrôleur local ou de
l'API ? On a travaillé principalement sur ces 3 points séparément
mais on s'est entraidé donc les frontières floues entre ces points n'ont pas
posé de problèmes.

### Mécanique (Sel)

L'aspect le plus important de la boîte est son haut, avec le panneau de
contrôle. Avec des pièces d'arcade qui traînaient, on était sûrs au début de
mettre un joystick et deux boutons. Aussi, un potentiomètre semblait une
option tentante. Mais installer un potentiomètre peut introduire de la
complexité : _a priori_ la Raspi Pico ne peut pas lire la résistance du
potentiomètre directement car elle n'a que des entrées numériques...

La boîte fait environ 20cm x 20cm x 11cm, les dimensions étant choisies
surtout pour contenir la (grosse) batterie de Maurice tout en ayant assez de
hauteur pour installer les contrôles.

Initialement j'ai voulu réaliser une boîte beaucoup trop ambitieuse à la CNC,
où les "murs" sont biseautés à 45° chacun avant d'être collés. Un étrange
bug de soft limit sur la CNC a empêché l'usinage des pièces. Avec un peu trop
d'enthousiasme, j'ai alors essayé d'usiner cela à la défonceuse. C'était une
__très__ mauvaise idée, comme en témoignent 4 pauvres chutes de bois encore
à hackENS.

J'ai donc dû tout reprendre de 0 le dimanche pour le mardi, avec un design plus
simple : 4 murs rectangulaires, avec deux paires égales car découpées ensemble.
Les murs sont collés ensemble, et une planche de contreplaqué usinée à la CNC
(bouton par bouton, pour éviter partiellement le bug) tient les contrôles :
les 2 boutons, le joystick, un commutateur ON/OFF et un encodeur. En effet,
après avoir trouvé un encodeur numérique, qui donne par l'état de 8
interrupteurs l'angle de son axe, on a décidé de l'ajouter à la place du
potentiomètre.

Le fond de la boîte a un rebord pour s'aligner sans jeu en dessous
des murs, mais la boîte est fermée par 2 équerres dans tous les cas. Des pieds
en caoutchouc s'assurent que la boîte ne glisse pas, même maltraitée, et permet
aux équerres de ne pas racler le sol.

![la boîte, ouverte](boite_ouverte_oct24.jpg)

### Software embarqué (catvayor)

Pour le software embarqué, la raspberry était sous NixOS, avec une unité systemd
pour interfacer les commandes avec l'API de l'AGB. La config NixOS complète est
[ici](https://git.dgnum.eu/HackENS/hackens-org-configurations/src/commit/fecddb1f7720d40cacdcfd7b7e91d4f9c0289184/machines/agb02),
elle n'a rien de particulièrement mystèrieux, mise à part l'import du module pour
faire une image prête à booter pour la carte SD. La connection internet se faisait
par WiFi en l'absence d'autre possibilité, qui pendant l'agb aura été fourni par
mon partage de connection, car la solution prévue qui passait par une autre Raspberry Pi
n'a pas fonctionné. Pour pouvoir débugguer en live, on l'avait mis sur le VPN d'Hackens,
ce qui n'aura pas été utile pour débugguer, mais pour autre chose.

L'interface entre les commandes et le serveur de l'agb se fait en C++, avec `libgpiod`
pour lire les entrées des commandes, et un socket C pour envoyer les commandes
correspondantes. Initialement, on voulait utiliser les endpoints HTTPS, mais
on a remarqué une lenteur considérable de curl sur la Raspberry,
ammenant le temps de réponse à 700ms (on n'a pas pris le temps d'identifier la source
du problème). L'authentification par token était alors impossible et on a choisi
de modifier de serveur pour recevoir un flux de json par un simple socket, ouvert
que sur le VPN.

Petit point à noter: certains des pins de la raspberry pi ont des usages particulier,
ce qui peut poser problème si on les utilise, notamment, la Rraspberry ne bootait que si
le décodeur était dans la bonne position, sinon les pins I2C sont mis à GND, ce qui gêne
manifestement le boot.

### API de l'AGB (Maurice)

L'API est un petit programme rust pour le backend et une application django pour
l'authentification et le frontend. Le code source est public:
[https://git.dgnum.eu/HackENS/ragb](https://git.dgnum.eu/HackENS/ragb). Pour
mettre à jour la base de données interne d'états des projecteurs on utilise des
requêtes POST (ou une socket tcp over wireguard pour la boîte). La notification des clients (pages du frontend ouvertes ainsi que
le boîtier de contrôle DMX, cf plus tard) d'un changement de l'état de la base
de donnée est réalisé via un SSE
([https://fr.wikipedia.org/wiki/Server-sent_events](https://fr.wikipedia.org/wiki/Server-sent_events)).
Voici un exemple typique de message que l'on peut recevoir sur le SSE:
```
data: {"type":"Color","address":129,"value":{"red":0,"green":0,"blue":0}}

data:
{"type":"Motor","pan":164,"tilt":97,"focus":173,"white_button":0,"black_button":false,"bump_color":{"red":246,"green":49,"blue":49}}
```

Pour expérimenter un peu vous pouvez consulter la documentation de l'api:
[https://agb.hackens.org/api-docs/](https://agb.hackens.org/api-docs/) et lire
le SSE avec la commande `curl -ns https://agb.hackens.org/api/sse`


### Le contrôle DMX des projecteurs

Pour le contrôle des projecteur on utilise le protocole standard de PLS: le
[DMX-512](https://fr.wikipedia.org/wiki/DMX_%28%C3%A9clairage%29).  Il s'agit d'un bus série assez simple: Le contrôleur envoie des
paquets de 512 octets sur le bus et les projecteurs lisent une partie de ce
paquet pour savoir dans quel état se mettre (la partie du paquet correspondant à
chaque projecteur est déterminé par _l'addresse_ du projecteur). Une fois les
projecteurs installés et raccordés au bus il nous reste à connecter un boîtier
de contrôle usb (le [Entec DMX USB
PRO](https://www.enttec.com/product/dmx-usb-interfaces/dmx-usb-pro-professional-1u-usb-to-dmx512-converter/)) à une raspberry pi qui écoute le SSE et traduit les changement de couleur. Le script réalisant l'opération est dispo [ici](https://git.dgnum.eu/HackENS/hackens-org-configurations/src/commit/da09ce104af8c83343e0987299b2df2102f33f97/machines/agb01/script.py). Une particularité de ce script est qu'il est capable de s'adapter entre les AGB à des changement de setup lumière grâce au fichier [https://agb.hackens.org/api-docs/patch.json](https://agb.hackens.org/api-docs/patch.json) qui décrit l'installation lumière.

#### Amélioration possible: Ajout de messages en batch dans le SSE

Pour le bump, le SSE envoie un message par addresse DMX pour signaler le
changement de couleur. Ainsi le boîtier de commande DMX change de façon
séquentielle toutes les couleurs et c'est LEENNNNNNNT. Il faut absoluement pour
la prochaine fois ajouter un type de message "batch" dans le SSE pour que le
changement de plusieurs couleur soit atomique et simultané.


## Installation

![Installation en Galois](agb_galois.jpeg)
