Commit 052adb4d authored by Jérome Perrin's avatar Jérome Perrin

experimental: event generator to update gui using websockets

parent 6fa102c7
......@@ -218,8 +218,30 @@ def main(*args):
file_handler.setLevel(logging.DEBUG)
app.logger.addHandler(file_handler)
# start the server
app.run(debug=True, host=arguments.host, port=arguments.port)
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
http_server = WSGIServer((arguments.host, arguments.port),
app, handler_class=WebSocketHandler)
http_server.serve_forever()
@app.route('/api')
def api():
if request.environ.get('wsgi.websocket'):
ws = request.environ['wsgi.websocket']
while True:
message = ws.receive()
parameter_dict = json.loads(message)
from dream.simulation import Globals
Globals.ws = ws
result = getGUIInstance().run(parameter_dict)
ws.send(json.dumps({'success': result}))
return "No websocket"
def run(*args):
# run with one topology input
......
......@@ -382,6 +382,12 @@ border: 1px solid black;
transition:box-shadow 0.25s ease-in;
}
.status {
position:absolute;
bottom:0px;
right:5px;
}
._jsPlumb_source_hover, ._jsPlumb_target_hover, .dragHover {
background-color:#1e8151;
background-image: none;
......
......@@ -71,7 +71,9 @@
<div id="shift_spreadsheet" style="display: none; overflow: scroll"></div>
</div>
<div class="twelve columns">
<div>
Current time in simulation clock : <span id="now"/>
</div>
<div id="result_zone">
<h1>Results</h1>
<ul id="result_list"></ul>
......
......@@ -170,7 +170,7 @@
});
// Enable "Run Simulation" button
$("#run_simulation").button().click(
$("#xxrun_simulation").button().click(
function (e) {
$("#loading_spinner").show();
$("#run_simulation").button('disable');
......@@ -276,5 +276,56 @@
$("#shift_spreadsheet").hide();
}
});
// XXX create socket on click ?
var webSocket = new WebSocket("ws://localhost:5000/api");
webSocket.onmessage = function(e) {
var message = JSON.parse(e.data)
$.each(message.update_gui || [], function(i, msg){
if (msg.action === "update_queue_stat"){
dream_instance.updateElementData(msg.node,
{status: msg.capacity});
}
if (msg.action === "update_machine_status"){
dream_instance.updateElementData(msg.node,
{status: msg.status});
}
});
if (message['now']) {
$("#now").text(message['now']);
}
if (message['success']) {
$("#json_result").val(JSON.stringify(message['success'],
undefined, " "));
$("#loading_spinner").hide();
$("#run_simulation").button('enable');
$("#result_zone").show();
$('#result_list').empty();
$('.window > .status').remove();
$.each(message['success'], function (idx, obj) {
$('#result_list').append('<li class="result"></li>');
$('#result_list').children().last().text(
idx + ' : ' + obj['score'] + ' ' + obj['key']).click(
function (e) {
dream_instance.displayResult(idx);
}
);
});
dream_instance.displayResult(0);
}
}
$("#run_simulation").button().on('click', function(e) {
// TODO: we need to update global properties
$("#loading_spinner").show();
$("#run_simulation").button('disable');
var msg = JSON.stringify(dream_instance.getData());
webSocket.send(msg);
return false;
});
});
})(jQuery);
......@@ -360,6 +360,13 @@
$("#" + element_id).text(data["name"]).append('<div class="ep"></div></div>');
priv.node_container[node_id].name = data['name'];
}
if (data['status']) {
var statusdiv = $("#" + element_id).find(".status");
if (!statusdiv.length) {
statusdiv = $("<div>").addClass("status").appendTo($("#" + element_id));
}
statusdiv.text(data['status']);
}
var new_id = data['id'];
delete(data['id']);
$.extend(priv.node_container[node_id], data.data);
......
{
"edges": {
"con_10": [
"M2",
"E1",
{}
],
"con_15": [
"S1",
"M1",
{}
],
"con_20": [
"Q1",
"M3",
{}
],
"con_25": [
"M3",
"Q2",
{}
],
"con_30": [
"Q2",
"M2",
{}
],
"con_5": [
"M1",
"Q1",
{}
]
},
"general": {
"confidenceLevel": 0.5,
"currentDate": "2014/03/01",
"maxSimTime": 200,
"numberOfReplications": 1,
"processTimeout": 10,
"trace": "Yes"
},
"nodes": {
"E1": {
"_class": "Dream.Exit",
"element_id": "DreamNode_1"
},
"M1": {
"_class": "Dream.Machine",
"element_id": "DreamNode_2",
"failures": {
"MTTF": 40,
"MTTR": 10,
"failureDistribution": "No",
"repairman": "None"
},
"name": "M1: working",
"processingTime": {
"distributionType": "Normal",
"max": 3.9,
"mean": 0.1,
"min": 0.1,
"stdev": 2
}
},
"M2": {
"_class": "Dream.Machine",
"element_id": "DreamNode_3",
"failures": {
"MTTF": 40,
"MTTR": 10,
"failureDistribution": "No",
"repairman": "None"
},
"name": "M2: working",
"processingTime": {
"distributionType": "Normal",
"max": 3,
"mean": 0.1,
"min": 0.1,
"stdev": 2
}
},
"M3": {
"_class": "Dream.Machine",
"element_id": "DreamNode_8",
"failures": {
"MTTF": 40,
"MTTR": 10,
"failureDistribution": "No",
"repairman": "None"
},
"name": "M3: working",
"processingTime": {
"distributionType": "Normal",
"max": 4,
"mean": 3,
"min": 0.1,
"stdev": 2
}
},
"Q1": {
"_class": "Dream.Queue",
"capacity": 100,
"element_id": "DreamNode_4",
"isDummy": "0",
"name": "Q1: 3",
"schedulingRule": "FIFO"
},
"Q2": {
"_class": "Dream.Queue",
"capacity": 130,
"element_id": "DreamNode_7",
"isDummy": "0",
"name": "Q2: 4",
"schedulingRule": "FIFO"
},
"QS1": {
"_class": "Dream.EventGenerator",
"argumentDict": "{}",
"duration": 10,
"element_id": "DreamNode_5",
"interval": 10,
"method": "Globals.countQueueMetrics",
"name": "Queue Statistics",
"start": 1,
"stop": -1
},
"QS2": {
"_class": "Dream.EventGenerator",
"argumentDict": "{}",
"duration": 10,
"element_id": "DreamNode_9",
"interval": 1,
"method": "Globals.updateGui",
"name": "Queue Statistics",
"start": 1,
"stop": -1
},
"S1": {
"_class": "Dream.Source",
"element_id": "DreamNode_6",
"entity": "Dream.Part",
"interarrivalTime": {
"distributionType": "Fixed",
"mean": 0.3
},
"name": "S1"
}
},
"preference": {
"coordinates": {
"E1": {
"left": 0.8900794036136932,
"top": 0.8658660582253224
},
"M1": {
"left": 0.42307670353585936,
"top": 0.026878325532493377
},
"M2": {
"left": 0.5502309040521013,
"top": 0.741073832538746
},
"M3": {
"left": 0.08785199308394895,
"top": 0.4895695007704151
},
"Q1": {
"left": 0.4762502782971969,
"top": 0.2764627769056462
},
"Q2": {
"left": 0.5224881693940121,
"top": 0.5222074674884428
},
"QS1": {
"left": 0.060109258425859804,
"top": 0.85818653664461
},
"QS2": {
"left": 0.9756195021428015,
"top": 0.2783826573008243
},
"S1": {
"left": 0.053173574761337515,
"top": 0.10367354133961731
}
},
"zoom_level": 1.1111
},
"shift_spreadsheet": [
[
"Day",
"Machines",
"Start",
"End"
],
[
null,
null,
null,
null
]
],
"wip_part_spreadsheet": [
[
"Order ID",
"Due Date",
"Priority",
"Project Manager",
"Part",
"Part Type",
"Sequence",
"Processing Times",
"Prerequisites Parts"
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null
]
]
}
......@@ -25,12 +25,12 @@ Created on 8 Nov 2012
carries some global variables
'''
#from SimPy.Simulation import *
from Machine import Machine
from Queue import Queue
from Repairman import Repairman
import xlwt
import xlrd
import json
from random import Random, expovariate, gammavariate, normalvariate
from SimPy.Simulation import now
......@@ -254,7 +254,6 @@ def countQueueMetrics(argumentDict={}):
if isinstance(obj, Queue):
obj.wip_stat_list.append((now(), len(obj.Res.activeQ)))
# =======================================================================
# Helper function to calculate the confidence intervals of a serie.
# =======================================================================
......@@ -272,3 +271,24 @@ def getConfidenceIntervals(value_list):
'ub': ub,
'avg': numpy.mean(value_list) }
from Queue import Queue
from Machine import Machine
def updateGui(argumentDict={}):
message_list = []
for obj in G.ObjList:
if isinstance(obj, Queue):
message_list.append({'node': obj.id,
'action': 'update_queue_stat',
'capacity': len(obj.Res.activeQ),
})
if isinstance(obj, Machine):
message_list.append({'node': obj.id,
'action': 'update_machine_status',
'debug': repr(obj.Res.activeQ),
'status': obj.status,
})
import Globals
Globals.ws.send(json.dumps({'update_gui': message_list, 'now': now()}))
import time
time.sleep(0.08)
......@@ -9,6 +9,8 @@ setup(
package_dir={'': '.', 'simulation': 'simulation'},
install_requires=[
'flask',
'gunicorn',
'gevent-websocket',
'SimPy>=2,<3',
'xlrd',
'xlwt',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment