diff --git a/.gitignore b/.gitignore
index bb2256e64c7ca2269012d3ff1472466354f34b87..3e4c418522a91e7029d9a6cd11ec81fd85fc178a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ db.sqlite3
 uploads/tmp/*
 uploads/media/*
 uploads/current_experiment/*
+dump.rdb
diff --git a/iotamak_ihm/settings.py b/iotamak_ihm/settings.py
index e16d92c172cf5b31792755c6991f6367c4e56f36..c80c96a35a2ff12b951ee991782aae0f37432592 100644
--- a/iotamak_ihm/settings.py
+++ b/iotamak_ihm/settings.py
@@ -87,8 +87,12 @@ CHANNEL_LAYERS = {
 
 DATABASES = {
     'default': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': BASE_DIR / 'db.sqlite3',
+        'ENGINE': 'django.db.backends.postgresql_psycopg2',
+        'NAME': 'iotamak',
+        'USER': 'raspberry',
+        'PASSWORD': 'raspberry',
+        'HOST': "localhost",
+        'PORT': '5432'
     }
 }
 
diff --git a/ping/admin.py b/ping/admin.py
index 4cadb755cdf11d8b98d1f1efa56f043e7f3fb45d..e43d25f202f05c77baf33d788c47ade50750775b 100644
--- a/ping/admin.py
+++ b/ping/admin.py
@@ -6,4 +6,5 @@ admin.site.register(Client)
 admin.site.register(Agent)
 admin.site.register(Experiment)
 admin.site.register(Metrics)
-admin.site.register(CurrentExperiment)
\ No newline at end of file
+admin.site.register(CurrentExperiment)
+admin.site.register(Network)
\ No newline at end of file
diff --git a/ping/models.py b/ping/models.py
index 7731b893404518c72be9642b47fe585292ffddea..58bc5f985890c04f22c16cb45ee8755c145d33f6 100644
--- a/ping/models.py
+++ b/ping/models.py
@@ -22,6 +22,7 @@ class Agent(models.Model):
     def __str__(self):
         return self.command
 
+
 class Experiment(models.Model):
     name = models.CharField(max_length=60)
     status = models.CharField(max_length=60, default="Not checked")
@@ -34,6 +35,7 @@ class ExperimentForm(ModelForm):
         model = Experiment
         fields = ["name", "description", "media"]
 
+
 class Metrics(models.Model):
     cycle = models.PositiveIntegerField()
     _metrics = models.BinaryField()
@@ -48,11 +50,23 @@ class Metrics(models.Model):
 
 
 class CurrentExperiment(models.Model):
-
     name = models.CharField(max_length=60)
     cycle = models.PositiveIntegerField(default=0)
     nbr_agent = models.PositiveIntegerField(default=0)
 
     amas_pid = models.PositiveIntegerField(default=0)
     scheduler_pid = models.PositiveIntegerField(default=0)
-    env_pid = models.PositiveIntegerField(default=0)
\ No newline at end of file
+    env_pid = models.PositiveIntegerField(default=0)
+
+    seed = models.CharField(default="0", max_length=64)
+    scheduling = models.CharField(default="sync", max_length=10)
+
+
+class Network(models.Model):
+    broker_ip = models.CharField(max_length=60)
+    broker_username = models.CharField(max_length=60)
+    broker_password = models.CharField(max_length=60)
+
+    iotamak_core_version = models.CharField(max_length=60)
+
+    path_to_iotamak = models.CharField(max_length=60)
diff --git a/ping/templates/ping/play.html b/ping/templates/ping/play.html
index 058ca30906118a256d5aed5617519c160ed3b049..48d9d4b708c1f726d176d0f0d6d3916b5c09af93 100644
--- a/ping/templates/ping/play.html
+++ b/ping/templates/ping/play.html
@@ -105,21 +105,25 @@
   {% endif %}
 
 
-<canvas id="myChart" width="500" height="500" style="border:1px solid #000000;"></canvas>
+<canvas id="line-chart" width="800" height="450"></canvas>
 <script>
 
-var chart_data = {
-    labels: ["0", "1", "2", "3"],
-    type: 'line',
-    data: {
-        datasets: [{
-            data: [0,0,0,0]
-        }]
-    }
-};
+chart_data = {
+    labels: ["t-9","t-8","t-7","t-6","t-5","t-4","t-3","t-2","t-1","t"],
+    datasets: [{
+        data: [0,0,0,0,0,0,0,0,0,0],
+        label: "Colored agents",
+        borderColor: "#3e95cd",
+        fill: false
+      }
+    ]
+  };
 
-const ctx = document.getElementById('myChart').getContext('2d');
-const myChart = new Chart(ctx, chart_data);
+const myChart = new Chart(document.getElementById("line-chart"), {
+  type: 'line',
+  data: chart_data,
+  options: {}
+});
 
 
     const graphSocket = new WebSocket(
@@ -130,14 +134,11 @@ const myChart = new Chart(ctx, chart_data);
 
     graphSocket.onmessage = function (e) {
       const metrics = JSON.parse(e.data).message;
-      console.log(metrics);
-      new_graph_data = chart_data.data.datasets[0].data;
+      new_graph_data = chart_data.datasets[0].data;
       new_graph_data.shift();
       new_graph_data.push(metrics[0]);
-      console.log(new_graph_data);
 
-      chart_data.data.datasets[0].data = new_graph_data;
-      console.log(new_graph_data);
+      chart_data.datasets[0].data = new_graph_data;
 
       myChart.update();
 
diff --git a/ping/views/experiment.py b/ping/views/experiment.py
index 4ac42b75e09582bf5e0f27b75892b617eb2dff53..593169acb21a8dc67058ebd2a603a6a2e8b60365 100644
--- a/ping/views/experiment.py
+++ b/ping/views/experiment.py
@@ -1,5 +1,4 @@
 import os
-import zipfile
 
 from django.conf import settings
 
@@ -7,6 +6,7 @@ from django.http import HttpResponse, HttpResponseRedirect
 from django.template import loader
 from django.urls import reverse
 
+from .experiment_checker import unzip, contains_basic_files, check_config
 from .tool import delete_folder
 from ..models import Experiment, ExperimentForm
 
@@ -27,33 +27,20 @@ def entry(request):
 
 
 def check(request, experiment_id):
-    # get the path
     exp = Experiment.objects.get(pk=experiment_id)
-    # check if it's a zip -> wrong format : not zip
 
-    if not zipfile.is_zipfile(str(settings.MEDIA_ROOT) + str(exp.media)):
-        exp.status = "Wrong format : zip file expected"
-        exp.save()
+    if not unzip(str(settings.MEDIA_ROOT) + str(exp.media), str(settings.MEDIA_ROOT) + "/tmp", exp):
         return HttpResponseRedirect(reverse('ping:experiment'))
 
-    with zipfile.ZipFile(str(settings.MEDIA_ROOT) + str(exp.media), 'r') as zip_ref:
-        zip_ref.extractall(str(settings.MEDIA_ROOT) + "/tmp")
-
     folder_path = str(settings.MEDIA_ROOT) + "/tmp/" + exp.name
 
-    if not os.path.isdir(folder_path):
-        exp.status = "Wrong format : zip should contain a folder"
-        exp.save()
+    if not contains_basic_files(folder_path, exp):
         delete_folder(str(settings.MEDIA_ROOT) + "/tmp")
         return HttpResponseRedirect(reverse('ping:experiment'))
 
-    required_files = ["amas.py", "agent.py", "env.py", "scheduler.py", "config.json"]
-    for required_file in required_files:
-        if not os.path.exists(folder_path + "/" + required_file):
-            exp.status = "Wrong format : " + required_file + " file is expected"
-            exp.save()
-            delete_folder(str(settings.MEDIA_ROOT) + "/tmp")
-            return HttpResponseRedirect(reverse('ping:experiment'))
+    if not check_config(folder_path, exp):
+        delete_folder(str(settings.MEDIA_ROOT) + "/tmp")
+        return HttpResponseRedirect(reverse('ping:experiment'))
 
     exp.status = "Checked"
     exp.save()
diff --git a/ping/views/experiment_checker.py b/ping/views/experiment_checker.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c331ddbd5fa84d634739d0bf7bbf794d73d151c
--- /dev/null
+++ b/ping/views/experiment_checker.py
@@ -0,0 +1,71 @@
+import json
+import os
+import zipfile
+
+from ..models import Network
+
+
+def unzip(src_path: str, dest_path: str, exp) -> bool:
+    if not zipfile.is_zipfile(src_path):
+        exp.status = "Wrong format : zip file expected"
+        exp.save()
+        return False
+
+    with zipfile.ZipFile(src_path, 'r') as zip_ref:
+        zip_ref.extractall(dest_path)
+
+    return True
+
+
+def contains_basic_files(path: str, exp) -> bool:
+    if not os.path.isdir(path):
+        exp.status = "Wrong format : zip should contain a folder"
+        exp.save()
+        return False
+
+    required_files = ["amas.py", "env.py", "config.json"]
+    for required_file in required_files:
+        if not os.path.exists(path + "/" + required_file):
+            exp.status = "Wrong format : " + required_file + " file is expected"
+            exp.save()
+            return False
+    return True
+
+
+def check_config(path: str, exp) -> bool:
+    with open(path + "/config.json") as json_file:
+        config = json.load(json_file)
+
+    required_keys = ["iotamak_version", "scheduling_type"]
+    for key in required_keys:
+        if key not in config:
+            exp.status = "Wrong config : " + key + " is expected in config.json"
+            exp.save()
+            return False
+
+    if config.get("scheduling_type") not in ["sync", "async"]:
+        exp.status = "Wrong config : scheduling_type is either sync or async"
+        exp.save()
+        return False
+
+    n = Network.objects.all()[0]
+    version = n.iotamak_core_version
+
+    if int(config.get("iotamak_version").replace(".", "00")) < int(version.replace(".", "00")):
+        exp.status = "Wrong version : experiment version is outdated"
+        exp.save()
+        return False
+    elif int(config.get("iotamak_version").replace(".", "00")) > int(version.replace(".", "00")):
+        exp.status = "Wrong version : experiment version is ahead of the server version"
+        exp.save()
+        return False
+
+    if config.get("scheduling_type") == "sync":
+        if not os.path.exists(path + "/scheduler.py"):
+            exp.status = "Wrong format : scheduler.py file is expected"
+            exp.save()
+            return False
+    else:
+        pass
+
+    return True
diff --git a/ping/views/network.py b/ping/views/network.py
index 7c669d5ab0532fd05b1f22ad0c8e3ed1c74d712d..e5e4997cc763efc5c8bc08d398e4544563d50f1c 100644
--- a/ping/views/network.py
+++ b/ping/views/network.py
@@ -8,25 +8,32 @@ from django.urls import reverse
 from iotAmak.tool.ssh_client import Cmd
 
 from .tool import get_ssh_client
-from ..models import Client, Agent
+from ..models import Client, Agent, Network
 
 
 def update(request):
     ssh = get_ssh_client()
-    version = "0.0.3"
+    n = Network.objects.all()[0]
+    version = n.iotamak_core_version
     commands = [
         Cmd(
-            cmd="cd Desktop/mqtt_goyon/iotamak-core"
+            cmd="cd "+n.path_to_iotamak+"iotamak-core"
         ),
         Cmd(
             cmd="git pull"
         ),
         Cmd(
-            cmd="git checkout main"
+            cmd="git reset --hard origin/main"
+        ),
+        Cmd(
+            cmd="git clean -f -d"
         ),
         Cmd(
             cmd="git pull"
         ),
+        Cmd(
+            cmd="git checkout main"
+        ),
         Cmd(
             cmd="python3 -m pip install --force-reinstall dist/iotAmak-" + version + "-py3-none-any.whl"
         )
diff --git a/ping/views/play.py b/ping/views/play.py
index f987cbcc5f99ed1cbabf8b5313e6e6422044c270..046b2aa38bcc763b3f07f26e74f02f3a2bee9aa9 100644
--- a/ping/views/play.py
+++ b/ping/views/play.py
@@ -1,5 +1,6 @@
 import csv
 import os
+import random
 import sys
 import zipfile
 import json
@@ -16,7 +17,7 @@ from iotAmak.tool.ssh_client import Cmd
 from paho.mqtt.client import Client as MQTTClient
 
 from .tool import delete_folder, get_ssh_client, canvas_event_triger, graph_event_triger
-from ..models import Experiment, CurrentExperiment, Metrics
+from ..models import Experiment, CurrentExperiment, Metrics, Network
 
 client = MQTTClient(client_id="django-ihm")
 
@@ -63,6 +64,7 @@ def cycle_done(client, userdata, message) -> None:
 
 def update_nbr_agent(client, userdata, message) -> None:
     exp = CurrentExperiment.objects.all()[0]
+    subscribe(client, "agent/"+str(exp.nbr_agent)+"/log", agent_log)
     exp.nbr_agent += 1
     exp.save()
 
@@ -81,13 +83,50 @@ def experiment_load(request):
     # drop current experiment table and create new instance
     CurrentExperiment.objects.all().delete()
     cur_exp = CurrentExperiment(name=Experiment.objects.get(status="Selected").name)
+
+    with open(str(settings.MEDIA_ROOT) + "current_experiment/"+str(exp.name)+"/config.json") as json_file:
+        config = json.load(json_file)
+
+    if "seed" in config:
+        cur_exp.seed = str(config.get("seed"))
+    else:
+        random.seed()
+        cur_exp.seed = str(random.randint(0,9999999))
+
+    cur_exp.scheduling = config.get("scheduling_type")
+
     cur_exp.save()
 
     return HttpResponseRedirect(reverse('ping:play'))
 
+def delete_nohup():
+    ssh = get_ssh_client()
+
+    commands = [
+        Cmd(
+            cmd="rm nohup.out"
+        )
+
+    ]
+    for i_client in range(len(ssh.clients)):
+        print(" Ip : ", ssh.clients[i_client].hostname)
+        ssh.run_cmd(i_client, commands)
+
+def get_nohup():
+    ssh = get_ssh_client()
+
+    commands = [
+        Cmd(
+            cmd="cat nohup.out"
+        )
+
+    ]
+    for i_client in range(len(ssh.clients)):
+        print(" Ip : ", ssh.clients[i_client].hostname)
+        ssh.run_cmd(i_client, commands)
 
 def experiment_start(request):
-    broker_ip = "192.168.193.209"
+    n = Network.objects.all()[0]
     ssh = get_ssh_client()
 
     experiment_path = str(settings.MEDIA_ROOT) + "current_experiment/" + Experiment.objects.get(status="Selected").name
@@ -96,25 +135,47 @@ def experiment_start(request):
     global client
     client.disconnect()
     client = MQTTClient(client_id="django-ihm")
-    client.username_pw_set(username="goyon", password="mosquitto")
-    client.connect(host=broker_ip)
+    client.username_pw_set(username=n.broker_username, password=n.broker_password)
+    client.connect(host=n.broker_ip)
     client.loop_start()
     subscribe(client, "amas/agent/new", update_nbr_agent)
     subscribe(client, "scheduler/cycledone", cycle_done)
     subscribe(client, "amas/all_metric", agent_metric)
 
-    # start subprocess scheduler
-    p1 = Popen([sys.executable, experiment_path + '/scheduler.py', broker_ip])
-    sleep(1)
+    delete_nohup()
+
+    exp = CurrentExperiment.objects.all()[0]
+
+    if exp.scheduling == "sync":
+        p1 = Popen(
+            [sys.executable, experiment_path + '/scheduler.py', n.broker_ip, n.broker_username, n.broker_password]
+        )
+        exp.scheduler_pid = p1.pid
+        sleep(1)
     # start subprocess amas
-    send_client = [c.to_send() for c in ssh.clients]
-    p2 = Popen([sys.executable, experiment_path + '/amas.py', broker_ip, str(send_client)])
+    amas_dict = {
+        "broker_ip": n.broker_ip,
+        "clients": str([c.to_send() for c in ssh.clients]),
+        "seed": exp.seed,
+        "iot_path": n.path_to_iotamak+"example/",
+        "broker_username": n.broker_username,
+        "broker_password":  n.broker_password
+    }
+    if not exp.scheduling == "sync":
+        amas_dict["wait_delay"] = str(5)
+    p2 = Popen([sys.executable, experiment_path + '/amas.py', json.dumps(amas_dict)])
     # start subprocess env
-    p3 = Popen([sys.executable, experiment_path + '/env.py', broker_ip])
+    env_dict = {
+        "broker_ip": n.broker_ip,
+        "seed": exp.seed,
+        "broker_username": n.broker_username,
+        "broker_password":  n.broker_password
+    }
+    if not exp.scheduling == "sync":
+        env_dict["wait_delay"] = str(5)
+    p3 = Popen([sys.executable, experiment_path + '/env.py', json.dumps(env_dict)])
 
-    exp = CurrentExperiment.objects.all()[0]
     exp.amas_pid = p2.pid
-    exp.scheduler_pid = p1.pid
     exp.env_pid = p3.pid
     exp.save()
 
@@ -174,6 +235,7 @@ def scheduler_start(request):
 def experiment_share(request):
     # get selected experiment
     exp = Experiment.objects.get(status="Selected")
+    n = Network.objects.all()[0]
 
     # open ssh connection
     ssh = get_ssh_client()
@@ -181,19 +243,21 @@ def experiment_share(request):
     # file transfer
     commands = [
         Cmd(
-            cmd="rm -r Desktop/mqtt_goyon/example/" + exp.name
+            cmd="rm -r " + n.path_to_iotamak + "example/" + exp.name
         )
 
     ]
     for i_client in range(len(ssh.clients)):
+        print(" Ip : ", ssh.clients[i_client].hostname)
         ssh.run_cmd(i_client, commands)
 
-    ssh.update(exp.name, str(settings.MEDIA_ROOT) + "current_experiment/" + exp.name)
+    ssh.update("example/" + exp.name, str(settings.MEDIA_ROOT) + "current_experiment/" + exp.name)
 
     return HttpResponseRedirect(reverse('ping:play'))
 
 
 def experiment_stop(request):
+    get_nohup()
     client.publish("ihm/exit")
     client.publish("ihm/step")
     return HttpResponseRedirect(reverse('ping:play'))
diff --git a/ping/views/tool.py b/ping/views/tool.py
index fa938597057ba9fe708cd2c20b6a25417fccac87..5eb763ee76780a098187122a3199e1a88f698685 100644
--- a/ping/views/tool.py
+++ b/ping/views/tool.py
@@ -6,7 +6,7 @@ from channels.layers import get_channel_layer
 from iotAmak.tool.remote_client import RemoteClient
 from iotAmak.tool.ssh_client import SSHClient
 
-from ping.models import Client
+from ping.models import Client, Network
 
 
 def delete_folder(folder_name):
@@ -20,6 +20,7 @@ def delete_folder(folder_name):
         except Exception as e:
             print('Failed to delete %s. Reason: %s' % (file_path, e))
 
+
 def get_remote_client():
     res = []
     for client in Client.objects.all():
@@ -28,8 +29,10 @@ def get_remote_client():
 
     return res
 
+
 def get_ssh_client():
-    return SSHClient(get_remote_client())
+    n = Network.objects.all()[0]
+    return SSHClient(get_remote_client(), n.path_to_iotamak)
 
 
 def canvas_event_triger(metrics):
@@ -42,6 +45,7 @@ def canvas_event_triger(metrics):
         }
     )
 
+
 def graph_event_triger(metrics):
     channel_layer = get_channel_layer()
     async_to_sync(channel_layer.group_send)(
diff --git a/requirements.txt b/requirements.txt
index 290785cc1291fbc4564ea13de31fdfe29ebda52e..7ef1ac3858f40212c364c7442c2bd74591bd9fdb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
 Django >= 4.0.4
 channels >= 3.0.4
 channels-redis >= 3.4.0
+psycopg2 >= 2.9.3
\ No newline at end of file