import json import asyncio from modele.donnees import SchemaReader, GraphStructException from modele.graphe import Graphe from modele.cocosim import Cocosim from api_server.state import State import logging import modele.exceptions class CocosimInstance(object): def __init__(self, cmd_q, state_q): self.runner = None try: conf_fp = open("modele/config.json") conf = json.load(conf_fp) self.pause_simulation = False #pause flag self.conf = conf self.dt = self.conf['circuit']['DT'] self.cocosim = None self.state = None self.cmd_q = cmd_q self.state_q = state_q self.quit = False except (OSError, json.JSONDecodeError) as e: logging.exception("Reading conf. file") raise modele.G def setup(self, schema_d): logging.info("Setting up") reader = SchemaReader(schema_d) reader.process() logging.info("Schema is loaded") self.state = State(self) self.state.load_conf(schema_d) logging.info(f"State is made up with {len(self.state.composants)} items.") graphe = Graphe(self.conf['circuit']) graphe.load_data_from_schema_reader(reader) logging.info("Graph is initialized.") self.cocosim = Cocosim(self.conf, graphe, {}, {}) logging.info("Cocosim is initialized") async def handler(self): loop = asyncio.get_running_loop() data = await loop.run_in_executor(None, self.cmd_q.get) message = data['cmd'] try: if message == "start": logging.log(logging.INFO, "Starting") self.runner = asyncio.create_task(self.run()) elif message == "stop": logging.log(logging.INFO, "Stopping") await self.stop() elif message == "state": self.state_q.put(self.state.to_json()) elif message == "quit": logging.log(logging.INFO, "Quitting") await self.stop() self.quit = True elif message == "load": logging.log(logging.INFO, "Loading file") try: self.setup(data['args'] if type(data['args']) == dict else json.loads(data['args'])) # Compatibilité avec certaines IHM self.state_q.put("OK") except GraphStructException: self.state_q.put("Error") elif message == "pause": but_name = data['args'] logging.log(logging.INFO,"Simulation paused {but_name}") self.pause_simulation = True elif message == "resume": but_name = data['args'] logging.log(logging.INFO,"Simulation resumed {but_name}") self.pause_simulation = False elif message == "push": but_name = data['args'] logging.log(logging.INFO, f"Push button {but_name}") if self.cocosim.graphe[but_name] == "Bouton": self.cocosim.graphe[but_name].ferme() else: self.cocosim.graphe[but_name].bascule() elif message == "release": but_name = data['args'] logging.log(logging.INFO, f"Release button {but_name}") if self.cocosim.graphe[but_name].type == "Bouton": self.cocosim.graphe[but_name].ouvre() # Dans le cas contraire on ne traite pas le release else: logging.log(logging.ERROR, "Commande inconnue") except Exception: logging.exception("Exception occured in handler") def cycle(self): try: self.cocosim.cycle() for nom in self.state.keys(): if nom not in self.cocosim.graphe and nom[-7:] == ".double": # TODO : a supprimer apràs refactoring contact double nom_translate = nom[:-7] + ".travail" value = self.cocosim.graphe[nom_translate].etat() if nom_translate in self.cocosim.graphe else None self.state.update(nom, value) else: value = self.cocosim.graphe[nom].etat() if nom in self.cocosim.graphe else None self.state.update(nom, value) except modele.base.SurintensiteException as e: self.state.exception("Surintensité") raise e except modele.base.SurtensionException as e: self.state.exception("Surtension") raise e async def run(self): try: while not self.quit: if not self.pause_simulation: self.state.reset_exception() self.cycle() else: print("Simulation paused. Awaiting resume...") while self.pause_simulation: await asyncio.sleep(1) #wait until the simulation is resumed await asyncio.sleep(self.dt) except Exception as e: logging.exception("Exception occured during simulation run") async def stop(self): if self.runner: self.runner.cancel() try: await self.runner except asyncio.CancelledError: logging.info("Runner is stopped.") self.runner = None async def handle_requests(self): while not self.quit: await self.handler() logging.info("Stop handling request") def __del__(self): logging.info("Cocosim instance destroyed") def run_instance(uid, cmd_q, state_q): logging.basicConfig(filename=f"cocosim.log", filemode="w", level=logging.INFO) logging.info("Creating instance") i = CocosimInstance(cmd_q, state_q) asyncio.run(i.handle_requests())