Compare commits
	
		
			3 Commits
		
	
	
		
			5f84dad372
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2e59700bfa | |||
| 88aced27bf | |||
| 25610fd4fa | 
							
								
								
									
										
											BIN
										
									
								
								api_server/__pycache__/__init__.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								api_server/__pycache__/app.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								api_server/__pycache__/state.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										233
									
								
								api_server/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,233 @@ | |||||||
|  | """ | ||||||
|  | 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/<obj>') | ||||||
|  | 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/<obj>') | ||||||
|  | def release(obj): | ||||||
|  |     """ | ||||||
|  |     Release button | ||||||
|  |     """ | ||||||
|  |     if not PROCESS_BASE.known(): | ||||||
|  |         return "Unknown", 401 | ||||||
|  |  | ||||||
|  |     PROCESS_BASE.cmd_q().put({'cmd': "release", "args": obj}) | ||||||
|  |     return "OK" | ||||||
|  |  | ||||||
|  | @app.route('/pause/<obj>') | ||||||
|  | def pause_simulation(obj): | ||||||
|  |     if not PROCESS_BASE.known(): | ||||||
|  |         return "Unknown", 401 | ||||||
|  |  | ||||||
|  |     PROCESS_BASE.cmd_q.put({'cmd': "pause", "arg": obj}) | ||||||
|  |     return "Simulation paused" | ||||||
|  |  | ||||||
|  | @app.route('/resume/<obj>') | ||||||
|  | def resume_simulation(obj): | ||||||
|  |     if not PROCESS_BASE.known(): | ||||||
|  |         return "Unknown", 401 | ||||||
|  |  | ||||||
|  |     PROCESS_BASE.cmd_q.put({'cmd': "resume", "arg": obj}) | ||||||
|  |     return "Simulation resumed" | ||||||
|  |  | ||||||
|  | def just_run(): | ||||||
|  |     """ | ||||||
|  |     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 | ||||||
							
								
								
									
										46
									
								
								api_server/state.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | import json | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class State(object): | ||||||
|  |     IGNORE = frozenset(['Coude', 'Noeud', 'P24', 'P0', 'Pulse']) | ||||||
|  |     # these components do not have any states (value/ true or flase...) | ||||||
|  |  | ||||||
|  |     Breakpoints = ['Relais'] | ||||||
|  |     #possibility to add other breakpoints in the future ;)  | ||||||
|  |   | ||||||
|  |     def __init__(self, cocosim_server): | ||||||
|  |         self.cocosim_server = cocosim_server | ||||||
|  |         self.conf = self.cocosim_server.conf["ui"] | ||||||
|  |         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 | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								api_server/test_client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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()) | ||||||
							
								
								
									
										156
									
								
								api_worker/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,156 @@ | |||||||
|  | import json | ||||||
|  | import asyncio | ||||||
|  | from modele.donnees import SchemaReader, GraphStructException | ||||||
|  | from modele.graphe import Graphe | ||||||
|  | from modele.cocosim import Cocosim | ||||||
|  | from api_server.state import State | ||||||
|  | import logging | ||||||
|  | import modele.exceptions | ||||||
|  |  | ||||||
|  | class CocosimInstance(object): | ||||||
|  |     def __init__(self, cmd_q, state_q): | ||||||
|  |         self.runner = None | ||||||
|  |         try: | ||||||
|  |             conf_fp = open("modele/config.json") | ||||||
|  |             conf = json.load(conf_fp) | ||||||
|  |  | ||||||
|  |             self.pause_simulation = False  #pause flag | ||||||
|  |             self.conf = conf | ||||||
|  |             self.dt = self.conf['circuit']['DT'] | ||||||
|  |             self.cocosim = None | ||||||
|  |             self.state = None | ||||||
|  |             self.cmd_q = cmd_q | ||||||
|  |             self.state_q = state_q | ||||||
|  |             self.quit = False | ||||||
|  |         except (OSError, json.JSONDecodeError) as e: | ||||||
|  |             logging.exception("Reading conf. file") | ||||||
|  |             raise modele.G | ||||||
|  |  | ||||||
|  |     def setup(self, schema_d): | ||||||
|  |         logging.info("Setting up") | ||||||
|  |         reader = SchemaReader(schema_d) | ||||||
|  |         reader.process() | ||||||
|  |         logging.info("Schema is loaded") | ||||||
|  |         self.state = State(self) | ||||||
|  |         self.state.load_conf(schema_d) | ||||||
|  |         logging.info(f"State is made up with {len(self.state.composants)} items.") | ||||||
|  |         graphe = Graphe(self.conf['circuit']) | ||||||
|  |         graphe.load_data_from_schema_reader(reader) | ||||||
|  |         logging.info("Graph is initialized.") | ||||||
|  |         self.cocosim = Cocosim(self.conf, graphe, {}, {}) | ||||||
|  |         logging.info("Cocosim is initialized") | ||||||
|  |  | ||||||
|  |     async def handler(self): | ||||||
|  |         loop = asyncio.get_running_loop() | ||||||
|  |         data = await loop.run_in_executor(None, self.cmd_q.get) | ||||||
|  |         message = data['cmd'] | ||||||
|  |         try: | ||||||
|  |             if message == "start": | ||||||
|  |                 logging.log(logging.INFO, "Starting") | ||||||
|  |                 self.runner = asyncio.create_task(self.run()) | ||||||
|  |                  | ||||||
|  |             elif message == "stop": | ||||||
|  |                 logging.log(logging.INFO, "Stopping") | ||||||
|  |                 await self.stop() | ||||||
|  |  | ||||||
|  |             elif message == "state": | ||||||
|  |                 self.state_q.put(self.state.to_json()) | ||||||
|  |  | ||||||
|  |             elif message == "quit": | ||||||
|  |                 logging.log(logging.INFO, "Quitting") | ||||||
|  |                 await self.stop() | ||||||
|  |                 self.quit = True | ||||||
|  |  | ||||||
|  |             elif message == "load": | ||||||
|  |                 logging.log(logging.INFO, "Loading file") | ||||||
|  |                 try: | ||||||
|  |                     self.setup(data['args'] if type(data['args']) == dict else json.loads(data['args']))  # Compatibilité avec certaines IHM | ||||||
|  |                     self.state_q.put("OK") | ||||||
|  |                 except GraphStructException: | ||||||
|  |                     self.state_q.put("Error") | ||||||
|  |  | ||||||
|  |             elif message == "pause": | ||||||
|  |                 but_name = data['args'] | ||||||
|  |                 logging.log(logging.INFO,"Simulation paused {but_name}") | ||||||
|  |                 self.pause_simulation = True | ||||||
|  |  | ||||||
|  |             elif message == "resume": | ||||||
|  |                 but_name = data['args'] | ||||||
|  |                 logging.log(logging.INFO,"Simulation resumed {but_name}") | ||||||
|  |                 self.pause_simulation = False | ||||||
|  |  | ||||||
|  |             elif message == "push": | ||||||
|  |                 but_name = data['args'] | ||||||
|  |                 logging.log(logging.INFO, f"Push button {but_name}") | ||||||
|  |                 if self.cocosim.graphe[but_name] == "Bouton": | ||||||
|  |                     self.cocosim.graphe[but_name].ferme() | ||||||
|  |                 else: | ||||||
|  |                     self.cocosim.graphe[but_name].bascule() | ||||||
|  |             elif message == "release": | ||||||
|  |                 but_name = data['args'] | ||||||
|  |                 logging.log(logging.INFO, f"Release button {but_name}") | ||||||
|  |                 if self.cocosim.graphe[but_name].type == "Bouton": | ||||||
|  |                     self.cocosim.graphe[but_name].ouvre() | ||||||
|  |                 # Dans le cas contraire on ne traite pas le release | ||||||
|  |             else: | ||||||
|  |                 logging.log(logging.ERROR, "Commande inconnue") | ||||||
|  |         except Exception: | ||||||
|  |             logging.exception("Exception occured in handler") | ||||||
|  |  | ||||||
|  |     def cycle(self): | ||||||
|  |         try: | ||||||
|  |             self.cocosim.cycle() | ||||||
|  |  | ||||||
|  |             for nom in self.state.keys(): | ||||||
|  |                 if nom not in self.cocosim.graphe and nom[-7:] == ".double":  # TODO : a supprimer apràs refactoring contact double | ||||||
|  |                     nom_translate = nom[:-7] + ".travail" | ||||||
|  |                     value = self.cocosim.graphe[nom_translate].etat() if nom_translate in self.cocosim.graphe else None | ||||||
|  |                     self.state.update(nom, value) | ||||||
|  |                 else: | ||||||
|  |                     value = self.cocosim.graphe[nom].etat() if nom in self.cocosim.graphe else None | ||||||
|  |                     self.state.update(nom, value) | ||||||
|  |         except modele.base.SurintensiteException as e: | ||||||
|  |             self.state.exception("Surintensité") | ||||||
|  |             raise e | ||||||
|  |         except modele.base.SurtensionException as e: | ||||||
|  |             self.state.exception("Surtension") | ||||||
|  |             raise e | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     async def run(self): | ||||||
|  |         try: | ||||||
|  |             while not self.quit: | ||||||
|  |                 if not self.pause_simulation: | ||||||
|  |                     self.state.reset_exception() | ||||||
|  |                     self.cycle() | ||||||
|  |                 else:  | ||||||
|  |                     print("Simulation paused. Awaiting resume...") | ||||||
|  |                     while self.pause_simulation: | ||||||
|  |                         await asyncio.sleep(1)  #wait until the simulation is resumed | ||||||
|  |                 await asyncio.sleep(self.dt) | ||||||
|  |         except Exception as e: | ||||||
|  |             logging.exception("Exception occured during simulation run") | ||||||
|  |  | ||||||
|  |     async def stop(self): | ||||||
|  |         if self.runner: | ||||||
|  |             self.runner.cancel() | ||||||
|  |             try: | ||||||
|  |                 await self.runner | ||||||
|  |             except asyncio.CancelledError: | ||||||
|  |                 logging.info("Runner is stopped.") | ||||||
|  |                 self.runner = None | ||||||
|  |  | ||||||
|  |     async def handle_requests(self): | ||||||
|  |         while not self.quit: | ||||||
|  |             await self.handler() | ||||||
|  |         logging.info("Stop handling request") | ||||||
|  |  | ||||||
|  |     def __del__(self): | ||||||
|  |         logging.info("Cocosim instance destroyed") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def run_instance(uid, cmd_q, state_q): | ||||||
|  |     logging.basicConfig(filename=f"cocosim.log", filemode="w", level=logging.INFO) | ||||||
|  |     logging.info("Creating instance") | ||||||
|  |     i = CocosimInstance(cmd_q, state_q) | ||||||
|  |     asyncio.run(i.handle_requests()) | ||||||
							
								
								
									
										
											BIN
										
									
								
								api_worker/__pycache__/__init__.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2
									
								
								cocosim.log
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | INFO:root:Creating instance | ||||||
|  | INFO:root:Cocosim instance destroyed | ||||||
							
								
								
									
										
											BIN
										
									
								
								images_v1/CoCoSIM_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 18 KiB | 
							
								
								
									
										83
									
								
								images_v1/CoCoSIM_icon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,83 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    width="256" | ||||||
|  |    height="256" | ||||||
|  |    viewBox="0 0 256 256" | ||||||
|  |    fill="none" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg71" | ||||||
|  |    sodipodi:docname="CoCoSIM_icon.svg" | ||||||
|  |    inkscape:export-filename="CoCoSIM_icon.png" | ||||||
|  |    inkscape:export-xdpi="96" | ||||||
|  |    inkscape:export-ydpi="96" | ||||||
|  |    inkscape:version="1.2.2 (732a01da63, 2022-12-09)" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview73" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      showgrid="false" | ||||||
|  |      inkscape:zoom="3.3189655" | ||||||
|  |      inkscape:cx="-31.184416" | ||||||
|  |      inkscape:cy="125.49091" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1001" | ||||||
|  |      inkscape:window-x="2391" | ||||||
|  |      inkscape:window-y="-9" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="svg71" /> | ||||||
|  |   <g | ||||||
|  |      inkscape:groupmode="layer" | ||||||
|  |      id="layer1" | ||||||
|  |      inkscape:label="Layer 1"> | ||||||
|  |     <rect | ||||||
|  |        style="fill:#000000;stroke-width:4.75706" | ||||||
|  |        id="rect286" | ||||||
|  |        width="256.48053" | ||||||
|  |        height="256.55585" | ||||||
|  |        x="-0.60259742" | ||||||
|  |        y="-0.67792207" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      clip-path="url(#clip0_22_80)" | ||||||
|  |      id="g64" | ||||||
|  |      transform="matrix(10.390846,0,0,10.390846,24,3.997707)"> | ||||||
|  |     <path | ||||||
|  |        d="M 2.49756,19.4869 C 2.61625,19.6506 2.581,19.8814 2.41915,20.0014 2.2573,20.1215 2.02926,20.0859 1.91057,19.9221 1.29913,19.0808 0.815726,18.1383 0.487704,17.1252 0.171191,16.1463 -7.32422e-4,15.1012 -7.32422e-4,14.0182 -7.32422e-4,12.4309 0.366854,10.9279 1.02002,9.59315 1.69836,8.20814 2.68459,7.00509 3.88878,6.07641 4.04847,5.95341 4.2765,5.98398 4.39807,6.14555 4.51964,6.30712 4.48943,6.53784 4.32974,6.66084 3.21403,7.52183 2.29974,8.63609 1.67175,9.91848 1.0675,11.1521 0.727966,12.5444 0.727966,14.0175 c 0,1.0065 0.158256,1.9745 0.451034,2.8791 0.30356,0.9382 0.75171,1.8108 1.31784,2.5896 M 18.7649,11.9061 c -0.0454,-0.198 0.0762,-0.3959 0.2719,-0.4425 0.1956,-0.0459 0.3913,0.0771 0.4373,0.2751 0.0849,0.369 0.1504,0.746 0.1936,1.1296 0.0431,0.3799 0.0654,0.7634 0.0654,1.1484 0,2.7562 -1.1042,5.2518 -2.8896,7.059 -1.7854,1.8064 -4.2521,2.9236 -6.97695,2.9236 -0.91573,0 -1.80556,-0.1274 -2.65151,-0.3661 C 6.34391,23.3879 5.52025,23.0233 4.76278,22.5597 4.59158,22.4549 4.53691,22.2285 4.64049,22.0553 4.74408,21.8821 4.9678,21.826 5.139,21.9316 c 0.69993,0.4287 1.46243,0.7656 2.27026,0.9934 0.77905,0.2191 1.60342,0.337 2.45801,0.337 2.52343,0 4.80813,-1.0349 6.46113,-2.7074 1.6538,-1.6732 2.676,-3.984 2.676,-6.5371 0,-0.3632 -0.0201,-0.7191 -0.0597,-1.0648 -0.0403,-0.3552 -0.1007,-0.7038 -0.1791,-1.0459 z" | ||||||
|  |        fill="#ea4c89" | ||||||
|  |        id="path56" /> | ||||||
|  |     <path | ||||||
|  |        d="m 11.0398,4.12735 c -0.2331,-0.23581 -0.556,-0.38137 -0.9136,-0.38137 -0.35748,0 -0.67975,0.14629 -0.91353,0.38283 H 9.21123 c -0.23307,0.2358 -0.37694,0.56259 -0.37694,0.9243 0,0.36172 0.13739,0.67395 0.36111,0.9083 l 0.01727,0.01601 c 0.23378,0.23654 0.55677,0.38283 0.91353,0.38283 0.3568,0 0.6813,-0.14556 0.9136,-0.38137 l 0.0014,-0.00146 c 0.2331,-0.2358 0.377,-0.56259 0.377,-0.92431 0,-0.36171 -0.1439,-0.68922 -0.377,-0.9243 z M 10.1262,3.00799 c 0.5568,0 1.0611,0.22853 1.4279,0.59898 l 0.0022,0.00219 c 0.3654,0.37117 0.5913,0.88136 0.5913,1.44323 0,0.56186 -0.2259,1.0735 -0.592,1.44468 L 11.5534,6.49926 C 11.1866,6.86898 10.6823,7.09751 10.127,7.09751 9.57162,7.09751 9.06376,6.86825 8.69761,6.49853 L 8.67747,6.47597 C 8.32355,6.10697 8.10559,5.60479 8.10559,5.05239 8.10559,4.49998 8.33218,3.97815 8.69833,3.60697 9.06304,3.23579 9.56874,3.00726 10.127,3.00726 Z" | ||||||
|  |        fill="#2ed73c" | ||||||
|  |        id="path58" /> | ||||||
|  |     <path | ||||||
|  |        d="m 7.59772,10.9221 c 0.09135,-0.1812 0.31075,-0.2533 0.48987,-0.1616 0.17912,0.0925 0.25033,0.3145 0.1597,0.4957 L 2.58027,22.5124 C 2.48891,22.6936 2.26951,22.7656 2.0904,22.6739 1.91128,22.5815 1.84006,22.3595 1.9307,22.1783 Z" | ||||||
|  |        fill="#2d7aff" | ||||||
|  |        id="path60" /> | ||||||
|  |     <path | ||||||
|  |        d="m 2.57814,21.9964 h 2.05805 c 3.7406,-1.9251 5.01169,-4.38 4.95702,-6.543 C 9.55005,13.7402 8.68251,12.203 7.56033,11.262 6.48203,10.3581 5.17858,10.016 4.19523,10.6412 L 4.11466,10.695 c -0.01295,0.011 -0.02661,0.0204 -0.041,0.0299 -0.87904,0.6463 -1.50559,2.1113 -1.50559,4.695 H 2.56663 l 0.01079,6.5772 z M 17.2427,14.647 c -7e-4,1.0801 -0.2359,2.0451 -0.2373,2.0524 l -0.0029,0.0124 c -1.4409,5.7707 -5.3527,6.0196 -5.3635,6.0204 l -0.0287,0.0014 H 2.21631 c -0.20142,0 -0.36471,-0.1652 -0.36471,-0.3683 L 1.85304,22.3326 1.84153,15.4199 H 1.84009 c 0,-2.735 0.69201,-4.3755 1.68039,-5.1914 V 8.36753 c 0,-2.23872 0.78481,-4.29549 2.14294,-5.80931 C 6.9791,1.09169 8.83214,0.13609 11.029,0.0167308 14.1388,-0.152119 16.3831,0.991986 17.8527,2.71469 c 0.9402,1.10262 1.5589,2.44032 1.8804,3.81951 0.3209,1.37482 0.3475,2.79621 0.1058,4.0706 -0.3439,1.81 -1.2316,3.3326 -2.5962,4.0422 z M 13.5381,4.88209 c 0,-0.00728 0.0453,-2.36463 2.3825,-2.92504 C 14.6797,1.12081 13.072,0.641185 11.0664,0.750355 9.07312,0.858798 7.39417,1.72488 6.20221,3.05312 4.96493,4.43231 4.2499,6.31295 4.2499,8.3668 V 9.78966 C 5.44689,9.3013 6.86113,9.71688 8.02575,10.6936 c 1.26677,1.0619 2.24585,2.8013 2.29475,4.7416 0.0546,2.1703 -1.04668,4.5837 -4.2003,6.5604 h 5.48 c 0.2647,-0.0247 3.4399,-0.4257 4.6973,-5.4672 0.0302,-0.1259 1.1711,-4.9811 -2.2616,-3.8821 -0.0417,0.0167 -0.087,0.0255 -0.1338,0.0255 -0.2014,0 -0.3647,-0.1653 -0.3647,-0.369 V 4.89228 h 0.0014 z m 3.1745,-2.29986 c -2.3163,0.14556 -2.4415,2.15211 -2.448,2.30932 h 0.0015 v 6.92865 c 2.0516,-0.4832 2.7479,0.6893 2.9256,2.0051 0.9955,-0.6586 1.6552,-1.8981 1.9329,-3.3595 0.223,-1.17541 0.1978,-2.48983 -0.1,-3.76493 C 18.7282,5.43012 18.1621,4.20232 17.3032,3.19577 17.1197,2.98107 16.9234,2.7751 16.7126,2.58223 Z" | ||||||
|  |        fill="#2d7aff" | ||||||
|  |        id="path62" /> | ||||||
|  |   </g> | ||||||
|  |   <defs | ||||||
|  |      id="defs69"> | ||||||
|  |     <clipPath | ||||||
|  |        id="clip0_22_80"> | ||||||
|  |       <rect | ||||||
|  |          width="20" | ||||||
|  |          height="24" | ||||||
|  |          fill="#ffffff" | ||||||
|  |          id="rect66" | ||||||
|  |          x="0" | ||||||
|  |          y="0" /> | ||||||
|  |     </clipPath> | ||||||
|  |   </defs> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 6.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/CoCoSIM_logo_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 31 KiB | 
							
								
								
									
										84
									
								
								images_v1/CoCoSIM_logo_01.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 17 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/bouton_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										18
									
								
								images_v1/bouton_ferme.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,18 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M4.199,50.153 L73.998,45.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M60.429,46.554 L55.564,54.459 L61.854,53.716 L55.92,61.131 L62.505,60.135 L55.974,68.734 C55.974,68.734 62.767,67.244 62.767,67.244" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/bouton_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										20
									
								
								images_v1/bouton_ouvert.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,20 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M5.417,50.404 L73.417,30.404" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |       <path d="M59.29,36.05 L56.43,45.325 L62.325,42.358 L58.32,51.552 L64.443,48.238 L60.137,58.773 C60.137,58.773 66.345,54.913 66.345,54.913" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/condensateur.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 523 B | 
							
								
								
									
										20
									
								
								images_v1/condensateur.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,20 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M4.5,50.5 L36.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M44.5,50.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M36.5,30.5 L36.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M44.5,30.5 L44.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/contact_basculeur_droite.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										21
									
								
								images_v1/contact_basculeur_droite.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M70.5,20.5 L38.12,96.229" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M5,38 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M55,38 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M70.5,24.5 C70.5,22.291 72.739,20.5 75.5,20.5 C78.261,20.5 80.5,22.291 80.5,24.5 C80.5,26.709 78.261,28.5 75.5,28.5 C72.739,28.5 70.5,26.709 70.5,24.5 z" fill="#000000"/> | ||||||
