diff --git a/db.sqlite3 b/db.sqlite3
index e33654f60a42bd1bdaf59e30dc8587fc89bd53be..8db1a619382a48f53c27a90a51d809a2091ac1f2 100644
Binary files a/db.sqlite3 and b/db.sqlite3 differ
diff --git a/ping/admin.py b/ping/admin.py
index f8dd658921a7e457d2651b11af8b8e020a498a0b..4cadb755cdf11d8b98d1f1efa56f043e7f3fb45d 100644
--- a/ping/admin.py
+++ b/ping/admin.py
@@ -1,7 +1,9 @@
 from django.contrib import admin
 
-from .models import Client, Agent, Experiment
+from .models import *
 
 admin.site.register(Client)
 admin.site.register(Agent)
-admin.site.register(Experiment)
\ No newline at end of file
+admin.site.register(Experiment)
+admin.site.register(Metrics)
+admin.site.register(CurrentExperiment)
\ No newline at end of file
diff --git a/ping/migrations/0003_currentexperiment_metrics_alter_experiment_media.py b/ping/migrations/0003_currentexperiment_metrics_alter_experiment_media.py
new file mode 100644
index 0000000000000000000000000000000000000000..d014e25f9508d4c05a52c3c3bb4038f585fa4c7a
--- /dev/null
+++ b/ping/migrations/0003_currentexperiment_metrics_alter_experiment_media.py
@@ -0,0 +1,37 @@
+# Generated by Django 4.0.4 on 2022-05-13 12:19
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ping', '0002_experiment'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='CurrentExperiment',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=60)),
+                ('cycle', models.PositiveIntegerField(default=0)),
+                ('nbr_agent', models.PositiveIntegerField(default=0)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Metrics',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('experiment_name', models.CharField(max_length=60)),
+                ('cycle', models.PositiveIntegerField()),
+                ('agent_id', models.PositiveIntegerField()),
+                ('_metrics', models.BinaryField()),
+            ],
+        ),
+        migrations.AlterField(
+            model_name='experiment',
+            name='media',
+            field=models.FileField(blank=True, null=True, upload_to='media'),
+        ),
+    ]
diff --git a/ping/models.py b/ping/models.py
index c6a47a184abdd614fc87b20e17fb3f7a3a709b3a..ecc17795aad954629623f58144890dc7fdfbd6b5 100644
--- a/ping/models.py
+++ b/ping/models.py
@@ -1,3 +1,5 @@
+import pickle
+
 from django.db import models
 from django.forms import ModelForm
 
@@ -30,3 +32,24 @@ class ExperimentForm(ModelForm):
     class Meta:
         model = Experiment
         fields = ["name", "description", "media"]
+
+class Metrics(models.Model):
+    experiment_name = models.CharField(max_length=60)
+    cycle = models.PositiveIntegerField()
+    agent_id = models.PositiveIntegerField()
+    _metrics = models.BinaryField()
+
+    def set_data(self, data):
+        self._metrics = pickle.dumps(data)
+
+    def get_data(self):
+        return pickle.loads(self._metrics)
+
+    metrics = property(get_data, set_data)
+
+
+class CurrentExperiment(models.Model):
+
+    name = models.CharField(max_length=60)
+    cycle = models.PositiveIntegerField(default=0)
+    nbr_agent = models.PositiveIntegerField(default=0)
\ No newline at end of file
diff --git a/ping/templates/ping/entry.html b/ping/templates/ping/entry.html
index b718dd690422ca999abb822edda5e42a6a8dd29b..a46a985dac76700a26dcc23084cd7ac1c21b24f9 100644
--- a/ping/templates/ping/entry.html
+++ b/ping/templates/ping/entry.html
@@ -16,6 +16,7 @@
   <div class="topnav">
     <a href="/network">Network</a>
     <a class="active" href="/experiment">Experiment</a>
+    <a href="/play">Play</a>
   </div>
     <form action="/experiment/new/" method="POST" enctype="multipart/form-data">
         {% csrf_token %}
