import de fichiers
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
218
api_server/app.py
Normal file
@ -0,0 +1,218 @@
|
||||
"""
|
||||
Lancer avec python -m flask --debug --app server\\__init__.py run
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
|
||||
from flask import Flask, request, session
|
||||
import multiprocessing as mp
|
||||
from api_worker.__init__ import run_instance
|
||||
import uuid
|
||||
from flask_cors import CORS
|
||||
|
||||
app = Flask("COCOSIM")
|
||||
CORS(app, supports_credentials=True)
|
||||
app.secret_key = bytes.fromhex('192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf')
|
||||
|
||||
|
||||
class ProcessBase(object):
|
||||
SESSION_MAX_AGE = 60 * 5
|
||||
|
||||
def __init__(self):
|
||||
self._cmd_q = {}
|
||||
self._state_q = {}
|
||||
self._process = {}
|
||||
self._last = {}
|
||||
|
||||
def known(self):
|
||||
return 'id' in session and session['id'] in self._cmd_q
|
||||
|
||||
def update(self):
|
||||
self._last[session['id']] = time.time()
|
||||
|
||||
def cmd_q(self):
|
||||
self.update()
|
||||
return self._cmd_q[session['id']]
|
||||
|
||||
def state_q(self):
|
||||
self.update()
|
||||
return self._state_q[session['id']]
|
||||
|
||||
def init_q(self):
|
||||
self.update()
|
||||
self._state_q[session['id']] = mp.Queue()
|
||||
self._cmd_q[session['id']] = mp.Queue()
|
||||
|
||||
def init_process(self, p):
|
||||
self.update()
|
||||
self.cleanup()
|
||||
self._process[session['id']] = p
|
||||
|
||||
def process(self):
|
||||
return self._process[session['id']]
|
||||
|
||||
def purge(self, k=None):
|
||||
if k is None:
|
||||
k = session['id']
|
||||
|
||||
del self._cmd_q[k]
|
||||
del self._state_q[k]
|
||||
del self._process[k]
|
||||
del self._last[k]
|
||||
|
||||
def quit(self):
|
||||
self.purge()
|
||||
self.cleanup()
|
||||
|
||||
def cleanup(self):
|
||||
ctime = time.time()
|
||||
to_purge = []
|
||||
|
||||
for k, v in self._last.items():
|
||||
if ctime - v > self.SESSION_MAX_AGE:
|
||||
to_purge.append(k)
|
||||
|
||||
for k in to_purge:
|
||||
logging.info(f"Purging {k}")
|
||||
self.purge(k)
|
||||
|
||||
def __str__(self):
|
||||
return str(list(self._process.keys()))
|
||||
|
||||
def __len__(self):
|
||||
return len(self._process.keys())
|
||||
|
||||
|
||||
PROCESS_BASE = ProcessBase()
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def hello():
|
||||
PROCESS_BASE.cleanup()
|
||||
return f"Hello sailor !\nProcess base : {str(PROCESS_BASE)}"
|
||||
|
||||
|
||||
@app.route('/init')
|
||||
def init():
|
||||
session['id'] = uuid.uuid4().int
|
||||
PROCESS_BASE.init_q()
|
||||
PROCESS_BASE.init_process(mp.Process(target=run_instance, args=(session['id'], PROCESS_BASE.cmd_q(), PROCESS_BASE.state_q())))
|
||||
PROCESS_BASE.process().start()
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.route('/start')
|
||||
def start():
|
||||
if not PROCESS_BASE.known():
|
||||
return "Unknown", 401
|
||||
PROCESS_BASE.cmd_q().put({'cmd': "start"})
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.route('/stop')
|
||||
def stop():
|
||||
if not PROCESS_BASE.known():
|
||||
return "Unknown", 401
|
||||
|
||||
PROCESS_BASE.cmd_q().put({'cmd': "stop"})
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.route('/state')
|
||||
def state():
|
||||
if not PROCESS_BASE.known():
|
||||
return "Unknown", 401
|
||||
|
||||
PROCESS_BASE.cmd_q().put({'cmd': "state"})
|
||||
data = PROCESS_BASE.state_q().get()
|
||||
return data
|
||||
|
||||
|
||||
@app.route('/quit')
|
||||
def quit():
|
||||
if not PROCESS_BASE.known():
|
||||
PROCESS_BASE.cleanup()
|
||||
return "Unknown", 401
|
||||
|
||||
PROCESS_BASE.cmd_q().put({'cmd': "quit"})
|
||||
PROCESS_BASE.process().join()
|
||||
PROCESS_BASE.quit()
|
||||
del session['id']
|
||||
logging.info("Purge effectuée")
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.route('/load', methods=['POST'])
|
||||
def load():
|
||||
if not PROCESS_BASE.known():
|
||||
return "Unknown", 401
|
||||
|
||||
try:
|
||||
data = request.json
|
||||
PROCESS_BASE.cmd_q().put({'cmd': "load", "args": data})
|
||||
except Exception:
|
||||
logging.exception("ERROR")
|
||||
return "Error", 418
|
||||
|
||||
if PROCESS_BASE.state_q().get() == "OK":
|
||||
return "OK"
|
||||
else:
|
||||
return "Error in graph", 418
|
||||
|
||||
|
||||
@app.route('/push/<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"
|
||||
|
||||
|
||||
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
|
41
api_server/state.py
Normal file
@ -0,0 +1,41 @@
|
||||
import json
|
||||
|
||||
|
||||
class State(object):
|
||||
IGNORE = frozenset(['Coude', 'Noeud', 'P24', 'P0', 'Pulse'])
|
||||
|
||||
def __init__(self, cocosim_server):
|
||||
self.cocosim_server = cocosim_server
|
||||
self.conf = self.cocosim_server.conf["ui"]
|
||||
self.composants = {}
|
||||
self._exception = None
|
||||
|
||||
def load_conf(self, schema_d):
|
||||
# Chargement des blocs
|
||||
for nom, valeur in schema_d['blocs'].items():
|
||||
if valeur['type'] not in self.IGNORE:
|
||||
self.composants[nom] = None
|
||||
|
||||
def to_json(self):
|
||||
if self._exception:
|
||||
return json.dumps({'exn': self._exception})
|
||||
else:
|
||||
return json.dumps(self.composants)
|
||||
|
||||
def __iter__(self):
|
||||
return self.conf.__iter__
|
||||
|
||||
def items(self):
|
||||
return self.composants.items()
|
||||
|
||||
def keys(self):
|
||||
return self.composants.keys()
|
||||
|
||||
def update(self, nom, valeur):
|
||||
self.composants[nom] = valeur
|
||||
|
||||
def exception(self, e):
|
||||
self._exception = e
|
||||
|
||||
def reset_exception(self):
|
||||
self._exception = None
|
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())
|
135
api_worker/__init__.py
Normal file
@ -0,0 +1,135 @@
|
||||
import json
|
||||
import asyncio
|
||||
from modele.donnees import SchemaReader, GraphStructException
|
||||
from modele.graphe import Graphe
|
||||
from modele.cocosim import Cocosim
|
||||
from api_server.state import State
|
||||
import logging
|
||||
import modele.exceptions
|
||||
|
||||
class CocosimInstance(object):
|
||||
def __init__(self, cmd_q, state_q):
|
||||
self.runner = None
|
||||
try:
|
||||
conf_fp = open("modele/config.json")
|
||||
conf = json.load(conf_fp)
|
||||
|
||||
self.conf = conf
|
||||
self.dt = self.conf['circuit']['DT']
|
||||
self.cocosim = None
|
||||
self.state = None
|
||||
self.cmd_q = cmd_q
|
||||
self.state_q = state_q
|
||||
self.quit = False
|
||||
except (OSError, json.JSONDecodeError) as e:
|
||||
logging.exception("Reading conf. file")
|
||||
raise modele.G
|
||||
|
||||
def setup(self, schema_d):
|
||||
logging.info("Setting up")
|
||||
reader = SchemaReader(schema_d)
|
||||
reader.process()
|
||||
logging.info("Schema is loaded")
|
||||
self.state = State(self)
|
||||
self.state.load_conf(schema_d)
|
||||
logging.info(f"State is made up with {len(self.state.composants)} items.")
|
||||
graphe = Graphe(self.conf['circuit'])
|
||||
graphe.load_data_from_schema_reader(reader)
|
||||
logging.info("Graph is initialized.")
|
||||
self.cocosim = Cocosim(self.conf, graphe, {}, {})
|
||||
logging.info("Cocosim is initialized")
|
||||
|
||||
async def handler(self):
|
||||
loop = asyncio.get_running_loop()
|
||||
data = await loop.run_in_executor(None, self.cmd_q.get)
|
||||
message = data['cmd']
|
||||
try:
|
||||
if message == "start":
|
||||
logging.log(logging.INFO, "Starting")
|
||||
self.runner = asyncio.create_task(self.run())
|
||||
elif message == "stop":
|
||||
logging.log(logging.INFO, "Stopping")
|
||||
await self.stop()
|
||||
elif message == "state":
|
||||
self.state_q.put(self.state.to_json())
|
||||
elif message == "quit":
|
||||
logging.log(logging.INFO, "Quitting")
|
||||
await self.stop()
|
||||
self.quit = True
|
||||
elif message == "load":
|
||||
logging.log(logging.INFO, "Loading file")
|
||||
try:
|
||||
self.setup(data['args'] if type(data['args']) == dict else json.loads(data['args'])) # Compatibilité avec certaines IHM
|
||||
self.state_q.put("OK")
|
||||
except GraphStructException:
|
||||
self.state_q.put("Error")
|
||||
elif message == "push":
|
||||
but_name = data['args']
|
||||
logging.log(logging.INFO, f"Push button {but_name}")
|
||||
if self.cocosim.graphe[but_name] == "Bouton":
|
||||
self.cocosim.graphe[but_name].ferme()
|
||||
else:
|
||||
self.cocosim.graphe[but_name].bascule()
|
||||
elif message == "release":
|
||||
but_name = data['args']
|
||||
logging.log(logging.INFO, f"Release button {but_name}")
|
||||
if self.cocosim.graphe[but_name].type == "Bouton":
|
||||
self.cocosim.graphe[but_name].ouvre()
|
||||
# Dans le cas contraire on ne traite pas le release
|
||||
else:
|
||||
logging.log(logging.ERROR, "Commande inconnue")
|
||||
except Exception:
|
||||
logging.exception("Exception occured in handler")
|
||||
|
||||
def cycle(self):
|
||||
try:
|
||||
self.cocosim.cycle()
|
||||
|
||||
for nom in self.state.keys():
|
||||
if nom not in self.cocosim.graphe and nom[-7:] == ".double": # TODO : a supprimer apràs refactoring contact double
|
||||
nom_translate = nom[:-7] + ".travail"
|
||||
value = self.cocosim.graphe[nom_translate].etat() if nom_translate in self.cocosim.graphe else None
|
||||
self.state.update(nom, value)
|
||||
else:
|
||||
value = self.cocosim.graphe[nom].etat() if nom in self.cocosim.graphe else None
|
||||
self.state.update(nom, value)
|
||||
except modele.base.SurintensiteException as e:
|
||||
self.state.exception("Surintensité")
|
||||
raise e
|
||||
except modele.base.SurtensionException as e:
|
||||
self.state.exception("Surtension")
|
||||
raise e
|
||||
|
||||
|
||||
async def run(self):
|
||||
try:
|
||||
while True:
|
||||
self.state.reset_exception()
|
||||
self.cycle()
|
||||
await asyncio.sleep(self.dt)
|
||||
except:
|
||||
logging.exception("Exception occured in 'cycle'")
|
||||
|
||||
async def stop(self):
|
||||
if self.runner:
|
||||
self.runner.cancel()
|
||||
try:
|
||||
await self.runner
|
||||
except asyncio.CancelledError:
|
||||
logging.info("Runner is stopped.")
|
||||
self.runner = None
|
||||
|
||||
async def handle_requests(self):
|
||||
while not self.quit:
|
||||
await self.handler()
|
||||
logging.info("Stop handling request")
|
||||
|
||||
def __del__(self):
|
||||
logging.info("Cocosim instance destroyed")
|
||||
|
||||
|
||||
def run_instance(uid, cmd_q, state_q):
|
||||
logging.basicConfig(filename=f"cocosim.log", filemode="w", level=logging.INFO)
|
||||
logging.info("Creating instance")
|
||||
i = CocosimInstance(cmd_q, state_q)
|
||||
asyncio.run(i.handle_requests())
|
BIN
api_worker/__pycache__/__init__.cpython-312.pyc
Normal file
19
cocosim.log
Normal file
@ -0,0 +1,19 @@
|
||||
INFO:root:Creating instance
|
||||
INFO:root:Loading file
|
||||
INFO:root:Setting up
|
||||
INFO:root:Schema is loaded
|
||||
INFO:root:State is made up with 5 items.
|
||||
INFO:root:Graph is initialized.
|
||||
INFO:root:Cocosim is initialized
|
||||
INFO:root:Starting
|
||||
INFO:root:Push button b
|
||||
INFO:root:Release button b
|
||||
INFO:root:Stopping
|
||||
ERROR:root:Exception occured in 'cycle'
|
||||
Traceback (most recent call last):
|
||||
File "C:\Users\0203209E\Downloads\gittea\cocosim_python\api_worker\__init__.py", line 109, in run
|
||||
await asyncio.sleep(self.dt)
|
||||
File "C:\Program Files\Python312\Lib\asyncio\tasks.py", line 655, in sleep
|
||||
return await future
|
||||
^^^^^^^^^^^^
|
||||
asyncio.exceptions.CancelledError
|
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()
|
||||
|
||||
|
264
modele/composants.py
Normal file
@ -0,0 +1,264 @@
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
def add_travail(self, nom):
|
||||
self._contacts_travail.append(nom)
|
||||
|
||||
def add_repos(self, nom):
|
||||
self._contacts_repos.append(nom)
|
||||
|
||||
def add_double(self, nom):
|
||||
self._contacts_double.append(nom)
|
||||
|
||||
def monte(self):
|
||||
self.haut = True
|
||||
for nom in self._contacts_repos:
|
||||
self.graphe[nom].ouvre()
|
||||
|
||||
for nom in self._contacts_travail:
|
||||
self.graphe[nom].ferme()
|
||||
|
||||
for nom in self._contacts_double:
|
||||
self.graphe[nom].active()
|
||||
|
||||
def chute(self):
|
||||
self.haut = False
|
||||
for nom in self._contacts_repos:
|
||||
self.graphe[nom].ferme()
|
||||
|
||||
for nom in self._contacts_travail:
|
||||
self.graphe[nom].ouvre()
|
||||
|
||||
for nom in self._contacts_double:
|
||||
self.graphe[nom].desactive()
|
||||
|
||||
def update(self):
|
||||
super().update()
|
||||
if self.branche.i() >= self.SEUIL:
|
||||
self.monte()
|
||||
else:
|
||||
self.chute()
|
||||
|
||||
def etat(self):
|
||||
return self.haut
|
||||
|
||||
|
||||
class DemiRelaisBasculeur(Composant):
|
||||
def __init__(self, conf, nom, graphe, cote):
|
||||
super().__init__(conf, nom)
|
||||
self.SEUIL = self.conf["SEUIL_RELAIS"]
|
||||
self.r = self.conf["RES_RELAIS"]
|
||||
self._contacts_basc = []
|
||||
self.haut = False
|
||||
self.cote = cote
|
||||
self.graphe = graphe
|
||||
|
||||
def add_contact(self, nom):
|
||||
self._contacts_basc.append(nom)
|
||||
|
||||
def monte(self):
|
||||
self.haut = True
|
||||
if self.cote == Dir.GAUCHE:
|
||||
for nom in self._contacts_basc:
|
||||
self.graphe.elements[nom].bascule_gauche()
|
||||
elif self.cote == Dir.DROITE:
|
||||
for nom in self._contacts_basc:
|
||||
self.graphe.elements[nom].bascule_droite()
|
||||
else:
|
||||
assert False
|
||||
|
||||
def chute(self):
|
||||
self.haut = False
|
||||
|
||||
def update(self):
|
||||
super().update()
|
||||
if self.branche.i() >= self.SEUIL:
|
||||
self.monte()
|
||||
else:
|
||||
self.chute()
|
||||
|
||||
def etat(self):
|
||||
return self.haut
|
||||
|
||||
|
||||
class Tempo(Composant):
|
||||
"""
|
||||
Tempo type "bilame piloté par le temps"
|
||||
"""
|
||||
def __init__(self, conf, nom, tempo_blocage, tempo_liberation):
|
||||
super().__init__(conf, nom)
|
||||
self.SEUIL = self.conf["SEUIL_TEMPO"]
|
||||
self.h_trans = 0 # heure de la transition
|
||||
self.h = 0 # heure courante
|
||||
self.i_prec = 0.0 # intensité précédente
|
||||
self.tempo_blocage = tempo_blocage / self.conf["DT"] # durée de la tempo de blocage
|
||||
self.tempo_liberation = tempo_liberation / self.conf["DT"] # durée de la tempo de blocage
|
||||
self.blocage = False
|
||||
self.r = self.conf['RMIN']
|
||||
|
||||
def update(self):
|
||||
if self.blocage:
|
||||
if self.h - self.h_trans >= self.tempo_liberation:
|
||||
self.h_trans = self.h
|
||||
self.blocage = False
|
||||
self.r = self.conf["RMIN"]
|
||||
else:
|
||||
if self.branche.i() >= self.SEUIL:
|
||||
if self.i_prec < self.SEUIL:
|
||||
self.h_trans = self.h # On mémorise l'heure de la transition
|
||||
|
||||
if self.h - self.h_trans >= self.tempo_blocage - 1:
|
||||
self.r = self.conf["RMAX"]
|
||||
self.blocage = True
|
||||
self.h_trans = self.h # On mémorise l'heure à laquelle on bloque
|
||||
else:
|
||||
pass # On est au-delà du seuil mais la tempo n'est pas échue
|
||||
self.i_prec = self.branche.i()
|
||||
self.h += 1
|
||||
|
||||
@property
|
||||
def ouvert(self):
|
||||
return self.blocage
|
||||
|
||||
def etat(self):
|
||||
return not self.blocage
|
||||
|
||||
|
||||
class Diode(Composant):
|
||||
def __init__(self, conf, nom):
|
||||
super().__init__(conf, nom)
|
||||
self.r = self.conf["RMAX"]
|
||||
self.reversed = False # La diode est dans le sens opposé à la branche
|
||||
|
||||
def init_cycle(self):
|
||||
self.r = self.conf["RMAX"]
|
||||
|
||||
def passe_calcul(self):
|
||||
if (not self.reversed and (self.branche.amont.u() > self.branche.aval.u())) \
|
||||
or (self.reversed and (self.branche.amont.u() < self.branche.aval.u())):
|
||||
self.r = self.conf["RMIN"]
|
||||
else:
|
||||
self.r = self.conf["RMAX"]
|
||||
|
||||
def reverse(self):
|
||||
self.reversed = True
|
||||
|
||||
def etat(self):
|
||||
return None
|
28
modele/config.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"circuit": {
|
||||
"DT": 0.05,
|
||||
"RMIN": 1E-32,
|
||||
"RMAX": 1E32,
|
||||
"UMAX": 24.5,
|
||||
"USEUIL": 5,
|
||||
"ISEUIL": 0.05,
|
||||
"IMAX": 5.0,
|
||||
"RES_DEFAULT": 100,
|
||||
"RES_LAMPE": 100.0,
|
||||
"SEUIL_LAMPE": 0.05,
|
||||
"RES_RELAIS": 100.0,
|
||||
"SEUIL_RELAIS": 0.05,
|
||||
"SEUIL_TEMPO": 0.05,
|
||||
"PULSE_PERIODE": 1.0
|
||||
},
|
||||
"ui": {
|
||||
"DT": 0.13,
|
||||
"BLOCK_H": 50,
|
||||
"BLOCK_W": 40,
|
||||
"RELAISBASC_WIDTH": 1.6,
|
||||
"LINE_W": 1,
|
||||
"WINDOW_W": 1100,
|
||||
"WINDOW_H": 600
|
||||
}
|
||||
}
|
||||
|
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
|
514
modele/elements.py
Normal file
@ -0,0 +1,514 @@
|
||||
from modele.exceptions import (WrongElecPropertyException, SurtensionException,
|
||||
SurintensiteException, Dir)
|
||||
|
||||
|
||||
class Element(object):
|
||||
"""
|
||||
Classe mère.
|
||||
Le graphe lui-même est composé de Potentiels fixes (Potentiel), de Noeuds, et de Branches.
|
||||
Les branches contiennent une liste de composants en série.
|
||||
|
||||
Les éléments doivent implémenter quatre méthodes pour le calcul des valeurs :
|
||||
init_cycle est appelée avant chaque cycle, avant l'initialisation de la matrice
|
||||
report_pass_1 est appelée après la première passe pour report des valeurs de la matrice (et avant la construction
|
||||
de la matrice de la deuxième passe)
|
||||
report_pass2 est appelée après la 2e passe pour reporter les valeurs finales calculées
|
||||
update est appelée après le report de la 2e passe, pour pouvoir faire la mise à jour des états des éléments
|
||||
|
||||
"""
|
||||
P_CST, P_NOEUD, P_DLT, P_COND, P_EQVAR, P_BSCLAME = range(6)
|
||||
|
||||
def __init__(self, conf, nom, type_potentiel):
|
||||
self.type_potentiel = type_potentiel
|
||||
self.conf = conf
|
||||
self.nom = nom
|
||||
|
||||
def init_cycle(self):
|
||||
pass
|
||||
|
||||
def passe_calcul(self, solutions, index):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
def etat(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def coherence(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def eq_elts(self):
|
||||
"""
|
||||
Retourne les équipotentiels
|
||||
Par défaut, un seul équipotentiel
|
||||
"""
|
||||
return [self]
|
||||
|
||||
def get_potentiel(self, direction):
|
||||
"""
|
||||
Par défaut, un seul potentiel quel que soit la direction
|
||||
"""
|
||||
return self
|
||||
|
||||
|
||||
class Potentiel(Element):
|
||||
"""
|
||||
Potentiel à 24V ou à 0V
|
||||
"""
|
||||
|
||||
def __init__(self, conf, nom, u=0.0, voisins=None):
|
||||
super().__init__(conf, nom, self.P_CST)
|
||||
self._u = u
|
||||
if voisins is None:
|
||||
voisins = []
|
||||
self._voisins = voisins
|
||||
|
||||
def add_voisins(self, voisins):
|
||||
self._voisins += voisins
|
||||
|
||||
def voisins(self):
|
||||
return self._voisins
|
||||
|
||||
def u(self):
|
||||
return self._u
|
||||
|
||||
def i(self):
|
||||
raise WrongElecPropertyException
|
||||
|
||||
def coherence(self):
|
||||
pass
|
||||
|
||||
def etat(self):
|
||||
return self.u() >= self.conf['USEUIL']
|
||||
|
||||
class PotPulse(Potentiel):
|
||||
def __init__(self, conf, nom, u=0.0, periode=None, voisins=None):
|
||||
super().__init__(conf, nom, u, voisins)
|
||||
if periode is None:
|
||||
periode = self.conf['PULSE_PERIODE']
|
||||
self.periode = periode / self.conf['DT']
|
||||
self.u_max = u
|
||||
self.actif = True
|
||||
self.compteur = 0
|
||||
|
||||
def update(self):
|
||||
self.compteur += 1
|
||||
if self.actif:
|
||||
if self.compteur >= self.periode:
|
||||
self.compteur = 0
|
||||
self._u = 0.
|
||||
self.actif = False
|
||||
else:
|
||||
if self.compteur >= self.periode:
|
||||
self.compteur = 0
|
||||
self._u = self.u_max
|
||||
self.actif = True
|
||||
|
||||
|
||||
class Noeud(Element):
|
||||
"""
|
||||
Nœud du graphe
|
||||
|
||||
self._voisins: liste de (Graphe, polarité) avec polarité = +1 ou -1 pour les branches
|
||||
"""
|
||||
def __init__(self, conf, nom, voisins=None):
|
||||
super().__init__(conf, nom, self.P_NOEUD)
|
||||
self._u = None
|
||||
if voisins is None:
|
||||
voisins = []
|
||||
self._voisins = voisins
|
||||
|
||||
def add_voisins(self, voisins):
|
||||
self._voisins += voisins
|
||||
|
||||
def voisins(self):
|
||||
return self._voisins
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self._u = vect[index]
|
||||
|
||||
def u(self):
|
||||
return self._u
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.u()) >= self.conf['UMAX']:
|
||||
raise SurtensionException
|
||||
|
||||
def etat(self):
|
||||
return self.u() >= self.conf['USEUIL']
|
||||
|
||||
|
||||
class Branche(Element):
|
||||
"""
|
||||
Branche du graphe.
|
||||
La branche contient un certain nombre de composants en série, qui peuvent être des relais, tempos, résistances
|
||||
ou contacts (équation). N'est pas utilisable pour les condensateurs.
|
||||
"""
|
||||
def __init__(self, conf, nom, composants):
|
||||
super().__init__(conf, nom, self.P_DLT)
|
||||
self.composants = composants
|
||||
self.amont = None
|
||||
self.aval = None
|
||||
self._i = 0.0
|
||||
|
||||
def add_voisins(self, amont, aval):
|
||||
self.amont = amont
|
||||
self.aval = aval
|
||||
|
||||
def r(self):
|
||||
return sum([x.r for x in self.composants]) + self.conf['RMIN']
|
||||
|
||||
def init_cycle(self):
|
||||
super().init_cycle()
|
||||
[x.init_cycle() for x in self.composants]
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self._i = vect[index] # Important de mettre à jour i avant de mettre à jour les composants
|
||||
[x.passe_calcul() for x in self.composants]
|
||||
|
||||
def update(self):
|
||||
super().update()
|
||||
[x.update() for x in self.composants]
|
||||
|
||||
def i(self):
|
||||
return self._i
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.i()) >= self.conf['IMAX']:
|
||||
raise SurintensiteException(f"Dans la branche {self.nom}")
|
||||
|
||||
def etat(self):
|
||||
return self.i() >= self.conf['ISEUIL']
|
||||
|
||||
|
||||
class Condensateur(Element):
|
||||
"""
|
||||
Condensateur.
|
||||
|
||||
La seule truande est que la tension au borne est en réalité calculée avec la charge du cycle précédent.
|
||||
"""
|
||||
def __init__(self, conf, nom, capacite, coef_mul_tension):
|
||||
super().__init__(conf, nom, self.P_COND)
|
||||
self.capacite = capacite
|
||||
self.amont = None
|
||||
self.aval = None
|
||||
self._i = 0.0
|
||||
self.q = 0.0
|
||||
self.q_prec = 0.0
|
||||
self.coef_mul_tension = coef_mul_tension
|
||||
|
||||
def add_voisins(self, amont, aval):
|
||||
self.amont = amont
|
||||
self.aval = aval
|
||||
|
||||
def r(self):
|
||||
raise WrongElecPropertyException
|
||||
|
||||
def init_cycle(self):
|
||||
super().init_cycle()
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self._i = vect[index] # Important de mettre à jour i avant de mettre à jour les composants
|
||||
|
||||
def update(self):
|
||||
super().update()
|
||||
self.q_prec = self.q
|
||||
q = self.q + self.i() * self.conf['DT']
|
||||
self.q = q
|
||||
|
||||
def i(self):
|
||||
return self._i
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.i()) >= self.conf['IMAX']:
|
||||
raise SurintensiteException
|
||||
|
||||
def etat(self):
|
||||
return bool(self.i() >= self.conf['ISEUIL'])
|
||||
|
||||
|
||||
class ContactBasculeur(Noeud):
|
||||
"""
|
||||
Nœud du graphe
|
||||
|
||||
self._voisins: liste de (Graphe, polarité) avec polarité = +1 ou -1 pour les branches
|
||||
"""
|
||||
UMAX = 24.5
|
||||
|
||||
class PotentielLocal(Element):
|
||||
def __init__(self, conf, nom, voisins=None):
|
||||
self.lame = None
|
||||
super().__init__(conf, nom, self.P_NOEUD)
|
||||
self._u = None
|
||||
if voisins is None:
|
||||
voisins = []
|
||||
self._voisins = voisins
|
||||
self.etat = False
|
||||
|
||||
def set_lame(self, lame):
|
||||
self.lame = lame
|
||||
|
||||
def add_voisins(self, voisins):
|
||||
self._voisins += voisins
|
||||
|
||||
def set_etat(self, etat):
|
||||
self.etat = etat
|
||||
|
||||
def voisins(self):
|
||||
return self._voisins + ([(self.lame, +1, "foo")] if self.etat else [])
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self._u = vect[index]
|
||||
|
||||
def u(self):
|
||||
return self._u
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.u()) >= self.conf['UMAX']:
|
||||
raise SurtensionException
|
||||
|
||||
class Lame(Element):
|
||||
def __init__(self, conf, nom, contact, gauche, droite):
|
||||
self.amont = contact
|
||||
self.aval = None
|
||||
self.gauche = gauche
|
||||
self.droite = droite
|
||||
self.position = None
|
||||
super().__init__(conf, nom, self.P_DLT)
|
||||
self._i = None
|
||||
|
||||
def bascule(self, position):
|
||||
self.position = position
|
||||
if position == Dir.GAUCHE:
|
||||
self.aval = self.gauche
|
||||
else:
|
||||
self.aval = self.droite
|
||||
|
||||
def i(self):
|
||||
return self._i
|
||||
|
||||
def r(self):
|
||||
return self.conf['RMIN']
|
||||
|
||||
# Classe principale
|
||||
def __init__(self, conf, nom, graphe, voisins=None):
|
||||
self.graphe = graphe
|
||||
self.position = None
|
||||
self.potentiel_gauche = self.PotentielLocal(conf, nom + ".G")
|
||||
self.potentiel_droit = self.PotentielLocal(conf, nom + ".D")
|
||||
self.lame = self.Lame(conf, nom + ".L", self, self.potentiel_gauche, self.potentiel_droit)
|
||||
self.potentiel_gauche.set_lame(self.lame)
|
||||
self.potentiel_droit.set_lame(self.lame)
|
||||
self._voisins = [(self.lame, -1, "foo")] + voisins if voisins is not None else []
|
||||
super().__init__(conf, nom, self.P_NOEUD)
|
||||
self.bascule_gauche()
|
||||
|
||||
def eq_elts(self):
|
||||
return [self, self.potentiel_gauche, self.potentiel_droit, self.lame]
|
||||
|
||||
def add_voisins(self, voisins):
|
||||
for vois_tuple in voisins:
|
||||
_, _, connecteur = vois_tuple
|
||||
if connecteur == 'b':
|
||||
self._voisins = [vois_tuple]
|
||||
else:
|
||||
# Les autres connecteurs doivent être câblés vers les ConnecteursLocaux
|
||||
raise "Invalid connector for RelaisBasculeur"
|
||||
|
||||
def voisins(self):
|
||||
return self._voisins
|
||||
|
||||
def bascule_gauche(self):
|
||||
self.position = Dir.GAUCHE
|
||||
self.lame.bascule(self.position)
|
||||
self.potentiel_gauche.set_etat(True)
|
||||
self.potentiel_droit.set_etat(False)
|
||||
|
||||
def bascule_droite(self):
|
||||
self.position = Dir.DROITE
|
||||
self.lame.bascule(self.position)
|
||||
self.potentiel_gauche.set_etat(False)
|
||||
self.potentiel_droit.set_etat(True)
|
||||
|
||||
def get_potentiel(self, direction):
|
||||
"""
|
||||
Par défaut, un seul potentiel quel que soit la direction
|
||||
"""
|
||||
if direction == "b":
|
||||
return self
|
||||
elif direction == "g":
|
||||
return self.potentiel_gauche
|
||||
elif direction == "d":
|
||||
return self.potentiel_droit
|
||||
else:
|
||||
assert False
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self.potentiel_droit.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_droit))
|
||||
self.potentiel_gauche.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_gauche))
|
||||
self._u = vect[index]
|
||||
|
||||
def u(self):
|
||||
return self._u
|
||||
|
||||
def etat(self):
|
||||
return self.lame.position
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.u()) >= self.conf['UMAX']:
|
||||
raise SurtensionException
|
||||
self.potentiel_droit.coherence()
|
||||
self.potentiel_gauche.coherence()
|
||||
|
||||
|
||||
class ContactDouble(Noeud):
|
||||
"""
|
||||
Nœud du graphe
|
||||
|
||||
self._voisins: liste de (Graphe, polarité) avec polarité = +1 ou -1 pour les branches
|
||||
"""
|
||||
UMAX = 24.5
|
||||
|
||||
class PotentielLocal(Element):
|
||||
def __init__(self, conf, nom, voisins=None):
|
||||
self.lame = None
|
||||
super().__init__(conf, nom, self.P_NOEUD)
|
||||
self._u = None
|
||||
if voisins is None:
|
||||
voisins = []
|
||||
self._voisins = voisins
|
||||
self.etat = False
|
||||
|
||||
def set_lame(self, lame):
|
||||
self.lame = lame
|
||||
|
||||
def add_voisins(self, voisins):
|
||||
self._voisins += voisins
|
||||
|
||||
def set_etat(self, etat):
|
||||
self.etat = etat
|
||||
|
||||
def voisins(self):
|
||||
return self._voisins + ([(self.lame, +1, "foo")] if self.etat else [])
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self._u = vect[index]
|
||||
|
||||
def u(self):
|
||||
return self._u
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.u()) >= self.conf['UMAX']:
|
||||
raise SurtensionException
|
||||
|
||||
class Lame(Element):
|
||||
def __init__(self, conf, nom, contact, gauche, droite):
|
||||
self.amont = contact
|
||||
self.aval = None
|
||||
self.repos = gauche
|
||||
self.travail = droite
|
||||
self.position = False # Travail = True
|
||||
super().__init__(conf, nom, self.P_DLT)
|
||||
self._i = None
|
||||
|
||||
def set_position(self, position):
|
||||
self.position = position
|
||||
if position:
|
||||
self.aval = self.travail
|
||||
else:
|
||||
self.aval = self.repos
|
||||
|
||||
def i(self):
|
||||
return self._i
|
||||
|
||||
def r(self):
|
||||
return self.conf['RMIN']
|
||||
|
||||
# Classe principale
|
||||
def __init__(self, conf, nom, graphe, voisins=None, orientation=0):
|
||||
self.graphe = graphe
|
||||
self.orientation = orientation
|
||||
self.potentiel_repos = self.PotentielLocal(conf, nom + ".repos")
|
||||
self.potentiel_travail = self.PotentielLocal(conf, nom + ".travail")
|
||||
self.lame = self.Lame(conf, nom + ".L", self, self.potentiel_repos, self.potentiel_travail)
|
||||
self.potentiel_repos.set_lame(self.lame)
|
||||
self.potentiel_travail.set_lame(self.lame)
|
||||
self._voisins = [(self.lame, -1, "foo")] + voisins if voisins is not None else []
|
||||
super().__init__(conf, nom, self.P_NOEUD)
|
||||
self.lame.set_position(False)
|
||||
|
||||
def eq_elts(self):
|
||||
return [self, self.potentiel_repos, self.potentiel_travail, self.lame]
|
||||
|
||||
def add_voisins(self, voisins):
|
||||
for vois_tuple in voisins:
|
||||
_, _, connecteur = vois_tuple
|
||||
if (self.orientation == 0 and connecteur == 'd') \
|
||||
or (self.orientation == 180 and connecteur == 'g'):
|
||||
self._voisins = [vois_tuple]
|
||||
else:
|
||||
# Les autres connecteurs doivent être câblés vers les ConnecteursLocaux
|
||||
raise "Invalid connector for ContactDouble"
|
||||
|
||||
def voisins(self):
|
||||
return self._voisins
|
||||
|
||||
def get_potentiel(self, direction):
|
||||
"""
|
||||
Par défaut, un seul potentiel quel que soit la direction
|
||||
"""
|
||||
if self.orientation == 0:
|
||||
if direction == "d":
|
||||
return self
|
||||
elif direction == "bg":
|
||||
return self.potentiel_repos
|
||||
elif direction == "hg":
|
||||
return self.potentiel_travail
|
||||
else:
|
||||
assert False
|
||||
elif self.orientation == 180:
|
||||
if direction == "g":
|
||||
return self
|
||||
elif direction == "bd":
|
||||
return self.potentiel_repos
|
||||
elif direction == "hd":
|
||||
return self.potentiel_travail
|
||||
else:
|
||||
assert False
|
||||
else:
|
||||
assert False
|
||||
|
||||
def passe_calcul(self, vect, index):
|
||||
super().passe_calcul(vect, index)
|
||||
self.potentiel_travail.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_travail))
|
||||
self.potentiel_repos.passe_calcul(vect, self.graphe.vecteur.index(self.potentiel_repos))
|
||||
self._u = vect[index]
|
||||
|
||||
def u(self):
|
||||
return self._u
|
||||
|
||||
def etat(self):
|
||||
return self.lame.position
|
||||
|
||||
def coherence(self):
|
||||
if abs(self.u()) >= self.conf['UMAX']:
|
||||
raise SurtensionException
|
||||
self.potentiel_travail.coherence()
|
||||
self.potentiel_repos.coherence()
|
||||
|
||||
def active(self):
|
||||
self.lame.set_position(True)
|
||||
self.potentiel_travail.set_etat(True)
|
||||
self.potentiel_repos.set_etat(False)
|
||||
|
||||
def desactive(self):
|
||||
self.lame.set_position(False)
|
||||
self.potentiel_travail.set_etat(False)
|
||||
self.potentiel_repos.set_etat(True)
|
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
|
171
modele/graphe.py
Normal file
@ -0,0 +1,171 @@
|
||||
import modele.composants as mc
|
||||
import modele.elements as me
|
||||
from modele.exceptions import Dir
|
||||
from modele.donnees import GraphStructException
|
||||
|
||||
|
||||
class Vecteur(object):
|
||||
"""
|
||||
Associe les éléments du graphe à leur rang dans le vecteur correspondant aux rangs dans la matrice.
|
||||
"""
|
||||
def __init__(self, elements):
|
||||
self._liste = [eq_elt for element in elements.values() for eq_elt in element.eq_elts()]
|
||||
|
||||
self._index = {} # Associe à un élément son index dans la matrice
|
||||
for index, element in enumerate(self._liste):
|
||||
self._index[element] = index
|
||||
|
||||
def __len__(self):
|
||||
return len(self._liste)
|
||||
|
||||
def index(self, element):
|
||||
return self._index[element]
|
||||
|
||||
def __iter__(self):
|
||||
return self._liste.__iter__()
|
||||
|
||||
|
||||
class Graphe(object):
|
||||
ID_BR = -1
|
||||
|
||||
@classmethod
|
||||
def branch_id(cls):
|
||||
cls.ID_BR += 1
|
||||
return f"b{cls.ID_BR}"
|
||||
|
||||
def __init__(self, conf):
|
||||
self.conf = conf
|
||||
self.elements = None
|
||||
self.composants = None
|
||||
self.vecteur = None
|
||||
|
||||
def load_data_from_schema_reader(self, reader):
|
||||
self.elements = {}
|
||||
self.composants = {}
|
||||
|
||||
# Construction des éléments et composants
|
||||
for nom, valeur in reader.composants.items():
|
||||
if valeur.type == 'Bouton' or valeur.type == 'ContactTravail' or valeur.type == 'ContactRepos' \
|
||||
or valeur.type == 'Levier':
|
||||
self.composants[nom] = mc.Contact(self.conf, nom, valeur.type)
|
||||
elif valeur.type == 'Relais':
|
||||
if valeur.donnees.get('basculeur') == 'gauche':
|
||||
self.composants[nom] = mc.DemiRelaisBasculeur(self.conf, nom, self, Dir.GAUCHE)
|
||||
elif valeur.donnees.get('basculeur') == 'droite':
|
||||
self.composants[nom] = mc.DemiRelaisBasculeur(self.conf, nom, self, Dir.DROITE)
|
||||
else:
|
||||
self.composants[nom] = mc.Relais(self.conf, nom, self)
|
||||
elif valeur.type == 'Tempo':
|
||||
self.composants[nom] = mc.Tempo(self.conf, nom, valeur.donnees['tempo_blocage'],
|
||||
valeur.donnees['tempo_liberation'])
|
||||
elif valeur.type == 'Resistance':
|
||||
if 'valeur' not in valeur.donnees:
|
||||
v = None
|
||||
else:
|
||||
v = valeur.donnees['valeur']
|
||||
self.composants[nom] = mc.Resistance(self.conf, nom, v)
|
||||
del v
|
||||
elif valeur.type == 'Lampe':
|
||||
self.composants[nom] = mc.Lampe(self.conf, nom)
|
||||
elif valeur.type == 'Diode':
|
||||
d = mc.Diode(self.conf, nom)
|
||||
self.composants[nom] = d
|
||||
self.composants["!" + nom] = d
|
||||
del d
|
||||
|
||||
for nom, valeur in reader.noeuds.items():
|
||||
if valeur.type == "Noeud":
|
||||
self.elements[nom] = me.Noeud(self.conf, nom)
|
||||
elif valeur.type == "P24":
|
||||
self.elements[nom] = me.Potentiel(self.conf, nom, 24.)
|
||||
elif valeur.type == "P0":
|
||||
self.elements[nom] = me.Potentiel(self.conf, nom, 0.)
|
||||
elif valeur.type == "Pulse":
|
||||
if "periode" not in valeur.donnees:
|
||||
p = None
|
||||
else:
|
||||
p = valeur.donnees["periode"]
|
||||
self.elements[nom] = me.PotPulse(self.conf, nom, 24., p)
|
||||
elif valeur.type == "ContactBasculeur":
|
||||
self.elements[nom] = me.ContactBasculeur(self.conf, nom, self)
|
||||
elif valeur.type == "ContactDouble":
|
||||
self.elements[nom] = me.ContactDouble(self.conf, nom, self, orientation=valeur.donnees['orientation'])
|
||||
|
||||
for nom, valeur in reader.condensateurs.items():
|
||||
cnd = me.Condensateur(self.conf, nom, valeur.donnees['capacite'], valeur.donnees['coef_mul_tension'])
|
||||
|
||||
v_amont_schm, v_amont_dir = valeur.get_amont()
|
||||
v_aval_schm, v_aval_dir = valeur.get_aval()
|
||||
|
||||
v_amont = self.elements[v_amont_schm.nom]
|
||||
v_aval = self.elements[v_aval_schm.nom]
|
||||
|
||||
cnd.add_voisins(v_amont, v_aval)
|
||||
v_amont.add_voisins([(cnd, -1, v_amont_dir)])
|
||||
v_aval.add_voisins([(cnd, +1, v_aval_dir)])
|
||||
self.elements[nom] = cnd
|
||||
del cnd
|
||||
|
||||
# Ajout des liens entre relais et contacts
|
||||
try:
|
||||
for nom, valeur in reader.composants.items():
|
||||
if valeur.type == "ContactTravail":
|
||||
self.composants[valeur.donnees["relais"]].add_travail(nom)
|
||||
elif valeur.type == "ContactRepos":
|
||||
self.composants[valeur.donnees["relais"]].add_repos(nom)
|
||||
|
||||
for nom, valeur in reader.noeuds.items():
|
||||
if valeur.type == "ContactBasculeur":
|
||||
self.composants[valeur.donnees["relais"] + ".gauche"].add_contact(nom)
|
||||
self.composants[valeur.donnees["relais"] + ".droite"].add_contact(nom)
|
||||
elif valeur.type == "ContactDouble":
|
||||
self.composants[valeur.donnees["relais"]].add_double(nom)
|
||||
except KeyError:
|
||||
raise GraphStructException("Mauvais identificateur de relais dans un contact")
|
||||
|
||||
# Construction des branches
|
||||
for branche in reader.branches:
|
||||
nom = self.branch_id()
|
||||
br = me.Branche(self.conf, nom, [self.composants[x.nom] for x in branche.composants])
|
||||
[self.composants[x.nom].reverse() for x in branche.composants if x.nom[0] == '!'] # Diode
|
||||
for c in br.composants:
|
||||
c.branche = br
|
||||
|
||||
v_amont_schm, v_amont_dir = branche.get_amont()
|
||||
v_aval_schm, v_aval_dir = branche.get_aval()
|
||||
|
||||
v_amont = self.elements[v_amont_schm.nom].get_potentiel(v_amont_dir)
|
||||
v_aval = self.elements[v_aval_schm.nom].get_potentiel(v_aval_dir)
|
||||
|
||||
br.add_voisins(v_amont, v_aval)
|
||||
v_amont.add_voisins([(br, -1, v_amont_dir)])
|
||||
v_aval.add_voisins([(br, +1, v_aval_dir)])
|
||||
self.elements[nom] = br
|
||||
del br
|
||||
|
||||
self.vecteur = Vecteur(self.elements)
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""
|
||||
Retourne un composant
|
||||
"""
|
||||
if item in self.composants:
|
||||
res = self.composants[item]
|
||||
else:
|
||||
res = self.elements[item]
|
||||
return res
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.composants or item in self.elements
|
||||
|
||||
def init_cycle(self):
|
||||
[elt.init_cycle() for elt in self.elements.values()]
|
||||
|
||||
def passe_calcul(self, solutions):
|
||||
[elt.passe_calcul(solutions, self.vecteur.index(elt)) for elt in self.elements.values()]
|
||||
|
||||
def update(self):
|
||||
[elt.update() for elt in self.elements.values()]
|
||||
|
||||
def coherence(self):
|
||||
[x.coherence() for x in self.elements.values()]
|
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)
|
@ -0,0 +1,3 @@
|
||||
numpy>=1.24.3
|
||||
flask>=2.3.2
|
||||
Flask-Cors>=4.0.0
|
6
run.py
@ -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"]
|
||||
]
|
||||
}
|