|  |       <path d="M70.5,24.5 C70.5,22.291 72.739,20.5 75.5,20.5 C78.261,20.5 80.5,22.291 80.5,24.5 C80.5,26.709 78.261,28.5 75.5,28.5 C72.739,28.5 70.5,26.709 70.5,24.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M32.5,96.5 C32.5,94.291 34.739,92.5 37.5,92.5 C40.261,92.5 42.5,94.291 42.5,96.5 C42.5,98.709 40.261,100.5 37.5,100.5 C34.739,100.5 32.5,98.709 32.5,96.5 z" fill="#000000"/> | ||||||
|  |       <path d="M32.5,96.5 C32.5,94.291 34.739,92.5 37.5,92.5 C40.261,92.5 42.5,94.291 42.5,96.5 C42.5,98.709 40.261,100.5 37.5,100.5 C34.739,100.5 32.5,98.709 32.5,96.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M0.5,24.5 C0.5,22.291 2.739,20.5 5.5,20.5 C8.261,20.5 10.5,22.291 10.5,24.5 C10.5,26.709 8.261,28.5 5.5,28.5 C2.739,28.5 0.5,26.709 0.5,24.5 z" fill="#000000"/> | ||||||
|  |       <path d="M0.5,24.5 C0.5,22.291 2.739,20.5 5.5,20.5 C8.261,20.5 10.5,22.291 10.5,24.5 C10.5,26.709 8.261,28.5 5.5,28.5 C2.739,28.5 0.5,26.709 0.5,24.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/contact_basculeur_gauche.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										21
									
								
								images_v1/contact_basculeur_gauche.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M10.5,20.5 L38.12,96.229" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M5,38 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M55,38 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M70.5,24.5 C70.5,22.291 72.739,20.5 75.5,20.5 C78.261,20.5 80.5,22.291 80.5,24.5 C80.5,26.709 78.261,28.5 75.5,28.5 C72.739,28.5 70.5,26.709 70.5,24.5 z" fill="#000000"/> | ||||||
