Sommaire

Vous pouvez créer des applications graphiques et les déployer sur vos sentinelles UI grâce à Constellation.

Chaque package UI pourra invoquer ou exposer des MessageCallbacks, consommer ou produire des StateObjects, etc…

Hello World WPF

Dans Visual Studio, vous créez un package WPF :

Création d'un package UI

Le template est une application WPF classique :

Structure du package WPF

Le IPackage de ce package est la classe “App” (App.xaml.cs). Ce package lance la fenêtre MainWindow au démarrage (méthode “OnStart”).

La “MainWindow” est une Window WPF classique à l’exception que dans le constructeur, on enregistre automatiquement les [StateObjectLink] et les [MessageCallback] de la classe. De plus on renvoie la description du package (dans le cas où vous avez ajoutez des MessageCallbacks).

Au chargement de la fenêtre on logge un message dans Constellation et on affiche quelques propriété sur l’état du package dans le titre de cette fenêtre !

Ajoutons un simple label “Hello World” au centre de notre fenêtre :

Le code XAML sera donc:

Pour tester notre package en debug sans être connecté à Constellation : “F5”

Debug du package en local

Vous noterez que les WriteLog Constellation sont toujours afficher dans la fenêtre de sortie de Visual Studio.

Maintenant pour lançons le debug de notre package dans Visual Studio tout en le connectant à Constellation (raccourci Ctrl+Alt+F8)

image

Debug du package dans Constellation

Invoquer des MessageCallbacks

Vous pouvez invoquer ou exposer des MessageCallbacks comme n’importe quel package connecté dans votre Constellation.

Pour exposer des MessageCallbacks (des méthodes NET), il suffit d’ajouter l’attribut [MessageCallback] sur vos méthodes.

Pour invoquer des MessageCallbacks, il faut créer un scope et envoyer le message. Grace au proxy dynamique, vous pouvez invoquer un MessageCallback comme vous invoquerez une méthode .NET.

Dans cet exemple nous allons invoquer des MessageCallbacks des packages WindowsControl et GoogleTraffic. Vous pouvez suivre le guide ici pour déployer ces deux packages.

En vous rendant sur la page “MessageCallbacks Explorer” de la Console, vous pouvez explorer les MC exposés par les packages.

Par exemple, le package WindowsControl expose plusieurs MessageCallbacks pour arrêter, redémarrer, mettre en veille ou verrouiller l’ordinateur (= la sentinelle) sur lequel le package est déployé.

Le package GoogleTraffic expose un MessageCallback “GetRoute” pour calculer le temps de route en spécifiant un point de départ et d’arrivée. Ce MessageCallback  est une saga pour vous retourner la réponse.

MessageCallbacks Explorer

Pour simplifier le développement et éviter de travailler avec des types dynamiques, nous allons auto-générer le code.

Cliquez sur le bouton “Generate Code” :

Génération de code

Sélectionnez votre Constellation, cliquez sur “Discover” et sélectionnez les packages que vous souhaitez ajouter dans le code généré puis cliquez sur “Generate” :

Génération de code

Editez le code de la MainWindow (MainWindow.xaml.cs) pour ajouter le code généré des MessageCallbacks pour les packages GoogleTraffic et WindowsControl :

Dans la vue XAML, ajoutons deux boutons : l’un pour mettre en veille et l’autre pour faire un test d’itinéraire :

Pour le premier bouton, nous allons sélectionner l’instance du package “WindowsControl” sur la sentinelle “PO_SEB” pour créer un scope afin d’invoquer le MessageCallback “Sleep” :

Prenez garde à créer un scope sur une instance (sentinelle + package) car sinon, si vous créez un scope sur le package “WindowsControl”, toutes les sentinelles hébergeant ce package se mettront en veille !

Pour le deuxième bouton, nous allons demander les différentes routes pour un “Lille-Paris”. Comme il s’agit d’une saga (message avec réponse) nous allons l’invoquer en “async/await” et afficher dans le label la meilleure route :

Lancer le debug dans Constellation : Debug On Constellation  (ou Ctrl+Alt+F8).

Premier test, en cliquant sur Sleep, vous allez envoyer un message pour invoquer le MessageCallback “Sleep” du package “WindowsControl” sur la sentinelle ici nommée “PO-SEB”. Ainsi le Windows “PO-SEB” se mettra instantanément en veille !

Test du MC "Sleep"

Deuxième test, pour invoquer le MessageCallback “GetRoutes” du package GoogleTraffic :

Test du MC "GetRoutes" en AsyncRéponse à la saga "GetRoutes"

Consommer des StateObjects dans votre vue XAML

Assurez-vous d’avoir dans votre Constellation au moins un package “HWMonitor” déployé sur une sentinelle. Au besoin, vous pouvez suivre ce guide ici.

HWMonitor

Pour comprendre en détail, la consommation des StateObjects dans vos packages n’hésitez pas à relire cet article.

Par exemple, pour afficher en temps réel la consommation CPU (StateObject nommé “/intelcpu/0/load/0”) mesurée par le package HWMonitor sur sa sentinelle (ici “PO-SEB”), ajoutons un StateObjectLink :

Vous pouvez également générer du code en sélectionnant le package HWMonitor. Vous pourrez ensuite ajouter un “using” vers les StateObjects de ce package :

Cela vous permettra d’utiliser un le “HWMonitorStateObjectLink” avec des énumérations générées pour vos sentinelles et nom de StateObjects :

Comme vous le savez, le StateObjectNotifier implémente l’interface INotifyPropertyChanged. Vous pouvez donc lier cette propriété dans votre vue XAML pour voir votre StateObject en temps réel sur votre interface.

Nous allons modifier le label “Hello World” pour afficher en temps réel votre consommation CPU. Pour cela changeons le contenu (Content) du label avec la propriété “Value” du StateObject publié par le package HWMonitor.

Cette propriété contient la valeur (ici de l’utilisation du CPU) avec un nombre décimal. Nous ajoutons également l’attribut “ContentStringFormat” pour n’afficher que 2 chiffres après la virgule.

Pour pourvoir utiliser des propriétés .NET comme binding dans votre vue XAML, vous devez spécifier le DataContext de votre fenêtre vers votre classe MainWindow soit via le code (this.DataContent = this) ou soit directement dans votre vue XAML en ajoutant cette attribut sur l’élément Window :

Résultat, vous pouvez suivre en temps réel le CPU ici de la machine “PO-SEB” :

Binding au CPU du package HWMonitor

Allons un peu plus loin en ajoutons dans notre code C#, un nouveau StateObjectLink :

Ce “lien” ne précise que le nom du StateObject (ici “/intelcpu/0/load/0”) et le package (HWMonitorStateObjectLink est la classe générée qui spécifie implicitement le package à “HWMonitor).

De ce fait, toutes les consommations CPU mesurées par les instances du package HWMonitor seront captées par ce “link” ! On utilisera donc un StateObjectCollectionNotifier car on aura autant de StateObjects qu’on a d’instance de ce package.

Dans la vue XAML, ajoutons un menu déroulant (combobox) pour afficher le nom des sentinelles (= le nom des machines) des StateObjects de votre collection “CPUs” :

Enfin, modifions une nouvelle fois notre label. Cette fois ci la valeur à afficher n’est pas celle du StateObject “CPU”, mais celle du StateObject sélectionné par la combobox :

On obtient donc la possibilité de suivre la consommation de chaque machine (= sentinelle) où le package HWMonitor est déployé :

image

Pour terminer on pourrait également ajouter un StateObjectLink qui contiendrait TOUS les StateObjects produits par les packages HWMonitor, peut importe le nom du StateObject et la sentinelle :

Pour afficher toutes ces données, on peut utiliser un DataGrid lié à votre collection de StateObject “HWMonitor” :

On obtiendrait une vue avec deux colonnes, la propriété DynamicValue et Value des StateObjectNotifier :

DataGrid sur une collection de StateObjectNotifier

Pour rendre cela plus visuelle, définissions explicitement des colonnes avec le nom de la sentinelle, le nom du StateObject, la propriété “Name” de la valeur du StateObject  (le nom du compteur), la “Value” et l’unité de la mesure (Unit).

En XAML cela se traduit par le code suivant :

Le résultat :

StateObjects des packages HWMonitor

Prenez garde car les StateObjects sont mis à jour dans le StateObjectsCollectionNotifier par des threads différents. Vous risquez donc d’avoir des exceptions du type “An ItemsControl is inconsistent with its items source”. Afin d’éviter ce genre d’erreur, utilisez la  méthode “BindingOperations.EnableCollectionSynchronization”.

Pour cela, dans votre classe, ajoutez un objet de synchronisation :

Puis dans le constructeur de votre fenêtre, après le InitializeComponent(), activez la synchronisation de la collection sur votre StateObjectCollectionNotifier (ici nommé ‘HWMonitor’) :

