Sommaire
Vous pouvez développer des packages Constellation avec le langage Python. Sur vos sentinelles Windows comme sur vos sentinelles Linux vous pourrez profiter des différentes libraires et de l’écosystème Python connectés dans Constellation.
Découvrons dans cet article comment créer et déployer votre premier package Constellation en Python.
Prérequis
Tout d’abord, que vous soyez sur Windows ou Linux, il vous faudra un interpréteur Python 2 ou Python 3 et une ou deux libraires indispensables pour Constellation.
Notez que ces prérequis sont automatiquement installés sur Linux avec le Web Platform Installer.
Installer Python sur Windows
Téléchargez Python pour Windows (en version 2.x ou 3.x) puis lancez l’installation en choisissant une installation pour tous les utilisateurs :
Sélectionnez le composant “PIP” ( le gestionnaire de package Python) et ajoutez “Python.exe” dans les “Paths” Windows :
Une fois l’installation terminée, lancez une invite de commande (cmd.exe) et assurez-vous que la commande “python” fonctionne :
Toujours dans une invite de commande Windows, installez via PIP les librairies “pyzmq” (et “enum34” si vous êtes en Python 2.x) grâce aux commandes suivantes :
1 2 |
pip install pyzmq pip install enum34 |
Si vous êtes sur Python 3.x, vous n’avez pas besoin du module “enum34”, seulement “pyzmq”.
Et voilà, votre environnement Windows est prêt !
Installer Python sur Linux
Sur un système Debian ou similaire (Raspbian, Ubuntu, etc …), vous n’avez qu’à installer (et enregistrer dans votre Constellation) une sentinelle Constellation.
Le Web Platform Installer vous proposera d’installer tous les prérequis nécessaires à savoir Python et les librairies “pyZmq” et “enum34” (si Python 2.x) via PIP.
Autrement, pour installer manuellement ces prérequis, vous pouvez utiliser les mêmes commandes que sur Windows :
1 2 3 |
sudo easy_install pip sudo pip install pyzmq sudo pip install enum34 |
Encore une fois, la libraire “enum34” est seulement requise sur Python 2.x.
Enfin si vous utilisez un Raspberry Pi, vous pouvez également consulter cet article en particulier.
Et voilà, votre environnement Linux est prêt !
Développer un package Python en ligne de commande
Vous pouvez soit utiliser le SDK Constellation basé sur Visual Studio pour créer, tester et déployer des packages Constellation (.NET ou Python) ou bien, utiliser l’outil en ligne de commande nommé « Constellation Package Tools CLI ».
Le développement sous Visual Studio est abordé ci-dessous. Pour l’outil en ligne de commande, rendez-vous sur la page : Créer, tester et déployer des packages Python en ligne de commande
Développer un package Python avec Visual Studio
Après avoir installé les prérequis et le SDK Constellation, lancez Visual Studio et créez un nouveau package Constellation de type “Python” :
Une fois créé le projet Visual Studio a la structure suivante :
Vous retrouverez une structure classique pour un package Constellation :
-
App.config : le fichier de configuration local pour définir les valeurs locales de vos settings (lire ici) ainsi que les scripts Python à démarrer
-
PackageInfo.xml : le manifeste de votre package
-
packages.config : le fichier des packages Nuget de votre projet (réservé à Nuget)
-
Program.cs : le point d’entrée (C#) de votre package qui se chargera de lancer le “Python Proxy” (le pont entre vos scripts Python et Constellation)
-
Le répertoire “Scripts” (qui contient vos scripts Python)
-
Constellation.py : le proxy Python Constellation (la librairie Python) : ne pas modifier !
-
Demo.py : un script Python d’exemple
-
Configurer les scripts à démarrer
Vous pouvez ajouter autant de scripts Python dans le dossier “Scripts” comme vous le souhaitez. Pour cela, cliquez-droit sur ce répertoire et sélectionnez « Ajouter un nouvel élément ».
Dans la catégorie « Constellation » sélectionnez « Constellation Python Script » :
Chaque script sera démarré dans un processus dédié et connecté à Constellation.
Attention : si vous rajoutez des scripts Python dans ce dossier, il faut obligatoirement les inclure dans le package en sélectionnant “Copy if newer” pour la propriété “Copy to Output directory”. Cette propriété est automatiquement définie à cette valeur si vous avez créé votre fichier Python en sélectionnant l’élément « Constellation Python Script » comme expliqué ci-dessus.
Dans le fichier « App.config » vous devez déclarer les fichiers Python à démarrer. Les scripts Python créé en sélectionnant l’élément « Constellation Python Script » sont automatiquement ajoutés dans ce fichier lors de la création. Si vous renommez ou supprimer vos scripts, n’oubliez pas de mettre à jour ce fichier.
1 2 3 4 5 6 7 |
<pythonProxy xmlns="urn:Constellation.PythonProxy"> <scripts> <script filename="Scripts\Demo.py" /> <script filename="Scripts\LightSensor.py" /> <script filename="Scripts\Camera.py" /> </scripts> </pythonProxy> |
Le script “Demo.py” est créé à titre d’exemple. Vous pouvez le supprimer, renommer ou modifier à votre convenance.
Grâce à Visual Studio et au SDK Constellation, vous bénéficiez d’un environnement de développement agréable pour créer vos packages Python avec la coloration syntaxique et l’IntelliSense :
Les bases
Chaque script Python doit impérativement importer la librairie Constellation et démarrer la “connexion” avec le proxy Python en invoquant la méthode “Start” :
1 2 3 |
import Constellation # Votre code ! Constellation.Start() |
Vous avez trois façon de démarrer cette connexion :
1 – La plus simple est d’invoquer la méthode “Start” :
1 |
Constellation.Start() |
La méthode “Start” démarre la connexion et maintient le script en “vie” grâce à une boucle qui tourne tant que le package Constellation est lancé.
Autrement dit le code après la méthode “Start” ne sera jamais appelé !
2 – Invoquer la méthode “Start” en passant une fonction de démarrage :
Vous pouvez passer le nom d’une fonction en paramètre de la méthode “Start” qui sera invoquée dès que le script Python est connecté à Constellation.
Cela vous permet de définir du code au démarrage du package :
1 2 3 4 5 |
def OnStart(): # Mon code de démarrage ici pass Constellation.Start(OnStart); |
3 – Troisième méthode : invoquer la méthode “StartAsync” (non bloquante)
Mais attention vous devrez vous même créer une boucle pour maintenant votre script “en vie” autrement il s’arrêtera automatiquement !
1 2 3 4 |
Constellation.StartAsync() while Constellation.IsRunning: pass time.sleep(1) |
Interpréteurs Python et environnements virtuels
Par défaut chaque script est lancé avec la commande “python”. C’est pour cela qu’il est recommandé d’ajouter Python dans le PATH de votre système afin de pouvoir “résoudre” la commande “python”.
Vous pouvez aussi définir dans le fichier App.config de votre package Python, l’attribut “pythonCmd” pour spécifier la commande à lancer. Ci-dessous un exemple avec l’interpréteur Python 2.7 :
1 2 3 4 5 6 |
<pythonProxy xmlns="urn:Constellation.PythonProxy" pythonCmd="C:\Python27\python.exe"> <scripts> <script filename="Scripts\Demo.py" /> <script filename="Scripts\Demo2.py" /> </scripts> </pythonProxy> |
L’attribut “pythonCmd” peut-être également défini de manière individuelle pour chaque script. Prenez par exemple la configuration suivante :
1 2 3 4 5 6 7 |
<pythonProxy xmlns="urn:Constellation.PythonProxy" pythonCmd="python3"> <scripts> <script filename="Scripts\Demo.py" /> <script filename="Scripts\Demo2.py" pythonCmd="C:\Users\Sebastien\venv\Scripts\python.exe" /> <script filename="Scripts\Demo3.py" pythonCmd="C:\Python27\python.exe" /> </scripts> </pythonProxy> |
Ci-dessus le package Python démarre trois scripts Demo.py, Demo2.py et Demo3.py de la façon suivante :
- Demo.py sera lancé par l’interpréteur Python 3 (via la commande “python3” défini au niveau global)
- Demo2.py sera lancé par un environnement virtuel ici nommé “venv” (défini pour le script)
- Demo3.py sera lancé par l’interpréteur Python 2.7 installé dans “C:\Python27”
Vous pouvez donc utiliser cet attribut pour spécifier l’interpréteur Python à utiliser (Python 2 vs 3 ou même des interpréteurs dans des environnements virtuels). Quelque soit l’interpréteur utilisé n’oubliez d’installer les librairies “pyzmq” (et “enum34” si Python 2.x).
Note : vous pouvez aussi les Settings Constellation dans l’attribut « pythonCmd » vous permettant ainsi de définir/changer d’interpréteur sans modifier le code de votre package, simplement en manipulant les settings de votre package depuis la Console Constellation. Plus d’information sur ce billet.
Produire des logs
Pour écrire des logs dans le hub Constellation, tout comme en C#, vous disposez des méthodes suivantes :
-
WriteInfo
-
WriteWarn
-
WriteError
Exemple :
1 2 3 |
Constellation.WriteInfo("Hello world from Python !") Constellation.WriteWarn("This is a warning !") Constellation.WriteError("This is an error !") |
En Python vous pouvez formater vos messages avec des variables grâce à l’opérateur “%”.
Par exemple, affichons dans les logs Constellation l’état de notre package :
1 2 |
Constellation.WriteInfo("Hi I'm '%s' and I run on %s" % (Constellation.PackageName, Constellation.SentinelName)) Constellation.WriteInfo("IsConnected = %s | IsStandAlone = %s " % (Constellation.IsConnected, Constellation.IsStandAlone)) |
Vous remarquez par la même occasion quelques propriétés accessibles dans vos scripts Python (IsConnected, IsStandAlone, SentinelName, PackageName, etc…).
Accès aux settings
Le fonctionnement des settings est strictement identique à l’API .NET décrite ici.
Les settings sont définis sur le serveur au niveau du package ou via des groupes, et par héritage peuvent être définis dans le fichier local App.config et/ou dans le manifeste. Je vous invite vivement à lire cet article pour bien comprendre le fonctionnement des settings.
Avec l’API Python de Constellation vous disposez de la méthode “GetSetting” pour récupérer la valeur de vos settings.
Par exemple pour afficher la valeur du setting “Demo1” :
1 |
Constellation.WriteInfo("Demo1 = " + str(Constellation.GetSetting("Demo1"))) |
Si la valeur du setting n’existe pas, la méthode vous retourne un “Null” :
1 2 |
if Constellation.GetSetting("Demo1") <> Null: Constellation.WriteInfo("Demo1 = " + str(Constellation.GetSetting("Demo1"))) |
Vous avez également la possibilité d’attacher une méthode callback pour être notifier dans votre code Python lorsque les settings de votre packages sont mises à jour dans Constellation :
1 2 3 4 5 6 7 8 9 |
import Constellation def OnSettingsUpdated(): print("Mise à jour de mes settings depuis Constellation !!") def Start(): Constellation.OnSettingsUpdated = OnSettingsUpdated Constellation.Start(Start); |
Publier des StateObjects
Comme pour l’API .NET, vous disposez de la méthode PushStateObject pour publier un StateObject.
Chaque StateObject a obligatoirement un nom et une valeur de n’importe quel type :
1 2 3 4 |
Constellation.PushStateObject("MyString", "OK") Constellation.PushStateObject("MyNumber", 123) Constellation.PushStateObject("MyDecimal", 123.12) Constellation.PushStateObject("MyBoolean", True) |
Vous pouvez publier des StateObjects dont la valeur est un objet complexe :
1 |
Constellation.PushStateObject("Demo", { "UneString": "DemoPython", "UnNombre": 123 }) |
Dans l’exemple ce-dessus, le StateObject « Demo » est un objet contenant deux propriétés : « UneString » et « UnNombre ».
Lorsqu’il s’agit de type complexe, il est vivement conseiller de décrire le type du StateObject à Constellation.
Pour cela au démarrage de votre package (méthode Start), enregistrez vos différents types de StateObjects avec la méthode « DescribeStateObjectType ».
Par exemple :
1 2 3 4 |
Constellation.DescribeStateObjectType("MyStateObject", "StateObject à deux propriétés de démonstration", [ { 'Name':'UneString', 'Type':'string', 'Description': 'Une chaine de caractère tout simplement' }, { 'Name':'UnNombre', 'Type':'int', 'Description': 'Un nombre entier' } ]) |
Pour chaque type on spécifiera un nom, une description du type et la liste ses propriétés. Sachant que pour chaque propriété nous avons un nom, un type et une description.
Le type d’une propriété peut faire elle-même référence à un autre type complexe que vous avez enregistré.
Pour finir il faudra déclarer le package descriptor après avoir décrit tous vos types :
1 |
Constellation.DeclarePackageDescriptor() |
Enfin, pour chaque publication de StateObject, vous pouvez spécifier le type (simple ou complexe que vous aurez enregistré ci-dessus), un dictionnaire de méta-données ou encore une durée de vie (en seconde) :
1 |
Constellation.PushStateObject("Demo", { "UneString": "DemoPython", "UnNombre": 123 }, type = "MyStateObject", metadatas = { "DeviceId": "RPi", "SerialNumber":"123" }, lifetime = 300) |
Tester son package dans Visual Studio
Laissons le code de démo du script “Demo.py” créé par le Template du projet tel quel :
Notons simplement qu’au démarrage du package on enregistre la méthode “OnStart” pour :
-
Produire différents logs via des “WriteInfo” (Warning & Error) contenant notamment différentes propriétés comme le IsConnected & IsStandalone.
-
Publier le StateObject “Demo”
Debug local (hors Constellation)
Commençons par tester notre package hors Constellation en lançant simplement le package avec le bouton “Start” de Visual Studio (F5) :
Votre package démarre et vous pouvez suivre dans la console les différents logs produits par votre package.
Vous observerez que votre package n’est pas connecté à Constellation (IsConnected = false).
Debug dans Constellation
Maintenant lançons toujours le debugging de votre package Constellation depuis Visual Studio mais en connectant votre package à Constellation. (Assurez-vous d’avoir défini dans Visual Studio la Constellation à utiliser pour le debug comme nous l’avons vu dans ce guide).
Cette fois ci, votre package démarre dans Visual Studio mais en étant connecté à Constellation (IsConnected = true).
Vous pouvez donc suivre en temps réel les logs depuis la Console Constellation :
Vous retrouverez également dans le StateObject Explorer de la Console, le StateObject “Demo” publié par notre package :
Publiez votre package
Lorsque votre package est testé et validé, nous pouvons le publier dans Constellation.
Pour cela cliquez sur le bouton de publication :
Sélectionnez votre serveur Constellation cible et cliquez sur “Publish” :
Une fois publié, vous retrouverez votre package dans le “Package Repository” de la Console.
N’oubliez pas que vous pouvez personnaliser les différentes informations (nom du package, auteur, URL, version, description, etc…) en éditant le manifeste de votre package.
Déployez votre package sur une sentinelle
Maintenant que votre package est dans le catalogue de votre Constellation, vous pouvez le déployer sur autant de sentinelle que vous le souhaitez!
Par l’édition du fichier de configuration
Pour cela, vous pouvez éditer manuellement la configuration (via le Configuration Editor) pour ajouter une instance de package sur la sentinelle de votre choix par la ligne :
1 |
<package name="MonPackagePython" /> |
On peut également déclarer le setting “Demo1” pour cette instance de package :
1 2 3 4 5 |
<package name="MonPackagePython"> <settings> <setting key="Demo1" value="Hello Python !!!!" /> </settings> </package> |
Cliquez sur le bouton “Save & Deploy” et votre package sera automatiquement démarré sur la sentinelle ici nommée “PO-SWARIN” !
Par l’interface graphique de la Console Constellation
Autre moyen, plus intuitif et rapide pour déployer un package, cliquez sur le bouton “Deploy” dans menu contextuel de votre package Python :
Vous pouvez également cliquer sur le bouton “Deploy new package” sur la page “Packages”.
Un assistant vous proposera de sélectionner la sentinelle sur laquelle déployer votre package Python :
Si les settings de votre package sont déclarés dans le manifeste (voir ici), la Console vous affichera une fenêtre de paramétrage :
Une fois votre package déployé, vous pourrez suivre dans la Console Log votre package :
Et voilà votre premier package Python créé et déployé dans votre Constellation !
Démarrez la discussion sur le forum Constellation