|  |       <path d="M70.5,24.5 C70.5,22.291 72.739,20.5 75.5,20.5 C78.261,20.5 80.5,22.291 80.5,24.5 C80.5,26.709 78.261,28.5 75.5,28.5 C72.739,28.5 70.5,26.709 70.5,24.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M32.5,96.5 C32.5,94.291 34.739,92.5 37.5,92.5 C40.261,92.5 42.5,94.291 42.5,96.5 C42.5,98.709 40.261,100.5 37.5,100.5 C34.739,100.5 32.5,98.709 32.5,96.5 z" fill="#000000"/> | ||||||
|  |       <path d="M32.5,96.5 C32.5,94.291 34.739,92.5 37.5,92.5 C40.261,92.5 42.5,94.291 42.5,96.5 C42.5,98.709 40.261,100.5 37.5,100.5 C34.739,100.5 32.5,98.709 32.5,96.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M0.5,24.5 C0.5,22.291 2.739,20.5 5.5,20.5 C8.261,20.5 10.5,22.291 10.5,24.5 C10.5,26.709 8.261,28.5 5.5,28.5 C2.739,28.5 0.5,26.709 0.5,24.5 z" fill="#000000"/> | ||||||
|  |       <path d="M0.5,24.5 C0.5,22.291 2.739,20.5 5.5,20.5 C8.261,20.5 10.5,22.291 10.5,24.5 C10.5,26.709 8.261,28.5 5.5,28.5 C2.739,28.5 0.5,26.709 0.5,24.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/contact_double_repos.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										21
									
								
								images_v1/contact_double_repos.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M4.5,60.5 L76.5,49" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,40.5 C2.291,40.5 0.5,38.261 0.5,35.5 C0.5,32.739 2.291,30.5 4.5,30.5 C6.709,30.5 8.5,32.739 8.5,35.5 C8.5,38.261 6.709,40.5 4.5,40.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,40.5 C2.291,40.5 0.5,38.261 0.5,35.5 C0.5,32.739 2.291,30.5 4.5,30.5 C6.709,30.5 8.5,32.739 8.5,35.5 C8.5,38.261 6.709,40.5 4.5,40.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,70.5 C2.291,70.5 0.5,68.261 0.5,65.5 C0.5,62.739 2.291,60.5 4.5,60.5 C6.709,60.5 8.5,62.739 8.5,65.5 C8.5,68.261 6.709,70.5 4.5,70.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,70.5 C2.291,70.5 0.5,68.261 0.5,65.5 C0.5,62.739 2.291,60.5 4.5,60.5 C6.709,60.5 8.5,62.739 8.5,65.5 C8.5,68.261 6.709,70.5 4.5,70.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/contact_double_travail.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1014 B | 
							
								
								
									
										21
									
								
								images_v1/contact_double_travail.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M4.5,40.5 L76.5,49" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,40.5 C2.291,40.5 0.5,38.261 0.5,35.5 C0.5,32.739 2.291,30.5 4.5,30.5 C6.709,30.5 8.5,32.739 8.5,35.5 C8.5,38.261 6.709,40.5 4.5,40.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,40.5 C2.291,40.5 0.5,38.261 0.5,35.5 C0.5,32.739 2.291,30.5 4.5,30.5 C6.709,30.5 8.5,32.739 8.5,35.5 C8.5,38.261 6.709,40.5 4.5,40.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,70.5 C2.291,70.5 0.5,68.261 0.5,65.5 C0.5,62.739 2.291,60.5 4.5,60.5 C6.709,60.5 8.5,62.739 8.5,65.5 C8.5,68.261 6.709,70.5 4.5,70.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,70.5 C2.291,70.5 0.5,68.261 0.5,65.5 C0.5,62.739 2.291,60.5 4.5,60.5 C6.709,60.5 8.5,62.739 8.5,65.5 C8.5,68.261 6.709,70.5 4.5,70.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/diode_dg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 713 B | 
							
								
								
									
										22
									
								
								images_v1/diode_dg.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,22 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M76.5,50.5 L4.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M68.5,0.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M68.5,50.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M24.5,76.5 L24.5,25.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M56.5,75.5 L24.5,50.5 L56.5,25.5 L56.5,75.5 z" fill="#000000"/> | ||||||
|  |       <path d="M56.5,75.5 L24.5,50.5 L56.5,25.5 L56.5,75.5 z" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linejoin="bevel"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/diode_gd.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 782 B | 
							
								
								
									
										22
									
								
								images_v1/diode_gd.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,22 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M4.5,50.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M56.5,25.5 L56.5,75.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M24.5,25.5 L56.5,50.5 L24.5,75.5 z" fill="#000000"/> | ||||||
|  |       <path d="M24.5,25.5 L56.5,50.5 L24.5,75.5 z" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linejoin="bevel"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/lampe.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										22
									
								
								images_v1/lampe.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,22 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M5.5,55.5 C2.739,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.739,45.5 5.5,45.5 C8.261,45.5 10.5,47.739 10.5,50.5 C10.5,53.261 8.261,55.5 5.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M5.5,55.5 C2.739,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.739,45.5 5.5,45.5 C8.261,45.5 10.5,47.739 10.5,50.5 C10.5,53.261 8.261,55.5 5.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M75.5,55.5 C72.739,55.5 70.5,53.261 70.5,50.5 C70.5,47.739 72.739,45.5 75.5,45.5 C78.261,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.261,55.5 75.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M75.5,55.5 C72.739,55.5 70.5,53.261 70.5,50.5 C70.5,47.739 72.739,45.5 75.5,45.5 C78.261,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.261,55.5 75.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M40.5,80.5 C23.931,80.5 10.5,67.069 10.5,50.5 C10.5,33.931 23.931,20.5 40.5,20.5 C57.069,20.5 70.5,33.931 70.5,50.5 C70.5,67.069 57.069,80.5 40.5,80.5 z" fill="#FFFFFF"/> | ||||||
|  |       <path d="M40.5,80.5 C23.931,80.5 10.5,67.069 10.5,50.5 C10.5,33.931 23.931,20.5 40.5,20.5 C57.069,20.5 70.5,33.931 70.5,50.5 C70.5,67.069 57.069,80.5 40.5,80.5 z" fill-opacity="0" stroke="#000000" stroke-width="2.7"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M20.5,70.5 L60.5,30.5" fill-opacity="0" stroke="#000000" stroke-width="2" stroke-linecap="round"/> | ||||||
|  |     <path d="M20.5,30.5 L60.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2" stroke-linecap="round"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/levier_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.3 KiB | 
							
								
								
									
										100
									
								
								images_v1/levier_ferme.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,100 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    version="1.1" | ||||||
|  |    x="0" | ||||||
|  |    y="0" | ||||||
|  |    width="80" | ||||||
|  |    height="100" | ||||||
|  |    viewBox="0, 0, 80, 100" | ||||||
|  |    id="svg10" | ||||||
|  |    sodipodi:docname="levier_ouvert.svg" | ||||||
|  |    inkscape:version="1.3-beta (cedbd6c, 2023-05-28)" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <defs | ||||||
|  |      id="defs10" /> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview10" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:zoom="8.2929269" | ||||||
|  |      inkscape:cx="33.884297" | ||||||
|  |      inkscape:cy="51.972001" | ||||||
|  |      inkscape:window-width="1710" | ||||||
|  |      inkscape:window-height="1069" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="38" | ||||||
|  |      inkscape:window-maximized="0" | ||||||
|  |      inkscape:current-layer="svg10" /> | ||||||
|  |   <path | ||||||
|  |      d="M 12.5,101.5 Z" | ||||||
|  |      fill-opacity="0" | ||||||
|  |      stroke="#000000" | ||||||
|  |      stroke-width="0.9" | ||||||
|  |      id="path1" /> | ||||||
|  |   <path | ||||||
|  |      d="M 12.5,51.5 Z" | ||||||
|  |      fill-opacity="0" | ||||||
|  |      stroke="#000000" | ||||||
|  |      stroke-width="0.9" | ||||||
|  |      id="path2" /> | ||||||
|  |   <g | ||||||
|  |      id="g4"> | ||||||
|  |     <path | ||||||
|  |        d="m 5.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill="#000000" | ||||||
|  |        id="path3" /> | ||||||
|  |     <path | ||||||
|  |        d="m 5.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path4" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      id="g6" | ||||||
|  |      transform="translate(-0.72350814)"> | ||||||
|  |     <path | ||||||
|  |        d="m 75.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill="#000000" | ||||||
|  |        id="path5" /> | ||||||
|  |     <path | ||||||
|  |        d="m 75.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path6" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      id="g8"> | ||||||
|  |     <path | ||||||
|  |        d="m 40.5,80.5 c -16.569,0 -30,-13.431 -30,-30 0,-16.569 13.431,-30 30,-30 16.569,0 30,13.431 30,30 0,16.569 -13.431,30 -30,30 z" | ||||||
|  |        fill="#ffffff" | ||||||
|  |        id="path7" /> | ||||||
|  |     <path | ||||||
|  |        d="m 40.5,80.5 c -16.569,0 -30,-13.431 -30,-30 0,-16.569 13.431,-30 30,-30 16.569,0 30,13.431 30,30 0,16.569 -13.431,30 -30,30 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="2.7" | ||||||
|  |        id="path8" /> | ||||||
|  |   </g> | ||||||
|  |   <path | ||||||
|  |      style="fill:#121212;stroke:#000000;stroke-width:4.41824" | ||||||
|  |      id="path11" | ||||||
|  |      sodipodi:type="arc" | ||||||
|  |      sodipodi:cx="40.160213" | ||||||
|  |      sodipodi:cy="49.300335" | ||||||
|  |      sodipodi:rx="29.252346" | ||||||
|  |      sodipodi:ry="27.2386" | ||||||
|  |      sodipodi:start="3.1415927" | ||||||
|  |      sodipodi:end="0" | ||||||
|  |      sodipodi:arc-type="slice" | ||||||
|  |      d="m 10.907867,49.300335 a 29.252346,27.2386 0 0 1 29.252346,-27.2386 29.252346,27.2386 0 0 1 29.252347,27.2386 H 40.160213 Z" /> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/levier_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.8 KiB | 
							
								
								
									
										106
									
								
								images_v1/levier_ouvert.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,106 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    version="1.1" | ||||||
