Agir sur le device
Module d’exemple : helloindiactions.
Dans Créer des propriétés dynamiquement, le bouton d’action modifiait l’état interne du module (hellodyn). Ici, l’action modifie réellement quelque chose sur le device — le device lui-même la persiste, pas le module.
HelloIndiActions::HelloIndiActions(...)
: IndiModule(...)
{
giveMeADevice("device", "Device", INDI::BaseDevice::GENERAL_INTERFACE);
giveMeAnActions();
OST::ElementBool *saveconfig = new OST::ElementBool("saveconfig", "Save device config", "1", "");
saveconfig->setDirectEdit(true);
getProperty("actions")->addElt(saveconfig);
}giveMeAnActions() construit la propriété actions (vide au départ) ; addElt() y ajoute l’élément saveconfig, en C++, comme dans Créer des propriétés dynamiquement — ce chapitre ne change rien à la façon de construire une propriété, seulement à ce qui se passe quand elle est actionnée.
void HelloIndiActions::onExternalEvent(OST::ExtEvent event)
{
if (event.ev != OST::ExtEvType::SV || event.prpkey != "actions" || event.eltkey != "saveconfig") return;
sendModNewSwitch(getString("devices", "device"), "CONFIG_PROCESS", "CONFIG_SAVE", ISS_ON);
getEltBool("actions", "saveconfig")->setValue(false, true);
}CONFIG_PROCESS/CONFIG_SAVE est un switch INDI standard, présent sur tout driver (sauvegarder la configuration courante) — ce qui rend cet exemple testable contre n’importe quel device connecté, sans dépendre d’une fonctionnalité propre à un simulateur en particulier.
Ces helpers n’écrivent qu’un seul élément à la fois : ils récupèrent la propriété telle qu’elle est actuellement connue côté client, modifient la valeur de l’élément visé, puis renvoient le vecteur complet — les autres éléments partent avec leur dernière valeur connue, pas forcément 0, pas forcément celle que le driver attend.
Exemple concret : envoyer une pulsation de guidage à une monture. TELESCOPE_TIMED_GUIDE_NS a deux éléments, TIMED_GUIDE_N et TIMED_GUIDE_S — on ne pulse jamais que dans un seul sens à la fois, donc le driver s’attend à recevoir les deux valeurs à chaque envoi, l’une d’elles valant explicitement 0. En se contentant d’écrire TIMED_GUIDE_N via sendModNewNumber(), TIMED_GUIDE_S repart avec sa dernière valeur connue — potentiellement non nulle, ce que le driver peut tout simplement ignorer ou mal interpréter.
Dans ce genre de cas, mieux vaut descendre directement au niveau INDI::BaseClient (voir la vue d’ensemble : un IndiModule est un vrai client INDI) : construire soi-même le INDI::PropertyNumber complet, fixer explicitement chaque élément, puis appeler sendNewNumber() directement — plutôt que de faire confiance à un helper pensé pour le cas simple d’une propriété à un seul élément pertinent.