diff --git a/ping/templates/ping/experiment.html b/ping/templates/ping/experiment.html
index 86454db688d053b9a18b89d3b7fb044bf907711c..e725a128fed66979a861d03286772ffa7fa3cf80 100644
--- a/ping/templates/ping/experiment.html
+++ b/ping/templates/ping/experiment.html
@@ -16,6 +16,7 @@
   <div class="topnav">
     <a href="/network">Network</a>
     <a class="active" href="/experiment">Experiment</a>
+    <a href="/play">Play</a>
   </div>
 
   <form action='new' method='GET'>
diff --git a/ping/templates/ping/index.html b/ping/templates/ping/index.html
index e39a748b2828a0220baaa7799f4de10fdaef5575..4e63881224eaf9e740978e16f18b2350aef391ab 100644
--- a/ping/templates/ping/index.html
+++ b/ping/templates/ping/index.html
@@ -15,6 +15,7 @@
   <div class="topnav">
     <a class="active" href="/network">Network</a>
     <a href="/experiment">Experiment</a>
+    <a href="/play">Play</a>
   </div>
 
 
@@ -46,6 +47,10 @@
     {% endfor %}
   </table>
 
+  <form action='./agent/kill' method='GET'>
+    <button type='submit'> Kill agents</button>
+  </form>
+
   {% if agents %}
   <table>
     <tr>
diff --git a/ping/templates/ping/play.html b/ping/templates/ping/play.html
new file mode 100644
index 0000000000000000000000000000000000000000..2b9de00b064390b137da66fe1291e9c902256fd3
--- /dev/null
+++ b/ping/templates/ping/play.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8">
+  {% load static %}
+  <link rel="stylesheet" type="text/css" href="{% static 'ping/index.css' %}">
+
+  <title>Play - IOTAMAK</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+
+</head>
+
+<body>
+
+  <div class="topnav">
+    <a href="/network">Network</a>
+    <a href="/experiment">Experiment</a>
+    <a class="active" href="/play">Play</a>
+  </div>
+
+  <p>Scheduler :</p>
+
+  <form action='./scheduler/step' method='GET'>
+    <button type='submit'> Step</button>
+  </form>
+
+  <form action='./scheduler/stop' method='GET'>
+    <button type='submit'> Stop</button>
+  </form>
+
+  <form action='./scheduler/start' method='GET'>
+    <button type='submit'> Start</button>
+  </form>
+
+  <p>Experiment :</p>
+
+  <form action='./global/exit' method='GET'>
+    <button type='submit'> Exit</button>
+  </form>
+
+  <form action='./global/share' method='GET'>
+    <button type='submit'> Share</button>
+  </form>
+
+  <form action='./global/start' method='GET'>
+    <button type='submit'> Start</button>
+  </form>
+
+  <form action='./global/load' method='GET'>
+    <button type='submit'> Load</button>
+  </form>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/ping/urls.py b/ping/urls.py
index f7f30028c5c1823c88de037886b4b053f0628569..133b8fbff2a66971b9292a6bb3193c535437f0bf 100644
--- a/ping/urls.py
+++ b/ping/urls.py
@@ -8,7 +8,16 @@ urlpatterns = [
     path('network/pressed/', views.pressed, name='pressed'),
     path('network/update/', views.update, name='update'),
     path('network/agents/', views.agents, name='agents'),
+    path('network/agent/kill', views.kill, name='kill'),
     path('experiment/new/', views.entry, name='entry'),
     path('experiment/', views.experiment, name='experiment'),
     path('experiment/<int:experiment_id>/check/', views.check, name='check'),
+    path('play/', views.main_play, name='play'),
+    path('play/scheduler/start', views.scheduler_start, name='start'),
+    path('play/scheduler/step', views.scheduler_step, name='step'),
+    path('play/scheduler/stop', views.scheduler_stop, name='stop'),
+    path('play/global/exit', views.experiment_stop, name='exit'),
+    path('play/global/share', views.experiment_share, name='share'),
+    path('play/global/start', views.experiment_start, name='start_exp'),
+    path('play/global/load', views.experiment_load, name='load_exp'),
 ]
\ No newline at end of file
diff --git a/ping/views/__init__.py b/ping/views/__init__.py
index 2b38d03c969c294b0845027299537c3b93e7abcf..c041ce84eedd648974daaeda69e9a8946842d31c 100644
--- a/ping/views/__init__.py
+++ b/ping/views/__init__.py
@@ -1,2 +1,3 @@
 from .experiment import *
 from .network import *