|  |    x="0" | ||||||
|  |    y="0" | ||||||
|  |    width="80" | ||||||
|  |    height="100" | ||||||
|  |    viewBox="0, 0, 80, 100" | ||||||
|  |    id="svg10" | ||||||
|  |    sodipodi:docname="levier_ferme.svg" | ||||||
|  |    inkscape:version="1.3-beta (cedbd6c, 2023-05-28)" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <defs | ||||||
|  |      id="defs10" /> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview10" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:zoom="8.2929269" | ||||||
|  |      inkscape:cx="33.884297" | ||||||
|  |      inkscape:cy="51.972001" | ||||||
|  |      inkscape:window-width="1710" | ||||||
|  |      inkscape:window-height="1069" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="38" | ||||||
|  |      inkscape:window-maximized="0" | ||||||
|  |      inkscape:current-layer="svg10" /> | ||||||
|  |   <path | ||||||
|  |      d="M 12.5,101.5 Z" | ||||||
|  |      fill-opacity="0" | ||||||
|  |      stroke="#000000" | ||||||
|  |      stroke-width="0.9" | ||||||
|  |      id="path1" /> | ||||||
|  |   <path | ||||||
|  |      d="M 12.5,51.5 Z" | ||||||
|  |      fill-opacity="0" | ||||||
|  |      stroke="#000000" | ||||||
|  |      stroke-width="0.9" | ||||||
|  |      id="path2" /> | ||||||
|  |   <g | ||||||
|  |      id="g4"> | ||||||
|  |     <path | ||||||
|  |        d="m 5.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill="#000000" | ||||||
|  |        id="path3" /> | ||||||
|  |     <path | ||||||
|  |        d="m 5.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path4" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      id="g6"> | ||||||
|  |     <path | ||||||
|  |        d="m 75.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill="#000000" | ||||||
|  |        id="path5" /> | ||||||
|  |     <path | ||||||
|  |        d="m 75.5,55.5 c -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path6" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      id="g8"> | ||||||
|  |     <path | ||||||
|  |        d="m 40.5,80.5 c -16.569,0 -30,-13.431 -30,-30 0,-16.569 13.431,-30 30,-30 16.569,0 30,13.431 30,30 0,16.569 -13.431,30 -30,30 z" | ||||||
|  |        fill="#ffffff" | ||||||
|  |        id="path7" /> | ||||||
|  |     <path | ||||||
|  |        d="m 40.5,80.5 c -16.569,0 -30,-13.431 -30,-30 0,-16.569 13.431,-30 30,-30 16.569,0 30,13.431 30,30 0,16.569 -13.431,30 -30,30 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="2.7" | ||||||
|  |        id="path8" /> | ||||||
|  |   </g> | ||||||
|  |   <path | ||||||
|  |      d="m 20.5,70.5 40,-40" | ||||||
|  |      fill-opacity="0" | ||||||
|  |      stroke="#000000" | ||||||
|  |      stroke-width="2" | ||||||
|  |      stroke-linecap="round" | ||||||
|  |      id="path9" /> | ||||||
|  |   <path | ||||||
|  |      style="fill:#121212;stroke:#000000;stroke-width:4.41824" | ||||||
|  |      id="path11" | ||||||
|  |      sodipodi:type="arc" | ||||||
|  |      sodipodi:cx="40.160213" | ||||||
|  |      sodipodi:cy="49.300335" | ||||||
|  |      sodipodi:rx="29.252346" | ||||||
|  |      sodipodi:ry="27.2386" | ||||||
|  |      sodipodi:start="2.3561945" | ||||||
|  |      sodipodi:end="5.4925512" | ||||||
|  |      sodipodi:arc-type="slice" | ||||||
|  |      d="M 19.475681,68.560933 A 29.252346,27.2386 0 0 1 19.421601,30.090226 29.252346,27.2386 0 0 1 60.73616,29.939153 L 40.160213,49.300335 Z" /> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_bouton_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_bouton_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_contact_double_repos.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 684 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_contact_double_travail.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 610 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_moins.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 316 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_plus.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_pulse.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										18
									
								
								images_v1/mirror_pulse.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,18 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <text transform="matrix(1, 0, 0, 1, 44.212, 50)"> | ||||||
|  |       <tspan x="-20.012" y="5.5" font-family="Helvetica" font-size="16" fill="#000000">Pulsé</tspan> | ||||||
|  |     </text> | ||||||
|  |     <text transform="matrix(1, 0, 0, 1, 47.2, 33.5)"> | ||||||
|  |       <tspan x="-24.427" y="6.5" font-family="Helvetica" font-size="28.8" fill="#000000">+24</tspan> | ||||||
|  |     </text> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_relais_cote.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_repos_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 645 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_repos_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 431 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_travail_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 508 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/mirror_travail_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 714 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/moins.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 661 B | 
							
								
								
									
										15
									
								
								images_v1/moins.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <text transform="matrix(1, 0, 0, 1, 22.837, 29)"> | ||||||
|  |       <tspan x="-8.991" y="12" font-family="Helvetica" font-size="54" fill="#000000">-</tspan> | ||||||
|  |     </text> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/noeud.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 594 B | 
							
								
								
									
										12
									
								
								images_v1/noeud.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M40.5,55.5 C38.291,55.5 36.5,53.261 36.5,50.5 C36.5,47.739 38.291,45.5 40.5,45.5 C42.709,45.5 44.5,47.739 44.5,50.5 C44.5,53.261 42.709,55.5 40.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M40.5,55.5 C38.291,55.5 36.5,53.261 36.5,50.5 C36.5,47.739 38.291,45.5 40.5,45.5 C42.709,45.5 44.5,47.739 44.5,50.5 C44.5,53.261 42.709,55.5 40.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 921 B | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/plus.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										15
									
								
								images_v1/plus.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <text transform="matrix(1, 0, 0, 1, 47.2, 33.5)"> | ||||||
|  |       <tspan x="-24.427" y="6.5" font-family="Helvetica" font-size="28.8" fill="#000000">+24</tspan> | ||||||
|  |     </text> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/pulse.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										18
									
								
								images_v1/pulse.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,18 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <text transform="matrix(1, 0, 0, 1, 47.2, 33.5)"> | ||||||
|  |       <tspan x="-24.427" y="6.5" font-family="Helvetica" font-size="28.8" fill="#000000">+24</tspan> | ||||||
|  |     </text> | ||||||
|  |     <text transform="matrix(1, 0, 0, 1, 44.212, 50)"> | ||||||
|  |       <tspan x="-20.012" y="5.5" font-family="Helvetica" font-size="16" fill="#000000">Pulsé</tspan> | ||||||
|  |     </text> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/relais.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										22
									
								
								images_v1/relais.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,22 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <g> | ||||||
|  |       <path d="M8.5,10.5 L72.5,10.5 L72.5,90.5 L8.5,90.5 z" fill="#FFFFFF"/> | ||||||
|  |       <path d="M8.5,10.5 L72.5,10.5 L72.5,90.5 L8.5,90.5 z" fill-opacity="0" stroke="#000000" stroke-width="4.05"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M8.5,30.5 L40.5,60.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M40.5,60.5 L72.5,30.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/relais_basculeur.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.3 KiB | 
							
								
								
									
										46
									
								
								images_v1/relais_basculeur.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="160" height="100" viewBox="0, 0, 160, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <g> | ||||||
