Actuar sobre el device

Módulo de ejemplo: helloindiactions.

En Crear propiedades dinámicamente, el botón de acción modificaba el estado interno del módulo (hellodyn). Aquí, la acción modifica realmente algo en el device — el propio device lo persiste, no el módulo.

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() construye la propiedad actions (vacía al principio); addElt() le añade el elemento saveconfig, en C++, como en Crear propiedades dinámicamente — este capítulo no cambia nada en la forma de construir una propiedad, solo en lo que ocurre cuando se activa.

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 es un switch INDI estándar, presente en todo driver (guardar la configuración actual) — lo que hace que este ejemplo sea comprobable contra cualquier device conectado, sin depender de una funcionalidad propia de un simulador en particular.

sendModNewSwitch/Number/String son traicioneros — no siempre la herramienta correcta

Estos helpers solo escriben un solo elemento a la vez: recuperan la propiedad tal como se conoce actualmente del lado del cliente, modifican el valor del elemento señalado, y luego devuelven el vector completo — los demás elementos se van con su último valor conocido, no necesariamente 0, no necesariamente el que el driver espera.

Ejemplo concreto: enviar un pulso de guiado a una montura. TELESCOPE_TIMED_GUIDE_NS tiene dos elementos, TIMED_GUIDE_N y TIMED_GUIDE_S — nunca se pulsa más que en un solo sentido a la vez, así que el driver espera recibir los dos valores en cada envío, uno de ellos valiendo explícitamente 0. Al limitarse a escribir TIMED_GUIDE_N mediante sendModNewNumber(), TIMED_GUIDE_S se va con su último valor conocido — potencialmente no nulo, lo que el driver puede simplemente ignorar o interpretar mal.

En este tipo de casos, es mejor bajar directamente al nivel INDI::BaseClient (ver la vista de conjunto: un IndiModule es un verdadero cliente INDI): construir uno mismo el INDI::PropertyNumber completo, fijar explícitamente cada elemento, y luego llamar directamente a sendNewNumber() — en lugar de confiar en un helper pensado para el caso simple de una propiedad con un solo elemento relevante.