Add entry and exit commands.
authorBenjamin Braatz <benjamin.braatz@graph-it.com>
Wed, 12 Jan 2022 11:35:17 +0000 (12:35 +0100)
committerBenjamin Braatz <benjamin.braatz@graph-it.com>
Wed, 12 Jan 2022 11:35:17 +0000 (12:35 +0100)
controlpi_plugins/statemachine.py

index 3415f410174abd407558002b48b26421a41ce186..e38228f02e174d9ca4689a51e7b9548018019e7c 100644 (file)
@@ -16,7 +16,11 @@ class StateMachine(BasePlugin):
                      {'^[A-Za-z ]+$':
                       {'type': 'object',
                        'properties':
-                       {'commands':
+                       {'entry':
+                        {'type': 'array', 'items': {'type': 'object'}},
+                        'exit':
+                        {'type': 'array', 'items': {'type': 'object'}},
+                        'commands':
                         {'type': 'array', 'items': {'type': 'object'}},
                         'transitions':
                         {'type': 'array',
@@ -32,7 +36,7 @@ class StateMachine(BasePlugin):
 
     def process_conf(self) -> None:
         """Register plugin as bus client."""
-        self._current_state = ''
+        self._state = ''
         sends = []
         sends.append(MessageTemplate({'event': {'const': 'changed'},
                                       'state': {'type': 'string'}}))
@@ -92,7 +96,7 @@ class StateMachine(BasePlugin):
 
     async def _get_state(self, message: Message) -> None:
         await self.bus.send(Message(self.name,
-                                    {'state': self._current_state}))
+                                    {'state': self._state}))
 
     async def _get_machine(self, message: Message) -> None:
         await self.bus.send(Message(self.name,
@@ -100,30 +104,38 @@ class StateMachine(BasePlugin):
                                      'states': self.conf['states']}))
 
     async def _set_state(self, message: Message) -> None:
-        if (message['new state'] != self._current_state and
+        if (message['new state'] != self._state and
                 message['new state'] in self.conf['states']):
             assert isinstance(message['new state'], str)
             new_state = message['new state']
-            self._current_state = new_state
+            commands = self.conf['states'][self._state]['exit']
+            for command in commands:
+                await self.bus.send(Message(self.name, command))
+            self._state = new_state
             await self.bus.send(Message(self.name,
                                         {'event': 'changed',
                                          'state': new_state}))
-            commands = self.conf['states'][new_state]['commands']
+            commands = (self.conf['states'][self._state]['entry']
+                        + self.conf['states'][self._state]['commands'])
             for command in commands:
                 await self.bus.send(Message(self.name, command))
 
     async def _trigger(self, message: Message) -> None:
-        transitions = self.conf['states'][self._current_state]['transitions']
+        transitions = self.conf['states'][self._state]['transitions']
         for transition in transitions:
             if (MessageTemplate(transition['trigger']).check(message) and
                     transition['to'] in self.conf['states']):
                 assert isinstance(transition['to'], str)
                 new_state = transition['to']
-                self._current_state = new_state
+                commands = self.conf['states'][self._state]['exit']
+                for command in commands:
+                    await self.bus.send(Message(self.name, command))
+                self._state = new_state
                 await self.bus.send(Message(self.name,
                                             {'event': 'changed',
                                              'state': new_state}))
-                commands = self.conf['states'][new_state]['commands']
+                commands = (self.conf['states'][self._state]['entry']
+                            + self.conf['states'][self._state]['commands'])
                 for command in commands:
                     await self.bus.send(Message(self.name, command))
                 break
@@ -131,7 +143,8 @@ class StateMachine(BasePlugin):
     async def run(self) -> None:
         """Go into initial state."""
         if self.conf['init'] in self.conf['states']:
-            self._current_state = self.conf['init']
-            commands = self.conf['states'][self.conf['init']]['commands']
+            self._state = self.conf['init']
+            commands = (self.conf['states'][self._state]['entry']
+                        + self.conf['states'][self._state]['commands'])
             for command in commands:
                 await self.bus.send(Message(self.name, command))