Relation maître/esclave

Modules d’exemple : hellomaster (le maître) et helloslave (l’esclave).

Un module peut en commander un autre, choisi par instance (son nom, pas sa classe). Ce mécanisme ne demande aucun matériel INDI — c’est pour ça qu’il est couvert ici plutôt que dans le chapitre suivant.

Côté esclave : se déclarer disponible

HelloSlave::HelloSlave(...)
    : Basemodule(...)
{
    giveMeAState();                       // propriété "signals" : état + description
    setStateEvent(OST::Idle, "idle", "", "");
    declareFamily("hello");               // famille arbitraire pour cette paire
}
  • giveMeAState() crée, à la demande (comme tous les giveMeA*()), la propriété signals (état + description) — rien d’automatique, un Basemodule nu n’a pas cette propriété par défaut.
  • setStateEvent(état, description, événement, description-événement, ...) la met à jour en une fois.
  • declareFamily(nom) inscrit le module dans une famille — ce qui alimente automatiquement une liste de valeurs contrôleur loadedFamilies-<nom>, que n’importe quel maître peut référencer pour laisser l’utilisateur choisir une instance. Aucun lien avec INDI : declareFamily() vit sur Basemodule lui-même.
void HelloSlave::onExternalEvent(OST::ExtEvent event)
{
    if (event.eltkey == "dowork")
    {
        setStateEvent(OST::Busy, "working", "dowork", "");
        getEltBool("actions", "dowork")->setValue(false, true);
        // ... travail réel ...
        setStateEvent(OST::Ok, "ready", "dowork", "");
    }
}

Côté maître : choisir une instance et commander

"slaves": {
  "permission": 2,
  "hasprofile": true,
  "e": {
    "slavemodule": {
      "type": "string",
      "directedit": true, "autoupdate": true,
      "value": "helloslave",
      "listOfValues": "loadedFamilies-hello",
      "listOfValuesIsExternal": true
    }
  }
}
Bonne pratique : la propriété slaves est hasprofile:true

Quel esclave commander est un choix utilisateur qui doit survivre aux redémarrages — un maître qui l’oublierait redemanderait son esclave à chaque rechargement du module.

otherModuleSetValue(getString("slaves", "slavemodule"), "actions", "dowork", true);

otherModuleSetValue(instance, propriété, élément, valeur) envoie, par nom d’instance.

Observer ce que l’esclave rapporte

void HelloMaster::onOtherModuleEvent(OST::EvType ev, QString mod, QString prp, QString elt, QVariant data, int line)
{
    if (mod != getString("slaves", "slavemodule")) return;
    if (ev != OST::EvType::ea || prp != "signals") return;

    QJsonObject o = data.toJsonValue().toObject()["e"].toObject();
    getEltLight("etat", "etat")->setValue(OST::IntToState(o["state"].toInt()), true);
}
Un événement diffusé à tous, filtré par chacun

Le contrôleur diffuse l’événement de n’importe quel module à tous les modules chargés — il n’existe aucun abonnement explicite à faire. C’est à onOtherModuleEvent() de filtrer lui-même sur mod (le nom de l’instance qui l’intéresse), comme ci-dessus.