Si lancez votre package dans une Constellation avec plusieurs instances du packages HWMonitor sur vos différentes sentinelles, vous aurez une vision temps réel de l’ensemble de vos machines Windows avec seulement ces quelques lignes de XAML et Constellation :

StateObjects des packages HWMonitor

Déployez votre package UI

Publier le package

Le sujet a été traité dans le guide de démarrage, il suffit de cliquer-droit sur votre projet et sélectionner dans le menu Constellation “Publish On Constellation” ou directement depuis la toolbar :

Publication du package

Vous pourrez alors choisir le type de publication (Local ou Upload sur le serveur Constellation) :

Publication du package

Déployer le package sur une sentinelle UI

Vous devez impérativement déployer un package “UI” sur une sentinelle UI. Si vous tentez d’ajouter un package UI sur une sentinelle service, le package démarrera mais aucune fenêtre ne pourra être visible (le service ne peut pas interagir avec le bureau Windows).

Les sentinelles UI ont le suffixe “_UI” dans leurs noms. Ici pour cette Constellation, il y a deux sentinelles connectées, l’une de type “Service” et l’autre “UI”, toutes deux sur la même machine (nommé “PO-SEB”).

Sentinelles connectées

Pour ajouter notre package à la sentinelle UI, vous pouvez éditer la configuration de vos Constellation directement depuis Visual Studio :

Ajout du package depuis Visual Studio

Ou bien depuis la Console Constellation :

Ajout du package dans une sentinelle UI

Pour déployer la configuration, cliquez sur le bouton “Save & Deploy” depuis la Console, ou directement sur la page des “Packages” cliquez sur “Reload & Deploy”.

Votre package UI sera démarré et vous pourrez le contrôler depuis la Console comme pour les autres packages.

Contrôle du package UI sur la Console

Démarrer son package “manuellement”

Si vous créez une application à destination d’une borne d’affichage, comme un miroir, le package est démarré automatiquement par la sentinelle (comportement par défaut) et est relancé si le package plante !

Cependant, si votre package est destiné à être utilisé par un utilisateur comme une application Windows classique vous voudriez certainement ne pas la lancer automatiquement au démarrage de la sentinelle. Au contraire vous voudriez que ce soit l’utilisateur qui décide de la lancer en lançant un raccourci Windows par exemple sans devoir se connecter sur la Console de votre Constellation.

Pour cela vous pouvez lancer la sentinelle en passant un ordre en paramètre :

Les actions peuvent être :

  • Start
  • Stop
  • Restart
  • Reload

Par exemple, créons un raccourci sur le bureau vers :

Ainsi dès que vous double-cliquerez sur ce raccourci, la sentinelle téléchargera la dernière version du package sur le serveur et lancera votre package (Reload) :

image

Bien entendu, l’état du package sera automatiquement synchronisé dans la Constellation. Vous pourrez donc contrôler l’état du package depuis la Console par exemple.

Par défaut, une sentinelle démarre tous les packages qui lui sont assignés. Si c’est un package destiné à être lancé manuellement par l’utilisateur, vous voudriez peut être ne pas lancer automatiquement le package. Vous pouvez donc définir l’attribut “autoStart” à false au niveau de la configuration de votre package.

Aussi l’ordre d’arrêt d’un package doit provenir du hub de contrôle de Constellation, qui se chargera de communiquer l’ordre au package lui même (de s’arrêter) et à sa sentinelle (de tuer le package si il ne s’est pas arrêté dans le temps imparti).

Seulement, dans un package UI de ce type, c’est à dire “application Windows classique”, l’utilisateur fermera naturellement l’application en cliquant sur la croix rouge en haut à droite !

La sentinelle détectera la mort du processus du package alors qu’elle n’a pas eu l’ordre de Constellation d’arrêter le package ! Du point de vue de la sentinelle, c’est un arrêt brutal !

Elle appliquera donc les options de récupération qui par défaut redémarre un package 30 secondes après un arrêt brutal :

RecoveryOption par défaut

Les options par défaut sont définis dans la configuration de la Constellation :

RecoveryOption par défaut

Dans notre cas, nous allons redéfinir ces options de récupération au niveau du package lui même pour ne pas redémarrer un package suite à un arrêt forcé et ne pas démarrer automatiquement notre package au démarrage. La configuration du package sera :

Configuration d'un package UI

Créer des packages UI en Winform ou WPF
Editer la page sur GitHub
Étiqueté avec :                                

Démarrez la discussion sur le forum Constellation