diff --git a/api_server/__pycache__/app.cpython-312.pyc b/api_server/__pycache__/app.cpython-312.pyc index 5d83b0a..6a74406 100644 Binary files a/api_server/__pycache__/app.cpython-312.pyc and b/api_server/__pycache__/app.cpython-312.pyc differ diff --git a/api_server/__pycache__/state.cpython-312.pyc b/api_server/__pycache__/state.cpython-312.pyc index 71d9a07..b4ec3c3 100644 Binary files a/api_server/__pycache__/state.cpython-312.pyc and b/api_server/__pycache__/state.cpython-312.pyc differ diff --git a/api_server/app.py b/api_server/app.py index f5cea62..c254cce 100644 --- a/api_server/app.py +++ b/api_server/app.py @@ -184,6 +184,21 @@ def release(obj): PROCESS_BASE.cmd_q().put({'cmd': "release", "args": obj}) return "OK" +@app.route('/pause/') +def pause_simulation(obj): + if not PROCESS_BASE.known(): + return "Unknown", 401 + + PROCESS_BASE.cmd_q.put({'cmd': "pause", "arg": obj}) + return "Simulation paused" + +@app.route('/resume/') +def resume_simulation(obj): + if not PROCESS_BASE.known(): + return "Unknown", 401 + + PROCESS_BASE.cmd_q.put({'cmd': "resume", "arg": obj}) + return "Simulation resumed" def just_run(): """ diff --git a/api_server/state.py b/api_server/state.py index 9cba09c..74594e6 100644 --- a/api_server/state.py +++ b/api_server/state.py @@ -3,7 +3,11 @@ import json class State(object): IGNORE = frozenset(['Coude', 'Noeud', 'P24', 'P0', 'Pulse']) + # these components do not have any states (value/ true or flase...) + Breakpoints = ['Relais'] + #possibility to add other breakpoints in the future ;) + def __init__(self, cocosim_server): self.cocosim_server = cocosim_server self.conf = self.cocosim_server.conf["ui"] @@ -38,4 +42,5 @@ class State(object): self._exception = e def reset_exception(self): - self._exception = None \ No newline at end of file + self._exception = None + diff --git a/api_worker/__init__.py b/api_worker/__init__.py index 4668ecb..3e99e02 100644 --- a/api_worker/__init__.py +++ b/api_worker/__init__.py @@ -14,6 +14,7 @@ class CocosimInstance(object): 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 @@ -47,15 +48,19 @@ class CocosimInstance(object): 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: @@ -63,6 +68,17 @@ class CocosimInstance(object): 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}") @@ -103,12 +119,17 @@ class CocosimInstance(object): async def run(self): try: - while True: - self.state.reset_exception() - self.cycle() + 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: - logging.exception("Exception occured in 'cycle'") + except Exception as e: + logging.exception("Exception occured during simulation run") async def stop(self): if self.runner: diff --git a/api_worker/__pycache__/__init__.cpython-312.pyc b/api_worker/__pycache__/__init__.cpython-312.pyc index 3f974ce..fe05b87 100644 Binary files a/api_worker/__pycache__/__init__.cpython-312.pyc and b/api_worker/__pycache__/__init__.cpython-312.pyc differ diff --git a/cocosim.log b/cocosim.log index 32f7cbb..118e628 100644 --- a/cocosim.log +++ b/cocosim.log @@ -1,19 +1,2 @@ INFO:root:Creating instance -INFO:root:Loading file -INFO:root:Setting up -INFO:root:Schema is loaded -INFO:root:State is made up with 5 items. -INFO:root:Graph is initialized. -INFO:root:Cocosim is initialized -INFO:root:Starting -INFO:root:Push button b -INFO:root:Release button b -INFO:root:Stopping -ERROR:root:Exception occured in 'cycle' -Traceback (most recent call last): - File "C:\Users\0203209E\Downloads\gittea\cocosim_python\api_worker\__init__.py", line 109, in run - await asyncio.sleep(self.dt) - File "C:\Program Files\Python312\Lib\asyncio\tasks.py", line 655, in sleep - return await future - ^^^^^^^^^^^^ -asyncio.exceptions.CancelledError +INFO:root:Cocosim instance destroyed diff --git a/modele/__pycache__/cocosim.cpython-312.pyc b/modele/__pycache__/cocosim.cpython-312.pyc index eb8bd23..0cbc9ba 100644 Binary files a/modele/__pycache__/cocosim.cpython-312.pyc and b/modele/__pycache__/cocosim.cpython-312.pyc differ diff --git a/modele/__pycache__/composants.cpython-312.pyc b/modele/__pycache__/composants.cpython-312.pyc index a0ae861..c25e5fc 100644 Binary files a/modele/__pycache__/composants.cpython-312.pyc and b/modele/__pycache__/composants.cpython-312.pyc differ diff --git a/modele/__pycache__/donnees.cpython-312.pyc b/modele/__pycache__/donnees.cpython-312.pyc index 1e61176..8bb5823 100644 Binary files a/modele/__pycache__/donnees.cpython-312.pyc and b/modele/__pycache__/donnees.cpython-312.pyc differ diff --git a/modele/__pycache__/elements.cpython-312.pyc b/modele/__pycache__/elements.cpython-312.pyc index e85419f..f73fbcc 100644 Binary files a/modele/__pycache__/elements.cpython-312.pyc and b/modele/__pycache__/elements.cpython-312.pyc differ diff --git a/modele/__pycache__/graphe.cpython-312.pyc b/modele/__pycache__/graphe.cpython-312.pyc index 6730ddb..d6f43a9 100644 Binary files a/modele/__pycache__/graphe.cpython-312.pyc and b/modele/__pycache__/graphe.cpython-312.pyc differ diff --git a/modele/composants.py b/modele/composants.py index 9382e80..7a41846 100644 --- a/modele/composants.py +++ b/modele/composants.py @@ -1,6 +1,5 @@ from modele.exceptions import NonPolariseException, Dir - class Composant(object): def __init__(self, conf, nom): """ @@ -38,6 +37,10 @@ class Composant(object): def etat(self): raise NotImplementedError + + def pause_simulation(self): + + pass class Contact(Composant): @@ -117,6 +120,8 @@ class Relais(Composant): self._contacts_repos = [] self._contacts_double = [] self.haut = False + self.etat_precedent = False #etat precedent du relais + self.est_point_arret = False #indicateur de point d'arret def add_travail(self, nom): self._contacts_travail.append(nom) @@ -150,12 +155,16 @@ class Relais(Composant): self.graphe[nom].desactive() def update(self): + etat_precedent = self.haut super().update() if self.branche.i() >= self.SEUIL: self.monte() else: self.chute() + if self.est_point_arret and etat_precedent != self.haut: + self.graphe.flag_arret_simulation = True + def etat(self): return self.haut diff --git a/modele/config.json b/modele/config.json index cdc17c8..ac4bbd7 100644 --- a/modele/config.json +++ b/modele/config.json @@ -13,7 +13,8 @@ "RES_RELAIS": 100.0, "SEUIL_RELAIS": 0.05, "SEUIL_TEMPO": 0.05, - "PULSE_PERIODE": 1.0 + "PULSE_PERIODE": 1.0, + "TOLERANCE_COURANT": 1e6 }, "ui": { "DT": 0.13, diff --git a/modele/elements.py b/modele/elements.py index c03400e..3ba55f2 100644 --- a/modele/elements.py +++ b/modele/elements.py @@ -138,6 +138,26 @@ class Noeud(Element): def etat(self): return self.u() >= self.conf['USEUIL'] + + + + def verifier_loi_des_noeuds(self): + + """Dans cette méthode, self._voisins contient les branches connectées au nœud, et polarite indique si le courant est entrant (-1) ou sortant (+1). + La variable courant_total accumule la somme des courants, et self.conf['TOLERANCE_COURANT'] est une petite valeur seuil pour tolérer des imprécisions + numériques (par exemple, 1e-6).""" + + courant_total = 0 + for voisin, polarite, _ in self._voisins: + if polarite == -1: + courant_total -= voisin.i() + else: + courant_total += voisin.i() + + if abs(courant_total) > self.conf['TOLERANCE_COURANT']: + raise Exception(f"La loi des nœuds n'est pas respectée pour le noeud {self.nom}. Total courant: {courant_total}") + + class Branche(Element): diff --git a/modele/graphe.py b/modele/graphe.py index 574c49d..3dcc1b3 100644 --- a/modele/graphe.py +++ b/modele/graphe.py @@ -38,6 +38,7 @@ class Graphe(object): self.elements = None self.composants = None self.vecteur = None + self.flag_arret_simulation = False def load_data_from_schema_reader(self, reader): self.elements = {} @@ -168,4 +169,4 @@ class Graphe(object): [elt.update() for elt in self.elements.values()] def coherence(self): - [x.coherence() for x in self.elements.values()] + [x.coherence() for x in self.elements.values()] \ No newline at end of file diff --git a/schemas_v1/output-file.ccs b/schemas_v1/output-file.ccs new file mode 100644 index 0000000..18f43ea --- /dev/null +++ b/schemas_v1/output-file.ccs @@ -0,0 +1 @@ +{"blocs":{"p24-1":{"type":"P24","valeur":24,"orientation":0,"x":0,"y":500},"p24-2":{"type":"P24","valeur":24,"orientation":0,"x":0,"y":300},"p0-1":{"type":"P0","valeur":0,"orientation":0,"x":1200,"y":500},"p0-2":{"type":"P0","valeur":0,"x":1200,"y":300},"r1":{"type":"Relais","x":400,"y":500},"r2":{"type":"Relais","x":1000,"y":500},"c3":{"type":"Bouton","x":200,"y":500,"orientation":0},"r2.double":{"type":"ContactDouble","relais":"r2","orientation":0,"x":1000,"y":300},"w1":{"type":"Lampe","x":600,"y":500},"w2":{"type":"Lampe","x":600,"y":300},"n1":{"type":"Noeud","x":800,"y":500},"coude1":{"type":"Coude","x":800,"y":310}},"cables":[["p24-1","d","c3","g"],["c3","d","r1","g"],["r1","d","w1","g"],["w1","d","n1","m"],["n1","m","r2","g"],["r2","d","p0-1","g"],["n1","m","coude1","m"],["coude1","m","r2.double","hg"],["r2.double","d","p0-2","g"],["p24-2","d","w2","g"],["w2","d","r2.double","bg"]]} \ No newline at end of file diff --git a/schemas_v1/output-file11.ccs b/schemas_v1/output-file11.ccs new file mode 100644 index 0000000..d7f3670 --- /dev/null +++ b/schemas_v1/output-file11.ccs @@ -0,0 +1 @@ +{"blocs":{"p24-1":{"type":"P24","valeur":24,"orientation":0,"x":0,"y":500},"p24-2":{"type":"P24","valeur":24,"orientation":0,"x":0,"y":300},"p0-1":{"type":"P0","valeur":0,"orientation":0,"x":1200,"y":500},"p0-2":{"type":"P0","valeur":0,"x":1200,"y":300},"r1":{"type":"Relais","x":400,"y":500},"r2":{"type":"Relais","x":1000,"y":500},"c3":{"type":"Bouton","x":200,"y":500,"orientation":0},"r2.double":{"type":"ContactDouble","relais":"r2","orientation":0,"x":1000,"y":300},"w1":{"type":"Lampe","x":600,"y":500},"w2":{"type":"Lampe","x":600,"y":200},"n1":{"type":"Noeud","x":800,"y":500},"coude1":{"type":"Coude","x":800,"y":310}},"cables":[["p24-1","d","c3","g"],["c3","d","r1","g"],["r1","d","w1","g"],["w1","d","n1","m"],["n1","m","r2","g"],["r2","d","p0-1","g"],["n1","m","coude1","m"],["coude1","m","r2.double","hg"],["r2.double","d","p0-2","g"],["p24-2","d","w2","g"],["w2","d","r2.double","bg"]]} \ No newline at end of file