|  |       <path d="M5,30.385 C2.239,30.385 0,28.189 0,25.481 C0,22.773 2.239,20.577 5,20.577 C7.761,20.577 10,22.773 10,25.481 C10,28.189 7.761,30.385 5,30.385 z" fill="#000000"/> | ||||||
|  |       <path d="M5,30.385 C2.239,30.385 0,28.189 0,25.481 C0,22.773 2.239,20.577 5,20.577 C7.761,20.577 10,22.773 10,25.481 C10,28.189 7.761,30.385 5,30.385 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <g> | ||||||
|  |         <g> | ||||||
|  |           <path d="M9.678,8.5 L72.586,8.5 L72.586,88.5 L9.678,88.5 z" fill="#FFFFFF"/> | ||||||
|  |           <path d="M9.678,8.5 L72.586,8.5 L72.586,88.5 L9.678,88.5 z" fill-opacity="0" stroke="#000000" stroke-width="4.05"/> | ||||||
|  |         </g> | ||||||
|  |         <path d="M9.678,28.5 L41.132,58.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |         <path d="M41.132,58.5 L72.586,28.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |       </g> | ||||||
|  |       <path d="M0,100 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |       <path d="M0,50 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |       <g> | ||||||
|  |         <g> | ||||||
|  |           <path d="M87.103,8.5 L150.011,8.5 L150.011,88.5 L87.103,88.5 z" fill="#FFFFFF"/> | ||||||
|  |           <path d="M87.103,8.5 L150.011,8.5 L150.011,88.5 L87.103,88.5 z" fill-opacity="0" stroke="#000000" stroke-width="4.05"/> | ||||||
|  |         </g> | ||||||
|  |         <path d="M87.103,28.5 L118.557,58.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |         <path d="M118.557,58.5 L150.011,28.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |       </g> | ||||||
|  |       <g> | ||||||
|  |         <path d="M70.378,8.5 L88.429,8.5 L88.429,88.5 L70.378,88.5 L70.378,8.5 z" fill="#000000"/> | ||||||
|  |         <path d="M70.378,8.5 L88.429,8.5 L88.429,88.5 L70.378,88.5 L70.378,8.5 z" fill-opacity="0" stroke="#000000" stroke-width="1"/> | ||||||
|  |       </g> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M5,69.916 C2.239,69.916 -0,67.677 -0,64.916 C-0,62.155 2.239,59.916 5,59.916 C7.761,59.916 10,62.155 10,64.916 C10,67.677 7.761,69.916 5,69.916 z" fill="#000000"/> | ||||||
|  |       <path d="M5,69.916 C2.239,69.916 -0,67.677 -0,64.916 C-0,62.155 2.239,59.916 5,59.916 C7.761,59.916 10,62.155 10,64.916 C10,67.677 7.761,69.916 5,69.916 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M155.005,30.385 C152.247,30.385 150.011,28.146 150.011,25.385 C150.011,22.624 152.247,20.385 155.005,20.385 C157.764,20.385 160,22.624 160,25.385 C160,28.146 157.764,30.385 155.005,30.385 z" fill="#000000"/> | ||||||
|  |       <path d="M155.005,30.385 C152.247,30.385 150.011,28.146 150.011,25.385 C150.011,22.624 152.247,20.385 155.005,20.385 C157.764,20.385 160,22.624 160,25.385 C160,28.146 157.764,30.385 155.005,30.385 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M155.005,69.916 C152.247,69.916 150.011,67.677 150.011,64.916 C150.011,62.155 152.247,59.916 155.005,59.916 C157.764,59.916 160,62.155 160,64.916 C160,67.677 157.764,69.916 155.005,69.916 z" fill="#000000"/> | ||||||
|  |       <path d="M155.005,69.916 C152.247,69.916 150.011,67.677 150.011,64.916 C150.011,62.155 152.247,59.916 155.005,59.916 C157.764,59.916 160,62.155 160,64.916 C160,67.677 157.764,69.916 155.005,69.916 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/relais_cote.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										107
									
								
								images_v1/relais_cote.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,107 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    version="1.1" | ||||||
|  |    x="0" | ||||||
|  |    y="0" | ||||||
|  |    width="80" | ||||||
|  |    height="100" | ||||||
|  |    viewBox="0, 0, 80, 100" | ||||||
|  |    id="svg29" | ||||||
|  |    sodipodi:docname="relais_cote.svg" | ||||||
|  |    inkscape:version="1.2.2 (732a01da63, 2022-12-09)" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <defs | ||||||
|  |      id="defs33" /> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview31" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      showgrid="false" | ||||||
|  |      inkscape:zoom="8.14" | ||||||
|  |      inkscape:cx="37.100737" | ||||||
|  |      inkscape:cy="50.061425" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1001" | ||||||
|  |      inkscape:window-x="-9" | ||||||
|  |      inkscape:window-y="-9" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="svg29" /> | ||||||
|  |   <g | ||||||
|  |      id="Layer_1"> | ||||||
|  |     <g | ||||||
|  |        id="g6"> | ||||||
|  |       <path | ||||||
|  |          d="M8.5,10.5 L72.5,10.5 L72.5,90.5 L8.5,90.5 z" | ||||||
|  |          fill="#FFFFFF" | ||||||
|  |          id="path2" /> | ||||||
|  |       <path | ||||||
|  |          d="M8.5,10.5 L72.5,10.5 L72.5,90.5 L8.5,90.5 z" | ||||||
|  |          fill-opacity="0" | ||||||
|  |          stroke="#000000" | ||||||
|  |          stroke-width="4.05" | ||||||
|  |          id="path4" /> | ||||||
|  |     </g> | ||||||
|  |     <path | ||||||
|  |        d="M8.5,30.5 L40.5,60.5" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="2.7" | ||||||
|  |        stroke-linecap="round" | ||||||
|  |        id="path8" /> | ||||||
|  |     <path | ||||||
|  |        d="M40.5,60.5 L72.5,30.5" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="2.7" | ||||||
|  |        stroke-linecap="round" | ||||||
|  |        id="path10" /> | ||||||
|  |     <path | ||||||
|  |        d="M12.5,101.5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path12" /> | ||||||
|  |     <path | ||||||
|  |        d="M12.5,51.5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path14" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      id="g26" | ||||||
|  |      transform="translate(-71.954546,-22.40172)"> | ||||||
|  |     <path | ||||||
|  |        d="m 76.5,55.5 c -2.209,0 -4,-2.239 -4,-5 0,-2.761 1.791,-5 4,-5 2.209,0 4,2.239 4,5 0,2.761 -1.791,5 -4,5 z" | ||||||
|  |        fill="#000000" | ||||||
|  |        id="path22" /> | ||||||
|  |     <path | ||||||
|  |        d="m 76.5,55.5 c -2.209,0 -4,-2.239 -4,-5 0,-2.761 1.791,-5 4,-5 2.209,0 4,2.239 4,5 0,2.761 -1.791,5 -4,5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path24" /> | ||||||
|  |   </g> | ||||||
|  |   <g | ||||||
|  |      id="g20" | ||||||
|  |      transform="translate(0.07985261,18.114251)"> | ||||||
|  |     <path | ||||||
|  |        d="m 4.5,55.5 c -2.209,0 -4,-2.239 -4,-5 0,-2.761 1.791,-5 4,-5 2.209,0 4,2.239 4,5 0,2.761 -1.791,5 -4,5 z" | ||||||
|  |        fill="#000000" | ||||||
|  |        id="path16" /> | ||||||
|  |     <path | ||||||
|  |        d="m 4.5,55.5 c -2.209,0 -4,-2.239 -4,-5 0,-2.761 1.791,-5 4,-5 2.209,0 4,2.239 4,5 0,2.761 -1.791,5 -4,5 z" | ||||||
|  |        fill-opacity="0" | ||||||
|  |        stroke="#000000" | ||||||
|  |        stroke-width="0.9" | ||||||
|  |        id="path18" /> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/repos_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										23
									
								
								images_v1/repos_ferme.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,23 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,65.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M16.5,75.5 C14.291,75.5 12.5,73.261 12.5,70.5 C12.5,67.739 14.291,65.5 16.5,65.5 C18.709,65.5 20.5,67.739 20.5,70.5 C20.5,73.261 18.709,75.5 16.5,75.5 z" fill="#000000"/> | ||||||
