From 52c92c28707572a2adb958131eda573aa9f0ce2a Mon Sep 17 00:00:00 2001 From: Sebastien GOYON <shinedday@gmail.com> Date: Wed, 3 Aug 2022 08:56:39 +0200 Subject: [PATCH] Last push --- ping/consumers.py | 1 + ping/models.py | 14 +++- ping/templates/ping/play.html | 130 ++++++++++++++++++++++------------ ping/views/play.py | 36 +++++++--- ping/views/tool.py | 11 ++- 5 files changed, 128 insertions(+), 64 deletions(-) diff --git a/ping/consumers.py b/ping/consumers.py index 0e45079..add2989 100644 --- a/ping/consumers.py +++ b/ping/consumers.py @@ -3,6 +3,7 @@ from channels.generic.websocket import AsyncWebsocketConsumer import json + class GraphConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = 'event' diff --git a/ping/models.py b/ping/models.py index 174903d..3c99ce0 100644 --- a/ping/models.py +++ b/ping/models.py @@ -69,6 +69,12 @@ class CurrentExperiment(models.Model): com_fun = models.CharField(default="linear", max_length=64) com_refresh = models.PositiveIntegerField(default=1) + graph = models.BooleanField(default=False) + graph_height = models.PositiveIntegerField(default=1) + graph_width = models.PositiveIntegerField(default=1) + graph_refresh = models.PositiveIntegerField(default=1) + + class Network(models.Model): broker_ip = models.CharField(max_length=60) @@ -98,4 +104,10 @@ class Canvas(models.Model): color = models.CharField(max_length=60) - cycle = models.PositiveIntegerField(default=0) \ No newline at end of file + cycle = models.PositiveIntegerField(default=0) + +class GraphPoint(models.Model): + + name = models.CharField(max_length=60) + cycle = models.PositiveIntegerField(default=0) + y = models.IntegerField(default=0) \ No newline at end of file diff --git a/ping/templates/ping/play.html b/ping/templates/ping/play.html index f9f3e07..08d91f1 100644 --- a/ping/templates/ping/play.html +++ b/ping/templates/ping/play.html @@ -127,50 +127,6 @@ text { </script> {% endif %} - - {% if canvas %} -<canvas id="line-chart" width="800" height="450"></canvas> -<script> - -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 myChart = new Chart(document.getElementById("line-chart"), { - type: 'line', - data: chart_data, - options: {} -}); - - - const graphSocket = new WebSocket( - 'ws://' - + window.location.host - + '/ws/graph/' - ); - - graphSocket.onmessage = function (e) { - const metrics = JSON.parse(e.data).message; - new_graph_data = chart_data.datasets[0].data; - new_graph_data.shift(); - new_graph_data.push(metrics[0]); - - chart_data.datasets[0].data = new_graph_data; - - myChart.update(); - - }; -</script> - {% endif %} - - {% if com_graph %} <svg width="500" height="500" style="border:1px solid #000000;"></svg> <script> @@ -224,8 +180,6 @@ const comSocket = new WebSocket( comSocket.onmessage = function (e) { graph = JSON.parse(e.data).message; - console.log(graph); - console.log(typeof graph); svg.selectAll("*").remove(); link = svg.append("g").attr("class", "links").selectAll("line").data(graph.links).enter().append("line") @@ -245,6 +199,90 @@ comSocket.onmessage = function (e) { {% endif %} +<div id="my_dataviz"></div> +<script> + +// set the dimensions and margins of the graph +const margin = {top: 10, right: 30, bottom: 30, left: 60}, + width =500 - margin.left - margin.right, //self.innerWidth - margin.left - margin.right, + height = 400 - margin.top - margin.bottom; + +var svg = d3.select("#my_dataviz") + .append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", `translate(${margin.left},${margin.top})`); + +const graphSocket = new WebSocket( + 'ws://' + + window.location.host + + '/ws/graph/' +); + +graphSocket.onmessage = function (e) { + data = JSON.parse(e.data).message; + console.log(data) + console.log(data[0]) +// group the data: I want to draw one line per group + const sumstat = d3.group(data, d => d.name); // nest function allows to group the calculation per level of a factor + +svg.selectAll("*").remove(); + + // Add X axis --> it is a date format + const x = d3.scaleLinear() + .domain(d3.extent(data, function(d) { return d.x; })) + .range([ 0, width ]); + svg.append("g") + .attr("transform", `translate(0, ${height})`) + .call(d3.axisBottom(x).ticks(5)); + + // Add Y axis + const y = d3.scaleLinear() + .domain([0, d3.max(data, function(d) { return +d.y; })]) + .range([ height, 0 ]); + svg.append("g") + .call(d3.axisLeft(y)); + + // color palette + const color = d3.scaleOrdinal() + .range(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#ffff33','#a65628','#f781bf','#999999']) + + // Draw the line + svg.selectAll(".line") + .data(sumstat) + .join("path") + .attr("fill", "none") + .attr("stroke", function(d){ return color(d[0]) }) + .attr("stroke-width", 1.5) + .attr("d", function(d){ + return d3.line() + .x(function(d) { return x(d.x); }) + .y(function(d) { return y(+d.y); }) + (d[1]) + }) + + var legendItemSize = 12; + var legendSpacing = 4; + + var lineLegend = svg.selectAll(".lineLegend").data([...sumstat.keys()]) + .enter().append("g") + .attr("class","lineLegend") + .attr("transform", function (d,i) { + return "translate(" + width + "," + (i*50)+")"; + }); + +lineLegend.append("text").text(function (d) {return d;}) + .attr('x', legendItemSize + 3) + .attr('y', (d, i) => (legendItemSize + legendSpacing) * i + 10); + +lineLegend.append("rect") + .attr("fill", function (d, i) {return color(d); }) + .attr("width", 10).attr("height", 10); + + }; +</script> + </body> </html> \ No newline at end of file diff --git a/ping/views/play.py b/ping/views/play.py index cddfaaa..99ecc1c 100644 --- a/ping/views/play.py +++ b/ping/views/play.py @@ -17,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, com_event_triger -from ..models import Experiment, CurrentExperiment, Metrics, Network, Link, Node, Canvas +from ..models import Experiment, CurrentExperiment, Metrics, Network, Link, Node, Canvas, GraphPoint client = MQTTClient(client_id="django-ihm") @@ -54,15 +54,6 @@ def agent_metric(client, userdata, message) -> None: metrics = Metrics(cycle=exp.cycle, metrics=results) metrics.save() - if False: - data = 0 - for metric in results: - if metric == {}: - pass - elif metric.get("color") != "#000000": - data += 1 - graph_event_triger([data, exp.cycle]) - def agent_canvas(client, userdata, message) -> None: results = literal_eval(message.payload.decode("utf-8")) @@ -119,6 +110,14 @@ def cycle_done(client, userdata, message) -> None: canvas_event_triger(canvas) + if cur_exp.graph and (cur_exp.cycle % cur_exp.graph_refresh == 0): + data = [ + {"name": elem.name, "x":elem.cycle, "y":elem.y} + for elem in GraphPoint.objects.all() + ] + graph_event_triger(data) + + cur_exp.cycle += 1 cur_exp.save() @@ -142,6 +141,12 @@ def update_nbr_agent(client, userdata, message) -> None: exp.nbr_agent += 1 exp.save() +def agent_graph(client, userdata, message) -> None: + results = literal_eval(message.payload.decode("utf-8")) + + for elem in results.get("point"): + point = GraphPoint(name=elem.get("name"),cycle=results.get("cycle"),y=elem.get("value")) + point.save() def experiment_load(request): delete_folder(str(settings.MEDIA_ROOT) + "current_experiment") @@ -180,6 +185,13 @@ def experiment_load(request): cur_exp.canvas_width = config.get("canvas").get("width") Canvas.objects.all().delete() + if "graph" in config: + cur_exp.graph = True + cur_exp.graph_height = config.get("graph").get("height") + cur_exp.graph_width = config.get("graph").get("width") + cur_exp.graph_refresh = config.get("graph").get("refresh") + GraphPoint.objects.all().delete() + cur_exp.scheduling = config.get("scheduling_type") cur_exp.save() @@ -230,6 +242,7 @@ def experiment_start(request): client.loop_start() subscribe(client, "amas/agent/new", update_nbr_agent) subscribe(client, "scheduler/cycledone", cycle_done) + subscribe(client, "amas/graph", agent_graph) subscribe(client, "amas/all_metric", agent_metric) delete_nohup() @@ -249,7 +262,8 @@ def experiment_start(request): "seed": exp.seed, "iot_path": n.path_to_iotamak + "example/", "broker_username": n.broker_username, - "broker_password": n.broker_password + "broker_password": n.broker_password, + "experiment_folder": exp.name } if not exp.scheduling == "sync": amas_dict["wait_delay"] = str(5) diff --git a/ping/views/tool.py b/ping/views/tool.py index 35036dc..4a4efc7 100644 --- a/ping/views/tool.py +++ b/ping/views/tool.py @@ -45,21 +45,20 @@ def canvas_event_triger(metrics): } ) - -def graph_event_triger(metrics): +def com_event_triger(data): channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( - 'event_graph', + 'event_com', { 'type': 'send_message_to_frontend', - 'message': metrics + 'message': data } ) -def com_event_triger(data): +def graph_event_triger(data): channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( - 'event_com', + 'event_graph', { 'type': 'send_message_to_frontend', 'message': data -- GitLab