+from .play import *
\ No newline at end of file
diff --git a/ping/views/experiment.py b/ping/views/experiment.py
index 4ba32dce132a779c726a09d3aa83e9ab98c4d721..ca83afb55b19a44481fd2e518ec02df151427151 100644
--- a/ping/views/experiment.py
+++ b/ping/views/experiment.py
@@ -41,12 +41,8 @@ def empty_tmp():
 
 def check(request, experiment_id):
     # get the path
-    print(experiment_id)
     exp = Experiment.objects.get(pk=experiment_id)
-    print(str(exp.media))
-    print(str(settings.MEDIA_ROOT) + str(exp.media))
     # check if it's a zip -> wrong format : not zip
-    print()
 
     if not zipfile.is_zipfile(str(settings.MEDIA_ROOT) + str(exp.media)):
         exp.status = "Wrong format : zip file expected"
diff --git a/ping/views/network.py b/ping/views/network.py
index 84e9734db5886687e08b8539042aec4bad3b5f9c..5a13bc786bd60451425f50eba978fc0257d2b894 100644
--- a/ping/views/network.py
+++ b/ping/views/network.py
@@ -41,14 +41,7 @@ def update(request):
         ),
         Cmd(
             cmd="python3 -m pip install --force-reinstall dist/iotAmak-" + version + "-py3-none-any.whl"
-        ),
-        Cmd(
-            cmd="cd ../../../"
-        )  # ,
-        # Cmd(
-        #    cmd="rm -r Desktop/mqtt_goyon/example/" + self.experiment_name
-        # )
-
+        )
     ]
     for i_client in range(len(ssh.clients)):
         print("Hostname :", ssh.clients[i_client].hostname, " User :", ssh.clients[i_client].user)
@@ -76,6 +69,19 @@ def agents(request):
 
     return HttpResponseRedirect(reverse('ping:index'))
 
+def kill(request):
+    ssh = get_ssh_client()
+
+    commands = [
+        Cmd(
+            cmd="for pid in $(ps -ef | grep 'python ' | awk '{print $2}'); do kill $pid; done",
+            do_print=False
+        )]
+    for i_client in range(len(ssh.clients)):
+        ssh.run_cmd(i_client, commands)
+    return HttpResponseRedirect(reverse('ping:index'))
+
+
 
 def index(request):
     template = loader.get_template('ping/index.html')
