Organisez et réutilisez vos séquences avec l'héritage de classes Python.
Par défaut, chaque séquence est une classe Python autonome qui hérite de Sequence. L'approche orientée objet permet de créer une classe de base commune dont d'autres séquences héritent, ce qui évite de répéter les mêmes étapes, transitions et logique de sécurité dans chaque fichier.
Sequence (classe fournie par AutomationView)
└── ProjectBaseSequence (classe de base commune à votre projet)
├── CylinderA
├── CylinderB
└── ConveyorMain
Ce motif est l'outil adapté lorsque plusieurs séquences partagent un même squelette (mêmes étapes, mêmes actions de sécurité) mais diffèrent par le détail (noms de capteurs, conditions, durées).
Le plus rapide est de générer une classe de base commune à tout le projet.
Commande : Ctrl+Shift+P -> AutomationView: Initialize Standards Library
Cela crée un fichier standards/base_sequence.py avec une classe ProjectBaseSequence prête à être personnalisée :
from automation_machine import Sequence, StepType, ActionQualifier
class ProjectBaseSequence(Sequence):
"""Classe de base commune à toutes les séquences du projet."""
def setup(self):
self.name = self.__class__.__name__
self._configure_safety()
self._define_steps()
self._define_transitions()
def _configure_safety(self):
"""Actions de sécurité communes. Redéfinir si nécessaire."""
pass
def _define_steps(self):
"""Définir les étapes. Appeler super()._define_steps() dans les sous-classes."""
self.s0 = self.add_step(StepType.INITIAL, name="Idle")
def _define_transitions(self):
"""Définir les transitions. Redéfinir dans les sous-classes."""
pass
Modifiez cette classe pour y placer tout ce qui est commun à votre projet : étape initiale, actions de sécurité, conventions de nommage.
Si plusieurs types de base sont nécessaires (une pour les vérins, une pour les convoyeurs, etc.), utilisez la commande dédiée.
Commande : Ctrl+Shift+P -> AutomationView: Create Base Class
Trois variantes sont proposées :
Pour standardiser un type de séquence répétitif. Les sous-classes ne redéfinissent que ce qui change.
from automation_machine import Sequence, StepType
class BaseCylinder(Sequence):
def setup(self):
self.name = self.__class__.__name__
self._define_steps()
self._define_transitions()
def _define_steps(self):
self.s0 = self.add_step(StepType.INITIAL, name="Idle")
def _define_transitions(self):
"""Redéfinir dans les sous-classes."""
pass
Pour des séquences configurées par des arguments passés à l'instanciation.
from automation_machine import Sequence, StepType
class ParametrizedSequence(Sequence):
"""
Args:
zones: Nombre de zones actives.
sensor_prefix: Préfixe des variables capteurs.
"""
def __init__(self, *args, zones: int = 1, sensor_prefix: str = "sensor", **kwargs):
self.zones = zones
self.sensor_prefix = sensor_prefix
super().__init__(*args, **kwargs)
def setup(self):
self.name = self.__class__.__name__
self.s0 = self.add_step(StepType.INITIAL, name="Idle")
for i in range(self.zones):
step = self.add_step(name=f"Zone_{i + 1}")
self.add_transition(self.s0, step, f"{self.sensor_prefix}_{i + 1}_active")
Pour ajouter un comportement transverse à plusieurs séquences sans imposer une hiérarchie unique.
from automation_machine import ActionQualifier
class SafetyMixin:
"""
Usage :
class MaSequence(SafetyMixin, Sequence):
...
"""
def add_standard_reset_action(self, step, variable: str) -> None:
"""Ajoute une action de remise à zéro (qualificateur R) sur l'étape donnée."""
step.add_action(variable, qualifier=ActionQualifier.R)
Dès qu'une classe de base est disponible dans le projet, la génération d'une séquence enfant tient en une commande.
Commande : Ctrl+Shift+P -> AutomationView: Create Sequence from Class
AutomationView liste les classes de base détectées dans le projet. Sélectionnez-en une, nommez la nouvelle séquence, et le fichier est généré avec l'import et la structure déjà en place :
from base_cylinder import BaseCylinder
class CylinderA(BaseCylinder):
"""CylinderA - hérite de BaseCylinder."""
def _define_transitions(self):
"""Transitions spécifiques à CylinderA."""
self.add_transition(self.s0, self.s1, "front_sensor")
Les classes de base générées par AutomationView suivent toujours la même recette : setup() appelle plusieurs petites méthodes _define_* et _configure_*. Les sous-classes ne redéfinissent que celles qui les concernent et utilisent super() pour préserver le comportement hérité.
def _define_steps(self):
super()._define_steps() # conserver l'étape Idle du parent
self.s1 = self.add_step(name="Extending")
self.s2 = self.add_step(name="Retracting")
| Hook | Contenu typique |
|---|---|
_configure_safety |
Remise à zéro arrêt d'urgence, chien de garde, sécurités |
_define_steps |
Liste d'étapes propres au projet |
_define_transitions |
Conditions câblées sur les E/S du projet |
Stockez toujours les étapes réutilisables sur
self(self.s0,self.s1, ...) pour que les sous-classes puissent les référencer dans leurs redéfinitions.
Lorsqu'une séquence hérite d'une classe de base personnalisée, l'éditeur visuel affiche un indicateur à côté du nom de la séquence :
CylinderA extends BaseCylinder
Cet indicateur est purement informatif. Il disparaît si la séquence hérite directement de Sequence sans classe intermédiaire.
Projet typique avec deux vérins similaires qui partagent squelette et logique de sécurité.
standards/base_sequence.py - base commune au projet :
from automation_machine import Sequence, StepType, ActionQualifier
class ProjectBaseSequence(Sequence):
def setup(self):
self.name = self.__class__.__name__
self._configure_safety()
self._define_steps()
self._define_transitions()
def _configure_safety(self):
"""Hook de sécurité projet - les sous-classes peuvent redéfinir."""
pass
def _define_steps(self):
self.s0 = self.add_step(StepType.INITIAL, name="Idle")
def _define_transitions(self):
pass
lib/base_cylinder.py - squelette commun aux vérins :
from standards.base_sequence import ProjectBaseSequence
from automation_machine import ActionQualifier
class BaseCylinder(ProjectBaseSequence):
def _configure_safety(self):
# Remise à zéro des deux solénoïdes à l'initialisation - tous les vérins.
self.s0.add_action("sol_extend", qualifier=ActionQualifier.R)
self.s0.add_action("sol_retract", qualifier=ActionQualifier.R)
def _define_steps(self):
super()._define_steps()
self.s1 = self.add_step(name="Extending")
self.s2 = self.add_step(name="Retracting")
def _define_transitions(self):
"""Redéfinir dans chaque vérin avec les E/S réelles."""
pass
sequences/cylinder_a.py - câblage Vérin A :
from lib.base_cylinder import BaseCylinder
class CylinderA(BaseCylinder):
def _define_transitions(self):
self.add_transition(self.s0, self.s1, "cmd_extend_a")
self.add_transition(self.s1, self.s2, "sensor_end_a")
self.add_transition(self.s2, self.s0, "sensor_retract_a")
sequences/cylinder_b.py - câblage Vérin B :
from lib.base_cylinder import BaseCylinder
class CylinderB(BaseCylinder):
def _define_transitions(self):
self.add_transition(self.s0, self.s1, "cmd_extend_b")
self.add_transition(self.s1, self.s2, "sensor_end_b")
self.add_transition(self.s2, self.s0, "sensor_retract_b")
Les deux vérins partagent les trois étapes et la remise à zéro des solénoïdes définies dans BaseCylinder. Seules les conditions d'E/S diffèrent ; une évolution future de la logique de sécurité se fera une seule fois, dans la classe de base.
AutomationView propose trois mécanismes de réutilisation. À choisir selon le cas :
| Mécanisme | À utiliser quand |
|---|---|
| Étape macro | Un bloc d'étapes est invoqué plusieurs fois dans une même séquence, comme un sous-programme autonome avec une entrée et une sortie. |
| Étape d'encapsulation | Une étape parente « possède » une séquence enfant qui s'exécute en parallèle tant que la parente est active. Utile pour la supervision ou la surveillance. |
| Héritage de classe | Plusieurs séquences distinctes partagent le même squelette ou les mêmes actions de sécurité. Les différences portent sur les E/S, les noms ou certaines transitions spécifiques. |
L'héritage est l'outil adapté à la duplication entre fichiers. Les macros et l'encapsulation traitent la duplication à l'intérieur d'un fichier.
Si deux fichiers déclarent une classe portant le même nom, AutomationView signale une erreur sur chacun des fichiers concernés. L'erreur indique le nom en double et disparaît dès que le conflit est résolu.
| Commande | Utilisation |
|---|---|
AutomationView: Initialize Standards Library |
Crée ProjectBaseSequence - point de départ recommandé |
AutomationView: Create Base Class |
Crée une nouvelle classe de base (simple, paramétrée ou mixin) |
AutomationView: Create Sequence from Class |
Crée une séquence enfant à partir d'une classe de base existante |