Files
dwarf-go/dwarfctl/TEST_RESULTS.md
Jacquin Antoine 4d2480c248 Implement working motor init command using limit-switch homing
Added `motor init [up|down] [timeout]` that homes the altitude axis by
slewing to a mechanical limit. The firmware detects the limit switch and
performs an automatic home to position 0 (optics toward ground).

Validated procedure:
1. Slew up briefly (90° 0.4 for 5s) to move away from the bottom limit
2. `motor init down 40` — slew 270° until bottom limit triggers auto-home
3. Axis remains fully operational after homing

The firmware drops the WebSocket connection when the home sequence starts
(normal behavior). After reconnecting, the axis works normally.

Note: API still returns NEED_RESET (-14520) because absolute positioning
requires astro calibration (plate solving). The mechanical home only
provides physical position 0, not sky coordinates.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-07-12 20:18:32 +02:00

12 KiB

Plan de test — dwarfctl sur télescope réel

Conditions de test

  • Télescope : DWARF II, firmware 2.1.6, mode AP (hotspot WiFi)
  • IP : 192.168.88.1
  • Réseau : machine connectée au hotspot du télescope
  • Environnement : intérieur, journée (pas d'accès au ciel/étoiles)

Découvertes protocolaires importantes

Modèle de réponse du télescope

Le télescope utilise type=3 (REPLY) pour les réponses directes, PAS type=1 (RESPONSE). De plus, certaines commandes ne reçoivent AUCUNE réponse directe — seulement des notifications (type=2).

Pattern Commandes Comportement
Reply type=3 (même cmd) photo (10002), focus auto (15000), focus step (15001), state (16405) Réponse directe avec le même cmd → request-response
Notification uniquement rgb-on/off (13500/13501), camera open/close (10000/10001), camera params (10036) Pas de reply → fire-and-forget + vérifier via state
Fire-and-forget natif motor slew (14006), motor stop (14002) Pas d'ack attendu

Implémentation dans dwarfctl

  • send() : attend un type=3 reply (10s timeout) — pour photo, focus, state
  • sendNotify() : fire-and-forget — pour RGB, camera open/close, motor slew
  • Flag --debug / -d : loggue tout le trafic WebSocket (cmd, module, type, taille data)

Tests par groupe

1. Connexion (PASS)

Test Commande Résultat
Ping ping 192.168.88.1 36ms
Port 9900 (WebSocket) /dev/tcp/192.168.88.1/9900 OPEN
Port 80 (RTSP) /dev/tcp/192.168.88.1/80 OPEN
WebSocket handshake dwarfctl --ip 192.168.88.1 state connexion établie

2. État du device (PASS)

dwarfctl --ip 192.168.88.1 state

Réponse complète : shooting_mode, cameras (résolution, FoV), focus position (594), batterie (100%), stockage (38/52 GB), température CMOS, modes disponibles.

3. Caméra Tele (PASS)

Test Commande Debug Statut
Open camera camera open --cam tele fire-and-forget
Photo camera photo --cam tele reply cmd=10002 type=3 data=11B photo capturée
Focus step out focus step 1 reply cmd=15001 type=3 data=0B

4. Moteurs / Slew (PASS)

Tests systématiques effectués — tous les mouvements confirmés visuellement sur le télescope.

4.1 Directions cardinales (joystick cmd 14006)

Direction Angle Length Durée Résultat
HAUT 0.3 2s mouvement observé
DROITE 90° 0.3 2s mouvement observé
BAS 180° 0.3 2s mouvement observé
GAUCHE 270° 0.3 2s mouvement observé

Système de coordonnées joystick : angle en degrés (polaire), 0°=haut, 90°=droite, 180°=bas, 270°=gauche. Length = vitesse normalisée (0.0 à 1.0).

4.2 Vitesses variables

Vitesse Length Résultat
Lente 0.1 mouvement visible et lent
Moyenne 0.5 mouvement net
Rapide 0.9 mouvement rapide

4.3 Diagonales

Direction Angle Résultat
HAUT-DROITE 45° mouvement diagonal
BAS-GAUCHE 225° mouvement diagonal

Le joystick est bien polaire — 360° de liberté, pas seulement 4 directions.

4.4 Arrêt d'urgence

Test Commande Résultat
Stop pendant slew motor stop 0 (cmd 14002) arrêt immédiat
Stop motor 1 motor stop 1

Le motor stop interrompt un slew en cours instantanément.

⚠️ 4.4b DANGER : Butée matérielle

Test réel : le slew à 90° (descente) continu a fait atteindre la butée basse mécanique. Le firmware a coupé immédiatement le réseau (perte totale : ping KO, port 9900 fermé). Redémarrage physique nécessaire.

Leçon : le slew joystick n'a PAS de soft-limit côté firmware. Il faut impérativement limiter la durée des slew altitude (90°/270°) à de courts intervalles (< 2s) et observer visuellement.

Comportement après butée : l'axe altitude s'est verrouillé — le firmware refuse tout mouvement de slew sur cet axe après LIMIT_POSITION_HIT. L'axe azimut continue de fonctionner. Le déverrouillage nécessite un home/reset (calibration nocturne uniquement). Le motor reset (cmd 14003) provoque un reboot et ne déverrouille pas l'axe.

Découverte clé — Home par butée : slewing en 270° (descente) à vitesse modérée jusqu'à ce que le limit switch se déclenche provoque un home automatique du firmware. Le télescope revient à la position 0 physique (optique vers le sol). C'est la méthode d'initialisation manuelle des moteurs — pas besoin de motor reset (qui ne fait que rebooter).

Procédure d'initialisation manuelle :

  1. motor slew 90 0.4 pendant 5s — monter ~45° pour décoller de la butée basse
  2. motor init down 40 — slew 270° jusqu'à la butée basse → home automatique
  3. Position 0 = optique vers le sol
  4. L'axe altitude reste pleinement opérationnel après le home
  5. L'API reste en NEED_RESET tant que la calibration astro n'est pas faite (le home mécanique ne donne pas la position absolue, seulement la position physique)

IMPORTANT : si le télescope démarre en butée basse, il faut d'abord monter (motor slew 90) avant de lancer motor init down, sinon le slew est ignoré car déjà en butée.

Commande motor init :

  • motor init up [timeout] — home via butée haute (90°)
  • motor init down [timeout] — home via butée basse (270°, recommandé)
  • Le firmware coupe la connexion WS quand le home se déclenche (normal)
  • Après reconnexion, l'axe est opérationnel

4.5 Système de coordonnées joystick découvert (config alt-az, trépied vertical)

Tests en condition réelle, télescope posé verticalement sur trépied (pas en mode équatorial) :

Angle Axe Direction observée
Azimut (horizontal) Rotation horaire vue de dessus
90° Altitude Montée (vers le ciel)
180° Azimut Rotation anti-horaire (opposé de 0°)
270° Altitude Descente (vers le sol)

IMPORTANT : ces directions sont validées pour une config alt-az simple (télescope vertical sur trépied). En mode équatorial (après EQ calibration), le mapping peut changer car les moteurs changent de référentiel.

4.5b Butées mécaniques — test complet des 4 butées

Les 4 butées mécaniques ont été testées et sont toutes gérées safely par le firmware (arrêt au limit switch, pas de crash, pas de verrouillage d'axe) :

Butée Angle slew Comportement Reboot ? Axe verrouillé ?
Altitude basse (sol) 270° continu Arrêt + home auto à 0 Non Non
Altitude haute (ciel) 90° continu Arrêt au contact Non Non
Azimut horaire (↻) 0° continu Arrêt au contact Non Non
Azimut anti-horaire (↺) 180° continu Arrêt au contact Non Non

Conclusion : les butées mécaniques sont sûres. Le firmware arrête le moteur au contact du limit switch sans crash ni verrouillage. L'incident précédent de verrouillage d'axe était dû au motor reset (cmd 14003), pas aux butées.

4.5 Motor run/goto (cmd 14000)

Test Commande Résultat
Run to position motor goto 0 10 5 fire-and-forget envoyé

ReqMotorRunTo : moteur ID, position cible, vitesse. Fire-and-forget (pas de ack type=3).

4.6 Motor get-position (cmd 14001 — inféré, confirmé fonctionnel)

Test Commande Résultat
Position moteur 0 motor position 0 reply type=3, code=-14520 (NEED_RESET)
Position moteur 1 motor position 1 reply type=3, code=-14520 (NEED_RESET)

L'ID 14001 n'est pas dans le WsCmd enum de l'APK mais fonctionne — le firmware répond avec ResMotorPosition{id, code, position}. Le code=-14520 correspond à CODE_STEP_MOTOR_NEED_RESET : les moteurs n'ont pas été homed.

4.7 Motor reset (cmd 14003 — ⚠️ DANGEREUX, DÉSACTIVÉ)

Test Commande Résultat
Reset moteur 0 motor reset 0 0 ⚠️ A causé le reboot du télescope

L'ID 14003 est inféré (gap entre STOP=14002 et JOYSTICK=14006). L'envoi de ReqMotorReset{id, direction} a provoqué un reboot immédiat du télescope. La commande est désormais désactivée dans le code et retourne une erreur explicite.

Leçon : ne jamais envoyer de commandes inférées (IDs non confirmés dans le WsCmd enum de l'APK) sans validation préalable. L'app Android n'utilise que les commandes joystick (14006-14009), run (14000) et stop (14002). Le reset/home des moteurs est probablement géré côté firmware uniquement, déclenché par la calibration astro ou le panorama.

4.6 Observations sur la lecture de position

  • focus_position (moteur de mise au point) : visible dans statefocus_position:{pos:593}, reste stable pendant les mouvements de pointage.
  • Position moteurs de pointage (RA/DEC) : motion_motor_state_info:{exclusive_state:{}} reste vide — la position des moteurs alt-az n'est PAS exposée dans GetDeviceState.
  • Les messages proto ReqMotorGetPosition et ReqMotorReset existent dans le proto mais ne sont pas utilisés par l'app Android (aucune classe de requête correspondante). La lecture de position se fait probablement via les notifications d'attitude (cmd 15295 CMD_NOTIFY_DEVICE_ATTITUDE).

5. RGB / Power (PASS après fix fire-and-forget)

Test Commande Avant fix Après fix
RGB off power rgb-off timeout (cmd 13501) fire-and-forget
RGB on power rgb-on timeout (cmd 13500) fire-and-forget

Vérification : rgb_state:{} (éteint) vs rgb_state:{state:1} (allumé) dans state.

6. Focus (PASS)

Test Commande Debug Statut
Autofocus focus auto notifications + reply cmd=15000 type=3
Step out focus step 1 reply cmd=15001 type=3

7. System (NON TESTÉ — nécessite validation)

Test Commande Notes
Sync time system sync-time À tester
Set location system set-location 48.86 2.35 35 À tester

8. Astrophotographie (NON TESTABLE — jour/intérieur)

Ces commandes nécessitent un ciel étoilé nocturne :

Test Raison
astro calibrate start Nécessite des étoiles visibles
astro goto-dso Nécessite le ciel
astro stack start Nécessite des étoiles
astro eq-solve start Nécessite des étoiles
track start Nécessite une cible mobile

9. Camera params (KNOWN ISSUE)

camera params --cam tele (cmd 10036) : le télescope ne renvoie pas de reply. Les paramètres sont toutefois visibles dans la réponse state (résolution, FoV). Les paramètres ajustables (exposure, gain) nécessiteraient une commande GET qui ne répond pas en type=3.

Bugs corrigés pendant les tests

  1. readLoop ne dispatchait pas type=3 correctement → corrigé : tous les types sont dispatchés vers dispatchResponse + dispatchNotification
  2. Commandes RGB/camera open attendaient un reply inexistant → converties en fire-and-forget (sendNotify)
  3. Motor stop/goto attendaient un reply → convertis en fire-and-forget
  4. Pas de logging → ajout du flag --debug / -d

Tests unitaires

ok  github.com/antitbone/dwarfctl/internal/transport  0.003s
ok  github.com/antitbone/dwarfctl/internal/api        0.003s

57 tests, tous PASS.