|  |       <path d="M16.5,75.5 C14.291,75.5 12.5,73.261 12.5,70.5 C12.5,67.739 14.291,65.5 16.5,65.5 C18.709,65.5 20.5,67.739 20.5,70.5 C20.5,73.261 18.709,75.5 16.5,75.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M4.5,50.5 L4.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M4.5,70.5 L16.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/repos_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 829 B | 
							
								
								
									
										23
									
								
								images_v1/repos_ouvert.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,23 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M16.5,50.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M16.5,75.5 C14.291,75.5 12.5,73.261 12.5,70.5 C12.5,67.739 14.291,65.5 16.5,65.5 C18.709,65.5 20.5,67.739 20.5,70.5 C20.5,73.261 18.709,75.5 16.5,75.5 z" fill="#000000"/> | ||||||
|  |       <path d="M16.5,75.5 C14.291,75.5 12.5,73.261 12.5,70.5 C12.5,67.739 14.291,65.5 16.5,65.5 C18.709,65.5 20.5,67.739 20.5,70.5 C20.5,73.261 18.709,75.5 16.5,75.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M4.5,50.5 L4.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M4.5,70.5 L16.5,70.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/resistance.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 561 B | 
							
								
								
									
										19
									
								
								images_v1/resistance.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M4.5,50.5 L20.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M60.5,50.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="2.7" stroke-linecap="round"/> | ||||||
|  |     <path d="M20.5,50.5 C20.5,50.5 20.5,35.5 20.5,35.5 L28.5,35.5 C28.5,35.5 28.5,65.5 28.5,65.5 C28.5,65.5 36.5,65.5 36.5,65.5 L36.5,35.5 L44.5,35.5 L44.5,65.5 L52.5,65.5 L52.5,35.5 L60.5,35.5 L60.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="2.7"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/tempo_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										25
									
								
								images_v1/tempo_ferme.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M4.199,50.153 L73.998,45.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M40.5,36.9 C35.033,36.9 30.601,31.489 30.601,24.815 C30.601,18.14 35.033,12.729 40.5,12.729 C45.967,12.729 50.399,18.14 50.399,24.815 C50.399,31.489 45.967,36.9 40.5,36.9 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M38.5,12.729 L38.5,7.729 L42.5,7.729 L42.5,12.729" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M45.682,14.113 L46.788,12.224 L48.304,13.611 L47.198,15.5" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M40.5,26.539 C40.044,26.539 39.674,26.075 39.674,25.503 C39.674,24.93 40.044,24.466 40.5,24.466 C40.956,24.466 41.326,24.93 41.326,25.503 C41.326,26.075 40.956,26.539 40.5,26.539 z" fill="#000000"/> | ||||||
|  |       <path d="M40.5,26.539 C40.044,26.539 39.674,26.075 39.674,25.503 C39.674,24.93 40.044,24.466 40.5,24.466 C40.956,24.466 41.326,24.93 41.326,25.503 C41.326,26.075 40.956,26.539 40.5,26.539 z" fill-opacity="0" stroke="#000000" stroke-width="0.9" stroke-linejoin="bevel"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M40.521,16.651 L40.474,25.251" fill-opacity="0" stroke="#000000" stroke-width="0.9" stroke-linejoin="bevel"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/tempo_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										25
									
								
								images_v1/tempo_ouvert.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M4.199,50.153 L74.515,31.649" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M40.5,36.9 C35.033,36.9 30.601,31.489 30.601,24.815 C30.601,18.14 35.033,12.729 40.5,12.729 C45.967,12.729 50.399,18.14 50.399,24.815 C50.399,31.489 45.967,36.9 40.5,36.9 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M38.5,12.729 L38.5,7.729 L42.5,7.729 L42.5,12.729" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M45.682,14.113 L46.788,12.224 L48.304,13.611 L47.198,15.5" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M40.5,26.539 C40.044,26.539 39.674,26.075 39.674,25.503 C39.674,24.93 40.044,24.466 40.5,24.466 C40.956,24.466 41.326,24.93 41.326,25.503 C41.326,26.075 40.956,26.539 40.5,26.539 z" fill="#000000"/> | ||||||
|  |       <path d="M40.5,26.539 C40.044,26.539 39.674,26.075 39.674,25.503 C39.674,24.93 40.044,24.466 40.5,24.466 C40.956,24.466 41.326,24.93 41.326,25.503 C41.326,26.075 40.956,26.539 40.5,26.539 z" fill-opacity="0" stroke="#000000" stroke-width="0.9" stroke-linejoin="bevel"/> | ||||||
|  |     </g> | ||||||
|  |     <path d="M40.521,16.651 L40.474,25.251" fill-opacity="0" stroke="#000000" stroke-width="0.9" stroke-linejoin="bevel"/> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/travail_ferme.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 857 B | 
							
								
								
									
										17
									
								
								images_v1/travail_ferme.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,17 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M8.5,75.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images_v1/travail_ouvert.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										17
									
								
								images_v1/travail_ouvert.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,17 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="80" height="100" viewBox="0, 0, 80, 100"> | ||||||
|  |   <g id="Layer_1"> | ||||||
|  |     <path d="M4.5,55.5 L76.5,50.5" fill-opacity="0" stroke="#000000" stroke-width="4.5" stroke-linecap="round"/> | ||||||
|  |     <path d="M12.5,101.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <path d="M12.5,51.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     <g> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M4.5,55.5 C2.291,55.5 0.5,53.261 0.5,50.5 C0.5,47.739 2.291,45.5 4.5,45.5 C6.709,45.5 8.5,47.739 8.5,50.5 C8.5,53.261 6.709,55.5 4.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |     <g> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill="#000000"/> | ||||||
|  |       <path d="M76.5,55.5 C74.291,55.5 72.5,53.261 72.5,50.5 C72.5,47.739 74.291,45.5 76.5,45.5 C78.709,45.5 80.5,47.739 80.5,50.5 C80.5,53.261 78.709,55.5 76.5,55.5 z" fill-opacity="0" stroke="#000000" stroke-width="0.9"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/cocosim.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/composants.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/donnees.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/elements.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/exceptions.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/graphe.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								modele/__pycache__/matrice.cpython-312.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										52
									
								
								modele/cocosim.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,52 @@ | |||||||
|  | from modele.matrice import Matrice | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Cocosim(object): | ||||||
|  |     def __init__(self, conf, graphe, scenario, observateur): | ||||||
|  |         self.conf = conf | ||||||
|  |         self.graphe = graphe | ||||||
|  |         self.scenario = scenario | ||||||
|  |         if 'max' in self.scenario: | ||||||
|  |             self.max_cycles = self.scenario['max'] | ||||||
|  |         else: | ||||||
|  |             self.max_cycles = None | ||||||
|  |         self.n_cycle = 0 | ||||||
|  |         self.matrice = Matrice(self.graphe) | ||||||
|  |         self.observatoire = {} | ||||||
|  |         self.observateur = observateur | ||||||
|  |         for k,_,_ in self.observateur: | ||||||
|  |             self.observatoire[k] = [] | ||||||
|  |  | ||||||
|  |     def cycle(self): | ||||||
|  |         """ | ||||||
|  |         Un cycle se fait en deux passes plus la mise à jour des composants. | ||||||
|  |         """ | ||||||
|  |         if self.n_cycle in self.scenario: | ||||||
|  |             [f(self.graphe[x]) for x, f in self.scenario[self.n_cycle]] | ||||||
|  |  | ||||||
|  |         self.graphe.init_cycle() | ||||||
|  |  | ||||||
|  |         # Passe 1 | ||||||
|  |         self.matrice.init_mat() | ||||||
|  |         xvect = self.matrice.solve() | ||||||
|  |         self.graphe.passe_calcul(xvect) | ||||||
|  |  | ||||||
|  |         # Passe 2 (pour les diodes) | ||||||
|  |         self.matrice.init_mat() | ||||||
|  |         xvect = self.matrice.solve() | ||||||
|  |         self.graphe.passe_calcul(xvect) | ||||||
|  |  | ||||||
|  |         # Mise à jour des états | ||||||
|  |         self.graphe.update() | ||||||
|  |         self.graphe.coherence() | ||||||
|  |  | ||||||
|  |         for k, obj, fun in self.observateur: | ||||||
|  |             self.observatoire[k].append(fun(self.graphe[obj])) | ||||||
|  |  | ||||||
|  |         self.n_cycle += 1 | ||||||
|  |  | ||||||
|  |     def run(self): | ||||||
|  |         for cycle in range(self.max_cycles): | ||||||
|  |             self.cycle() | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										273
									
								
								modele/composants.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,273 @@ | |||||||
