Anatomía de un módulo
Un módulo OST es una biblioteca compartida (.so), cargada dinámicamente por el servidor, que expone datos estructurados (propiedades, que contienen elementos) y reacciona a las escrituras enviadas por los clientes.
Dos clases base
Basemodule— lo estrictamente necesario: propiedades, elementos, eventos, persistencia en perfil. Sin ninguna dependencia de INDI. Es la clase a usar para todo módulo que no controle directamente un device INDI (lógica de negocio, agregación, procesamiento…).IndiModule(deriva deBasemodule) — añade toda la mecánica de conexión a un servidor INDI, de gestión de devices, y las propiedades derivadas comúnmente útiles (óptica, equipos, ubicación…). Ver el capítulo Módulos INDI.
Este capítulo solo cubre Basemodule — todo lo que describe se aplica también a IndiModule, que hereda de él.
El trío de archivos
Un módulo mínimo cabe en tres archivos, en su propia subcarpeta:
<nombre>.h— declara la clase (derivada deBasemodule), su constructor/destructor, y los métodos que sobrecarga (lo más frecuente,onExternalEvent()).<nombre>.cpp— implementa el constructor (que carga la estructura del módulo) y los métodos sobrecargados. Nada más es obligatorio: un módulo que no tiene ninguna acción que procesar no necesita sobrecargar ningún método.<nombre>.json— declara la estructura del módulo: sus propiedades y sus elementos. Embebido en el binario mediante un archivo<nombre>.qrc(recurso Qt) y cargado al inicio.
// <nom>.h
#ifndef HELLO_H
#define HELLO_H
#include <basemodule.h>
class Hello : public Basemodule
{
Q_OBJECT
public:
Hello(QString name, QString label, QString profile, QVariantMap availableModuleLibs);
~Hello();
};
extern "C" Hello* initialize(QString name, QString label, QString profile, QVariantMap availableModuleLibs);
#endif// <nom>.cpp
#include "hello.h"
Hello* initialize(QString name, QString label, QString profile, QVariantMap availableModuleLibs)
{
return new Hello(name, label, profile, availableModuleLibs);
}
Hello::Hello(QString name, QString label, QString profile, QVariantMap availableModuleLibs)
: Basemodule(name, label, profile, availableModuleLibs)
{
Q_INIT_RESOURCE(hello);
loadOstPropertiesFromFile(":hello.json");
}
Hello::~Hello() {}initialize()es la función de exportación, con enlace C (extern "C") para poder ser encontrada por su nombre tal cual una vez que el.sose carga dinámicamente. Su firma es siempre la misma; se limita a instanciar la clase.loadOstPropertiesFromFile(":nombre.json")lee el archivo JSON embebido y construye las propiedades/elementos que describe — ver El módulo más pequeño.
Un módulo normalmente registra su propia identidad (hash/fecha/mensaje del commit, versión) mediante setMetadata() en su constructor, a partir de las constantes generadas por el build (Version::GIT_SHA1, etc.):
setMetadata("description", "Ce que fait ce module");
setMetadata("thisGithash", QString::fromStdString(Version::GIT_SHA1));setMetadata() es un metadato libre, sin declaración JSON previa.
La cadena de eventos
Cuando un cliente escribe un valor (o dispara una acción), el servidor llama, en este orden, a tres métodos virtuales — nunca directamente, siempre a través de un punto de entrada final que el desarrollador del módulo no toca ni sobrecarga nunca:
onExternalEventRoot() (final — nunca sobrecargado)
→ onExternalEventBase() (validación común: existe la propiedad/elemento,
permiso, directedit, actualización automática)
→ onExternalEventIndi() (hook IndiModule — vacío para un Basemodule)
→ onExternalEvent() (el módulo responde aquí, si necesita reaccionar)onExternalEventBase() ya aplica por sí sola el valor escrito al datastore si el elemento (o su propiedad) tiene autoupdate:true — en ese caso, onExternalEvent() a menudo no tiene nada que hacer, o solo necesita releer el valor aplicado para reaccionar. Ver Reaccionar a una escritura para el detalle y una trampa frecuente.
Un módulo que no tiene ninguna acción propia que gestionar (como el ejemplo hello anterior) simplemente no tiene nada que sobrecargar: la implementación vacía por defecto de onExternalEvent() es suficiente.