Consommer un StateObject via l'API Python


#1

Bonjour !

J’ai suivi le tutoriel suivant https://developer.myconstellation.io/client-api/python-api/consommer-des-stateobjects-en-python/ et il montre bien comment consommer un stateObject à sa mise à jour avec la définition d’une fonction.

Cependant, je ne suis pas sûr de comprendre comment récupérer juste la valeur d’un StateObject (par exemple la température de ForecasteIO) et la récupérer n’importe où dans mon code à l’intérieur d’une fonction ?

En d’autres termes, comment faire un registerStateObjectLink en python ?

Merci !


#2

Hello,

Je vais modifier cet article pour donner d’autre exemple notamment sur la “conservation de la dernière valeur”.

Pour répondre à ta question le registerStateObjectLink est implicite en Python. Il suffit, comme le montre l’article, d’ajouter le décorateur @Constellation.StateObjectLink sur une méthode pour la lier à un (ou plusieurs) StateObjects.

Si tu souhaites “garder” la valeur d’un SO pour pouvoir l’intérroger n’importe où dans ton code, il suffit de le sauver dans une variable.

Par exemple, dans mon système S-Opener, j’ai besoin de connaitre l’état de la porte de garage (ouverte ou fermée). Cette info je peux la connaitre par un StateObject publié par le Package de mon alarme Paradox.

De ce fait, dans mon code Python je déclare une variable globale et j’ajoute un StateObjectLink sur le SO que je veux suivre qui affectera ma variable globale. Dans mon cas je n’ai besoin que de la propriété IsOpen de la valeur de ce StateObject.

global garageDoorOpened

@Constellation.StateObjectLink(package='Paradox', name="ZoneInfo5")
def ParadoxGarageDoorStateUpdated(stateObject):
    global garageDoorOpened
    garageDoorOpened = stateObject.Value.IsOpen
    Constellation.WriteInfo("ParadoxGarageDoor = %s" % garageDoorOpened)

Il ne faut pas oublier de déclarer la variable au niveau du script ET au niveau de la méthode du SO Link avec le mot clé “global”. Ainsi, partout dans mon code je peux me servir de la variable “garageDoorOpened” qui m’indiquera si ma porte de garage est ouverte ou fermée (propriété IsOpen de mon SO Paradox). Cette variable étant mise à jour en temps réel par le SOLink si le SO change.


#3

Merci pour votre réponse ! J’ai opté pour la même solution mais je crois avoir un souci !

Dans votre exemple la fonction ParadoxGaradeDoorStateUpdated ne s’active qu’au moment de l’update du StateObject demandé, il me semble ?

Dans le cas de ForecastIO par exemple, qui ne se met à jour qu’une fois par heure, si je relance mon packet après le lancement de ForecastIO, alors la variable globale sera vide…


#4

Non avec l’API Python, le décorateur StateObjectLink s’abonne au SO (Subscribe) pour être informé des futures updates et réalise dans la foulée un “RequestStateObject” au moment de l’enregistrement pour interroger la valeur actuelle du/des StateObject(s) lié(s).


#5

Merci ! J’ai fait quelques tests et le SO est bien récupéré au démarrage du packet !
Par contre j’ai l’impression que la fonction OnStart que j’utilise s’exécute avant que le SO ne soit récupéré :-/


#6

Oui tout à fait, c’est normal en fait !

Ton package ne peut pas savoir si il y a des SO liés à ton “links” ni en quelle quantité. Ainsi au démarrage les SOLink sont enregistrés, ton package demande à COnstellation un abonnement (subscribe) et fait la demande des valeurs en cours (request) puis l’API Python lance ton OnStart sans attendre quoique ce soit car il ne sait pas si ca va donner quelque chose.

Au démarrage d’un package il faut donc soit prendre en compte des valeurs temporaires/éphémères en attendant d’avoir es vrais valeurs des SO (si elles existent) ou bien attendre explicitement (via une boucle et un time.sleep par exemple) les valeurs SO considérées comme “obligatoire” pour le package que tu développes.