def test_timer(): if "s" is "s": print("same!") t0 = {"source": "initial", "target": "s_1"} m = Machine(transitions=[t0], obj=None, name="t") driver = Driver() driver.add_stm(m) m.start_timer("t", 1000) print(driver.print_status()) m.stop_timer("t") print(driver.print_status())
def test(self): terminate = Terminate() t0 = {"source": "initial", "target": "s_1"} t1 = { "trigger": "t", "source": "s_1", "target": "s_2", "effect": "action" } stm_terminate = Machine(name="stm_terminate", transitions=[t0, t1], obj=terminate) terminate.stm = stm_terminate scheduler = Driver() scheduler.add_machine(stm_terminate) scheduler.start(max_transitions=2, keep_active=False) scheduler.send("t", "stm_terminate") scheduler.wait_until_finished() _ = stmpy.get_graphviz_dot(stm_terminate) _ = scheduler.print_status() self.assertTrue(True)
def test(self): # print(stmpy.__version__) logger = logging.getLogger("stmpy") logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s") ch.setFormatter(formatter) logger.addHandler(ch) tick1 = Tick() t0 = { "source": "initial", "target": "active", "effect": "start_timer('tick', 1000); print('initial1')", } #'effect': 'print("initial1")'} t1 = { "trigger": "tick", "source": "active", "target": "active", "effect": "start_timer('tick', 1000); print('timeout1')", } #'effect': 'print("timeout1")'} stm_tick_1 = Machine(name="stm_tick_1", transitions=[t0, t1], obj=tick1) tick1.stm = stm_tick_1 tick2 = Tick() t0 = { "source": "initial", "target": "active", "effect": "start_timer('tick', 2000); print('initial2')", } #'effect': 'print("initial2")'} t1 = { "trigger": "tick", "source": "active", "target": "active", "effect": "start_timer('tick', 1000); print('timeout2')", } stm_tick_2 = Machine(name="stm_tick_2", transitions=[t0, t1], obj=tick2) tick2.stm = stm_tick_2 driver1 = Driver() driver1.start(max_transitions=6, keep_active=True) print("driver state: active {} and thread alive {} ".format( driver1._active, driver1.thread.is_alive())) driver1.add_machine(stm_tick_1) print(driver1.print_status()) driver1.add_machine(stm_tick_2) print(driver1.print_status()) driver1._wake_queue() print("driver state: active {} and thread alive {} ".format( driver1._active, driver1.thread.is_alive())) # driver1.start(max_transitions=6, keep_active=True) print(driver1.print_status()) # driver2 = Driver() # driver1.add_machine(stm_tick_2) # driver2.start(max_transitions=10) driver1.wait_until_finished()
class BikeRack: def __init__(self, name, mqtt_broker, mqtt_port): """ Start the component. ## Start of MQTT We subscribe to the topic(s) the component listens to. The client is available as variable `self.client` so that subscriptions may also be changed over time if necessary. The MQTT client reconnects in case of failures. ## State Machine driver We create a single state machine driver for STMPY. This should fit for most components. The driver is available from the variable `self.driver`. You can use it to send signals into specific state machines, for instance. """ # TODO Make the mqtt topics into bike/$name/command (input) and bike/$name (output). # Something wrong happened trying to do so. self.MQTT_TOPIC_INPUT = 'bike/' #, name, '/command' self.MQTT_TOPIC_OUTPUT = 'bike/' #, name # Get the logger object for the component self._logger = logging.getLogger(__name__) print('Logging under name {}.'.format(__name__)) # ::: DEBUGGING ::: # logging.DEBUG: Most fine-grained logging, printing everything # logging.INFO: Only the most important informational log items # logging.WARN: Show only warnings and errors. # logging.ERROR: Show only error messages. debug_level = logging.DEBUG logger = logging.getLogger(__name__) logger.setLevel(debug_level) ch = logging.StreamHandler() ch.setLevel(debug_level) formatter = logging.Formatter( '%(asctime)s - %(name)-12s - %(levelname)-8s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) # END DEBUGGING self._logger.info('Starting Component') # Create a new MQTT client self._logger.debug('Connecting to MQTT broker {} at port {}'.format( mqtt_broker, mqtt_port)) self.mqtt_client = mqtt.Client() # Callback methods self.mqtt_client.on_connect = self.on_connect self.mqtt_client.on_message = self.on_message # Connect to the broker self.mqtt_client.connect(mqtt_broker, mqtt_port) # Subscribe to proper topic(s) of your choice self.mqtt_client.subscribe(self.MQTT_TOPIC_INPUT) # Start the internal loop to process MQTT messages self.mqtt_client.loop_start() # We start the stmpy driver, without any state machines for now self.driver = Driver() self.driver.start(keep_active=True) self._logger.debug('Component initialization finished') # Active machines self.active_machines = {} self.name = name # Add test_lock lock_name = "en" self._logger.debug(f'Create machine with name: {lock_name}') lock_stm = BikeLock(self.driver, self, lock_name) self.driver.add_machine(lock_stm.stm) self.active_machines[lock_name] = lock_name self._logger.debug("Start driver") self.driver.start() # TEST END def stop(self): """ Stop the component. """ # Stop the MQTT client self.mqtt_client.loop_stop() # Stop the state machine Driver self.driver.stop() def on_connect(self, client, userdata, flags, rc): # We just log that we are connected self._logger.debug('MQTT connected to {}'.format(client)) def check_available(self): for name in self.active_machines: if self.driver._stms_by_id[name].state == "available": return True def on_message(self, client, userdata, msg): """ Processes incoming MQTT messages. We assume the payload of all received MQTT messages is an UTF-8 encoded string, which is formatted as a JSON object. The JSON object contains a field called `command` which identifies what the message should achieve. As a reaction to a received message, we can for example do the following: * create a new state machine instance to handle the incoming messages, * route the message to an existing state machine session, * handle the message right here, * throw the message away. """ self._logger.debug('Incoming message to topic {}'.format(msg.topic)) payload = json.loads(msg.payload) command = payload.get('command') self._logger.debug(f"Have detected this command: {command}") if command == "check_driver": self._logger.debug(f"State Machine: {self.driver.print_status()}") if self.check_available(): self.mqtt_client.publish(self.MQTT_TOPIC_OUTPUT, self.driver.print_status()) # Assumes payload with ``lock_name`` and ``nfc_tag`` elif command == "reserve": for name in self.active_machines: if self.driver._stms_by_id[name].state == "available": self._logger.debug(f"Reserving lock with id: {name}") kwargs = {"nfc_tag": payload.get("value")} self.driver.send(message_id='reserve', stm_id=name, kwargs=kwargs) self.mqtt_client.publish( self.MQTT_TOPIC_OUTPUT, f'Reserved lock with name {name}') self.mqtt_client.publish( self.get_stm_by_name(name)._obj.get_nfc_tag()) self._logger.debug( self.get_stm_by_name(name)._obj.get_nfc_tag()) return self._logger.debug("No locks available in this rack") self.mqtt_client.publish(self.MQTT_TOPIC_OUTPUT, f'No locks available') elif command == "add_lock": lock_name = payload.get("lock_name") self._logger.debug(f"Add lock with name: {lock_name}") lock_stm = BikeLock(self.driver, self, lock_name) self.driver.add_machine(lock_stm.stm) self.active_machines[lock_name] = lock_name # Assumes payload with``nfc_tag`` and ``lock_name`` elif command == "nfc_det": self._logger.debug("running nfc_det") self.nfc_det(nfc_tag=payload.get("value"), lock_name=payload.get("lock_name")) elif command == "check_state": name = payload.get("name") self._logger.debug( f"Machine: {name}, is in state: {self.get_stm_by_name(name).state}" ) self.mqtt_client.publish( self.MQTT_TOPIC_OUTPUT, f"Machine: {name}, is in state: {self.get_stm_by_name(name).state}" ) # Catch message without handler else: self._logger.debug(f"Command: {command} does not have a handler") def res_expired(self, nfc_tag): self.mqtt_client.publish(self.MQTT_TOPIC_OUTPUT, f'Reservetion timed out for {nfc_tag}') def nfc_det(self, nfc_tag, lock_name): self._logger.debug( f"Detected NFC-tag with value: {nfc_tag} presented to lock: {lock_name}" ) self._logger.debug(self.get_stm_by_name(lock_name).state) kwargs = {"nfc_tag": nfc_tag} self.driver.send(message_id='nfc_det', stm_id=lock_name, kwargs=kwargs) # Getter for stm_by name def get_stm_by_name(self, stm_name): if self.driver._stms_by_id[stm_name]: self._logger.debug(f"Getting stm with name: {stm_name}") return self.driver._stms_by_id[stm_name] # Did not find machine with ``stm_name`` self._logger.error(f"Error: did not find stm with name: {stm_name}") return None