2024-06-27 11:12:33 +02:00

157 lines
5.9 KiB
Python

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())