diff --git a/ping/views/play.py b/ping/views/play.py
new file mode 100644
index 0000000000000000000000000000000000000000..c7e0a72fbf80d7cb3f485ae85442bb10f1d632bc
--- /dev/null
+++ b/ping/views/play.py
@@ -0,0 +1,149 @@
+import os
+import shutil
+import sys
+import zipfile
+from ast import literal_eval
+from subprocess import Popen
+from time import sleep
+
+from django.conf import settings
+from django.http import HttpResponse, HttpResponseRedirect
+from django.template import loader
+from django.urls import reverse
+from iotAmak.tool.ssh_client import Cmd
+from paho.mqtt.client import Client as MQTTClient
+
+from ..models import Experiment, CurrentExperiment, Metrics
+
+from .network import get_ssh_client
+
+client = MQTTClient(client_id="django-ihm")
+
+def subscribe(mqttclient, topic, fun):
+    mqttclient.subscribe(topic)
+    mqttclient.message_callback_add(topic, fun)
+
+
+def agent_log(client, userdata, message) -> None:
+    """
+    Called when the amas receive a log from any agent, print it in stdout
+    """
+    print("[Log] " + str(message.payload.decode("utf-8")) + " on topic " + message.topic)
+
+
+def agent_metric(client, userdata, message) -> None:
+    result = literal_eval(message.payload.decode("utf-8"))
+    agent_id = result.get("id")
+
+    exp = CurrentExperiment.objects.all()[0]
+
+    metric = Metrics(experiment_name=exp.name, cycle=exp.cycle, agent_id=agent_id, metrics=result)
+    metric.save()
+
+
+def update_nbr_agent(client, userdata, message) -> None:
+    exp = CurrentExperiment.objects.all()[0]
+    subscribe(client, "agent/"+str(exp.nbr_agent)+"/metric", agent_metric)
+    exp.nbr_agent += 1
+    exp.save()
+
+def empty_current_experiment():
+    folder = str(settings.MEDIA_ROOT) + "current_experiment"
+    for filename in os.listdir(folder):
+        file_path = os.path.join(folder, filename)
+        try:
+            if os.path.isfile(file_path) or os.path.islink(file_path):
+                os.unlink(file_path)
+            elif os.path.isdir(file_path):
+                shutil.rmtree(file_path)
+        except Exception as e:
+            print('Failed to delete %s. Reason: %s' % (file_path, e))
+
+def experiment_load(request):
+
+    empty_current_experiment()
+
+    exp = Experiment.objects.get(status="Selected")
+
+    with zipfile.ZipFile(str(settings.MEDIA_ROOT) + str(exp.media), 'r') as zip_ref:
+        zip_ref.extractall(str(settings.MEDIA_ROOT) + "current_experiment")
+
+    # drop metrics table
+    Metrics.objects.all().delete()
+
+    # drop current experiment table and create new instance
+    CurrentExperiment.objects.all().delete()
+    cur_exp = CurrentExperiment(name=Experiment.objects.get(status="Selected").name)
+    cur_exp.save()
+
+    return HttpResponseRedirect(reverse('ping:play'))
+
+def experiment_start(request):
+
+    broker_ip = "192.168.201.209"
+    ssh = get_ssh_client()
+
+    experiment_path = str(settings.MEDIA_ROOT) + "current_experiment/" + Experiment.objects.get(status="Selected").name
+
+    # Connect to the broker
+    client.username_pw_set(username="goyon", password="mosquitto")
+    client.connect(host=broker_ip)
+    client.loop_start()
+    subscribe(client, "amas/agent/new", update_nbr_agent)
+
+    # start subprocess scheduler
+    p1 = Popen([sys.executable, experiment_path+'/scheduler.py', broker_ip])
+    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)])
+    # start subprocess env
+    p3 = Popen([sys.executable, experiment_path+'/env.py', broker_ip])
+    return HttpResponseRedirect(reverse('ping:play'))
+
+
+def main_play(request):
+    template = loader.get_template('ping/play.html')
+    context = {}
+    return HttpResponse(template.render(context, request))
+
+
+def scheduler_step(request):
+    client.publish("ihm/step")
+    return HttpResponseRedirect(reverse('ping:play'))
+
+
+def scheduler_stop(request):
+    client.publish("ihm/pause")
+    return HttpResponseRedirect(reverse('ping:play'))
+
+
+def scheduler_start(request):
+    client.publish("ihm/unpause")
+    return HttpResponseRedirect(reverse('ping:play'))
+
+def experiment_share(request):
+    # get selected experiment
+    exp = Experiment.objects.get(status="Selected")
+
+    # open ssh connection
+    ssh = get_ssh_client()
+
+    # file transfer
+    commands = [
+        Cmd(
+            cmd="rm -r Desktop/mqtt_goyon/example/" + exp.name
+        )
+
+    ]
+    for i_client in range(len(ssh.clients)):
+        ssh.run_cmd(i_client, commands)
+
+    ssh.update(exp.name, str(settings.MEDIA_ROOT) + "current_experiment/" + exp.name)
+
+    return HttpResponseRedirect(reverse('ping:play'))
+
+def experiment_stop(request):
+    client.publish("ihm/exit")
+    client.publish("ihm/step")
+    return HttpResponseRedirect(reverse('ping:play'))
diff --git a/uploads/current_experiment/ant/__init__.py b/uploads/current_experiment/ant/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/uploads/current_experiment/ant/agent.py b/uploads/current_experiment/ant/agent.py
new file mode 100644
index 0000000000000000000000000000000000000000..5accea62e91b4885d8fb8b4acc49424b2ab0ff02
--- /dev/null
+++ b/uploads/current_experiment/ant/agent.py
@@ -0,0 +1,28 @@
+import random
+import sys
+
+from iotAmak.agent import Agent
+
+
+class Ant(Agent):
+
+    def __init__(self, identifier: int, broker_ip: str):
+        self.x = 0
+        self.y = 0
+        super().__init__(identifier, broker_ip)
+
+    def on_act(self) -> None:
+        self.x += random.randint(-5, +5)
+        self.y += random.randint(-5, +5)
+        self.log("X : "+str(self.x)+" Y  : "+str(self.y))
+
+    def send_metric(self):
+        metric = super(Ant, self).send_metric()
+
+        metric["x"] = self.x
+        metric["y"] = self.y
+        return metric
+
+if __name__ == '__main__':
+    a = Ant(int(sys.argv[1]), str(sys.argv[2]))
+    a.run()
\ No newline at end of file
diff --git a/uploads/current_experiment/ant/amas.py b/uploads/current_experiment/ant/amas.py
new file mode 100644
index 0000000000000000000000000000000000000000..99a0586c10c2185bf7ed813e58b6ee83c7934747
--- /dev/null
+++ b/uploads/current_experiment/ant/amas.py
@@ -0,0 +1,20 @@
+import sys
+
+
+from iotAmak.amas import Amas
+
+
+class AntAmas(Amas):
+
+    def __init__(self, broker_ip: str, clients, nbr_agent):
+        self.agent_to_create = nbr_agent
+        super().__init__(broker_ip, clients)
+
+    def on_initial_agents_creation(self):
+        for _ in range(self.agent_to_create):
+            self.add_agent("ant")
+
+
+if __name__ == '__main__':
+    s = AntAmas(str(sys.argv[1]), sys.argv[2], 5)
+    s.run()
diff --git a/uploads/current_experiment/ant/env.py b/uploads/current_experiment/ant/env.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4f1c425069ef147cbc87de425cd47ea57910ab0
--- /dev/null
+++ b/uploads/current_experiment/ant/env.py
@@ -0,0 +1,15 @@
+import sys
+
+
+from iotAmak.environment import Environment
+
+
+class AntEnv(Environment):
+
+    def __init__(self, broker_ip):
+        super().__init__(broker_ip)
+
+
+if __name__ == '__main__':
+    s = AntEnv(str(sys.argv[1]))
+    s.run()
\ No newline at end of file
diff --git a/uploads/current_experiment/ant/scheduler.py b/uploads/current_experiment/ant/scheduler.py
new file mode 100644
index 0000000000000000000000000000000000000000..9aac6b62858864b24de49e4414435a3e307af319
--- /dev/null
+++ b/uploads/current_experiment/ant/scheduler.py
@@ -0,0 +1,7 @@
+import sys
+
+from iotAmak.scheduler import Scheduler
+
+if __name__ == '__main__':
+    a = Scheduler(str(sys.argv[1]))
+    a.run()
\ No newline at end of file
diff --git a/uploads/media/amas.py b/uploads/media/amas.py
new file mode 100644
index 0000000000000000000000000000000000000000..1b8e3f306293dc9151a0de60da43dd8a772f3b20
--- /dev/null
+++ b/uploads/media/amas.py
@@ -0,0 +1,20 @@
+import sys
+
+
+from iotAmak.amas import Amas
+
+
+class PhiAmas(Amas):
+
+    def __init__(self, broker_ip: str, clients, nbr_agent):
+        self.agent_to_create = nbr_agent
+        super().__init__(broker_ip, clients)
+
+    def on_initial_agents_creation(self):
+        for _ in range(self.agent_to_create):
+            self.add_agent("philosophers", [str(self.agent_to_create)])
+
+
+if __name__ == '__main__':
+    s = PhiAmas(str(sys.argv[1]), sys.argv[2], 5)
+    s.run()
diff --git a/uploads/media/ant.zip b/uploads/media/ant.zip
new file mode 100644
index 0000000000000000000000000000000000000000..412da9c2e93f2efd75892236c484c9a8068ba3c3
Binary files /dev/null and b/uploads/media/ant.zip differ
diff --git a/uploads/media/philosophers_7r4Esmi.zip b/uploads/media/philosophers_7r4Esmi.zip
new file mode 100644
index 0000000000000000000000000000000000000000..36a06f59b5c16b862e0b44f85cc23505f35b0377
Binary files /dev/null and b/uploads/media/philosophers_7r4Esmi.zip differ