Agire sul device

Modulo di esempio: helloindiactions.

In Creare proprietà dinamicamente, il pulsante d’azione modificava lo stato interno del modulo (hellodyn). Qui, l’azione modifica realmente qualcosa sul device — il device stesso la persiste, non il modulo.

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() costruisce la proprietà actions (vuota all’inizio); addElt() vi aggiunge l’elemento saveconfig, in C++, come in Creare proprietà dinamicamente — questo capitolo non cambia nulla al modo di costruire una proprietà, solo a ciò che accade quando viene azionata.

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 è uno switch INDI standard, presente su ogni driver (salvare la configurazione corrente) — il che rende questo esempio testabile contro qualsiasi device connesso, senza dipendere da una funzionalità propria a un particolare simulatore.

sendModNewSwitch/Number/String sono insidiosi — non sempre lo strumento giusto

Questi helper scrivono solo un unico elemento alla volta: recuperano la proprietà come attualmente conosciuta lato client, modificano il valore dell’elemento preso di mira, poi rinviano il vettore completo — gli altri elementi partono con il loro ultimo valore conosciuto, non necessariamente 0, non necessariamente quello che il driver si aspetta.

Esempio concreto: inviare un impulso di guida a una montatura. TELESCOPE_TIMED_GUIDE_NS ha due elementi, TIMED_GUIDE_N e TIMED_GUIDE_S — non si pulsa mai che in un solo senso alla volta, quindi il driver si aspetta di ricevere entrambi i valori a ogni invio, uno dei due valendo esplicitamente 0. Limitandosi a scrivere TIMED_GUIDE_N tramite sendModNewNumber(), TIMED_GUIDE_S riparte con il suo ultimo valore conosciuto — potenzialmente non nullo, cosa che il driver può semplicemente ignorare o interpretare male.

In questo genere di casi, è meglio scendere direttamente al livello INDI::BaseClient (vedi la panoramica: un IndiModule è un vero client INDI): costruire da soli l’INDI::PropertyNumber completo, fissare esplicitamente ogni elemento, poi chiamare direttamente sendNewNumber() — piuttosto che fidarsi di un helper pensato per il caso semplice di una proprietà con un solo elemento rilevante.