|  | from modele.exceptions import NonPolariseException, Dir | ||||||
|  |  | ||||||
|  | class Composant(object): | ||||||
|  |     def __init__(self, conf, nom): | ||||||
|  |         """ | ||||||
|  |         Un composant doit a minima savoir donner une résistance | ||||||
|  |         """ | ||||||
|  |         self.branche = None  # Pour récupérer l'intensité dans la branche | ||||||
|  |         self.nom = nom | ||||||
|  |         self.conf = conf | ||||||
|  |         self.r = None | ||||||
|  |  | ||||||
|  |     def init_cycle(self): | ||||||
|  |         """ | ||||||
|  |         Initialisation du composant avant la 1ere passe de calcul. | ||||||
|  |         Pour la plupart des composants (ceux qui se calculent en une seule passe) on ne fait | ||||||
|  |         rien. N'est utile que pour les composants se calculant en plusieurs passes (diodes...). | ||||||
|  |         """ | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |     def passe_calcul(self): | ||||||
|  |         """ | ||||||
|  |         Initialisation du composant apres la 1ere passe de calcul. | ||||||
|  |         Pour la plupart des composants (ceux qui se calculent en une seule passe) on ne fait | ||||||
|  |         rien. N'est utile que pour les composants se calculant en plusieurs passes (diodes...).        """ | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |     def update(self): | ||||||
|  |         # Par défaut ne fait rien | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |     def reverse(self): | ||||||
|  |         """ | ||||||
|  |         Permet de retourner les composants polarisés (s'ils sont préfixés par "!") | ||||||
|  |         """ | ||||||
|  |         raise NonPolariseException | ||||||
|  |  | ||||||
|  |     def etat(self): | ||||||
|  |         raise NotImplementedError | ||||||
|  |      | ||||||
|  |     def pause_simulation(self): | ||||||
|  |  | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Contact(Composant): | ||||||
|  |     def __init__(self, conf, nom, contact_type): | ||||||
|  |         super().__init__(conf, nom) | ||||||
|  |         self.ouvert = None | ||||||
|  |         self.ouvre() | ||||||
|  |         self.type = contact_type | ||||||
|  |  | ||||||
|  |     def ouvre(self): | ||||||
|  |         self.ouvert = True | ||||||
|  |         self.r = self.conf['RMAX'] | ||||||
|  |  | ||||||
|  |     def ferme(self): | ||||||
|  |         self.ouvert = False | ||||||
|  |         self.r = self.conf['RMIN'] | ||||||
|  |  | ||||||
|  |     def etat(self): | ||||||
|  |         return not self.ouvert | ||||||
|  |  | ||||||
|  |     def bascule(self): | ||||||
|  |         if self.ouvert: | ||||||
|  |             self.ferme() | ||||||
|  |         else: | ||||||
|  |             self.ouvre() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Resistance(Composant): | ||||||
|  |     def __init__(self, conf, nom, valeur): | ||||||
|  |         super().__init__(conf, nom) | ||||||
|  |         self.RDEFAULT = self.conf["RES_DEFAULT"] | ||||||
|  |         if valeur is None: | ||||||
|  |             self.r = self.RDEFAULT | ||||||
|  |         else: | ||||||
|  |             self.r = valeur | ||||||
|  |  | ||||||
|  |     def set_r(self, valeur): | ||||||
|  |         self.r = valeur | ||||||
|  |  | ||||||
|  |     def etat(self): | ||||||
|  |         return None | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Lampe(Resistance): | ||||||
|  |     def __init__(self, conf, nom): | ||||||
|  |         self.RLAMPE = conf["RES_LAMPE"] | ||||||
|  |         self.SEUIL = conf["SEUIL_LAMPE"] | ||||||
|  |         super().__init__(conf, nom, self.RLAMPE) | ||||||
|  |         self.haut = False | ||||||
|  |         self.chute() | ||||||
|  |  | ||||||
|  |     def monte(self): | ||||||
|  |         self.haut = True | ||||||
|  |  | ||||||
|  |     def chute(self): | ||||||
|  |         self.haut = False | ||||||
|  |  | ||||||
|  |     def update(self): | ||||||
|  |         super().update() | ||||||
|  |         if abs(self.branche.i()) >= 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 | ||||||
|  |         self.etat_precedent = False #etat precedent du relais | ||||||
|  |         self.est_point_arret = False   #indicateur de point d'arret | ||||||
|  |  | ||||||
|  |     def add_travail(self, nom): | ||||||
|  |         self._contacts_travail.append(nom) | ||||||
|  |  | ||||||
|  |     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): | ||||||
|  |         etat_precedent = self.haut | ||||||
|  |         super().update() | ||||||
|  |         if self.branche.i() >= self.SEUIL: | ||||||
|  |             self.monte() | ||||||
|  |         else: | ||||||
|  |             self.chute() | ||||||
|  |  | ||||||
|  |         if self.est_point_arret and etat_precedent != self.haut: | ||||||
|  |             self.graphe.flag_arret_simulation = True | ||||||
|  |  | ||||||
|  |     def etat(self): | ||||||
|  |         return self.haut | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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 | ||||||
							
								
								
									
										29
									
								
								modele/config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,29 @@ | |||||||
|  | { | ||||||
|  |     "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, | ||||||
|  |       "TOLERANCE_COURANT": 1e6 | ||||||
|  |     }, | ||||||
|  |     "ui": { | ||||||
|  |       "DT": 0.13, | ||||||
|  |       "BLOCK_H": 50, | ||||||
|  |       "BLOCK_W": 40, | ||||||
|  |       "RELAISBASC_WIDTH": 1.6, | ||||||
|  |       "LINE_W": 1, | ||||||
|  |       "WINDOW_W": 1100, | ||||||
|  |       "WINDOW_H": 600 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |    | ||||||
							
								
								
									
										356
									
								
								modele/donnees.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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"<Noeud : {self.nom}, {self.type}>" | ||||||
|  |  | ||||||
|  |     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 | ||||||
							
								
								
									
										534
									
								
								modele/elements.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,534 @@ | |||||||
|  | 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'] | ||||||
|  |      | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def verifier_loi_des_noeuds(self): | ||||||
|  |  | ||||||
|  |         """Dans cette méthode, self._voisins contient les branches connectées au nœud, et polarite indique si le courant est entrant (-1) ou sortant (+1).  | ||||||
|  |         La variable courant_total accumule la somme des courants, et self.conf['TOLERANCE_COURANT'] est une petite valeur seuil pour tolérer des imprécisions | ||||||
|  |           numériques (par exemple, 1e-6).""" | ||||||
|  |          | ||||||
|  |         courant_total = 0 | ||||||
|  |         for voisin, polarite, _ in self._voisins: | ||||||
|  |             if polarite == -1: | ||||||
|  |                 courant_total -= voisin.i() | ||||||
|  |             else: | ||||||
|  |                 courant_total += voisin.i() | ||||||
|  |  | ||||||
|  |         if abs(courant_total) > self.conf['TOLERANCE_COURANT']: | ||||||
|  |             raise Exception(f"La loi des nœuds n'est pas respectée pour le noeud {self.nom}. Total courant: {courant_total}") | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Branche(Element): | ||||||
|  |     """ | ||||||
|  |     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) | ||||||
							
								
								
									
										22
									
								
								modele/exceptions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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 | ||||||
							
								
								
									
										172
									
								
								modele/graphe.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,172 @@ | |||||||
|  | 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 | ||||||
|  |         self.flag_arret_simulation = False  | ||||||
|  |  | ||||||
|  |     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()] | ||||||
							
								
								
									
										57
									
								
								modele/matrice.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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) | ||||||
							
								
								
									
										3
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,3 @@ | |||||||
|  | numpy>=1.24.3 | ||||||
|  | flask>=2.3.2 | ||||||
|  | Flask-Cors>=4.0.0 | ||||||
							
								
								
									
										6
									
								
								run.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | |||||||
|  | from api_server.app import main | ||||||
|  |  | ||||||
|  | import sys | ||||||
|  |  | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     main(sys.argv) | ||||||
							
								
								
									
										1
									
								
								schemas_v1/basculeur.ccs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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"]]} | ||||||
							
								
								
									
										104
									
								
								schemas_v1/condensateur.ccs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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"] | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										87
									
								
								schemas_v1/contact_double.ccs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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"] | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										73
									
								
								schemas_v1/contact_double_180.ccs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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"] | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								schemas_v1/diodes.ccs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -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"] | ||||||
|  |     ] | ||||||
|  | } | ||||||