Skip to content
Snippets Groups Projects
Commit d6d87b39 authored by shinedday's avatar shinedday
Browse files

Reformat view code, and add play tab

parent d02b2402
Branches
No related tags found
No related merge requests found
Showing
with 389 additions and 14 deletions
No preview for this file type
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
# 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'),
),
]
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
......@@ -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 %}
......
......@@ -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'>
......
......@@ -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>
......
<!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
......@@ -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
from .experiment import *
from .network import *
from .play import *
\ No newline at end of file
......@@ -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"
......
......@@ -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')
......
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'))
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
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()
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
import sys
from iotAmak.scheduler import Scheduler
if __name__ == '__main__':
a = Scheduler(str(sys.argv[1]))
a.run()
\ No newline at end of file
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()
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment