From 88aced27bfd167b611634bb7074bf067b4f9ea2f Mon Sep 17 00:00:00 2001 From: wissal bendidi Date: Wed, 28 Feb 2024 11:40:09 +0100 Subject: [PATCH] import de fichiers --- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 169 bytes api_server/__pycache__/app.cpython-312.pyc | Bin 0 -> 10579 bytes api_server/__pycache__/state.cpython-312.pyc | Bin 0 -> 2455 bytes api_server/app.py | 218 ++++++++ api_server/state.py | 41 ++ api_server/test_client.py | 19 + api_worker/__init__.py | 135 +++++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 9642 bytes app/__init__.py | 0 app/models.py | 0 app/routes.py | 0 cocosim.log | 19 + images_v1/CoCoSIM_icon.png | Bin 0 -> 18311 bytes images_v1/CoCoSIM_icon.svg | 83 +++ images_v1/CoCoSIM_logo_01.png | Bin 0 -> 31387 bytes images_v1/CoCoSIM_logo_01.svg | 84 +++ images_v1/bouton_ferme.png | Bin 0 -> 2188 bytes images_v1/bouton_ferme.svg | 18 + images_v1/bouton_ouvert.png | Bin 0 -> 2543 bytes images_v1/bouton_ouvert.svg | 20 + images_v1/condensateur.png | Bin 0 -> 523 bytes images_v1/condensateur.svg | 20 + images_v1/contact_basculeur_droite.png | Bin 0 -> 1431 bytes images_v1/contact_basculeur_droite.svg | 21 + images_v1/contact_basculeur_gauche.png | Bin 0 -> 1549 bytes images_v1/contact_basculeur_gauche.svg | 21 + images_v1/contact_double_repos.png | Bin 0 -> 1041 bytes images_v1/contact_double_repos.svg | 21 + images_v1/contact_double_travail.png | Bin 0 -> 1014 bytes images_v1/contact_double_travail.svg | 21 + images_v1/diode_dg.png | Bin 0 -> 713 bytes images_v1/diode_dg.svg | 22 + images_v1/diode_gd.png | Bin 0 -> 782 bytes images_v1/diode_gd.svg | 22 + images_v1/lampe.png | Bin 0 -> 1821 bytes images_v1/lampe.svg | 22 + images_v1/levier_ferme.png | Bin 0 -> 2369 bytes images_v1/levier_ferme.svg | 100 ++++ images_v1/levier_ouvert.png | Bin 0 -> 2902 bytes images_v1/levier_ouvert.svg | 106 ++++ images_v1/mirror_bouton_ferme.png | Bin 0 -> 1823 bytes images_v1/mirror_bouton_ouvert.png | Bin 0 -> 2117 bytes images_v1/mirror_contact_double_repos.png | Bin 0 -> 684 bytes images_v1/mirror_contact_double_travail.png | Bin 0 -> 610 bytes images_v1/mirror_moins.png | Bin 0 -> 316 bytes images_v1/mirror_plus.png | Bin 0 -> 1890 bytes images_v1/mirror_pulse.png | Bin 0 -> 1754 bytes images_v1/mirror_pulse.svg | 18 + images_v1/mirror_relais_cote.png | Bin 0 -> 1572 bytes images_v1/mirror_repos_ferme.png | Bin 0 -> 645 bytes images_v1/mirror_repos_ouvert.png | Bin 0 -> 431 bytes images_v1/mirror_travail_ferme.png | Bin 0 -> 508 bytes images_v1/mirror_travail_ouvert.png | Bin 0 -> 714 bytes images_v1/moins.png | Bin 0 -> 661 bytes images_v1/moins.svg | 15 + images_v1/noeud.png | Bin 0 -> 594 bytes images_v1/noeud.svg | 12 + images_v1/plus.png | Bin 0 -> 2301 bytes images_v1/plus.svg | 15 + images_v1/pulse.png | Bin 0 -> 1759 bytes images_v1/pulse.svg | 18 + images_v1/relais.png | Bin 0 -> 1411 bytes images_v1/relais.svg | 22 + images_v1/relais_basculeur.png | Bin 0 -> 3379 bytes images_v1/relais_basculeur.svg | 46 ++ images_v1/relais_cote.png | Bin 0 -> 1644 bytes images_v1/relais_cote.svg | 107 ++++ images_v1/repos_ferme.png | Bin 0 -> 1070 bytes images_v1/repos_ferme.svg | 23 + images_v1/repos_ouvert.png | Bin 0 -> 829 bytes images_v1/repos_ouvert.svg | 23 + images_v1/resistance.png | Bin 0 -> 561 bytes images_v1/resistance.svg | 19 + images_v1/tempo_ferme.png | Bin 0 -> 1533 bytes images_v1/tempo_ferme.svg | 25 + images_v1/tempo_ouvert.png | Bin 0 -> 1745 bytes images_v1/tempo_ouvert.svg | 25 + images_v1/travail_ferme.png | Bin 0 -> 857 bytes images_v1/travail_ferme.svg | 17 + images_v1/travail_ouvert.png | Bin 0 -> 1088 bytes images_v1/travail_ouvert.svg | 17 + modele/__pycache__/cocosim.cpython-312.pyc | Bin 0 -> 2799 bytes modele/__pycache__/composants.cpython-312.pyc | Bin 0 -> 14395 bytes modele/__pycache__/donnees.cpython-312.pyc | Bin 0 -> 18209 bytes modele/__pycache__/elements.cpython-312.pyc | Bin 0 -> 27389 bytes modele/__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 1057 bytes modele/__pycache__/graphe.cpython-312.pyc | Bin 0 -> 11726 bytes modele/__pycache__/matrice.cpython-312.pyc | Bin 0 -> 3915 bytes modele/cocosim.py | 52 ++ modele/composants.py | 264 +++++++++ modele/config.json | 28 + modele/donnees.py | 356 ++++++++++++ modele/elements.py | 514 ++++++++++++++++++ modele/exceptions.py | 22 + modele/graphe.py | 171 ++++++ modele/matrice.py | 57 ++ requirements.txt | 3 + run.py | 6 + schemas_v1/basculeur.ccs | 1 + schemas_v1/condensateur.ccs | 104 ++++ schemas_v1/contact_double.ccs | 87 +++ schemas_v1/contact_double_180.ccs | 73 +++ schemas_v1/diodes.ccs | 68 +++ schemas_v1/errors/error.ccs | 70 +++ schemas_v1/errors/error_id.ccs | 72 +++ schemas_v1/errors/error_short_cc.ccs | 20 + schemas_v1/errors/no_pot.ccs | 24 + schemas_v1/errors/one_pot.ccs | 26 + schemas_v1/pulse.ccs | 26 + schemas_v1/relais_cote.ccs | 75 +++ schemas_v1/schema_s4.ccs | 73 +++ schemas_v1/simple.ccs | 71 +++ 112 files changed, 3678 insertions(+) create mode 100644 api_server/__pycache__/__init__.cpython-312.pyc create mode 100644 api_server/__pycache__/app.cpython-312.pyc create mode 100644 api_server/__pycache__/state.cpython-312.pyc create mode 100644 api_server/app.py create mode 100644 api_server/state.py create mode 100644 api_server/test_client.py create mode 100644 api_worker/__init__.py create mode 100644 api_worker/__pycache__/__init__.cpython-312.pyc delete mode 100644 app/__init__.py delete mode 100644 app/models.py delete mode 100644 app/routes.py create mode 100644 cocosim.log create mode 100644 images_v1/CoCoSIM_icon.png create mode 100644 images_v1/CoCoSIM_icon.svg create mode 100644 images_v1/CoCoSIM_logo_01.png create mode 100644 images_v1/CoCoSIM_logo_01.svg create mode 100644 images_v1/bouton_ferme.png create mode 100644 images_v1/bouton_ferme.svg create mode 100644 images_v1/bouton_ouvert.png create mode 100644 images_v1/bouton_ouvert.svg create mode 100644 images_v1/condensateur.png create mode 100644 images_v1/condensateur.svg create mode 100644 images_v1/contact_basculeur_droite.png create mode 100644 images_v1/contact_basculeur_droite.svg create mode 100644 images_v1/contact_basculeur_gauche.png create mode 100644 images_v1/contact_basculeur_gauche.svg create mode 100644 images_v1/contact_double_repos.png create mode 100644 images_v1/contact_double_repos.svg create mode 100644 images_v1/contact_double_travail.png create mode 100644 images_v1/contact_double_travail.svg create mode 100644 images_v1/diode_dg.png create mode 100644 images_v1/diode_dg.svg create mode 100644 images_v1/diode_gd.png create mode 100644 images_v1/diode_gd.svg create mode 100644 images_v1/lampe.png create mode 100644 images_v1/lampe.svg create mode 100644 images_v1/levier_ferme.png create mode 100644 images_v1/levier_ferme.svg create mode 100644 images_v1/levier_ouvert.png create mode 100644 images_v1/levier_ouvert.svg create mode 100644 images_v1/mirror_bouton_ferme.png create mode 100644 images_v1/mirror_bouton_ouvert.png create mode 100644 images_v1/mirror_contact_double_repos.png create mode 100644 images_v1/mirror_contact_double_travail.png create mode 100644 images_v1/mirror_moins.png create mode 100644 images_v1/mirror_plus.png create mode 100644 images_v1/mirror_pulse.png create mode 100644 images_v1/mirror_pulse.svg create mode 100644 images_v1/mirror_relais_cote.png create mode 100644 images_v1/mirror_repos_ferme.png create mode 100644 images_v1/mirror_repos_ouvert.png create mode 100644 images_v1/mirror_travail_ferme.png create mode 100644 images_v1/mirror_travail_ouvert.png create mode 100644 images_v1/moins.png create mode 100644 images_v1/moins.svg create mode 100644 images_v1/noeud.png create mode 100644 images_v1/noeud.svg create mode 100644 images_v1/plus.png create mode 100644 images_v1/plus.svg create mode 100644 images_v1/pulse.png create mode 100644 images_v1/pulse.svg create mode 100644 images_v1/relais.png create mode 100644 images_v1/relais.svg create mode 100644 images_v1/relais_basculeur.png create mode 100644 images_v1/relais_basculeur.svg create mode 100644 images_v1/relais_cote.png create mode 100644 images_v1/relais_cote.svg create mode 100644 images_v1/repos_ferme.png create mode 100644 images_v1/repos_ferme.svg create mode 100644 images_v1/repos_ouvert.png create mode 100644 images_v1/repos_ouvert.svg create mode 100644 images_v1/resistance.png create mode 100644 images_v1/resistance.svg create mode 100644 images_v1/tempo_ferme.png create mode 100644 images_v1/tempo_ferme.svg create mode 100644 images_v1/tempo_ouvert.png create mode 100644 images_v1/tempo_ouvert.svg create mode 100644 images_v1/travail_ferme.png create mode 100644 images_v1/travail_ferme.svg create mode 100644 images_v1/travail_ouvert.png create mode 100644 images_v1/travail_ouvert.svg create mode 100644 modele/__pycache__/cocosim.cpython-312.pyc create mode 100644 modele/__pycache__/composants.cpython-312.pyc create mode 100644 modele/__pycache__/donnees.cpython-312.pyc create mode 100644 modele/__pycache__/elements.cpython-312.pyc create mode 100644 modele/__pycache__/exceptions.cpython-312.pyc create mode 100644 modele/__pycache__/graphe.cpython-312.pyc create mode 100644 modele/__pycache__/matrice.cpython-312.pyc create mode 100644 modele/cocosim.py create mode 100644 modele/composants.py create mode 100644 modele/config.json create mode 100644 modele/donnees.py create mode 100644 modele/elements.py create mode 100644 modele/exceptions.py create mode 100644 modele/graphe.py create mode 100644 modele/matrice.py create mode 100644 schemas_v1/basculeur.ccs create mode 100644 schemas_v1/condensateur.ccs create mode 100644 schemas_v1/contact_double.ccs create mode 100644 schemas_v1/contact_double_180.ccs create mode 100644 schemas_v1/diodes.ccs create mode 100644 schemas_v1/errors/error.ccs create mode 100644 schemas_v1/errors/error_id.ccs create mode 100644 schemas_v1/errors/error_short_cc.ccs create mode 100644 schemas_v1/errors/no_pot.ccs create mode 100644 schemas_v1/errors/one_pot.ccs create mode 100644 schemas_v1/pulse.ccs create mode 100644 schemas_v1/relais_cote.ccs create mode 100644 schemas_v1/schema_s4.ccs create mode 100644 schemas_v1/simple.ccs diff --git a/api_server/__pycache__/__init__.cpython-312.pyc b/api_server/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..03083f3d3d3ca84c1e3cbaa6adbd30a4583ba897 GIT binary patch literal 169 zcmX@j%ge<81T_rzQbF`%5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!@^H3_2`x@7DvmKQ zGB7qWuyl=a$uG~#$xlovj!DlfDM?L?NzPBsFV4)3FQ_cZ$j^&OEXa%p>L^PsiiwZU p%*!l^kJl@x{Ka9Do1apelWJGQ3N)Azh>JmtkIamWj77{q7696SD+d4o literal 0 HcmV?d00001 diff --git a/api_server/__pycache__/app.cpython-312.pyc b/api_server/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d83b0ab37a2af9d29ff0986f4781443530f42a0 GIT binary patch literal 10579 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 literal 0 HcmV?d00001 diff --git a/api_server/app.py b/api_server/app.py new file mode 100644 index 0000000..f5cea62 --- /dev/null +++ b/api_server/app.py @@ -0,0 +1,218 @@ +""" +Lancer avec python -m flask --debug --app server\\__init__.py run +""" +import logging +import sys +import time + +from flask import Flask, request, session +import multiprocessing as mp +from api_worker.__init__ import run_instance +import uuid +from flask_cors import CORS + +app = Flask("COCOSIM") +CORS(app, supports_credentials=True) +app.secret_key = bytes.fromhex('192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf') + + +class ProcessBase(object): + SESSION_MAX_AGE = 60 * 5 + + def __init__(self): + self._cmd_q = {} + self._state_q = {} + self._process = {} + self._last = {} + + def known(self): + return 'id' in session and session['id'] in self._cmd_q + + def update(self): + self._last[session['id']] = time.time() + + def cmd_q(self): + self.update() + return self._cmd_q[session['id']] + + def state_q(self): + self.update() + return self._state_q[session['id']] + + def init_q(self): + self.update() + self._state_q[session['id']] = mp.Queue() + self._cmd_q[session['id']] = mp.Queue() + + def init_process(self, p): + self.update() + self.cleanup() + self._process[session['id']] = p + + def process(self): + return self._process[session['id']] + + def purge(self, k=None): + if k is None: + k = session['id'] + + del self._cmd_q[k] + del self._state_q[k] + del self._process[k] + del self._last[k] + + def quit(self): + self.purge() + self.cleanup() + + def cleanup(self): + ctime = time.time() + to_purge = [] + + for k, v in self._last.items(): + if ctime - v > self.SESSION_MAX_AGE: + to_purge.append(k) + + for k in to_purge: + logging.info(f"Purging {k}") + self.purge(k) + + def __str__(self): + return str(list(self._process.keys())) + + def __len__(self): + return len(self._process.keys()) + + +PROCESS_BASE = ProcessBase() + + +@app.route('/') +def hello(): + PROCESS_BASE.cleanup() + return f"Hello sailor !\nProcess base : {str(PROCESS_BASE)}" + + +@app.route('/init') +def init(): + session['id'] = uuid.uuid4().int + PROCESS_BASE.init_q() + PROCESS_BASE.init_process(mp.Process(target=run_instance, args=(session['id'], PROCESS_BASE.cmd_q(), PROCESS_BASE.state_q()))) + PROCESS_BASE.process().start() + return "OK" + + +@app.route('/start') +def start(): + if not PROCESS_BASE.known(): + return "Unknown", 401 + PROCESS_BASE.cmd_q().put({'cmd': "start"}) + return "OK" + + +@app.route('/stop') +def stop(): + if not PROCESS_BASE.known(): + return "Unknown", 401 + + PROCESS_BASE.cmd_q().put({'cmd': "stop"}) + return "OK" + + +@app.route('/state') +def state(): + if not PROCESS_BASE.known(): + return "Unknown", 401 + + PROCESS_BASE.cmd_q().put({'cmd': "state"}) + data = PROCESS_BASE.state_q().get() + return data + + +@app.route('/quit') +def quit(): + if not PROCESS_BASE.known(): + PROCESS_BASE.cleanup() + return "Unknown", 401 + + PROCESS_BASE.cmd_q().put({'cmd': "quit"}) + PROCESS_BASE.process().join() + PROCESS_BASE.quit() + del session['id'] + logging.info("Purge effectuée") + return "OK" + + +@app.route('/load', methods=['POST']) +def load(): + if not PROCESS_BASE.known(): + return "Unknown", 401 + + try: + data = request.json + PROCESS_BASE.cmd_q().put({'cmd': "load", "args": data}) + except Exception: + logging.exception("ERROR") + return "Error", 418 + + if PROCESS_BASE.state_q().get() == "OK": + return "OK" + else: + return "Error in graph", 418 + + +@app.route('/push/') +def push(obj): + """ + Push button + """ + if not PROCESS_BASE.known(): + return "Unknown", 401 + + PROCESS_BASE.cmd_q().put({'cmd': "push", "args": obj}) + return "OK" + + +@app.route('/release/') +def release(obj): + """ + Release button + """ + if not PROCESS_BASE.known(): + return "Unknown", 401 + + PROCESS_BASE.cmd_q().put({'cmd': "release", "args": obj}) + return "OK" + + +def just_run(): + """ + Pour lancer avec gunicorn + """ + mp.set_start_method('spawn') + app.run() # Ne pas mettre debug en mode multiprocess + + +def main(argv): + host = '127.0.0.1' + ssl_context = None + for arg in argv[1:]: + if arg == '-remote': + host = '0.0.0.0' + elif arg == '-secure-cookie': + app.config.update(SESSION_COOKIE_SAMESITE="None", SESSION_COOKIE_SECURE="True") + elif arg == '-ssl': + ssl_context = 'adhoc' + elif arg == '-h': + print(""" +Options : + -remote : bind on 0.0.0.0 instead of 127.0.0.1 + -secure-cookie : send secure cookie (for browser UI to be happy) + -ssl : enable https with adhoc certificate +""") + sys.exit(0) + else: + print(f"Unknown argument : {arg}") + sys.exit(-1) + mp.set_start_method('spawn') + app.run(debug=False, host=host, port=5555, ssl_context=ssl_context) # Ne pas mettre debug en mode multiprocess diff --git a/api_server/state.py b/api_server/state.py new file mode 100644 index 0000000..9cba09c --- /dev/null +++ b/api_server/state.py @@ -0,0 +1,41 @@ +import json + + +class State(object): + IGNORE = frozenset(['Coude', 'Noeud', 'P24', 'P0', 'Pulse']) + + def __init__(self, cocosim_server): + self.cocosim_server = cocosim_server + self.conf = self.cocosim_server.conf["ui"] + self.composants = {} + self._exception = None + + def load_conf(self, schema_d): + # Chargement des blocs + for nom, valeur in schema_d['blocs'].items(): + if valeur['type'] not in self.IGNORE: + self.composants[nom] = None + + def to_json(self): + if self._exception: + return json.dumps({'exn': self._exception}) + else: + return json.dumps(self.composants) + + def __iter__(self): + return self.conf.__iter__ + + def items(self): + return self.composants.items() + + def keys(self): + return self.composants.keys() + + def update(self, nom, valeur): + self.composants[nom] = valeur + + def exception(self, e): + self._exception = e + + def reset_exception(self): + self._exception = None \ No newline at end of file diff --git a/api_server/test_client.py b/api_server/test_client.py new file mode 100644 index 0000000..fe72172 --- /dev/null +++ b/api_server/test_client.py @@ -0,0 +1,19 @@ +import asyncio + + +async def tcp_client(): + reader, writer = await asyncio.open_connection( + '127.0.0.1', 8888) + + while not writer.is_closing(): + message = input("> ") + print(f'Send: {message!r}') + writer.write(message.encode()) + await writer.drain() + if message == "state": + data = await reader.read(1000) + else: + data = await reader.read(100) + print(f'Received: {data.decode()!r}') + +asyncio.run(tcp_client()) \ No newline at end of file diff --git a/api_worker/__init__.py b/api_worker/__init__.py new file mode 100644 index 0000000..4668ecb --- /dev/null +++ b/api_worker/__init__.py @@ -0,0 +1,135 @@ +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.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 == "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 True: + self.state.reset_exception() + self.cycle() + await asyncio.sleep(self.dt) + except: + logging.exception("Exception occured in 'cycle'") + + 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()) diff --git a/api_worker/__pycache__/__init__.cpython-312.pyc b/api_worker/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f974cef150b32f7df4c338a3de7e3da4c284b36 GIT binary patch literal 9642 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 F{{oM5bA12+ literal 0 HcmV?d00001 diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/models.py b/app/models.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/routes.py b/app/routes.py deleted file mode 100644 index e69de29..0000000 diff --git a/cocosim.log b/cocosim.log new file mode 100644 index 0000000..32f7cbb --- /dev/null +++ b/cocosim.log @@ -0,0 +1,19 @@ +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 diff --git a/images_v1/CoCoSIM_icon.png b/images_v1/CoCoSIM_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b7210a62c63d31d50c73fa4bce14fe44391f8cb8 GIT binary patch literal 18311 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 + + + + + + + + + + + + + + + + + diff --git a/images_v1/CoCoSIM_logo_01.png b/images_v1/CoCoSIM_logo_01.png new file mode 100644 index 0000000000000000000000000000000000000000..084f46b3cfe5dbc794633b16a245ab603a48808c GIT binary patch literal 31387 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 POQSszmlMku)${&84*G%1 literal 0 HcmV?d00001 diff --git a/images_v1/CoCoSIM_logo_01.svg b/images_v1/CoCoSIM_logo_01.svg new file mode 100644 index 0000000..8846111 --- /dev/null +++ b/images_v1/CoCoSIM_logo_01.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/bouton_ferme.png b/images_v1/bouton_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..79a20c5507291a28f14ec16a17c527622330769d GIT binary patch literal 2188 zcmb`H`#;ltAIHBl)SQwWa<~#=PLuPgOmkW&A*{=xiH!}H)6m4wjmRNop#x1sg(!0j z#f%)TLWGNK+Ju^89%Q;Db^ihP{dqiIpV#y8e!Sklz2EQat}aM%5d{$d0K^?n z+qv&K=9l&h@BNXi0uKNXl)&5Cx`x^!Z6m@WqR&TO3dAC@;n-+=pgYnA0L*i9J^gS> zp3?C9tyG<3?^4GqEAu6ICbt{H+(*);7I|3eA0KteVGW3z{Yx_?cnu@=?jyVwTpA(S z^<esY8$yFv}5q&kNM)&qy+|Hg&}&g zMc1d0p)R1SPz(D!%A&rRr_(KCx=6#~q+yuOjRNfg4Ui(6_Ihf0^=L0+VzYURAIzzB zMS?PC(kE-o2UJ;DfG5*a@0TKo*y)2z1aKkr6JfCAl#YMb7I`v_~(H%^*7d8Va0Xy0#Iea}U0v?FyVxygPels=t$E|02Dl4gQi zHjA{Q3qNH@QatBA#$?v%;i)~6d~7QovaSaBwY8^5i>$-xfu0HNN{ca1tIS3^bsmr1 z4VGl45@Wkg4)m_r?KT>qi$!9S+>6EL4;%qzS=zAYSGLrSJU@%q&K%4|;Y{Cr%jCAq z%LWOMR$#$+%ZXu&il8in?n*ZM+d;3#a60PggCd)sXjrp!ue#N>i^XCwefqJx-?!sX zC3p9;@-5^<6>`*%do`}x^d+Mjp^qfdO)<%NtdD(Xr^y2#%4>?kXIHW^dD$0Em${SM zf2u1jeo02(|B&6yqX+PbKK|v8MHCis4;L$N54j&^mzXrIA3UJhBZSw-Ssc-~spPAz z4Oh`tah_`JVoCA1>eyjOP^8+Jf#Y$<{8X-zDtS&{UZwnKKD7TlCI>TO=_FzDrcjlD z*=QXZiwCK>Q_Qm4vllNTdU?T^JF^W#Jx&xe$;qL~q0oVXiSUb-q;OPrn}ZjnZJh8W z=2);o2rQ;=YOExBh)+W=Ogu*~n0brw_9cOnIn!RvCLH5Gy+lYaBYfz{4J#K6yaMJK zc8OYE_PdGKwt(^=Kx!qn?GG0A*`3?!x6Tjk-^y3kNMkd zTTRtn?Io;-ofHa4L?;@zXkdtbA<`{&pJB6Wt^ zvSOb*OEoz!7u%FZDkU0=aG!za35Mph2uI#ex#{={EP*0yz6(9E<=td)V73N4yn`Dw zO$laqtO7OgO5&zF5lRnW3YdRL?e0RIQy8jN=6v@dhO0Ax$;6I}{GFdyNE_fWCeTvK z2lLg5qCJ7*gL?-e412*b=cSs1zTyTtLbUn+TYHFG!msm&Nq=gf*=~QWUO@qg!#RS#|#*w9%31>@uJ{&^PcO@ zf>DfXBsBW^uJ9{M72AO3#m}QB_#PWu`ek~I>v@n@V?^t)`vn=>?Cq5}gTjS_POH@i(Q-qqW=`M#GKW%G^h zWx{}tUq9KuW`Oy<#3PAG%5T$|k%=Q43_9bG8)KlijR4B(q~B<>*HYd^OICiX*krZp2*u!G%S6foQa1yL<$Tf z9>GVM`#pnKGm5eT0}wPChJ#Ew#45u<4dW$rriWDW(udNxdYzYLUnxD43$)63^3w2y zjnO(SLGNM~3er6_l}9!}x63R$$PSg0EK_Z1m%&FSeUjrW*0-X6daI7l-@dv~EHIN; zL{$5x(M>vNA#N@YHyWQ?%9s~Ad{kcOv~E>)1BM&_HhADhneanOm~bH{G)Y5Ix~RwY zQ!}XdGOCv2Tn|n&-H;w*cU1?_yVL + + + + + + + + + + + + + + + + + diff --git a/images_v1/bouton_ouvert.png b/images_v1/bouton_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..2b605086dff58ad16c9b623faea83a48a9779408 GIT binary patch literal 2543 zcmcIk`8U)H8~+ZnjIrEoVIm`0vXz~1DT#Y6*R@n)5XMA|vBa1$x|7SzRw^PJD~({s-AhqI%t2viOV0Dy?y zg>xi?aB{0AMwe&7lKe4^;HXPtx3+MW#y3B&%1@x2;g8xR_RMPGHXwFUs=v@|!b zAh?^P#iM%i$>Y7Gq2l6uqFjUf)gdkew?;YK0P^*5&CHN$t2^C`pYqTr^rrTnqtz`W zt;8v%tV|Z@Nl{h0R<@L)^{m?Y86Qb)yMNdA>0dHJ3-x;B#>~3lX8QQf?BkXAxrvD7 z3E?|+nx0t`Dmps&5#QQ;3T_`GIc1P_ z36f0Sy3L0g*sRGU@qD-G@yO&#Z8W(<91N&O3#};wUX4wOSm>HX`&GBNCO9YZ#Y>}s z){`YeIVf=^DJF_?rl)iH++NKoH{V%C2L2k-Tu=v=ZvZ#KcK#cOxDLWmzd!%hRB6C_-R;lpVJ=N}C{Zsu1OzlMt zy0Q=v{_FJvL$MHLmwcm?rWDQ%t4=P;KbuwE*I}P;BtFtN(ihzGfD!6#N(l8xX*}WT{n01 zwx`OzqB*sV>i?4yN9y-mLcTh< zXrnTTG#Rf({;sMp|1v^(g3ODE#n5u{@T8^d`7C}_eDTzZ9YCj7+il&` zQ-09O(;CvSnbrceg$7O|e4tpg=3&qbP!)IDm>Oos-Ip1QEeeRp=QrL{HQT!U);1os>BF)Tpgw#Jcy8hi*|ty4uHmi7XD{%g(y z07+`yG1N~kX4)}fN-^x?K^H0LRfcL-td-O^&^v?qk!d$o%0RX}h-w6S7A0GjL zLt=L4tXyLtOF4GQa5s2TVLC#sQ$$BQQ%%nK6jVDrg>54#BhF_qZzHaPbHyl`1h39p zUlF}6toEBA?r?{f;N3bzvfuIBO4=rMD%woOXM}k`R0Hm11FDm|KRM;roQreYXvTqC z4S@sC&cWJ${2$PI1O}%XY$~)xVgG>g-nNtty;(9Tzg^<#ec_U9oZE0Q){uX5?ztWd zZd^&H+;>|$`e3lC5U+dG#n6Qa>T?mTL<8-d-Xo5 z+3A7btclcm@H1@wFaeegI^Fb~lpTT1g2j7w@;Ytd&a&jC$(~MWOwkS)sfKNtVM{+j znO$!Z3yX?<_{E4LpE;_O+}Zd2>R!=>Wu;YQ0~h9n!)033)3qHWd82QC%HouiE^US z%t*nS$*b?L91^2+v5tR?+(FCdQ*d=Zq$j@ACE-O%+>XL+KH=q+W{E_Mltk4INRw6= z-vG~Z@)8!N!4%`UlI42I!i@UmI|xulqUuHItG$)nmJ60#>5-}3mW=sFrNnY}HuCyX z=^@2gkUnXliv%GKgBf!~;XcZe4=((s2Lm9kj2L$7eRJ6@M{j>OW16 zWAUt-PKnN)vMo^WUqTGOS#y1@M}L!rB7WqGR-DHbEpwLR#*GGzzQ(V{IXv0{FO4>e z;MYfKp#C5ZZk1w5jU;6)#4M*KOgNT~a#J2*mb{}vvQ5WUiI9v|kt#`P`!lpO3+IN9 z>YEulA2!CK{9)Lc0?zXne#c>^z9UoV2;0oUo(~Vo$`g;MVg@~*))C1aUIiJ*r@hu4 zUoB~5*_V1K*vSSa^AVWm^bYLRiMR{ahb*k|XiW%dM=?l!JH~iE#*cZJ(B-*TwSVf} z+;WGJn{!e|*2{cN-ZA$2UcEPU#}v~)F?@x`g_GKfe3FI;fim_{B5#PE)JY%Ge6mYZAS+vsIwSf|lO(J{MJ-jfQu_Vb3;dG&?H&FQGQ z>|PD}$L4XNnf(A8x`g+r&?D9xC38+?`kW)VB4a7xi$?3+tI7&ai>EOL9Rez{0;c?xW)ReFG}=Y%Vo~5&RxPR9BrQ*%fy>?gz63VqSY1mG+l-PsQGOA=l-xW)$!8 zT6vgii1`Z%{o|DUYFXvcRsN8~NWR0fr?n^9z2x}KoF{bo?wT9&7p{#iAv{ls^ZuW( b-rCwSo;!a<8b5aI``@&)aXeRH?ep8;NouLk literal 0 HcmV?d00001 diff --git a/images_v1/bouton_ouvert.svg b/images_v1/bouton_ouvert.svg new file mode 100644 index 0000000..921109c --- /dev/null +++ b/images_v1/bouton_ouvert.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/condensateur.png b/images_v1/condensateur.png new file mode 100644 index 0000000000000000000000000000000000000000..ba1cfa2c6a262b3985e3ba9ee7b729d39c698489 GIT binary patch literal 523 zcmeAS@N?(olHy`uVBq!ia0vp^DImQL70(Y)*K0-h6SE3jv*CsZ}0ee9dQtGefZ{BzCbG!&@*Jlv8MA^r#C(gnE-uRSQ;agfrD*oG*xAR; z{B!NLRpRX}l%RQ=RmQuiY; P0vSAA{an^LB{Ts5ke%nU literal 0 HcmV?d00001 diff --git a/images_v1/condensateur.svg b/images_v1/condensateur.svg new file mode 100644 index 0000000..d2c0a8a --- /dev/null +++ b/images_v1/condensateur.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/contact_basculeur_droite.png b/images_v1/contact_basculeur_droite.png new file mode 100644 index 0000000000000000000000000000000000000000..f79c4194ea76315842e148bdd914bcabed352d28 GIT binary patch literal 1431 zcmeAS@N?(olHy`uVBq!ia0vp^0YIF>!3HD+e{B~7QjEnx?oJHr&dIz4aw<|IJkxxA z8MJ_G4h9xRDF#-M5+Jr?l!mk27&RD}!QxB|4DFc=EKoImKpF%*fEc6)LNhO5gsKLL zEntGH4p_hpXQzO)g`G>Y15%s?9+AZi4BWyX%*Zfnjsyb(%MMQ$$B+ufw{x;Pd;>*} zumApgZg@+Fhl=N$kYqXJYqnes8(j`njK0Y7$FNgP;ME+W`&^ji+AU_x_O+>m$Q)#<{1(y?U+lyw)Y0F$Xmm|Fzsd z{$huq#Nr2nD)t7Zg(?Lsg+<>l%DtcQx>mw|(&e?Mdt+AoxOS{%tKRJ*#uveQ(c*t! z{?D31EpZVGu<~&gD z$jN%wwzZ$vq>)aAoc3vi;wuRDaEh zo#*iM_IKSs+upT*ur8X`ycYqlni+GwYdM@(q(Agb|7v|Wr$)V2I-k;WcJdzqt@8WqKi(!6<#-Cr;EO)A`0U;EM;;G!9;pC>qFJ_h zFTeCEpjRZ{uS{V`DCan^Qu0Z)>@C5oudh9|d-iEn@rl*qi?^M2`mw9@W~XHwv#$`x zha+|kr)D2_{~;^%DaX<`LCOu7#Pt>n`!8TQEqXy~#lPbMEEX(TLXHWx&wj=$e_h92 z<7C5S*;HBwTw_vV^AeGdA^v~c|wuc{59pdymN)78&qol`;+ E0OibGH2?qr literal 0 HcmV?d00001 diff --git a/images_v1/contact_basculeur_droite.svg b/images_v1/contact_basculeur_droite.svg new file mode 100644 index 0000000..119411f --- /dev/null +++ b/images_v1/contact_basculeur_droite.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/contact_basculeur_gauche.png b/images_v1/contact_basculeur_gauche.png new file mode 100644 index 0000000000000000000000000000000000000000..f0340e5593a73e6f5bbaea2155fd910a65d03c6e GIT binary patch literal 1549 zcmaJ>c~sI_6#jvdfSMSkqzd~_-#y(vQV3y>xa5e)ks*gcw$@D^mZxVk|@OxE~TG|sY~S_ zPvz7T2O&Yy=`tqX_}VUteYuolUCYnCd`(anp$3OVU=&(@(HnYFRN?2UzeWo`vu&9L z(Z#H&4pB#YoA=81+TtrtnNR`e|8^IgOP%oR#@BNsd{2+1I8Nux>bkqQ-gI~ouN$2n zk%5f~7WqJ`fdiO+Yq`sU*M!szHdNu>b^Op|B`1~a|M-ygQuouHAA93xc9-#T&#UP7 z&Te+kzv9Jt02v($NKJeQiaIz*>#heQd_$sHkWcTfZL+WgOLJekPGa5S;;*D7>D*DP zX4Z9?c7)1@?oIQiLt}P2W*b}H^C7$pzlzi1k9|R&Qg#}2eh#90yhtvkjR?tyY7bX^ z+ovc33E0r;4MJN=5^HfjLD`=fV|-?En2;)N;6)n&3GsK; zm{{{$7XT32Gn7+xb>7f$7NP)FZM>PT`h5R?MnoeA z@y9G$kBA+3vh#w94QIT}b~!?ziDSF%W=>9bf}!#}jRAAZ16+B;RNP!6 zuhw(Y)@?vIQ`2OxCSIWfQsVT*ar*~r5MMrm^VeM#N~D6dxTeUqFxzkQ{86E?a|^IX|e3&Lh?Bfg%@-N*&WJH2Gp5R7sm52z~G%eSb!UMHehm ze1V6?wPzy<+)v{QiQN{baqbNhn*=2j`R>=(IUEw$VgxlVqV zXdKq+ehp4Ry1pU}mU&b598S! z_Uuvd*2md`J>wPMfm%@`QWm9OGFd zA}OSgF^}^5Ek(#(FSmyn8Eaxi*Ce6g5fJTr_am@igk09m&!aStykE_*j!r49v~8&O zrUWM-LQRhRNr|nD;lrl1gQ(_nG)uK8_qWX|$(}9M^)YWXaUe{plcPU#+yjOf=xO0I z;@|!<+lmXXmBZq3tvAYf`?g}oX2~hE$Bwh0j=sO^l!19d{kIzEM + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/contact_double_repos.png b/images_v1/contact_double_repos.png new file mode 100644 index 0000000000000000000000000000000000000000..2b9942eb480b317953172e74f1fa75e7417d8126 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^0YIF>!3HD+e{B~7QjEnx?oJHr&dIz4aw<|IJkxxA z8MJ_G4h9xRDF#-M5+Jr?l!mk27&RD}!QxB|4DFc=EKoImKpF%*fEc6)LNhO5gsKLL zEntGH4p_hpXQzO)g`G>Y15%s?9+AZi4BWyX%*Zfnjsyb(vyrEZV@L(#+gm5Qt~kgX z|5)hm8Ytpe$S5A;x38h%Bj=X|aWxztP2~2Ras0??Qyn%xdES9imkWYN1q&s=fBi1Z z-4!r3#j4YGZq5G>%C;**tbY0g-PNqh>T+UWWD#&6l6VpJpsB1rymIlLfODE5zKxQ( z->oO!HvP?CwOQEeH$SIMvz|uYaxa#=mAa*0TT4OAXII5G1bJ@{mTa6FwcqfvSXlVh z_P1<1O&%QYGG3px{>8obY0T%s<|KtyyMF&?{yX^E{B0{go}YiNhU@wcwsq+Y%d@|v zPOfKqzID&~AD&12RqBiuLY=#Sm2uf`DTTD5L?eW=nQazyTwjs0xQB+oYg&RY8Rlg}07 zr*TT=Ti*3dT2sjU?m}SeYR$NJesZ~=r{3S%ZMl@=spk~`nRlzL-uFG)xFw?dKl6pj z+kQ`x(AaY?%4X5De{ompdW04n%6|M;;-Rh0-Ez%~?~7(Py#B)0KBeLD(tO8$|JPIX zUQI2_TEZZ5pvHPz?7Vlo7yVdQxiTg+ua9X*q%3ogjoaJnzuqLQ-WK?Jx|Llhli!{% zcb-P9<|$a-r^CjTvD?b(QU0y>%BpOiUbCM{PmK)Yd9m@;qM|6nYhp{gtJcpI%eVah zH{xS>Tj#1D+KucdvvuY69`7tLJ(_Snx~6~Qdo8vv3OlcS`til3vyti6?WON>gtqfH z7+d{#tg8MYG?#yBgYdMt?@O25SD5w3)$sf4HRV~>t1D`j7%}~^(q;}W|GLNQ%jN{V zyyZqr`%G;&MudgFO|7lIpLSqXe0=EE?{X{Ou<%+$Z*%PZ*7fdh{ + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/contact_double_travail.png b/images_v1/contact_double_travail.png new file mode 100644 index 0000000000000000000000000000000000000000..246661dc239090f0a00526baed672a12649ff879 GIT binary patch literal 1014 zcmeAS@N?(olHy`uVBq!ia0vp^0YIF>!3HD+e{B~7QjEnx?oJHr&dIz4aw<|IJkxxA z8MJ_G4h9xRDF#-M5+Jr?l!mk27&RD}!QxB|4DFc=EKoImKpF%*fEc6)LNhO5gsKLL zEntGH4p_hpXQzO)g`G>Y15%s?9+AZi4BWyX%*Zfnjsyb(v$&^=V@L(#+gqozL>xtq zeN1`8s;~WCFQkU);L-{10o!-YEDwn3uvXk{(PhV9f97yA z#8-6YOrJ^r#ASBv@+&R9-k)^o?#otIE+!6z1_mOD139d1QvX^XO@1`@QCrg`jSY+H zX3wm+R8g~jw{G?~X-S*rb((XQ_Xt+3iOKuwI{Wh!L#F(x+-vS!tMqbASny4`HOA!n zr;F>SM>E&0KC@@qdYOIOFSFHz%}mmbx2(xuKHbFj{^!_GnR7m0m*0}p*ryTmf9(Pl zrtZbRR&6Vv^eyP?W})>W>qYY?Rc+ZDemmYZ-;1H@(0S46>T`a|%f8=#t5JFb8~>N} z!t;{dW%udtoaMgCpKC{aa*T|t(UxQi&tB0m^=IWJ)fFrL?&i|(itmcD|2J4&2`hZ3xWMe4$*0%588@UZic?%F`etg4m*M1{=Ta_Alguxk z-)t4Xt84d-bF#NinSN#6aP-*{tJ1{1^}ZAB3bypP&UZP`zijqW2^HCu&sZzwPA|{Q ziw*O?Z~QFm;jy6427lkasCN7>x_^@5j`^93S1J?)zttD5oBf1epp6ThL=Jcyuw>k$;!CjXT@LtMbq?o z?)IlKU)#5D)zjaKp)-~;X0OlA`g!QW-%PpRyWDur1#2;_KK1+^^ZU>~<+&UmcBvg) i&_!%w1gi5<`M`hB_$1Q`wMuSK{_%A6b6Mw<&;$U4H-n-8 literal 0 HcmV?d00001 diff --git a/images_v1/contact_double_travail.svg b/images_v1/contact_double_travail.svg new file mode 100644 index 0000000..ca18dfc --- /dev/null +++ b/images_v1/contact_double_travail.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/diode_dg.png b/images_v1/diode_dg.png new file mode 100644 index 0000000000000000000000000000000000000000..0e2e8ec42f2b5747bc3b2ce1855b5d249f85c3d2 GIT binary patch literal 713 zcmeAS@N?(olHy`uVBq!ia0vp^DImQL70(Y)*J~22BtVq7srr_xVLvs=iUwwXiZF=&b8@`nL~`b zl?P{``b$M#i30I^5(UDZyx+{~7(VhSGKqiceKu*%?++jTH!wF&bNDb}nj60tJJ5Ut zh_BfT7j2E8@)=Y@;dZ+q%+g;B?-u%br z+}r1sr>dM6U8+3wpTyO;laeV4iwwny~sbMBMzCtoIi{roX#{r5@h>iy0y%sm=>vF@7k zyEshHz~RvBymoDUyO3?VcV1qKE^3e7VcX9 zLTCQ6{eIu?@Lu|$lRf*=Uz>~1_wOqBmE&DLWnIg4MLV&#>9$SJv_05gww(#w6ZHOw z*4gUF-l@~Bl~>n$7j4g<`C;0WXP+mqU7PYu_;A;?Y0r$mdTpEbY>jYw+)_*Z)1B#= z=VD3%7Mnc(mKU(vBz^z-kliNt`6E|^X6|zgU6Go(FF9g?`%7JC`#o_>uk-!=P&GZy z>dRs2r6n&f@aHc9hOhk|LGSs}zaI8RS($$+|JYr$Jl*TnCy$aB?_ZgVyZ;wFbN69- j5+foFFx=aI_@QW(s@9&R$pOG5$H3s}>gTe~DWM4fuW>|` literal 0 HcmV?d00001 diff --git a/images_v1/diode_dg.svg b/images_v1/diode_dg.svg new file mode 100644 index 0000000..12a7ff1 --- /dev/null +++ b/images_v1/diode_dg.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/diode_gd.png b/images_v1/diode_gd.png new file mode 100644 index 0000000000000000000000000000000000000000..96c0273174c1499ffed4aa1e72324e39f8cb7234 GIT binary patch literal 782 zcmeAS@N?(olHy`uVBq!ia0vp^DImQL70(Y)*J~22ByWHE{-7;ac}3`?Y-vRq+U|Hrdn{nlx2&rYAav2UKC`Ew8ViROLjcGZ*hBdd!UfySeP z6UUQ3H~)P6?%MSHrs>b3KVRHZBKJq(kLH)BUuuk=ABaDD{TcIToQMM~C7Nre#$jFT|>+?2|IL)%qgUuTyIp2Ncnj3;dNe=gW!<(Y<=Lrfxuy zy>3(Y-2y4*Q1*(?1u8CCQVnG219b`JY1VF?3smgBbK94zW|tN_$>(OjTz!0*d+WPI zZy*EcoOds4m#)9&-_K?11hjpxqK)DG+4p_y``>Ke_r|{8tyS*nrY~2mCYro`p8l-- za(wdX&Of_$fBmhjdEBDA_~q)~i!yGVuS+>)J$2v26X{)2k9qXUujH_-{asnL>x?_c z@mKo=E@#i!C4BtH`PM{>uz8B=#jhr0r?%C8)ti6o{_WVc0jGAasonDKIcNR<*W9Pe zqwO5;bIf;6ir6~;FGrZYBU_+f+Lq;imfVvTt!i2RFFMRW{KJ^H!U z+AP|Vy`pjnFan?M_On{-wAp2OV m|6aQUH4QN^e5fzl`G<8yvg-cdGbg + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/lampe.png b/images_v1/lampe.png new file mode 100644 index 0000000000000000000000000000000000000000..cef67ff9675a263bde5ce237d81f1840f1dd7217 GIT binary patch literal 1821 zcmaKtc{JPU8pnUco>7z%)z&(#j;)$j7-cTCL~LmgqPA8otx*IOw3wD^CWERqVrx|_ zwT$JW_9anT%P7V{kj9c`ZY@CwC2rh1r+?0S&iDO%-{*XvKcDBtBOR+JZZ!}vpP*uaztj9$vEa8fvKaKu-#KnWkNBJNAs!0H zgaZIr_E-WyUOof>L`-cg%$#uotND($t5%SHUmXdB5SP#Wo)vOn)JsBJXc<#UlPj~f z(nK4xl4N(f~E-*qZp zJx-TL;yN-YKiPamx$RONDM#{YL56z+jz*cg^Rrc#4$ud#Z1bM;=g%{UL?Z6iEmbcM zk1MK7iq!j@OxwMQaeQPXI9~hbPMIUbfy`SLixn6ddDY$9I}MFSzbY*)g@aj-W(e*Cv45hD|EbQP zC@CqidAzuXv9U@p{Y|G6%QtFnI->MAPkg_80h=8VaEN>N@9WM_PvdKAYVrcnxjER2 zMKQFPWo|&&#&0Pda<8}ZpNi@D#>N_Vc6RD&C~pdKkltj=$D$tU!O9Y?ChSJx?U)X? zLX0YhtxJfhSfFOmLCgWg#eXYPCFz5MgDnf|@1&%p<`ZY(@IyL~M$M)Rtq(waQmK*y zdwYA_&!5XBP44AH<8Y8CA8y-iq$WP2ow)mfR8WwTmX;PI8w^!%>1I9?TYI@M5-a~) zxVgRkjJKCpQ-$SneGf?YclUhp`x{cjpC`Z5ye}1Z3yjUQh@gTL457_i$e4hB7yt5J z(2VI;y-)JoNy0|L6w8f1#xhJ#fAk}qoD*Ix)<_}~7B8QnH$@?P%Ni8Ha8BoKl5++Xu@zMJ*A41l zFSe>n?(S{W(KHeRwEWR8qWvc@FYY1g;X~5Pz3-ysd!a4tk)8ttiA1vWKrCK=9;qdc zIY+3^E=lZJsC!)?s?}|;EyqGGyXkIVg}$37ZtQ4fM?q3@J_*n=AC4cOufUc#z`;qG zPfA0Dwl*u1i!(EMHv>u*Th%6pnIQSN-c!kX?N8hs5&FXGYis-T4F@Ne-zr%hzi5bm z3V4eU3kmt^jN+;AtPavNmh!o-3^JWO+I7vm^A(r;;Y}Y*ck4{zu8QZ$?;G_MO`H@98x9V-nb+}L^2qF8O|Ff>n7Tk2PrZ-5vYm{lQP`gsY0`5; z(9sm_YyPzeg_U0elTUfpg!Y9e1WpH$`v$C53LD1Cv`UsSY_ZvxofY;kWwi;)aPu8n z^z^W#*1{@j$hM@qTBqSIoC4)fV$>~{=*!My0mb8TZ%jdo%s)t(1~+5MF8m25jalOj zutvW^Mpb;8zQ?Av)KXKrgG~suRQ1|E&9=2G#a7814IXFbEn9QLieEzw0x5?GRPN)* z^S7;Z9z4y4yPn&wO88MhS3yfJsiuFa0;QkI(f5?9(##{ZrzPOVnLgzwRGp2QrUt7h z-LUe~bqib+a>_j81jcK2-GX~{yV|4Apkh5qNuu0X_Ot|irx7~Vq0gDPv-@Igq_WI2 z&vsXojG8e1<7_1-A~us?LT$C)PuG}q^g_r(jmJFqC#elaJ5|qiz7pCw?XA!pDZyh(J0sWLWm2ae~%F9YSE8pF@400C`WdHD6W4bx9-v^ zG(13jI5%B>&?*w0aQ!eyblIrwi@k|W$Hc-6EOft1|J9nI;(zek?>k{f9#`zx(eHX^ z)Iz@Y?{qb^wkCau)0{W%lAekW(Q-o6zWL`peZ0!A-4Nypn|N*I&RqXq^7xyvv2?Jg IG52}=U*$|#y#N3J literal 0 HcmV?d00001 diff --git a/images_v1/lampe.svg b/images_v1/lampe.svg new file mode 100644 index 0000000..f5645c7 --- /dev/null +++ b/images_v1/lampe.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/levier_ferme.png b/images_v1/levier_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..37d579a2e9c64bf82375eb0efed396d256de0127 GIT binary patch literal 2369 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 EH_kz8*Z=?k literal 0 HcmV?d00001 diff --git a/images_v1/levier_ferme.svg b/images_v1/levier_ferme.svg new file mode 100644 index 0000000..a89733b --- /dev/null +++ b/images_v1/levier_ferme.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/levier_ouvert.png b/images_v1/levier_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..49bb60a6f6002e5aeed795f543ae97303d3efd39 GIT binary patch literal 2902 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 PCI(oUTbtFHcqIJ?Mn#nd literal 0 HcmV?d00001 diff --git a/images_v1/levier_ouvert.svg b/images_v1/levier_ouvert.svg new file mode 100644 index 0000000..bf2c9b2 --- /dev/null +++ b/images_v1/levier_ouvert.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/mirror_bouton_ferme.png b/images_v1/mirror_bouton_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..6c3b0e7d971ebf1e540e1b2230229201c0797197 GIT binary patch literal 1823 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 literal 0 HcmV?d00001 diff --git a/images_v1/mirror_contact_double_repos.png b/images_v1/mirror_contact_double_repos.png new file mode 100644 index 0000000000000000000000000000000000000000..c2f515ad72b4247ffded53853599495b6949967a GIT binary patch literal 684 zcmV;d0#p5oP)DsEt>21>hzL?a)S526fZl`~b_)}gaMOAPZp4jCS53taP>X`C z^`oe0t#xry+A=4TrZcCLX`de)2pneK!#|UElF0!{k|arzBuSDaNs=TXudyGvo(2Gf>^yYT;nFc>~P% zquaaz=6hCfe#aXn+-+n1Zx-*u8*-C)fcL6gRNagbeu2yb)4-K#mm^92#m6-T__(Hk z2H^|gvB=yK@ECYPxOKOH*TCYIt*!M9;!mQQrRx^pBybfN ziHxE4@n!o#x?8fR87r1@Mc|XV>=F7Vr}IT}FWvJ!~_M67RF8fE0f_ECFv=-(y!^fA8f){Ssg& z`+@UhgFOfANmTO#*;X)3cvg_n?*Vo)2%I5%6Kev86V?1m2=fu}fOc=KYk+x9lI^i0 zg#KQZ>%d*uo&k1pglsEl0;lP{&prn(z|IP=lYPK2*>Hz}y*bB?1Gkc|uEqv{OTahW zowaH1&ML^=Sp~T}s~~r073A)$g4~@|0(WPXz};DrBuSDaNs=T!3HD+e{C0IU|`bpba4!+nDh45?mS^fiMEI3 z$_kG{8aM(HE?o|KuC~HyGWWt|4o*yk>>YfXA_d$gAs!|je3I^u1PX+mEL;qarhH8D z-*YUvde4j6B~!1<-TwXh^ZseJ)(W1JR1hdg@AZM|1>Aes%sx%KtmEGhm$G~A<`v5# zn74JZ?gADyw$9N6i=@j$| zJov6W@3Uk@K~A2kZlCG{qXN;0wRg5@{eFI|Vt)I9&q-#cX{Bv-5>K~z*)P#P@bO6U z9+q{?CTp2bzgt;$Iw9cs^MK=zi_$ML*&HoU(Ea7O)#Lp0zf4Eq80Hs_UXSLc2? zdz#^TV166eP4WV^ZqHh z*?oU?Qv4a&2ku#o-RtxY)IN|rEPF+5&aXvjhYXTqdjrg+gU#nEA38cQ;(P96*U202 zD9JszJIB@ZEZf7TLh%abJ7=Q%R6PIlho`F+l!h?@siM*_B?Pr9cCP7kEvX#d<-aFc n-Zf|S`;Le`U`+lp-_OYGcO{K6UE@74?J#({`njxgN@xNA!^0D^ literal 0 HcmV?d00001 diff --git a/images_v1/mirror_moins.png b/images_v1/mirror_moins.png new file mode 100644 index 0000000000000000000000000000000000000000..a0cb7e9d81747a75dd5a2e2b62d8215189376478 GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^DImYM zoj4$P!|01dOn-GsqT8GfQ;%3JrYQ$sHn~hvEL{BRx60|DPa@HEn{tkG0!@K|oV#b2 zT5m|?_l%qLM(t7DWE=gfFYX4(?{fO?IWO(VUj3UdLcXo^ar##tWsxVAePYLPpZ>t< zPm;gR0~rvrSIu+wr`=DpSKNMRIrVLDoy#}pTD|$6eTS>HGK1LungpJi;&p4vOoM4X zbsdYF^e%6HJY`9-{HA@er{3(CEBO2Ev4UEAPd?*hexab_(WlJHee90}I!=E1^|8e6 vHLJd9HvcQ%UTQbpqCKWzvK7q5FnR;${?rG4jSEt0yg)*pu6{1-oD!M<5*&d< literal 0 HcmV?d00001 diff --git a/images_v1/mirror_plus.png b/images_v1/mirror_plus.png new file mode 100644 index 0000000000000000000000000000000000000000..04362b66ebc06c1f3d9cf8701803a50c7e4c8e2f GIT binary patch literal 1890 zcmV-o2c7tdP)4Tx0C=2@Rb6NtRTMs(xw9)I&V$sZrjic+HI%e$QqhFk=>BE1ZQLxAY_vg; z$?V;oX(lt{{G@3qJ`_O^!KmPq;Qw2}Cn0L9?Tam?khm;cmfj@-EE=vY<#k5o0f^m&*sM6pBI0EL{uRZtU4R5Z`^X8`V)zNfJ8YaF z;u6EP09P2E5Ad?jnUOMxUqvh^s*L``+lU9}BlcPZ2XpY-jyyG}ttleQMaed+noc9r zy@UIIwng1*#M^^UkFzj+6yF25_LnMhmf?pGpH<}CbcnAmX|u%;|7E#p3GpKUUAw%6 zatiT2#A8)^yd3Cssj4^8z$>TJnP(8+gLrkpJj%xIMEtceUz`eceo~wa<_{hK;NmJR zuzL3+9o0iVC08s$)vACv7|KExH6jmbd4gn8^0FkllzkRT6fd|P0nrwSVAXrbt(XrcJk z;OyVRDf#{Yw^VBW$m{6QFhZvPBk<6w!tZERBfJcLd1$M3&)TehHS09YRtkN(Z(GDi^F2;vKBX;HY+Q*UEnTqUvgh@A9J5aYSek}G;8j!qp=F+X_rylpF&#L zEj%b>g+0Q~5^H*5N-?MwSLA ze5T{?GXqX;9WfX;*4pXw6&V*io?m|<6;W0GAb4f<-njQ>$>Q>9MPr@wU=n+0I+*9IKpp9 z{{0u*d8K7@p9VPmCp-6AwmA>rtOL;dXv;Q$XXCx^0IWWyc=l3wC&Xgk0yx!!!@*Zi z8qcdA>-AfBZYACT*nGWS|NH%Vee(m<-vGFv{{#OecnhgHyQTmD0~<+1K~#90?b=U> zO;H@c@$Vr2MUs?47AA(|&yt;3S&32>N?BW2$N~#CtVoJTF~vp{3#5pJB#}SGLjEkQ zWMZgcjIlWPdUx);ci$cF-^{z;Po3tydw%!a^Um+xd(ORYK$0X$k|arzBuSDaNzxeC zQOC9p1Dk=Dzz$$A=YF$+-M})S6Zj51j>=8oM;-fEDBXl43<7&|?z0j2l-Ms_9s;xK z-O-{*Cgdlurb_&Lpf|D43*ZEB0eF|#{sfrbm@c=sWI_gkH^8)v__K-FQ^5E{-9*CW zDz4wvfd00?1jy;X+m#hHD!D)y{4A@1tAvUF53m8aTOoD@VKoP^mhh-W zl;)7vb!u-Zr3wFZMqFD>>a||7YOw{FS|#Q!;mlj#`0k7jtxU)n!u3CorNA79&kt>< zo{t&^Qh)Qt=e0IRJ0opVlBBlN30wkt2oC{!qW7Jx>{L;85pJsDU-07ci*VQ7)w-?~ zQ~Y~HR`E<}qF-buqn~j3Qj_F)gx%A!-W5y-`Tpf|fYv@{DU7_2PI?>K3;i>Wu*}WU zPxvoFHA%JkqYqbEP1Qvh^z>>gzAy1Uqy@ZFmn2D&BuSDaNs=THq)$ literal 0 HcmV?d00001 diff --git a/images_v1/mirror_pulse.png b/images_v1/mirror_pulse.png new file mode 100644 index 0000000000000000000000000000000000000000..1781f8f2eaf5be7c2d8e012b2ae89279d3fcd409 GIT binary patch literal 1754 zcma)-e>~H99LK*ic4JLHNQF@vr9!u+iEe(h`8AW|xBLog3)zr_rAA3E3R8?t=SQK` zRfpVYxSQ5563JPbWAiKV*c3K#bJwH4?(w+$JRYyl^YwW@Uhn_jkM}3b!`%t4p{oG^ z0NlkH=c%NJQV~#y@?I-%&`|;u@9E?K)VyBCtd0p@1q#7f@S?D1`;- zee;f>?Ev`ix(WbfQUKMj8FwXDj{)IC(@295~iZ61B zY%ut}tYkEiJxXWCvq$&6udny8TBDf(9pgJRnp=Wn(JZea`mH#sj*&CilgnVD!Q|urX*flKBmW3J1ID2=Sz+?m#3cB zBA`S4j5||v0;5Le5Ji+Eo$XfE-H_I!jSn_ACwS#{?_;rOzBM)tp5pL<>VOA`?O*6|OJYlkjW){CdBexfK}GyIXM4 zfQ%emb-{3`PWPOD`!j}29mid7S$9OI@_3SJ6*Ga
    mQL(*$euIrJ+8PY=I@%f;8YXTh0$<G^^ak1*GtlmSw@!8#l z;M15(xBpD?7PLI-3l2iXw)Y3L@`lHQ>doSh3J#k0S}&WbBTke>l_P?-O^v~S{Cs|8 zQfJam@}|k9TOMOqcLqKAa#Qj8TI(lYe}pTa5T>)J5*Zm{$beI|BBE>=FRpT$t}!^7 zXU=Bd@J}wdv{>+PSF2iW?eco6RRL2G@(gYoSe7>p$>E%RznWE7-9s*yK9A{UqNzmt zp!SOj^~D5lpUb*qA>Sd6vL|06TPuIq2%)hfZj8Wku z3h>AdcE$!?5f!r^e2jPa%6Od0nLR=+QX6TedGccPC9VQrZjt@W(J94T0u@60jD-j0 zVKden7`m(3H%XK-ns2(Rlj!>rR^mDJ^+ij28#CWLoDS2hNG{CJeSPtBMyVhgXXzGu z7u_Yt7|%0D=#8sTy-^~NwonDzQhYrvkH2R0BvGaa<5#$H#RHWF1xpBd&#m8QNn|tT zhdw*}yQl)1O5Cjb`O{@Z*`W|FB;CHq2WdMH=+xfLo7>;xs<{z-Q4n3i5aG~ny^0DUdN!}0^R9tx5og3f scco8DvuFnYXIcJ_eflqvuKSvcFqnV-qjpvieC3aD!Mo$?96}j?0TP-2W&i*H literal 0 HcmV?d00001 diff --git a/images_v1/mirror_pulse.svg b/images_v1/mirror_pulse.svg new file mode 100644 index 0000000..f723a3f --- /dev/null +++ b/images_v1/mirror_pulse.svg @@ -0,0 +1,18 @@ + + + + + + Pulsé + + + +24 + + + + + + + + + diff --git a/images_v1/mirror_relais_cote.png b/images_v1/mirror_relais_cote.png new file mode 100644 index 0000000000000000000000000000000000000000..570dde5c656668aeb027ba8cbc87a5907ee619a9 GIT binary patch literal 1572 zcmb7^YdF&j9LN7I(-3A6Eph&cCo-2qQ#P07GPz$)$7pW3rjU&-mztVFWsIVvi!P_4 z&Ha?y9A?d#+*2x2jSNF%BI)d$7rpAud7jVr_kEu4oA0aNH^*MK;J0DNErNQAK1RlJ*6MwkAU z91e2VMA8VsK&`5^wWq(|CnPve8x!ckQ-~9kE<=U0vx1=^HB9f4h@B!rpin4+pnWeZ zxaEE4d5w(Ksp;wPJ*5|&p{`?1WO`S`0C{$Cg1>v~`2s`EPClQHCeK|nRWbCuHeP7x zWsO2>+9=rh3|7aJDrr3mDhUMEEc`@hMi&8R93#=!&Cam z=%^@;xUqhM$z(bgs=IXe_AY%E4z@1Y5+^r@G*hYvxj8UK_e2u<#Nr*+XkQ;Jq&0n8 z{6VebeM`v(H1tcGd)uG`de-XLxwn6C%WfXNM+609wRzTly_LRMuo`jmdjD;gi;RwOea$xzBbCznv{3`E37rsUlH6sFWo*_)fBLd<#FY@%;XQl z;fi3yw?SSNH14YQcJR*i#f%cgkpOvcw0OP)xy(&SmbVavK}IEefHd@aa%M%c*B}&BNtl?evFP)cRK>Y5h)zg#-7D!#EVSwTe`-8NDiy~AnP zx>`*d=;-KpO#G+}&w1pBGbp5dSpenaT1g0Ph zR@Apn`j8Ts21VV@P^wvR+@_5d^A1Y&aun?N@7atE992ZX7z%8pyrxZskJ6?xfh0)= z0oWxlj2f^WgC$i-jT0G=w0+pRqoEZMzU{-77^+5$J%zadQtoOyf^{M+pR03~HU4A}jC_)$<;=Yaoi6O-r5jrOQnO{H35ho{Mp z`QiqjN!4!i@_`KK3RdF0iQcF;p@hp8?%6+KLk6cbJY;3J1eYv4;OgY*$i#-8{s*y5 B%e?>q literal 0 HcmV?d00001 diff --git a/images_v1/mirror_repos_ferme.png b/images_v1/mirror_repos_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..2156b23bd180e0d3d3a50c56243ed2dd6b107590 GIT binary patch literal 645 zcmeAS@N?(olHy`uVBq!ia0vp^DIm`*SW=*JSTj@SLQA9lct^D8TsqfJ$ZWr0=0~7g)$M8Yj%zbM7{W zgxdV<>Vt)HdZj0_)=hcKqapY_&~Z8EhpOqD^A~nJvgmJIG5wFgBk>Q3D{C2-g`VAY z^jza@#=mvbJw2u=e&{TjWXDv$U1D?YI>GgQbq@DmZsR;@#Jq3gu32>lj= z@HJ|=@av+J-3`ar^naG95Z&aYH~F0T>Y34A;a>L|eoW7w%l%-9`=0-`{xPrfbV_Cj zq<^uHd}H?^VddSGIj8<_-TI{U$j{Gz&ieijvS*QFJl{C|K=>ok&@K1xE&0oGk3qjd z{iHaLW#GHXm2<@RhijeNE5%pEZK1e#QeR`URNvJrleSmP@_4$SuO;PW^2z9ur<^B? zPh?Gc7kGZpx6J9=w{xDn)H><?Z3RTT_`S*4IofZwB`9Ffr8b3<#)7*FEbJ^L7?!Q|W zUike;{DAd?ce6J7c(69T?`H3rI$Pj%_>K#^>ryL&?mNu<{V4U!q>aJsK^wgv_#aI^ z*RZ+k_?symSC{imzumE+xI@ceK}Eaik>xh!uR1JVoZh|m=c$jDFSH-jb9o>~a!~Uh Z=Ad~7S0tVkeFi2k22WQ%mvv4FO#oa^Gj0F? literal 0 HcmV?d00001 diff --git a/images_v1/mirror_repos_ouvert.png b/images_v1/mirror_repos_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..818f8263380515aaa0758aa8b9a81aa50fc639ec GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0vp^DImVt zJHE2yMOJY8KYClm8ouk&>x4&b4PD&cO&TR`QnH7?t4>~arsUEd@mtsZgn`DO0>5iI zp3_t2Jz09c?C<-Y&BJS z^PG`k@#tZ-e literal 0 HcmV?d00001 diff --git a/images_v1/mirror_travail_ferme.png b/images_v1/mirror_travail_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..06cf1098a3b3cea09f449e9b2747b7335f498d1b GIT binary patch literal 508 zcmeAS@N?(olHy`uVBq!ia0vp^DIm0570*dH5O+3%3`6*VU>mt3m8I&d&)GK$RrDOsvSBFySm~>``&{|SrozL1 zGtV@fu@Y}-36r|FhDEQ@{=oiQJ35aCzWwO?_UHePTe)su;yYVf$Hd3IEPTtP?+-(h zSz^?SU+&U+aa;4=<25mivn5}zTQ2Dl{_5behgWwO$9(wub3NBK_ZzL#jIP<8cUFki zr^C#?a$6$`?SoMha<|3^(EjYa0@&d)RNKZ>?>@(4}vmAz%M-Rs7-eY4Y@g6ACm zzUN@(%Zc)FQgwenO5MHoR^mtKT%90=*q4G#*|!(Iyu<&1+AmHVK|4w8koL0F WrEB^^4jBPsmBG{1&t;ucLK6VMIpjG2 literal 0 HcmV?d00001 diff --git a/images_v1/mirror_travail_ouvert.png b/images_v1/mirror_travail_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..5b06302df5e5ccc4ac8fb75219fb6effae36500b GIT binary patch literal 714 zcmeAS@N?(olHy`uVBq!ia0vp^DIm`Oe(7-5`C9EP*f*ZcJu06HdCGO@W*Ov-AR;VtxvHFV6NwXPmv=2Ty zr?R8axcvD%$xYV#^(}YKoH_aAoc||xJ}*BnAV?56XUhc7I9&AG>S~?+sgz?-M>=qrp zDSmsc&ab@r@n_^8PWgvd9edN}X0J5+VD&XNZ1dx+xBfM~+dl;TKfWz*ZD#A5J724F z{SA8$S1i4+9FxARWc}wwrf(GYZmIquvVQfnw+7PJ_r`sGTc>tQKWtgUxgNRWt~RSa zE?vF#_>Pv^Hgk!R)t~F`g#xYff~w- zk^=55(USPHsM5efQJu{-_t5WCtj%*IM6Mi?wpd(gFe41iGigiy5ePJqVZOJ4Mi$Ha zM|++fd|>n~xnu(KjTdT#QueR^7Hs((e(3lOs~hw8Z|q&wbkOw7tJ<%BTJt|{V`)x` zy0Mgtjo*}?&0SSO#Iy~>+P|{tARovr4`kMOFtNumhc+d-c9h;DwG?WhH*4)vr>67WKyk z=e{t0#oF8|{z<$2iU!{brH@$$6||qQW+tld3$P8*dob;dB6|9`DE^;mYiN?9_d>57 Qz%>FVdQ&MBb@011adcK`qY literal 0 HcmV?d00001 diff --git a/images_v1/moins.png b/images_v1/moins.png new file mode 100644 index 0000000000000000000000000000000000000000..fd0f1bba131a4ed0742ebe67f583da7d95815a83 GIT binary patch literal 661 zcmeAS@N?(olHy`uVBq!ia0vp^DImz0@t3^)NdMJMBJJXPpdw1pcY36dohY-QwwBoK| XtS*XVwu( + + + + + + + + + + + - + + + diff --git a/images_v1/noeud.png b/images_v1/noeud.png new file mode 100644 index 0000000000000000000000000000000000000000..2c939bd751f37778407260e6ef886c06bf9f2b28 GIT binary patch literal 594 zcmeAS@N?(olHy`uVBq!ia0vp^DIm9WfAKd+@4C zT;66!_>JhF54vA;o#WTlz2p^VX7Yiz#dr2X-un}Lt$dpp7@1f&1QZ+^sKMY-`w;WF zcI~&Yw`TvJS$%g+Z=7Cr-+k-(Ec@BtOurlJS#hSY=5%kk?!R%(6hGFJ_b+V{`qnkE zI@0o_uq?}_bQ#g4YWqs(qlW`F$Ewff{j(`f?%TfXCoc=Wv@rLp&j~&~vcc zKNf!Xm)@#yebGs|Pw^?Ds{SPcCthkUU-7nX + + + + + + + + + + + diff --git a/images_v1/plus.png b/images_v1/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..9e74a22b5e1d850bd60dc33dc6579c99d8727e24 GIT binary patch literal 2301 zcmb7^dpy(oAIHBN$(C3rQcJnaJ&Qsl=D6RErNVx;STZs9=91f7epE`L2`Q{{$*ssJ zxrSkKPADN`w7J#X<<9ow{LbV2{yo3X6m`}mVC1-QDoTe$nVlZb8?EsOy`Hz~=%*;C3v z9QEWK?S%ZtxZZ*SiYQO}VWrQ-p7_Bjo;%HVNG;W;(kP{4dN`Y?sL9#NBdVapjbKfM zqp72OT$7TlSIJBw@_D7*bHO;}weAgzXP+b?+;^I^+SF?A`p%*CiLAM(Nmk%2YhOyW z8ZMos09J#)LXLlC)7mHKbiJS^a`%36H}b^&G}Sak&{0lv|a`{0LLfgZ_I|h>CCwE$uteJ_=rID zN`@*a{o8FA)nRNXD52~mk=6?1yT2ns77&1QZQV^0bOA+obBL&unhGi^*6DeF;ze(! z2W%uRG`LCsL))zBR@Etd7Bo2OVwT8+*l}Q#t%@uUUqu`*wRQR}Es&wkiWfWcFQBudR zP4QvV5*k+ynx@Ez5hHO|a$i8IwXK-WN*_lLB8KNmf+A11NZ+>u(_7x+C$ z-UIH13}OuSW|O-3&G^awa{QzYR)n`VN+6ocbbPDL)%x8LO0Mz8(Jht?&;(RI(!s}- zmiydE+i?Rd-3gH2h1Lpt2;sKIRyzzS-W{tHX~k#`YYg@6V<448y*?7da2`EL!jtgV zr30xJUcF&+THdo|xv!xU#Ec6=RAcM_QeT;H)1bMfnP78%O5#>L#8o{!M5p9nlB9F3 zP_c`(|iwo-U*mS-_do6hQlN;t^JcN91n$)`rK=EEj}C*%%C# z#kK`5_~`Gs8i|k8LWvtT2gDs2No=?L!DUAY*lM87%$*8LLK(u6q=?<$ezF5^P|6j;DOWW5W2b32^8B+xqoR6pel z@D)P$wYv3n?i7TN`@gKN+1diCJ1h(cg5bcO9RlqL1v>gSn}d`Afj{5D0C1ZK2>z8p z@A&Sq+|lmLe;xc3{C9%zRN#NS8@-$WZP+nLfTdF)0PH)sD-iHF>+nuZ9kVhuvJVB# zWI7k3oesB?#}QtShEy#4E4@KdyNineJVEphUt8G_~| ze2MRk@NiW=xaa`$Df+7}TBOegoCE347h#)xNw$p0yU!RY+R!axTvJ^$`p_mPYgXw+ z?=uCM4$|=Dqoo@S%2673^BoKqw-P!j-zf3&4@EjuD`-$SOY-}Rtow+urHyZ>8-eUh zuH6);oyoLQl09-PO%p60_Y;ik3m%DN6&OOkC9zRgl9@)|CXBaO$pV0?^wR?sh$7!pk#;#A1t z9J};l&_>^rKy%=$opp^ijl$q^Qi@;7p4j7R1|FX*tj8?(UtoUWd@7>rT<|RuNJKPB zTX`!eDQh-bhBvJsxOHQ04J8gpS(X_RDRWv!Da58hSGMF!2z%?fXM~(@x(KQ&m{hrE zlAQL0BI;%wQDdF#dQQ!NTdckC!V9v1{!SoK-M-{VN3z!QMxJM-{C=jmLQ`w&@Sv=3 z25T=KE0Qe5%?-yci@D$FMTM*^+z!J^sr=a6O3b&)%U=d?oi8(w~^ z-Xqbv%ox^2utVy@Uta&jsfcpQY$KZd^+~&vA-{d9&rWf%;$cTW`EI_ZKz{34--7US z#r+$%rLEr{YqypgJpxmbEt@5{Djb-1Q+Waj>nQKi+HP{ls#LaA?N3v;AuLgOx;C^|&rcZ92w%a0B MW@yt_##jFRA5&}&KmY&$ literal 0 HcmV?d00001 diff --git a/images_v1/plus.svg b/images_v1/plus.svg new file mode 100644 index 0000000..51e40ae --- /dev/null +++ b/images_v1/plus.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + +24 + + + diff --git a/images_v1/pulse.png b/images_v1/pulse.png new file mode 100644 index 0000000000000000000000000000000000000000..7cd32019504dfe83cf8abf9e8c11ff4b30bf4f38 GIT binary patch literal 1759 zcmcJQX;jkr8pr<#A&N+*H7>Z)Q721r!Ai|BcQhT$eW`Jra6wWOnNm>$r@Xf*OQ$SQ zkrHo)p}3*fa*NEH3WK?fm18(Aji%8^+R!Ks&YjcS`|AGA`TjoN=Q-c!-E+?KPkd+q zLfcpy000Co(D%5Sc(qQ!pz2@mL&qL9K$PPF-aw-SwWKc25@K-4AtAs%wTA%^kTI}h zJEE2+$mEmv2iXGPzxo;gP?82f{?3G|x%~pw+Mf9@!5q-vX?2gI@hOexfIsR^gQDPcONEcRsl>^-HE3MzKL_Xhvc)hnnZb1<;|>Bn&FPq6DpJddhhj&&}=&Bx2@Eb{Hv8w z!k+_`U|xvqNMp9q&!li5R^MsrxMHKK3n-Tl;>3 zytuM=am&~-ZNqUTwJWvDKcfTMQ%!xVDO@+BH4(B{qvpgkq;>@(tJFKQV62rBlCArz z&Z-1gBR(Yb246^VR7_dR5gbYHgZGq zr?$`#GaG(l3(?wwti?8R42|J)(POJ$bC7+*mPOx7tB{Ep1FDsggzBVwk@&ptbO9X6 zsf#vQuJblYSvESNY{bTnLe359bAF02YS zC)TZ%>m-}yt~>ablofN0c5W{Fqa8+~7x!qO&GCvgA;0`hj%g^|^S~^8Ejv8=+O_-< zgFx(6)0ddFxqEY57mj~kSoX0((se$v&b~n?p@(8K>89`7hb47mzJ`>& zVqD}&X$i?8=15`P^oJCitfkvkE7`e(_@j4HF4LHNBtsZTF@6%prvY2~2XSjeX5el#RZ#FFK&;KThi$U)~%vAW^_4OsG`TpC(KUSK*ou z>15f*<#R7b-MkA6%)$+)W+gKf*8*y#z<7aG0huIM7|-yxf{jU!b^Q)@&*WVUd2ehXIE z#p5L--rXrq7FRxQKG|kP;ko9e&k>DMyICDp?)@>sCWf4Ucf=h%Y-@bzADfl^=M~4# z?xcMT!LqA!1t>QChg-aalDrq6i77>qDGppL5jB;y06PrYd~>70T}!bs>|B1@;i+Oa zq7%$!gv+x2L)FvjHF~41(iHiVXQ;kWqgaU2J&5_?1|j2nj{sR-r_*fc)0*PwwFJC= z-`4nkgp1q>zXbDO6bwt6Eq++YWXPqg4O0)$U3T&-kxOmp^ZO#o_-)Cp)o3o=HPMIh z6>jD{+%h^IFZrS9p3d_MG|wQR=Hq9#eD|Kb_4EU9=h*=VbrQHJZf>A}8a(_gs%f)U0HWmr4w zj2HF!<(DpoY6g(d%GWh#zGPPYH|(o=az~&L!)3-@@66BfvV&|ZH8bnu`X?VpVx@{{NM%1Xo&7kikV!vvrd7X) zVeM|E0*ZW|V9!0$5O~h{DlQ^XEz3l!y3${2(;W=<67GIECEaLJJh^|A5q3O%>GAv2-QF=ULJAp}_ft`ZjteGX4Z3D*!qG literal 0 HcmV?d00001 diff --git a/images_v1/pulse.svg b/images_v1/pulse.svg new file mode 100644 index 0000000..e883c82 --- /dev/null +++ b/images_v1/pulse.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + +24 + + + Pulsé + + + diff --git a/images_v1/relais.png b/images_v1/relais.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0387bad6d811270cf7e5877aec4e8eea468d67 GIT binary patch literal 1411 zcmeAS@N?(olHy`uVBq!ia0vp^DImWXua3e!#?!_;EgJgt~`O9RE>pw}?^qph>?ezDb zmXe08tCAEMg%prcVaFB4gQiktAWwnB@}=F}-=Gc|y5j?9llEn z<~nh4Z`i$DV7A9Yt5y-QgmQmHvx$dFxiobSyqo8gqtyCZBq*Zcu5IfL7q07zTWxG@ zMfob@?jHZtC00~h8+-Te-Lu_Z3o{OK?n(06GU52~>;DO?q$KTn!fs7;MpmnR*& zHjKA|qkwh87R@uJuBGf6$daZ`2}h?c@}70b>0N!0;)GAvI1XCA-`H|aU^2Ji24`lI z=jTghtr@yG86Qj#nYX%Q;rH+mj;20Y$6`T~5;hIJBMfp?%+IQHUteKd=El)*u9iz$ zxh~X6LAA7HVXsi?8lG_VBL`$&v-wu zk0I-kZ<57zeLrNJ4qQGe`RDd0*KKttKSfUy+n4iyr?8Z|eTtUo*TAfMt7 z&iVbuHX#O=r*0^=4(({1z}=8(UoyA4!J_5OqwXacm!5~J{ZQ#uWjRpfBe+m$*(>`X z4x{CjX>T@Nvo>2M;BeB`skUj^sS6&833qJ{R9{G)zuj(|0CSF(Lok1XqSJ@4r=kh+ zr&U>!iu@CI-ZpPuy<1L+Wqrc8;QQJd%LVRutP`{eWh+Zfunyvw_w;PE*t~afoOhFV zw$6|)VvJdTz1N`F?}XL#2NU)c`YjQ#$l$tHAGq=Uwh5LM`FW|nsx0P{t&T2<>z4@X zcJJsmp0wzvjMD364?c4&Tc0!kO8cEV7X;s(GN^gU@YXj{#;M6}<^S+U|F%!N>uR)w z`yA^H(^f`{Z{^AF>Rv9m{Y>OGpW=g=pj5E;pyqNN=^N3(7ov~9{kCky{%l2t7qbtY zJ9jRmPWRn=h!|uvSIo5f>WOs zX%;s)ohtbLP3jYmWWCUrw#^;PPj+&g-Q$T=pft*|{A09XdbscFwU9ti!RG1e=d#Wz Gp$PzRT0(^Y literal 0 HcmV?d00001 diff --git a/images_v1/relais.svg b/images_v1/relais.svg new file mode 100644 index 0000000..5fb0bed --- /dev/null +++ b/images_v1/relais.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/relais_basculeur.png b/images_v1/relais_basculeur.png new file mode 100644 index 0000000000000000000000000000000000000000..50f58a26430d54baaeb72526f7794e6d7a83ac43 GIT binary patch literal 3379 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 r=>G7Z?GgWQ`2QjF|8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/relais_cote.png b/images_v1/relais_cote.png new file mode 100644 index 0000000000000000000000000000000000000000..1236fb795de897f5e4ca4479d64de48d9452895b GIT binary patch literal 1644 zcmZ`)do!)(E zifNE#Dh=4us;M%qqqu$X0H9C*PBm%x>SR@DLf^iZ?oSP;Cxy`t14&6q$jI2J_(New z4aQI;A=<#%htS#vFZu}Rplz`xKgFeRL+tQ+Mv^}3#+A9EVKhdg z(=ox)(gA?RVY{E0+0~i_gl@aA-kbFumkFbo!YxUoK zGFYzV%oC+g}l;P;Oa#$CPjF}!t%1wf>M<1XnN z@OpX!U$FOfx0(DNA$IV=6K`9-M6IE2`KB@mg9t1_WmKT4G+$yr(c|BK4c&3%?r7}9 z`MB{{E-6L5(acCBxeeO;=4vXIsv<79w{;|SI5Nx{MIUq8xBlMstgLR#%u ziBDm5b#=?+WL(G=GJhYz$0wgm196{(96MCv*hOA6g~B3U^YFR1+pM~=u{~#{)BJ1` zkC&&dtu0B=Hw4c*I5?o<-Y|KKf_$sg#ksikm2X%DP9dMh`uUB@_J619Pkd|S1-}7t zcl@}D=?^a(-7>&*_-c?HK*wOm?$=dQDhxMo9yn<2O9;y}i9_ zq?Wq-NTlI(b~$rZ;}fr%jQoZemeTO1vXDa~rPUjTeK^auu{6>90%E@c zzAN&}St4L0Ze{T2>KSaU5;(4=P-7^0PiYj?10mB|(8Hc_VZdLomj}dJV?D7_b;TbQ zcDI_<6>Ax=-gILa3Mi$ZjCy<-n#Ch-khd-tjGm^KVwO3)nM$#)*U?A@-iI|{VHS)? z;C5AT$&$QbH&ZxL@*y(U)*gcb*3?2|RvS~EHc?PLR2a-__HpOZenKvL5rdU#D4ZF3 zfFXchGN<*8$TfC;{cLxBs+vsVdOxeLz{=XIoM)V9`P0e!RTwkqowhI=V*t&#b?5`G zy!*(lc~E{Feu`BARQ2Rtcxzp73K}i&JFT@#1y2XgydxuZAf0aFlxR + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/repos_ferme.png b/images_v1/repos_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..948fc40529d4a070a197c699c875a5ee11daebc8 GIT binary patch literal 1070 zcmeAS@N?(olHy`uVBq!ia0vp^DIm?@wvoxb8Rq!QC~^Ma$ovk(u!P67x%^)1kIqZ_HV> zy)0WB`eb6y|NDI@>QU0U?tEdp^B@Kb!byY3>f4&-?oOPtGa2b5PF9e~IkN z#Ul5@!&A$zm0#NSC1RKUTJPMj!oGcioxUD_V^nZJAX|bi82<_W^uv+uYSH1cdQ>#uNoi01!zuwa= z8_ungGE$iAVHtTPdd@G76H9{qxL>bXb*W)O(I$iE*1A#?UjOP`e#v%a|I&|_!Yp^q zUmC@ecCPrux~R7aQ*NDFTjZ6$;>#ab=11R+>O||Mq@NsoWx^}fy}mkk=`yqZ95q_^ ze_i7bwEO09Yl6+qWNrbDgJyHzSsuwet*rW`f2ys~v2S)hzHzeL3ztPbo!;LbRN=Sx z%=aH6M;F+cwzI5rJ<2@y?Dro$EgKttOf7m-aqOv7tj+unw)+In@9(;CeYI_<_1lun z;Qw;>RZm~buH;+!|Mo_^_KLoZ@@5Q->*ww1TE)I_U%q{g0#n_w0)|(sb^B%5Pk+5} sfW?Ms&a_4MJK6KN?b%6B#ukbn*nQ{AD{AekHUs5BPgg&ebxsLQ0MaFsW&i*H literal 0 HcmV?d00001 diff --git a/images_v1/repos_ferme.svg b/images_v1/repos_ferme.svg new file mode 100644 index 0000000..e62178f --- /dev/null +++ b/images_v1/repos_ferme.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/repos_ouvert.png b/images_v1/repos_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..9bb114677e0c33ab40ecdc60288c26cd407399dd GIT binary patch literal 829 zcmeAS@N?(olHy`uVBq!ia0vp^DImduk5ZGIW@-eH$-6wZAveSF@JcYaC^4GfG-EF1y~ zlrtJ7}1cvFAE(m~gCp z%yQbpQeR>3x!=dHSO`TOJh8K9&RwVaxbUC9PgUNL%|8CKa<;|$=RI;O&gd3v9(i3<)X1y1`t!R7I@urDtc4gZZ-|BH- z`n0a-*@T@_0;g0Jzswb_TQO&%imji*x!+fV!vej}m#toNT(Lj===$T8@%FDDvpgx- zIyKV1_lNxwfiMqsOZBG6TYm0d`=0OFGVj2PJ2lFaLa!xyIUKv9C4ai+A9JJ6t4nPx zEGf&YU&Y*}W5P{X>j{_67C|2}RGa^7caAI-kbNOY|G bt9=k>6wP8h6}#dJC`o#{`njxgN@xNAFwrzO literal 0 HcmV?d00001 diff --git a/images_v1/repos_ouvert.svg b/images_v1/repos_ouvert.svg new file mode 100644 index 0000000..cedde6c --- /dev/null +++ b/images_v1/repos_ouvert.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/resistance.png b/images_v1/resistance.png new file mode 100644 index 0000000000000000000000000000000000000000..d1d5911542fc2531d5c2b57a9fe06d5562068c5a GIT binary patch literal 561 zcmeAS@N?(olHy`uVBq!ia0vp^DImQL70(Y)*K0-hGU*Cjv*CsZ?8vZ9d_VpefVY>e{A~oOHaRU zHP3KYV-*zf{HiK-{*Szj)1&6O6ARzO01d(b(tp-;9Dn8hG2*Yr@-$tIE^O>+u_rY4 zzDpH1@>*Ygv$f~a>$oz-#b0(!$0}U*`O2qTpRRqXt)2S)(@!yw`tBvq{@nR=@6*ji z{C`Sor@qa8`M1*TWo1zDG~>nQQ4{B`*&Fnw&SvqKcPGzP?u_|&?!w*^l2h+VRoTxA ztookve9xb@Na_BL=RSLtH{Xd^!(07)@zKS*=dGGoQ-9Z1i+`t6ilM%)+}-aXU!VN8 zf3!qrfA043zqe21-@jGuG0kq?@>SbI%g&v?8~^TIm}C0e;IL_S(;#BpmH(!iZ}(>` za!XZ@{@0%J@^RIws_Gxt=RD;(mHPBwv(1EmP4iaWi(B=4&NNw{(0r?#2SdItn@otg un0<0DFc=$?c)`I5qZu*6p248+^i%O^D^d-=Kc1TdlJ<1>K literal 0 HcmV?d00001 diff --git a/images_v1/resistance.svg b/images_v1/resistance.svg new file mode 100644 index 0000000..90c7feb --- /dev/null +++ b/images_v1/resistance.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/tempo_ferme.png b/images_v1/tempo_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..bc2eb50998b0d22837eae5957db7017c55084c78 GIT binary patch literal 1533 zcmcJP_gB+b7{oaVju_y3}|EzDTE3^kd>lhA)&|~V$>8u z7=c)Z$dI8jG(@Ojv^ZkHGQtXipkR=O)}wzx?|Gj4dG33j_t#54g>{yOsz3n%kVd1B z9wG+sSYnsxzA#znDFTS-;fw%SgKB)y<5Gw>I@Hw_Fc4)400L40#CIwp+kjNRW+%{L z0Q~P<3;@!@0mzpQR>Yly5_xCmKZ0qXFKy9`Cib-*Oap(*J8No3=Hf(B=* z9fN>UsuBQ*A3!7RJuiV4Z@N|~dMWka-N+5B-j^mx#%saFaWEtc3605xIclH+>Y(;0 z2rPP(any038{_B>$9vNVHLkkyF!_|g0OY-=owg&~ZMUU-;tVf-nqzfWkTlKP2LCk3 zu^dX6<_I`cOX74&e_y1Yzt}gK&P#IUKPq2mZV6ERduHr;t`!du(Y%|ht5Lp$`8ak^ zeG@J*$Ya}}1DlAMqrzwLnU%*%tRUA2&---ihwn8tN()qGN7e@`WX4ONAqAv!2O3zg z77OkV{Hi9;O@~QpXW`-PlaH42eRFQ-#i7G0jOrp9jh1F#R=oCz?J*;m50shD7DV%% z_=^0rSX83R3mt2d4!HZ9vApiWnr+7W&L*!K)hPXbfi@ZY=fSOmgrZ2eB%Zk`<&Z>Y z#9Ms+r2BKVmCjj=7>;RUDySn9i`mSj(nSMX-8v@u?IctTSG5ok?sv^i9+c$1@E)ac z%H~~0#QfFnw7C|)3`7y`6XZ~K{Ls+=658OPyqxrP3@>Pwdp#dzrrDtf+ z1MBaZMMCZ-Ic*x&gHAl)7ksbH8|Ic@yl&iO2ejaOnI^$rQ4>Q~ZAUW(wcSn4H=)5TqRW-=H;v1MRF zNSWhVycb0Atu=)?l2rJ|4NuA<3+RKVhx-1gOD+WJl)h`>4rzA6)htNV~ zmE2gbjQ*97xivsAQ+xfsGvwAEl(IfGkZ54$c&!%BiuxV~ph}8?+<66!k|9??L?2ab1-NgnI+#0@d+j3a*m2xfPv~tHrTMuR4#b4QvuqY{XNPnR7T7N1z z>AvmgI?UTJ=u!ZBS8p7>W2IaeJ=*G8Gnrf}W2s-46I%Z6PA=fFyS7HSzn5&*<%dO6 z`TP1zZi8Bt7D0iq;7I2)oe0or*44f0d6~M=)9Vw+7d%ZNtEh0yx0{XgQ$AlWbnCs5 zRm8awCV`XPyWm?E|E91ReX~N9evxZH_K}S*tt+*IhLI3Sq@uO^T;E%;jRL z88eY=BPGyGtxPWiqgsg)h}Jsm%T83jeUxD+SjwHgkpH8q8i;s64deVBNY3gTMnP%9piaXyZ+7XLnA^flW0~VTq=>Px# literal 0 HcmV?d00001 diff --git a/images_v1/tempo_ferme.svg b/images_v1/tempo_ferme.svg new file mode 100644 index 0000000..629aaa0 --- /dev/null +++ b/images_v1/tempo_ferme.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/tempo_ouvert.png b/images_v1/tempo_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..9a6a813c0d9d144323b5a866a2ea5071d3d5509c GIT binary patch literal 1745 zcmcJQ`8V778ppqhBw`&(Z%Xy5c4~@NrzA?c&=C!DY8O?p+_bh1Vo9T!jtVJChcb$m zQ2TTdK^aRjM0-h9NMjksUZq4-jjbVRo=AQcp+|N1h&+Gj>=l%Tf{POvvySZRB zRP|K>0MKx9#CRwev@1AFaYw()^HKmr^1yxrF!=_Hih>gC;}qiT445iB9DsoI0qAZ- zp>v@9fB6fbqkz)C`(OaLa}9v}nQ>8Y_c$uFJM$kZm4g0ED|)5iztTaaO8@n{V+Kf3 zoB}G*j+aRQpr*4c5KvgO4*;NRPMGsv6wq>^Q`!NXZYusNI<-_Ag3>fX7S^BCHn6+C z_x64$xy-t%L4d>P>N>%R{=y6HmuN8^*2iwnT!6Z3cZOjaV$`(_%841;Um9~~q+{)K z{l!eyWkK5is-4k~|8cYkeFPl}cF zH${dkPgx0CXNz4`E|;hUTgk@!o|{7^R2vQ2((_Agvqv`0KEGu+K*XLXf7LG&1`auf zkDK!JZYkZ=s=|B-na1V6{@UcQQ1$w8iDqVnvfwu%bmQ;OsXkc{e!2W~*cU9#ygdB) z=J<~nUmlg{MPdkN_xLzbc>?<&TMZ`Y)|jX3 z^g$u~%4K|GMaNetl^?8S4+-p)S*|6~2LXv2Sm^Ifc=ZP<1s9Sv^G8I1XQS&^b@}$T zWnF`G7s{OBy}#u#hF(*+sD#;L3*eA&0p4cyzA$I^kumv0rt^Tt4=@DLXygMjyPgY8;DJ@|rX7C0 zgLSJHF&Bk0Iwv5#kVGd0=ZLB!WW`r`(Q9W2dXV`0J9}}h1b$x{-7h2jGv%r)#-gd@ z9SN5jc*=Zt6-LhiYvBv2aur*8-D6gtsx{B%e}_zs@0V${Wihce7MJWerL5__8KDyi zHFf;MpE8Bo8&>G#_-nUum8XKsd z?}?%YSf%DBL-ds=Et*)8HC|jx2ih79dE2h3OK@jhi z1VZBTPj=xxrv=#41s5&3vrS8nIkKE87N=NgRtWSY6)usIDf}mo1^Z%u z4t_8mfu&h><$s;sC)Avq-2F!)bB^6MKDcQ4>3Ed? zWq+k5(H!b}>>~QEcj=(5DEy*+-h1Xz1 z{^FF#RwotV(~mljt?0|iEt-KT=#_ZGZnbdsOF8c%cx4#V!icQYKpPFqT(a_U^XHW02MRQO$Ly4WAfuS8T;) z!QE_53E8$UvAtH@dT+GOf?r|WnX!!`YsDqsuiR|6 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images_v1/travail_ferme.png b/images_v1/travail_ferme.png new file mode 100644 index 0000000000000000000000000000000000000000..b3b9ba6ecc1d091fae86fac247f316ddce164773 GIT binary patch literal 857 zcmeAS@N?(olHy`uVBq!ia0vp^DIm<^@+LB#c?RU=)@>?+Nb6ef}$jU&wpt#++_5PBv3#M%j*U@*{ zzfHVbJ9P`|%BMDK?`LT5bKMyms`k}2+H!@|g$@5W&z8qUzDl#a+PzZt{_cB0dv4a| zgwFgjy)JD{NUz6V^Q`sD&ev~z`BP7WjmILHHG^%7r`%=hJb^WQf1^Hn)|UEQwfN(k zoHq5lRI)e!$qACWw^UbA8;AD1Lam)%z0+E1kOj9r*I& zMe%Lx(lv@-zl&y`_Z+kocSksRq`-1eQTJcx(|3CTYy6gKBbpfTnnC^VtaQ@(> z&s&P4Z-)NK`Qr8=dGXqqr>qyBUt789vD?C=6MK}6grz>vENxz83RhLp00i_>zopr E0G&i63jhEB literal 0 HcmV?d00001 diff --git a/images_v1/travail_ferme.svg b/images_v1/travail_ferme.svg new file mode 100644 index 0000000..0e35948 --- /dev/null +++ b/images_v1/travail_ferme.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/images_v1/travail_ouvert.png b/images_v1/travail_ouvert.png new file mode 100644 index 0000000000000000000000000000000000000000..7d54df4ef156e1d53ae699c9867d201aa1342b42 GIT binary patch literal 1088 zcmeAS@N?(olHy`uVBq!ia0vp^DImA=Jb=z(o znRaJVbdh)7N!^{Q!IPd&y3x3SQ*|eMFtZS^hYIJt@=uU{}0xB z?mu!n&pi(-W}a%3eynSUu$0U zOv7s~BJ-*R=f zv|aW7A6me6&pEPa?(ZAAZ$_$r|9GdW`c(9l3g$1% z3&q2?y>=}Si91lS&+6}-h1FG`>gF(>`W+kQr?xu!ydvil-U3!T$K{jkFMT(9BP+Rh z((^S9Io@~cg8JK8J|$~(ueMUGWUS(IPf!%`KJO~MIOhAO9Mw6kYK?zd|7}l@KEtrO zt#Rg-yNufxdMfN+{68~-QI2y$z*ePfLz(930i~}sxBvFL&pttC25%TI^IPFhp}$Nx zpCtZ@Z~AH=x<-nv$mt%xFY`~yWR(fx4WWk}m@L(wbaFje+motreMW=H+h&%c%fdxW zKSgxdnI$m zH#old(lV#c|Dl1z36B-QoKLP6@Yy+BUAz3wJLB4XCnihn)2k8{8uthT^+g}^P|#-v znXkQRngi2M(<%Q;!}sR1f66;%FkxcA@>`8HbNz1mt@6^}F1_qMYXmpQk`Sh!3OtUJ z9qOF^J6~A)|No)w_aap%Tt85mA$7uBBAFX%ZES(~tUo7y@&5I1YV2w8)3Q&iV|i-3 z?^P|+PdT8H86B@uj5hVEPT0Iw@`SJ + + + + + + + + + + + + + + + + diff --git a/modele/__pycache__/cocosim.cpython-312.pyc b/modele/__pycache__/cocosim.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb8bd23d177ff5869d04bdffb2ca21d74b057347 GIT binary patch literal 2799 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 literal 0 HcmV?d00001 diff --git a/modele/__pycache__/exceptions.cpython-312.pyc b/modele/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1d5cabb2da5387c97a251c6ba84f31cc6b0d7d2 GIT binary patch literal 1057 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 literal 0 HcmV?d00001 diff --git a/modele/__pycache__/matrice.cpython-312.pyc b/modele/__pycache__/matrice.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3238fac851819f9b960785b92ba022e8acaf135 GIT binary patch literal 3915 zcmcgvPiz!b7=N=nvt8F>cd-RAY4fNpb){4&g(87s>0&KlCHxUAOU7a6wM?CzS?0}D zw`r9aO(4P0o(d;QJkXUx^`st*hrM7p$aYQIjF>dhi#Mct@nHPk{Mjx218R&fyKmn6 z-uL~!Kkwi7?yOl8K~UQM{E>VLt)E!OFM`)tsE5V`l99}*sE-SvZX^djL~@V>ZUtSQ zzF?M%^S`i8Z^|XPHRp9a3I=wRUyxz+@p2GqLFS z4TI2(uE{t*35p0V+1LyQ`h!dvQB|@fo&OX(aae&<&F9hthGYv57*ggOY4MzMNq{XJEbXC{DxUxmQxrzp1)GX2rC` zz~&|Ltn0{|`5ewjMoPDU6XqG#hAZO2reJxM3R}kPzc2*V1RCK6OGD+x2og&j89~oq z+^{vESHd$Ze6|s^63#784rF+rGmGL}Z(Oh|yhUmYuzJN#_p{#)szkFnEgrCWO4NQk zAxjNsF1Rc}~}o zumy-plHML^$z<)YC@Pv_isEq8+k!1VB?@ZjW~eTpx%IUZ?~T8Ak-uCySF-^=5$|&^ zRy}rnA~~Kc#_BKfABPs0YpGI*pu@uA1o)(MLRSioPeTyqm8kuJ zMImJxobqq*7vYq&n@{?PpuN&>m%qMD0*wXEbRv`lZ$`P%z(`>5sWO+}0xFBZ%QzMt2Z{B|$9!!G zbY>g)3lSd;j`E|z2>(d?SB%~ub8Sf(3HmX0?B349ee+1qzFyU{XO}=j*YRxn@5EXT z0&eYc1mFK*SQ-D3$AQ7R74&#Jghc`D{r_yikFn*EvoXe9{%Fb@QeT;6*S$-KWRKj3%-*NM8JdT+vxrgYLTrY%+U?thy*Z--M-MoK9riH8i>Zpap#6wI!G+l%EX zcF0v?hcmh=8Ng_BB4rk`L!sd{2gcgx ztJcj{H5RHGr`Au`=4xlEcFu2Z8RI7+f1g$`Nf&f&lKys3em*eD?PWnzw7z7=gy(RD<@YMNPeCy z*6%MwyXMM96(9DxBiAt#duguw;OZ!g)INf1k*>|N4SNa=d%k?2uundv%mXCAJj-%`ra`%z(0yKx$`01g;zXM2gBUBgAZ($T& zdnJ1*d*%I0@53${zBWA7HoZHyyI8gJZg{5?(cX9k%QQ79O+?X-h$1ASmde_dq6jZL z)f=f0MOjaYqQP<~qlr~ac@8-!&aO7tgg6yzP_~gjM85_iLioWtUU=?7Wv$S<(7_As zt_Wj_^R@uTSSIUvuAd!*N1+S!B12=7?tuRh-s4)= self.SEUIL: + self.monte() + else: + self.chute() + + def etat(self): + return self.haut + + +class Relais(Composant): + def __init__(self, conf, nom, graphe): + super().__init__(conf, nom) + self.graphe = graphe + self.r = self.conf["RES_RELAIS"] + self.SEUIL = self.conf["SEUIL_RELAIS"] + prefix = nom.split('.') + self._contacts_travail = [] + self._contacts_repos = [] + self._contacts_double = [] + self.haut = False + + def add_travail(self, nom): + self._contacts_travail.append(nom) + + def add_repos(self, nom): + self._contacts_repos.append(nom) + + def add_double(self, nom): + self._contacts_double.append(nom) + + def monte(self): + self.haut = True + for nom in self._contacts_repos: + self.graphe[nom].ouvre() + + for nom in self._contacts_travail: + self.graphe[nom].ferme() + + for nom in self._contacts_double: + self.graphe[nom].active() + + def chute(self): + self.haut = False + for nom in self._contacts_repos: + self.graphe[nom].ferme() + + for nom in self._contacts_travail: + self.graphe[nom].ouvre() + + for nom in self._contacts_double: + self.graphe[nom].desactive() + + def update(self): + super().update() + if self.branche.i() >= self.SEUIL: + self.monte() + else: + self.chute() + + def etat(self): + return self.haut + + +class DemiRelaisBasculeur(Composant): + def __init__(self, conf, nom, graphe, cote): + super().__init__(conf, nom) + self.SEUIL = self.conf["SEUIL_RELAIS"] + self.r = self.conf["RES_RELAIS"] + self._contacts_basc = [] + self.haut = False + self.cote = cote + self.graphe = graphe + + def add_contact(self, nom): + self._contacts_basc.append(nom) + + def monte(self): + self.haut = True + if self.cote == Dir.GAUCHE: + for nom in self._contacts_basc: + self.graphe.elements[nom].bascule_gauche() + elif self.cote == Dir.DROITE: + for nom in self._contacts_basc: + self.graphe.elements[nom].bascule_droite() + else: + assert False + + def chute(self): + self.haut = False + + def update(self): + super().update() + if self.branche.i() >= self.SEUIL: + self.monte() + else: + self.chute() + + def etat(self): + return self.haut + + +class Tempo(Composant): + """ + Tempo type "bilame piloté par le temps" + """ + def __init__(self, conf, nom, tempo_blocage, tempo_liberation): + super().__init__(conf, nom) + self.SEUIL = self.conf["SEUIL_TEMPO"] + self.h_trans = 0 # heure de la transition + self.h = 0 # heure courante + self.i_prec = 0.0 # intensité précédente + self.tempo_blocage = tempo_blocage / self.conf["DT"] # durée de la tempo de blocage + self.tempo_liberation = tempo_liberation / self.conf["DT"] # durée de la tempo de blocage + self.blocage = False + self.r = self.conf['RMIN'] + + def update(self): + if self.blocage: + if self.h - self.h_trans >= self.tempo_liberation: + self.h_trans = self.h + self.blocage = False + self.r = self.conf["RMIN"] + else: + if self.branche.i() >= self.SEUIL: + if self.i_prec < self.SEUIL: + self.h_trans = self.h # On mémorise l'heure de la transition + + if self.h - self.h_trans >= self.tempo_blocage - 1: + self.r = self.conf["RMAX"] + self.blocage = True + self.h_trans = self.h # On mémorise l'heure à laquelle on bloque + else: + pass # On est au-delà du seuil mais la tempo n'est pas échue + self.i_prec = self.branche.i() + self.h += 1 + + @property + def ouvert(self): + return self.blocage + + def etat(self): + return not self.blocage + + +class Diode(Composant): + def __init__(self, conf, nom): + super().__init__(conf, nom) + self.r = self.conf["RMAX"] + self.reversed = False # La diode est dans le sens opposé à la branche + + def init_cycle(self): + self.r = self.conf["RMAX"] + + def passe_calcul(self): + if (not self.reversed and (self.branche.amont.u() > self.branche.aval.u())) \ + or (self.reversed and (self.branche.amont.u() < self.branche.aval.u())): + self.r = self.conf["RMIN"] + else: + self.r = self.conf["RMAX"] + + def reverse(self): + self.reversed = True + + def etat(self): + return None diff --git a/modele/config.json b/modele/config.json new file mode 100644 index 0000000..cdc17c8 --- /dev/null +++ b/modele/config.json @@ -0,0 +1,28 @@ +{ + "circuit": { + "DT": 0.05, + "RMIN": 1E-32, + "RMAX": 1E32, + "UMAX": 24.5, + "USEUIL": 5, + "ISEUIL": 0.05, + "IMAX": 5.0, + "RES_DEFAULT": 100, + "RES_LAMPE": 100.0, + "SEUIL_LAMPE": 0.05, + "RES_RELAIS": 100.0, + "SEUIL_RELAIS": 0.05, + "SEUIL_TEMPO": 0.05, + "PULSE_PERIODE": 1.0 + }, + "ui": { + "DT": 0.13, + "BLOCK_H": 50, + "BLOCK_W": 40, + "RELAISBASC_WIDTH": 1.6, + "LINE_W": 1, + "WINDOW_W": 1100, + "WINDOW_H": 600 + } + } + \ No newline at end of file diff --git a/modele/donnees.py b/modele/donnees.py new file mode 100644 index 0000000..4336fbb --- /dev/null +++ b/modele/donnees.py @@ -0,0 +1,356 @@ +import logging + + +class GraphStructException(Exception): + pass + + +class Noeud(object): + def __init__(self, donnees): + self.nom = donnees['nom'] + self.donnees = donnees + self.type = donnees['type'] + self.assoc_connecteurs = {} + + def __str__(self): + return f"" + + def set_branche(self, direction, branche): + # Associe la branche correspondant à un connecteur + if direction in self.assoc_connecteurs: + self.assoc_connecteurs[direction].append(branche) + else: + self.assoc_connecteurs[direction] = [branche] + + def get_branches(self, direction): + return self.assoc_connecteurs[direction] + + def get_branche(self, direction): + c = self.get_branches(direction) + if len(c) == 1: + return c[0] + else: + raise GraphStructException("Invalid number of connectors") + + def remove_branche(self, branche, direction): + self.assoc_connecteurs[direction].remove(branche) + + +class Arete(object): + def __init__(self, amont, amont_dir, aval, aval_dir): + self.amont = amont + self.amont_dir = amont_dir + self.aval = aval + self.aval_dir = aval_dir + + def deconnecte(self): + self.amont.remove_branche(self, self.amont_dir) + self.aval.remove_branche(self, self.aval_dir) + self.amont = None + self.aval = None + self.amont_dir = None + self.aval_dir = None + + def reconnecte_noeud(self, nsrc, ndir_src, ndest, ndir_dest): + """ + Déconnecte le noeud source, et le remplace par le noeud dest + """ + if nsrc == self.amont and self.amont_dir == ndir_src: + self.amont.remove_branche(self, self.amont_dir) + self.amont = ndest + self.amont_dir = ndir_dest + ndest.set_branche(ndir_dest,self) + elif nsrc == self.aval and self.aval_dir == ndir_src: + self.aval.remove_branche(self, self.aval_dir) + self.aval = ndest + self.aval_dir = ndir_dest + ndest.set_branche(ndir_dest,self) + else: + raise GraphStructException + + def get_neighbour(self, noeud, direction): + if self.amont == noeud and self.amont_dir == direction: + return self.aval, self.aval_dir + elif self.aval == noeud and self.aval_dir == direction: + return self.amont, self.amont_dir + else: + raise GraphStructException("No such neighbour") + + def get_amont(self): + return self.amont, self.amont_dir + + def get_aval (self): + return self.aval, self.aval_dir + + +class Branche(Arete): + def __init__(self, amont, amont_dir, aval, aval_dir, composants=None): + super().__init__(amont, amont_dir, aval, aval_dir) + self.composants = [] if composants is None else composants + + +class Condensateur(object): + """ + Un condensateur correspond en fait à l'objet connecteur câblé à deux noeuds amonts et aval + C'est donc "à la fois un noeud et deux branches" + """ + def __init__(self, donnees): + self.nom = donnees['nom'] + self.donnees = donnees + self.type = donnees['type'] + self.amont = None + self.aval = None + self.amont_dir = None # le connecteur du noeud amont auquel on est raccordé + self.aval_dir = None # le connecteur du noeud aval auquel on est raccordé + + def get_amont(self): + return self.amont, self.amont_dir + + def get_aval (self): + return self.aval, self.aval_dir + + +class SchemaReader(object): + """ + A la lecture du graphe, tous les objets sont des noeuds et ils sont raccordés par des branches. + La simplification permet de supprimer les coudes. + La réduction des branches permet de transformer une série de branches et de composants en une seule branche + contentant les composants. + """ + REDUCTIBLE = ["ContactRepos", "Relais", "Tempo", "ContactTravail", "Bouton", "Resistance", + "Diode", "Lampe", "RelaisCote", "Levier"] + RIEN_A_FAIRE = ["P24", "P0", "Pulse", "Noeud", "Condensateur", "ContactBasculeur", "ContactDouble"] + ID_NOM = -1 + + def __init__(self, d): + self.noeuds = {} + self.condensateurs = {} + self.branches = [] + self.composants = None + self.lire_donnees(d) + + @classmethod + def nouveau_nom(cls, prefix=""): + """ + Crée un nouveau nom + """ + cls.ID_NOM += 1 + return f"@{prefix}{cls.ID_NOM}" + + def connecte(self, n1, d1, n2, d2, composants=None): + """ + Crée une branche et connecte deux noeuds avec + """ + a = Branche(n1, d1, n2, d2, composants=composants) + self.branches.append(a) + n1.set_branche(d1, a) + n2.set_branche(d2, a) + + def connecte_condensateur_amont(self, cond, n1, d1): + cond.amont = n1 + cond.amont_dir = d1 + + def connecte_condensateur_aval(self, cond, n1, d1): + cond.aval = n1 + cond.aval_dir = d1 + + def remove_branche(self, branche): + self.branches.remove(branche) + branche.deconnecte() + return branche.composants + + def remove_noeud(self, noeud): + del self.noeuds[noeud] + + def lire_donnees(self, d): + """ + Lit le dictionnaire contenant le schéma + """ + # On commence par lire les noeuds + try: + for nom, donnees in d['blocs'].items(): + donnees['nom'] = nom + self.noeuds[nom] = Noeud(donnees) + + # On lit (et lie) ensuite les câbles + for amont, dir_amont, aval, dir_aval in d['cables']: + self.connecte(self.noeuds[amont], dir_amont, self.noeuds[aval], dir_aval) + except KeyError: + raise GraphStructException + + def traiter_composites(self): + """ + Traite les noeuds composites (contacts doubles, relais basculeurs, etc.) et les transforme en objets simples. + """ + noeuds_a_supprimer = [] + noeuds_a_ajouter = [] + + for nom, noeud in self.noeuds.items(): + # Parcoure les noeuds en cherchant les noeuds composites + + if noeud.type == "RelaisCote": + # On transforme en relais simple + noeud.type = "Relais" + + if 'orientation' not in noeud.donnees or noeud.donnees['orientation'] == 0: + b_hg = noeud.get_branche("hg") + b_bg = noeud.get_branche("bg") + b_hg.reconnecte_noeud(noeud, "hg", noeud, "g") + b_bg.reconnecte_noeud(noeud, "bg", noeud, "d") + elif noeud.donnees['orientation'] == 180: + b_hd = noeud.get_branche("hd") + b_bd = noeud.get_branche("bd") + b_hd.reconnecte_noeud(noeud, "hd", noeud, "g") + b_bd.reconnecte_noeud(noeud, "bd", noeud, "d") + else: + assert False, "Rien à faire là" + + elif noeud.type == "RelaisBasculeur": + noeuds_a_supprimer.append(nom) + rel_g = Noeud({'nom': noeud.nom + ".gauche", 'type': 'Relais', + 'orientation': noeud.donnees['orientation'], 'basculeur': 'gauche'}) + rel_d = Noeud({'nom': noeud.nom + ".droite", 'type': 'Relais', + 'orientation': noeud.donnees['orientation'], 'basculeur': 'droite'}) + + noeuds_a_ajouter.append((noeud.nom + ".gauche", rel_g)) + noeuds_a_ajouter.append((noeud.nom + ".droite", rel_d)) + + # On récupère les branches + br_hg = noeud.get_branche("hg") + br_bg = noeud.get_branche("bg") + br_hd = noeud.get_branche("hd") + br_bd = noeud.get_branche("bd") + + # Puis les voisins + vois_hg, vois_hg_dir = br_hg.get_neighbour(noeud, "hg") + vois_bg, vois_bg_dir = br_bg.get_neighbour(noeud, "bg") + vois_hd, vois_hd_dir = br_hd.get_neighbour(noeud, "hd") + vois_bd, vois_bd_dir = br_bd.get_neighbour(noeud, "bd") + + # On supprime les branches + cmp_hg = self.remove_branche(br_hg) + cmp_bg = self.remove_branche(br_bg) + cmp_hd = self.remove_branche(br_hd) + cmp_bd = self.remove_branche(br_bd) + + # On lie les nouveaux noeuds + self.connecte(rel_g, "g", vois_hg, vois_hg_dir, cmp_hg) + self.connecte(rel_g, "d", vois_bg, vois_bg_dir, cmp_bg) + self.connecte(rel_d, "g", vois_hd, vois_hd_dir, cmp_hd) + self.connecte(rel_d, "d", vois_bd, vois_bd_dir, cmp_bd) + + [self.remove_noeud(n) for n in noeuds_a_supprimer] + [self.noeuds.__setitem__(nom, valeur) for nom, valeur in noeuds_a_ajouter] + + def simplifier(self): + """ + Simplifie le graphe : + - supprime les coudes + """ + # Supprime les coudes + coudes = [] + for n in self.noeuds.values(): + if n.type == 'Coude': + try: + a1, a2 = n.get_branches("m") + except ValueError: + raise GraphStructException("Un coude doit avoir deux voisins") + + # On récupère les voisins + v1, d1 = a1.get_neighbour(n, "m") + v2, d2 = a2.get_neighbour(n, "m") + + comp1 = self.remove_branche(a1) + comp2 = self.remove_branche(a2) + + self.connecte(v1, d1, v2, d2, comp1 + comp2) + coudes.append(n) + + [self.remove_noeud(n.nom) for n in coudes] + + def traiter_condensateurs(self): + cond_list = [] + for nom, noeud in self.noeuds.items(): + if noeud.type == "Condensateur": + branche_g = noeud.get_branche("g") + branche_d = noeud.get_branche("d") + n1 = self.nouveau_nom() + nn_amont = Noeud({'nom': n1, 'type': 'Noeud'}) + cond_list.append(nn_amont) + n2 = self.nouveau_nom() + nn_aval = Noeud({'nom': n2, 'type': 'Noeud'}) + cond_list.append(nn_aval) + + cond = Condensateur(noeud.donnees) + self.condensateurs[nom] = cond + cond.amont = nn_amont + cond.aval = nn_aval + # On raccorde le nouveau noeud amont au voisin amont initial + voisin_g, dir_g = branche_g.get_neighbour(noeud, "g") + composants_g = self.remove_branche(branche_g) + self.connecte(voisin_g, dir_g, nn_amont, "m", composants_g) + + # Le noeud nouveau noeud amont au condensateur + self.connecte_condensateur_amont(cond, nn_amont, "m") + + # Le nouveau noeud aval au condensateur + self.connecte_condensateur_aval(cond, nn_aval, "m") + + # On raccorde le nouveau noeud aval à la branche aval initiale + voisin_d, dir_d = branche_d.get_neighbour(noeud, "d") + composants_d = self.remove_branche(branche_d) + self.connecte(voisin_d, dir_d, nn_aval, "m", composants_d) + + for c in cond_list: + self.noeuds[c.nom] = c + + def reduire_branches(self): + noeuds_a_supprimer = [] + for nom, noeud in self.noeuds.items(): + if noeud.type in self.REDUCTIBLE: + # Le composant est stockable dans la branche (composant simple en série) + b_gauche = noeud.get_branche("g") + b_droite = noeud.get_branche("d") + + voisin_g, voisin_g_dir = b_gauche.get_neighbour(noeud, "g") + voisin_d, voisin_d_dir = b_droite.get_neighbour(noeud, "d") + + comp_br_gauche = self.remove_branche(b_gauche) + comp_br_droite = self.remove_branche(b_droite) + + self.connecte(voisin_g, voisin_g_dir, voisin_d, voisin_d_dir, comp_br_gauche + [noeud] + comp_br_droite) + + noeuds_a_supprimer.append(nom) + + if noeud.type == "Diode" and noeud.donnees['orientation'] == 180: + noeud.nom = "!" + noeud.nom + + elif noeud.type == "Coude": + assert False, "Les coudes auraient dûs être éliminés !" + elif noeud.type in self.RIEN_A_FAIRE: + pass + else: + raise GraphStructException("Type inconnu : " + noeud.type) + + for n in noeuds_a_supprimer: + del self.noeuds[n] + + def make_liste_composants(self): + self.composants = {} + for b in self.branches: + for c in b.composants: + self.composants[c.nom] = c + + def process(self): + """ + Méthode principale de traitement du graphe + """ + try: + self.simplifier() + self.traiter_composites() + self.traiter_condensateurs() + self.reduire_branches() + self.make_liste_composants() + except KeyError: + logging.exception("Erreur de chaînage dans le graphe") + raise GraphStructException \ No newline at end of file diff --git a/modele/elements.py b/modele/elements.py new file mode 100644 index 0000000..c03400e --- /dev/null +++ b/modele/elements.py @@ -0,0 +1,514 @@ +from modele.exceptions import (WrongElecPropertyException, SurtensionException, + SurintensiteException, Dir) + + +class Element(object): + """ + Classe mère. + Le graphe lui-même est composé de Potentiels fixes (Potentiel), de Noeuds, et de Branches. + Les branches contiennent une liste de composants en série. + + Les éléments doivent implémenter quatre méthodes pour le calcul des valeurs : + init_cycle est appelée avant chaque cycle, avant l'initialisation de la matrice + report_pass_1 est appelée après la première passe pour report des valeurs de la matrice (et avant la construction + de la matrice de la deuxième passe) + report_pass2 est appelée après la 2e passe pour reporter les valeurs finales calculées + update est appelée après le report de la 2e passe, pour pouvoir faire la mise à jour des états des éléments + + """ + P_CST, P_NOEUD, P_DLT, P_COND, P_EQVAR, P_BSCLAME = range(6) + + def __init__(self, conf, nom, type_potentiel): + self.type_potentiel = type_potentiel + self.conf = conf + self.nom = nom + + def init_cycle(self): + pass + + def passe_calcul(self, solutions, index): + pass + + def update(self): + pass + + def etat(self): + raise NotImplementedError + + def coherence(self): + raise NotImplementedError + + def eq_elts(self): + """ + Retourne les équipotentiels + Par défaut, un seul équipotentiel + """ + return [self] + + def get_potentiel(self, direction): + """ + Par défaut, un seul potentiel quel que soit la direction + """ + return self + + +class Potentiel(Element): + """ + Potentiel à 24V ou à 0V + """ + + def __init__(self, conf, nom, u=0.0, voisins=None): + super().__init__(conf, nom, self.P_CST) + self._u = u + if voisins is None: + voisins = [] + self._voisins = voisins + + def add_voisins(self, voisins): + self._voisins += voisins + + def voisins(self): + return self._voisins + + def u(self): + return self._u + + def i(self): + raise WrongElecPropertyException + + def coherence(self): + pass + + def etat(self): + return self.u() >= self.conf['USEUIL'] + +class PotPulse(Potentiel): + def __init__(self, conf, nom, u=0.0, periode=None, voisins=None): + super().__init__(conf, nom, u, voisins) + if periode is None: + periode = self.conf['PULSE_PERIODE'] + self.periode = periode / self.conf['DT'] + self.u_max = u + self.actif = True + self.compteur = 0 + + def update(self): + self.compteur += 1 + if self.actif: + if self.compteur >= self.periode: + self.compteur = 0 + self._u = 0. + self.actif = False + else: + if self.compteur >= self.periode: + self.compteur = 0 + self._u = self.u_max + self.actif = True + + +class Noeud(Element): + """ + Nœud du graphe + + self._voisins: liste de (Graphe, polarité) avec polarité = +1 ou -1 pour les branches + """ + def __init__(self, conf, nom, voisins=None): + super().__init__(conf, nom, self.P_NOEUD) + self._u = None + if voisins is None: + voisins = [] + self._voisins = voisins + + def add_voisins(self, voisins): + self._voisins += voisins + + def voisins(self): + return self._voisins + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self._u = vect[index] + + def u(self): + return self._u + + def coherence(self): + if abs(self.u()) >= self.conf['UMAX']: + raise SurtensionException + + def etat(self): + return self.u() >= self.conf['USEUIL'] + + +class Branche(Element): + """ + Branche du graphe. + La branche contient un certain nombre de composants en série, qui peuvent être des relais, tempos, résistances + ou contacts (équation). N'est pas utilisable pour les condensateurs. + """ + def __init__(self, conf, nom, composants): + super().__init__(conf, nom, self.P_DLT) + self.composants = composants + self.amont = None + self.aval = None + self._i = 0.0 + + def add_voisins(self, amont, aval): + self.amont = amont + self.aval = aval + + def r(self): + return sum([x.r for x in self.composants]) + self.conf['RMIN'] + + def init_cycle(self): + super().init_cycle() + [x.init_cycle() for x in self.composants] + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self._i = vect[index] # Important de mettre à jour i avant de mettre à jour les composants + [x.passe_calcul() for x in self.composants] + + def update(self): + super().update() + [x.update() for x in self.composants] + + def i(self): + return self._i + + def coherence(self): + if abs(self.i()) >= self.conf['IMAX']: + raise SurintensiteException(f"Dans la branche {self.nom}") + + def etat(self): + return self.i() >= self.conf['ISEUIL'] + + +class Condensateur(Element): + """ + Condensateur. + + La seule truande est que la tension au borne est en réalité calculée avec la charge du cycle précédent. + """ + def __init__(self, conf, nom, capacite, coef_mul_tension): + super().__init__(conf, nom, self.P_COND) + self.capacite = capacite + self.amont = None + self.aval = None + self._i = 0.0 + self.q = 0.0 + self.q_prec = 0.0 + self.coef_mul_tension = coef_mul_tension + + def add_voisins(self, amont, aval): + self.amont = amont + self.aval = aval + + def r(self): + raise WrongElecPropertyException + + def init_cycle(self): + super().init_cycle() + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self._i = vect[index] # Important de mettre à jour i avant de mettre à jour les composants + + def update(self): + super().update() + self.q_prec = self.q + q = self.q + self.i() * self.conf['DT'] + self.q = q + + def i(self): + return self._i + + def coherence(self): + if abs(self.i()) >= self.conf['IMAX']: + raise SurintensiteException + + def etat(self): + return bool(self.i() >= self.conf['ISEUIL']) + + +class ContactBasculeur(Noeud): + """ + Nœud du graphe + + self._voisins: liste de (Graphe, polarité) avec polarité = +1 ou -1 pour les branches + """ + UMAX = 24.5 + + class PotentielLocal(Element): + def __init__(self, conf, nom, voisins=None): + self.lame = None + super().__init__(conf, nom, self.P_NOEUD) + self._u = None + if voisins is None: + voisins = [] + self._voisins = voisins + self.etat = False + + def set_lame(self, lame): + self.lame = lame + + def add_voisins(self, voisins): + self._voisins += voisins + + def set_etat(self, etat): + self.etat = etat + + def voisins(self): + return self._voisins + ([(self.lame, +1, "foo")] if self.etat else []) + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self._u = vect[index] + + def u(self): + return self._u + + def coherence(self): + if abs(self.u()) >= self.conf['UMAX']: + raise SurtensionException + + class Lame(Element): + def __init__(self, conf, nom, contact, gauche, droite): + self.amont = contact + self.aval = None + self.gauche = gauche + self.droite = droite + self.position = None + super().__init__(conf, nom, self.P_DLT) + self._i = None + + def bascule(self, position): + self.position = position + if position == Dir.GAUCHE: + self.aval = self.gauche + else: + self.aval = self.droite + + def i(self): + return self._i + + def r(self): + return self.conf['RMIN'] + + # Classe principale + def __init__(self, conf, nom, graphe, voisins=None): + self.graphe = graphe + self.position = None + self.potentiel_gauche = self.PotentielLocal(conf, nom + ".G") + self.potentiel_droit = self.PotentielLocal(conf, nom + ".D") + self.lame = self.Lame(conf, nom + ".L", self, self.potentiel_gauche, self.potentiel_droit) + self.potentiel_gauche.set_lame(self.lame) + self.potentiel_droit.set_lame(self.lame) + self._voisins = [(self.lame, -1, "foo")] + voisins if voisins is not None else [] + super().__init__(conf, nom, self.P_NOEUD) + self.bascule_gauche() + + def eq_elts(self): + return [self, self.potentiel_gauche, self.potentiel_droit, self.lame] + + def add_voisins(self, voisins): + for vois_tuple in voisins: + _, _, connecteur = vois_tuple + if connecteur == 'b': + self._voisins = [vois_tuple] + else: + # Les autres connecteurs doivent être câblés vers les ConnecteursLocaux + raise "Invalid connector for RelaisBasculeur" + + def voisins(self): + return self._voisins + + def bascule_gauche(self): + self.position = Dir.GAUCHE + self.lame.bascule(self.position) + self.potentiel_gauche.set_etat(True) + self.potentiel_droit.set_etat(False) + + def bascule_droite(self): + self.position = Dir.DROITE + self.lame.bascule(self.position) + self.potentiel_gauche.set_etat(False) + self.potentiel_droit.set_etat(True) + + def get_potentiel(self, direction): + """ + Par défaut, un seul potentiel quel que soit la direction + """ + if direction == "b": + return self + elif direction == "g": + return self.potentiel_gauche + elif direction == "d": + return self.potentiel_droit + else: + assert False + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self.potentiel_droit.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_droit)) + self.potentiel_gauche.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_gauche)) + self._u = vect[index] + + def u(self): + return self._u + + def etat(self): + return self.lame.position + + def coherence(self): + if abs(self.u()) >= self.conf['UMAX']: + raise SurtensionException + self.potentiel_droit.coherence() + self.potentiel_gauche.coherence() + + +class ContactDouble(Noeud): + """ + Nœud du graphe + + self._voisins: liste de (Graphe, polarité) avec polarité = +1 ou -1 pour les branches + """ + UMAX = 24.5 + + class PotentielLocal(Element): + def __init__(self, conf, nom, voisins=None): + self.lame = None + super().__init__(conf, nom, self.P_NOEUD) + self._u = None + if voisins is None: + voisins = [] + self._voisins = voisins + self.etat = False + + def set_lame(self, lame): + self.lame = lame + + def add_voisins(self, voisins): + self._voisins += voisins + + def set_etat(self, etat): + self.etat = etat + + def voisins(self): + return self._voisins + ([(self.lame, +1, "foo")] if self.etat else []) + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self._u = vect[index] + + def u(self): + return self._u + + def coherence(self): + if abs(self.u()) >= self.conf['UMAX']: + raise SurtensionException + + class Lame(Element): + def __init__(self, conf, nom, contact, gauche, droite): + self.amont = contact + self.aval = None + self.repos = gauche + self.travail = droite + self.position = False # Travail = True + super().__init__(conf, nom, self.P_DLT) + self._i = None + + def set_position(self, position): + self.position = position + if position: + self.aval = self.travail + else: + self.aval = self.repos + + def i(self): + return self._i + + def r(self): + return self.conf['RMIN'] + + # Classe principale + def __init__(self, conf, nom, graphe, voisins=None, orientation=0): + self.graphe = graphe + self.orientation = orientation + self.potentiel_repos = self.PotentielLocal(conf, nom + ".repos") + self.potentiel_travail = self.PotentielLocal(conf, nom + ".travail") + self.lame = self.Lame(conf, nom + ".L", self, self.potentiel_repos, self.potentiel_travail) + self.potentiel_repos.set_lame(self.lame) + self.potentiel_travail.set_lame(self.lame) + self._voisins = [(self.lame, -1, "foo")] + voisins if voisins is not None else [] + super().__init__(conf, nom, self.P_NOEUD) + self.lame.set_position(False) + + def eq_elts(self): + return [self, self.potentiel_repos, self.potentiel_travail, self.lame] + + def add_voisins(self, voisins): + for vois_tuple in voisins: + _, _, connecteur = vois_tuple + if (self.orientation == 0 and connecteur == 'd') \ + or (self.orientation == 180 and connecteur == 'g'): + self._voisins = [vois_tuple] + else: + # Les autres connecteurs doivent être câblés vers les ConnecteursLocaux + raise "Invalid connector for ContactDouble" + + def voisins(self): + return self._voisins + + def get_potentiel(self, direction): + """ + Par défaut, un seul potentiel quel que soit la direction + """ + if self.orientation == 0: + if direction == "d": + return self + elif direction == "bg": + return self.potentiel_repos + elif direction == "hg": + return self.potentiel_travail + else: + assert False + elif self.orientation == 180: + if direction == "g": + return self + elif direction == "bd": + return self.potentiel_repos + elif direction == "hd": + return self.potentiel_travail + else: + assert False + else: + assert False + + def passe_calcul(self, vect, index): + super().passe_calcul(vect, index) + self.potentiel_travail.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_travail)) + self.potentiel_repos.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_repos)) + self._u = vect[index] + + def u(self): + return self._u + + def etat(self): + return self.lame.position + + def coherence(self): + if abs(self.u()) >= self.conf['UMAX']: + raise SurtensionException + self.potentiel_travail.coherence() + self.potentiel_repos.coherence() + + def active(self): + self.lame.set_position(True) + self.potentiel_travail.set_etat(True) + self.potentiel_repos.set_etat(False) + + def desactive(self): + self.lame.set_position(False) + self.potentiel_travail.set_etat(False) + self.potentiel_repos.set_etat(True) \ No newline at end of file diff --git a/modele/exceptions.py b/modele/exceptions.py new file mode 100644 index 0000000..573d57a --- /dev/null +++ b/modele/exceptions.py @@ -0,0 +1,22 @@ +from enum import IntEnum + + +class WrongElecPropertyException(Exception): + pass + + +class NonPolariseException(Exception): + pass + + +class SurtensionException(Exception): + pass + + +class SurintensiteException(Exception): + pass + + +class Dir(IntEnum): + GAUCHE = 1 + DROITE = 2 \ No newline at end of file diff --git a/modele/graphe.py b/modele/graphe.py new file mode 100644 index 0000000..574c49d --- /dev/null +++ b/modele/graphe.py @@ -0,0 +1,171 @@ +import modele.composants as mc +import modele.elements as me +from modele.exceptions import Dir +from modele.donnees import GraphStructException + + +class Vecteur(object): + """ + Associe les éléments du graphe à leur rang dans le vecteur correspondant aux rangs dans la matrice. + """ + def __init__(self, elements): + self._liste = [eq_elt for element in elements.values() for eq_elt in element.eq_elts()] + + self._index = {} # Associe à un élément son index dans la matrice + for index, element in enumerate(self._liste): + self._index[element] = index + + def __len__(self): + return len(self._liste) + + def index(self, element): + return self._index[element] + + def __iter__(self): + return self._liste.__iter__() + + +class Graphe(object): + ID_BR = -1 + + @classmethod + def branch_id(cls): + cls.ID_BR += 1 + return f"b{cls.ID_BR}" + + def __init__(self, conf): + self.conf = conf + self.elements = None + self.composants = None + self.vecteur = None + + def load_data_from_schema_reader(self, reader): + self.elements = {} + self.composants = {} + + # Construction des éléments et composants + for nom, valeur in reader.composants.items(): + if valeur.type == 'Bouton' or valeur.type == 'ContactTravail' or valeur.type == 'ContactRepos' \ + or valeur.type == 'Levier': + self.composants[nom] = mc.Contact(self.conf, nom, valeur.type) + elif valeur.type == 'Relais': + if valeur.donnees.get('basculeur') == 'gauche': + self.composants[nom] = mc.DemiRelaisBasculeur(self.conf, nom, self, Dir.GAUCHE) + elif valeur.donnees.get('basculeur') == 'droite': + self.composants[nom] = mc.DemiRelaisBasculeur(self.conf, nom, self, Dir.DROITE) + else: + self.composants[nom] = mc.Relais(self.conf, nom, self) + elif valeur.type == 'Tempo': + self.composants[nom] = mc.Tempo(self.conf, nom, valeur.donnees['tempo_blocage'], + valeur.donnees['tempo_liberation']) + elif valeur.type == 'Resistance': + if 'valeur' not in valeur.donnees: + v = None + else: + v = valeur.donnees['valeur'] + self.composants[nom] = mc.Resistance(self.conf, nom, v) + del v + elif valeur.type == 'Lampe': + self.composants[nom] = mc.Lampe(self.conf, nom) + elif valeur.type == 'Diode': + d = mc.Diode(self.conf, nom) + self.composants[nom] = d + self.composants["!" + nom] = d + del d + + for nom, valeur in reader.noeuds.items(): + if valeur.type == "Noeud": + self.elements[nom] = me.Noeud(self.conf, nom) + elif valeur.type == "P24": + self.elements[nom] = me.Potentiel(self.conf, nom, 24.) + elif valeur.type == "P0": + self.elements[nom] = me.Potentiel(self.conf, nom, 0.) + elif valeur.type == "Pulse": + if "periode" not in valeur.donnees: + p = None + else: + p = valeur.donnees["periode"] + self.elements[nom] = me.PotPulse(self.conf, nom, 24., p) + elif valeur.type == "ContactBasculeur": + self.elements[nom] = me.ContactBasculeur(self.conf, nom, self) + elif valeur.type == "ContactDouble": + self.elements[nom] = me.ContactDouble(self.conf, nom, self, orientation=valeur.donnees['orientation']) + + for nom, valeur in reader.condensateurs.items(): + cnd = me.Condensateur(self.conf, nom, valeur.donnees['capacite'], valeur.donnees['coef_mul_tension']) + + v_amont_schm, v_amont_dir = valeur.get_amont() + v_aval_schm, v_aval_dir = valeur.get_aval() + + v_amont = self.elements[v_amont_schm.nom] + v_aval = self.elements[v_aval_schm.nom] + + cnd.add_voisins(v_amont, v_aval) + v_amont.add_voisins([(cnd, -1, v_amont_dir)]) + v_aval.add_voisins([(cnd, +1, v_aval_dir)]) + self.elements[nom] = cnd + del cnd + + # Ajout des liens entre relais et contacts + try: + for nom, valeur in reader.composants.items(): + if valeur.type == "ContactTravail": + self.composants[valeur.donnees["relais"]].add_travail(nom) + elif valeur.type == "ContactRepos": + self.composants[valeur.donnees["relais"]].add_repos(nom) + + for nom, valeur in reader.noeuds.items(): + if valeur.type == "ContactBasculeur": + self.composants[valeur.donnees["relais"] + ".gauche"].add_contact(nom) + self.composants[valeur.donnees["relais"] + ".droite"].add_contact(nom) + elif valeur.type == "ContactDouble": + self.composants[valeur.donnees["relais"]].add_double(nom) + except KeyError: + raise GraphStructException("Mauvais identificateur de relais dans un contact") + + # Construction des branches + for branche in reader.branches: + nom = self.branch_id() + br = me.Branche(self.conf, nom, [self.composants[x.nom] for x in branche.composants]) + [self.composants[x.nom].reverse() for x in branche.composants if x.nom[0] == '!'] # Diode + for c in br.composants: + c.branche = br + + v_amont_schm, v_amont_dir = branche.get_amont() + v_aval_schm, v_aval_dir = branche.get_aval() + + v_amont = self.elements[v_amont_schm.nom].get_potentiel(v_amont_dir) + v_aval = self.elements[v_aval_schm.nom].get_potentiel(v_aval_dir) + + br.add_voisins(v_amont, v_aval) + v_amont.add_voisins([(br, -1, v_amont_dir)]) + v_aval.add_voisins([(br, +1, v_aval_dir)]) + self.elements[nom] = br + del br + + self.vecteur = Vecteur(self.elements) + + def __getitem__(self, item): + """ + Retourne un composant + """ + if item in self.composants: + res = self.composants[item] + else: + res = self.elements[item] + return res + + def __contains__(self, item): + return item in self.composants or item in self.elements + + def init_cycle(self): + [elt.init_cycle() for elt in self.elements.values()] + + def passe_calcul(self, solutions): + [elt.passe_calcul(solutions, self.vecteur.index(elt)) for elt in self.elements.values()] + + def update(self): + [elt.update() for elt in self.elements.values()] + + def coherence(self): + [x.coherence() for x in self.elements.values()] diff --git a/modele/matrice.py b/modele/matrice.py new file mode 100644 index 0000000..30b3bf8 --- /dev/null +++ b/modele/matrice.py @@ -0,0 +1,57 @@ +import numpy as np + + +class Matrice(object): + """ + Le système d'équation est construit sur la base d'une matrice A et un vecteur B modélisant le système, tels que + A.X = B + + Chaque ligne de la matrice correspond à une équation, correspondant elle-même à un élément du graphe. + Les équations sont dans le même ordre que les éléments du graphe. + + Chaque colonne correspond à une inconnue, également prise dans le même ordre que les éléments du graphe. + Si l'élément est un Potentiel ou un noeud, l'inconnue est une tension. + Si l'élément est une branche, l'inconnue est l'intensité parcourant la branche. + """ + def __init__(self, graphe): + self.vecteur = graphe.vecteur + self.mat_A = None + self.mat_B = None # Equation matricielle AX = B + self.n = len(self.vecteur) + + def init_mat(self): + self.mat_A = np.zeros((self.n, self.n)) + self.mat_B = np.zeros(self.n) + + for ligne, element in enumerate(self.vecteur): # Potentiel constant + # assert ligne == self.vecteur.index(element) + if element.type_potentiel == element.P_CST: + # Potentiel constant : on ajoute une équation indiquant la valeur de la tension pour cette variable + self.mat_A[ligne][ligne] = 1.0 # à noter que par construction, ligne == index + self.mat_B[ligne] = element.u() + + elif element.type_potentiel == element.P_NOEUD: # On applique la loi des noeuds + # Noeud : on ajoute une équation sur la somme des intensités + for (voisin, polarite, _) in element.voisins(): + self.mat_A[ligne][self.vecteur.index(voisin)] = polarite + self.mat_B[ligne] = 0.0 + + elif element.type_potentiel == element.P_DLT: # On applique la loi d'Ohm + self.mat_A[ligne][ligne] = 1.0 + self.mat_A[ligne][self.vecteur.index(element.amont)] = -1.0 / element.r() + self.mat_A[ligne][self.vecteur.index(element.aval)] = 1.0 / element.r() + self.mat_B[ligne] = 0.0 + + elif element.type_potentiel == element.P_COND: # DU = q/C + self.mat_A[ligne][self.vecteur.index(element.amont)] = 1.0 + self.mat_A[ligne][self.vecteur.index(element.aval)] = -1.0 + self.mat_B[ligne] = element.coef_mul_tension * element.q / element.capacite + + else: + assert False, "Rien à faire là" + + def solve(self): + """ + Résout le système d'équation et retourne le vecteur solution. + """ + return np.linalg.solve(self.mat_A, self.mat_B) diff --git a/requirements.txt b/requirements.txt index e69de29..4755eea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1,3 @@ +numpy>=1.24.3 +flask>=2.3.2 +Flask-Cors>=4.0.0 \ No newline at end of file diff --git a/run.py b/run.py index e69de29..e828d5d 100644 --- a/run.py +++ b/run.py @@ -0,0 +1,6 @@ +from api_server.app import main + +import sys + +if __name__ == "__main__": + main(sys.argv) diff --git a/schemas_v1/basculeur.ccs b/schemas_v1/basculeur.ccs new file mode 100644 index 0000000..adaf496 --- /dev/null +++ b/schemas_v1/basculeur.ccs @@ -0,0 +1 @@ +{"blocs":{"p24-1":{"type":"P24","valeur":24,"x":0,"y":526},"b1":{"type":"Bouton","x":100,"y":526,"orientation":0},"rbas":{"type":"RelaisBasculeur","x":200,"y":520,"orientation":0},"b2":{"type":"Bouton","x":350,"y":526,"orientation":180},"p24-2":{"type":"P24","valeur":24,"x":450,"y":526,"orientation":180},"p0-1":{"type":"P0","x":0,"y":512,"orientation":180},"p0-2":{"type":"P0","x":450,"y":512,"orientation":0},"p0-3":{"type":"P0","x":0,"y":299,"orientation":180},"p0-4":{"type":"P0","x":450,"y":299,"orientation":0},"l3":{"type":"Lampe","x":100,"y":299,"orientation":0},"l4":{"type":"Lampe","x":350,"y":299,"orientation":0},"rbas.basc":{"type":"ContactBasculeur","relais":"rbas","x":200,"y":285,"orientation":0},"p24-3":{"type":"P24","x":150,"y":258.2}},"cables":[["p24-1","d","b1","g"],["b1","d","rbas","hg"],["p0-1","d","rbas","bg"],["p24-2","g","b2","d"],["b2","g","rbas","hd"],["p0-2","g","rbas","bd"],["p0-3","d","l3","g"],["p0-4","g","l4","d"],["l3","d","rbas.basc","g"],["l4","g","rbas.basc","d"],["p24-3","d","rbas.basc","b"]]} \ No newline at end of file diff --git a/schemas_v1/condensateur.ccs b/schemas_v1/condensateur.ccs new file mode 100644 index 0000000..b446539 --- /dev/null +++ b/schemas_v1/condensateur.ccs @@ -0,0 +1,104 @@ +{ + "blocs": { + "p24-1": { + "type": "P24", + "valeur": 24.0, + "x": 0, + "y": 500 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 1200, + "y": 500 + }, + "p0-2": { + "type": "P0", + "valeur": 0.0, + "x": 1200, + "y": 300 + }, + "p0-3": { + "type": "P0", + "valeur": 0.0, + "x": 600, + "y": 300 + }, + "xx": { + "type": "Noeud", + "x": 300, + "y": 500 + }, + "yy": { + "type": "Coude", + "x": 300, + "y": 300 + }, + "k1": { + "type": "Condensateur", + "capacite": 0.4, + "coef_mul_tension": 24, + "x": 400, + "y": 500 + }, + "r2": { + "type": "Relais", + "x": 1000, + "y": 500 + }, + "c3": { + "type": "Bouton", + "x": 200, + "y": 500, + "orientation": 180 + }, + "r2.travail": { + "type": "ContactTravail", + "relais": "r2", + "x": 1000, + "y": 300 + }, + "w1": { + "type": "Lampe", + "x": 600, + "y": 500 + }, + "n1": { + "type": "Noeud", + "x": 800, + "y": 500 + }, + "coude1": { + "type": "Coude", + "x": 800, + "y": 300 + }, + "b2": { + "type": "Bouton", + "x": 400, + "y": 300 + }, + "w2": { + "type": "Resistance", + "valeur": 20, + "x": 500, + "y": 300 + } + }, + "cables": [ + ["p24-1", "d", "c3", "g"], + ["c3", "d", "xx", "m"], + ["xx", "m", "k1", "g"], + ["k1", "d", "w1", "g"], + ["w1", "d", "n1", "m"], + ["n1", "m", "r2", "g"], + ["r2", "d", "p0-1", "g"], + ["n1", "m", "coude1", "m"], + ["coude1", "m", "r2.travail", "g"], + ["r2.travail", "d", "p0-2", "g"], + ["xx", "m", "yy", "m"], + ["yy", "m", "b2", "g"], + ["b2", "d", "w2", "g"], + ["w2", "d", "p0-3", "g"] + ] +} \ No newline at end of file diff --git a/schemas_v1/contact_double.ccs b/schemas_v1/contact_double.ccs new file mode 100644 index 0000000..d04d979 --- /dev/null +++ b/schemas_v1/contact_double.ccs @@ -0,0 +1,87 @@ +{ + "blocs": { + "p24-1": { + "type": "P24", + "valeur": 24.0, + "orientation": 0, + "x": 0.0, + "y": 500.0 + }, + "p24-2": { + "type": "P24", + "valeur": 24.0, + "orientation": 0, + "x": 0.0, + "y": 300.0 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "orientation": 0, + "x": 1200.0, + "y": 500.0 + }, + "p0-2": { + "type": "P0", + "valeur": 0.0, + "x": 1200.0, + "y": 300.0 + }, + "r1": { + "type": "Relais", + "x": 400.0, + "y": 500.0 + }, + "r2": { + "type": "Relais", + "x": 1000.0, + "y": 500.0 + }, + "c3": { + "type": "Bouton", + "x": 200.0, + "y": 500.0, + "orientation": 0 + }, + "r2.double": { + "type": "ContactDouble", + "relais": "r2", + "orientation": 0, + "x": 1000.0, + "y": 300.0 + }, + "w1": { + "type": "Lampe", + "x": 600.0, + "y": 500.0 + }, + "w2": { + "type": "Lampe", + "x": 600.0, + "y": 300.0 + }, + "n1": { + "type": "Noeud", + "x": 800.0, + "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/contact_double_180.ccs b/schemas_v1/contact_double_180.ccs new file mode 100644 index 0000000..efb84d0 --- /dev/null +++ b/schemas_v1/contact_double_180.ccs @@ -0,0 +1,73 @@ +{ + "blocs": { + "p24": { + "type": "P24", + "valeur": 24.0, + "x": 0, + "y": 500 + }, + "b": { + "type": "Levier", + "x": 100, + "y": 500 + }, + "r": { + "type": "Relais", + "x": 200, + "y": 500 + }, + "p0-1": { + "type": "P0", + "x": 400, + "y": 500 + }, + "pulse": { + "type": "Pulse", + "valeur": 24.0, + "periode": 0.5, + "x": 0, + "y": 300 + }, + "r.double": { + "type": "ContactDouble", + "relais": "r", + "orientation": 180, + "x": 200, + "y": 300 + }, + "l1": { + "type": "Lampe", + "x": 300, + "y": 330 + }, + "l2": { + "type": "Lampe", + "x": 300, + "y": 270 + }, + "p0-2": { + "type": "P0", + "valeur": 0.0, + "x": 400, + "y": 330 + }, + "p0-3": { + "type": "P0", + "valeur": 0.0, + "x": 400, + "y": 270 + } + }, + "cables": [ + ["p24", "d", "b", "g"], + ["b", "d", "r", "g"], + ["r", "d", "p0-1", "g"], + + ["pulse", "d", "r.double", "g"], + ["r.double", "hd", "l1", "g"], + ["l1", "d", "p0-2", "g"], + + ["r.double", "bd", "l2", "g"], + ["l2", "d", "p0-3", "g"] + ] +} diff --git a/schemas_v1/diodes.ccs b/schemas_v1/diodes.ccs new file mode 100644 index 0000000..6d96bbe --- /dev/null +++ b/schemas_v1/diodes.ccs @@ -0,0 +1,68 @@ +{ + "blocs": { + "pulse": { + "type": "Pulse", + "valeur": 24.0, + "periode": 1, + "x": 0, + "y": 500 + }, + "noeud": { + "type": "Noeud", + "x": 200, + "y": 500 + }, + "coude2": { + "type": "Coude", + "x": 200, + "y": 300 + }, + + "diode1": { + "type": "Diode", + "orientation": 0, + "x": 350, + "y": 500 + }, + "diode2": { + "type": "Diode", + "orientation": 180, + "x": 350, + "y": 300 + }, + + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 600, + "y": 500 + }, + "p0-2": { + "type": "P0", + "valeur": 0.0, + "x": 600, + "y": 300 + }, + "l1": { + "type": "Lampe", + "x": 450, + "y": 500 + }, + "l2": { + "type": "Lampe", + "x": 450, + "y": 300 + } + + }, + "cables": [ + ["pulse", "d", "noeud", "m"], + ["noeud", "m", "diode1", "g"], + ["diode1", "d", "l1", "g"], + ["l1", "d", "p0-1", "g"], + ["noeud", "m", "coude2", "m"], + ["coude2", "m", "diode2", "g"], + ["diode2", "d", "l2", "g"], + ["l2", "d", "p0-2", "g"] + ] +} diff --git a/schemas_v1/errors/error.ccs b/schemas_v1/errors/error.ccs new file mode 100644 index 0000000..711fad8 --- /dev/null +++ b/schemas_v1/errors/error.ccs @@ -0,0 +1,70 @@ +{ + "blocs": + "p24-1": { + "type": "P24", + "valeur": 24.0, + "x": 0, + "y": 500 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 1200, + "y": 500 + }, + "p0-2": { + "type": "P0", + "valeur": 0.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 + }, + "r2.travail": { + "type": "ContactTravail", + "x": 1000, + "y": 300 + }, + "t1": { + "type": "Tempo", + "tempo_blocage": 2, + "tempo_liberation": 1, + "x": 600, + "y": 500 + }, + "n1": { + "type": "Noeud", + "x": 800, + "y": 500 + }, + "coude1": { + "type": "Coude", + "x": 800, + "y": 300 + } + }, + "cables": [ + ["p24-1", "d", "c3", "g"], + ["c3", "d", "r1", "g"], + ["r1", "d", "t1", "g"], + ["t1", "d", "n1", "m"], + ["n1", "m", "r2", "g"], + ["r2", "d", "p0-1", "g"], + ["n1", "m", "coude1", "m"], + ["coude1", "m", "r2.travail", "g"], + ["r2.travail", "d", "p0-2", "g"] + ] +} diff --git a/schemas_v1/errors/error_id.ccs b/schemas_v1/errors/error_id.ccs new file mode 100644 index 0000000..77c108e --- /dev/null +++ b/schemas_v1/errors/error_id.ccs @@ -0,0 +1,72 @@ +{ + "blocs": { + "p24-1": { + "type": "P24", + "valeur": 24.0, + "orientation": 0, + "x": 0.0, + "y": 500.0 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "orientation": 0, + "x": 1200.0, + "y": 500.0 + }, + "p0-2": { + "type": "P0", + "valeur": 0.0, + "x": 1200.0, + "y": 300.0 + }, + "r1": { + "type": "Relais", + "x": 400.0, + "y": 500.0 + }, + "r2": { + "type": "Relais", + "x": 1000.0, + "y": 500.0 + }, + "c3": { + "type": "Bouton", + "x": 200.0, + "y": 500.0, + "orientation": 0 + }, + "r2.travail": { + "type": "ContactTravail", + "orientation": 0, + "x": 1000.0, + "y": 300.0 + }, + "w1": { + "type": "Lampe", + "x": 600.0, + "y": 500.0 + }, + "n1": { + "type": "Noeud", + "x": 800.0, + "y": 500 + }, + "coude1": { + "type": "Coude", + "x": 800, + "y": 300 + } + }, + "cables": [ + ["p24-1", "d", "c3", "g"], + ["c3", "d", "r1", "g"], + ["r1", "d", "w1", "g"], + ["w1", "d", "n2", "m"], + ["n1", "m", "r2", "g"], + ["r2", "d", "p0-1", "g"], + ["n1", "m", "coude1", "m"], + ["coude1", "m", "r2.travail", "g"], + ["r2.travail", "d", "p0-2", "g"] + ] +} \ No newline at end of file diff --git a/schemas_v1/errors/error_short_cc.ccs b/schemas_v1/errors/error_short_cc.ccs new file mode 100644 index 0000000..23be686 --- /dev/null +++ b/schemas_v1/errors/error_short_cc.ccs @@ -0,0 +1,20 @@ +{ + "blocs": { + "pulse": { + "type": "Pulse", + "valeur": 24.0, + "periode": 0.5, + "x": 0, + "y": 500 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 400, + "y": 500 + } + }, + "cables": [ + ["pulse", "d", "p0-1", "g"] + ] +} diff --git a/schemas_v1/errors/no_pot.ccs b/schemas_v1/errors/no_pot.ccs new file mode 100644 index 0000000..65069a5 --- /dev/null +++ b/schemas_v1/errors/no_pot.ccs @@ -0,0 +1,24 @@ +{ + "blocs": { + "n1": { + "type": "Noeud", + "x": 0, + "y": 500 + }, + "n2": { + "type": "Noeud", + "valeur": 0.0, + "x": 400, + "y": 500 + }, + "l": { + "type": "Lampe", + "x": 250, + "y": 500 + } + }, + "cables": [ + ["n1", "m", "l", "g"], + ["l", "d", "n2", "m"] + ] +} diff --git a/schemas_v1/errors/one_pot.ccs b/schemas_v1/errors/one_pot.ccs new file mode 100644 index 0000000..5209f76 --- /dev/null +++ b/schemas_v1/errors/one_pot.ccs @@ -0,0 +1,26 @@ +{ + "blocs": { + "pulse": { + "type": "Pulse", + "valeur": 24.0, + "periode": 1.0, + "x": 0, + "y": 500 + }, + "n": { + "type": "Noeud", + "valeur": 0.0, + "x": 400, + "y": 500 + }, + "l": { + "type": "Lampe", + "x": 250, + "y": 500 + } + }, + "cables": [ + ["pulse", "d", "l", "g"], + ["l", "d", "n", "m"] + ] +} diff --git a/schemas_v1/pulse.ccs b/schemas_v1/pulse.ccs new file mode 100644 index 0000000..df06e0d --- /dev/null +++ b/schemas_v1/pulse.ccs @@ -0,0 +1,26 @@ +{ + "blocs": { + "pulse": { + "type": "Pulse", + "valeur": 24.0, + "periode": 1.0, + "x": 0, + "y": 500 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 400, + "y": 500 + }, + "l": { + "type": "Lampe", + "x": 250, + "y": 500 + } + }, + "cables": [ + ["pulse", "d", "l", "g"], + ["l", "d", "p0-1", "g"] + ] +} diff --git a/schemas_v1/relais_cote.ccs b/schemas_v1/relais_cote.ccs new file mode 100644 index 0000000..da59ccc --- /dev/null +++ b/schemas_v1/relais_cote.ccs @@ -0,0 +1,75 @@ +{ + "blocs": { + "p24": { + "type": "P24", + "valeur": 24.0, + "x": 0, + "y": 550 + }, + "p0": { + "type": "P0", + "valeur": 0.0, + "orientation": 180, + "x": 0, + "y": 470 + }, + "b": { + "type": "Bouton", + "x": 120, + "y": 550 + }, + "c1": { + "type": "Coude", + "x": 200, + "y": 550 + }, + "c2": { + "type": "Coude", + "x": 200, + "y": 485 + }, + "r": { + "type": "RelaisCote", + "x": 375, + "y": 475, + "orientation": 0 + }, + + + "pulse": { + "type": "Pulse", + "valeur": 24.0, + "periode": 1, + "x": 0, + "y": 400 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 475, + "y": 400 + }, + "r.repos": { + "type": "ContactRepos", + "x": 375, + "y": 400, + "relais": "r" + }, + "l": { + "type": "Lampe", + "x": 250, + "y": 400 + } + }, + "cables": [ + ["p24", "d", "b", "g"], + ["b", "d", "c1", "m"], + ["c1", "m", "c2", "m"], + ["c2", "m", "r", "hg"], + ["p0", "d", "r", "bg"], + + ["pulse", "d", "l", "g"], + ["l", "d", "r.repos", "g"], + ["r.repos", "d", "p0-1", "g"] + ] +} diff --git a/schemas_v1/schema_s4.ccs b/schemas_v1/schema_s4.ccs new file mode 100644 index 0000000..38f826c --- /dev/null +++ b/schemas_v1/schema_s4.ccs @@ -0,0 +1,73 @@ +{ + "blocs": { + "p24-1": { + "type": "P24", + "valeur": 24.0, + "orientation": 0, + "x": 0.0, + "y": 500.0 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "orientation": 0, + "x": 1200.0, + "y": 500.0 + }, + "p0-2": { + "type": "P0", + "valeur": 0.0, + "x": 1200.0, + "y": 300.0 + }, + "r1": { + "type": "Relais", + "x": 400.0, + "y": 500.0 + }, + "r2": { + "type": "Relais", + "x": 1000.0, + "y": 500.0 + }, + "c3": { + "type": "Bouton", + "x": 200.0, + "y": 500.0, + "orientation": 0 + }, + "r2.travail": { + "type": "ContactTravail", + "orientation": 0, + "relais": "r2", + "x": 1000.0, + "y": 300.0 + }, + "w1": { + "type": "Lampe", + "x": 600.0, + "y": 500.0 + }, + "n1": { + "type": "Noeud", + "x": 800.0, + "y": 500 + }, + "coude1": { + "type": "Coude", + "x": 800, + "y": 300 + } + }, + "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.travail", "g"], + ["r2.travail", "d", "p0-2", "g"] + ] +} \ No newline at end of file diff --git a/schemas_v1/simple.ccs b/schemas_v1/simple.ccs new file mode 100644 index 0000000..66c0208 --- /dev/null +++ b/schemas_v1/simple.ccs @@ -0,0 +1,71 @@ +{ + "blocs": { + "p24-1": { + "type": "P24", + "valeur": 24.0, + "x": 0, + "y": 500 + }, + "p0-1": { + "type": "P0", + "valeur": 0.0, + "x": 1200, + "y": 500 + }, + "p0-2": { + "type": "P0", + "valeur": 0.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 + }, + "r2.travail": { + "type": "ContactTravail", + "x": 1000, + "y": 300, + "relais": "r2" + }, + "t1": { + "type": "Tempo", + "tempo_blocage": 2, + "tempo_liberation": 1, + "x": 600, + "y": 500 + }, + "n1": { + "type": "Noeud", + "x": 800, + "y": 500 + }, + "coude1": { + "type": "Coude", + "x": 800, + "y": 300 + } + }, + "cables": [ + ["p24-1", "d", "c3", "g"], + ["c3", "d", "r1", "g"], + ["r1", "d", "t1", "g"], + ["t1", "d", "n1", "m"], + ["n1", "m", "r2", "g"], + ["r2", "d", "p0-1", "g"], + ["n1", "m", "coude1", "m"], + ["coude1", "m", "r2.travail", "g"], + ["r2.travail", "d", "p0-2", "g"] + ] +}