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): ...@@ -218,8 +218,30 @@ def main(*args):
file_handler.setLevel(logging.DEBUG) file_handler.setLevel(logging.DEBUG)
app.logger.addHandler(file_handler) 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): def run(*args):
# run with one topology input # run with one topology input
......
...@@ -382,6 +382,12 @@ border: 1px solid black; ...@@ -382,6 +382,12 @@ border: 1px solid black;
transition:box-shadow 0.25s ease-in; transition:box-shadow 0.25s ease-in;
} }
.status {
position:absolute;
bottom:0px;
right:5px;
}
._jsPlumb_source_hover, ._jsPlumb_target_hover, .dragHover { ._jsPlumb_source_hover, ._jsPlumb_target_hover, .dragHover {
background-color:#1e8151; background-color:#1e8151;
background-image: none; background-image: none;
......
...@@ -71,7 +71,9 @@ ...@@ -71,7 +71,9 @@
<div id="shift_spreadsheet" style="display: none; overflow: scroll"></div> <div id="shift_spreadsheet" style="display: none; overflow: scroll"></div>
</div> </div>
<div class="twelve columns"> <div class="twelve columns">
<div>
Current time in simulation clock : <span id="now"/>
</div>
<div id="result_zone"> <div id="result_zone">
<h1>Results</h1> <h1>Results</h1>
<ul id="result_list"></ul> <ul id="result_list"></ul>
......
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
}); });
// Enable "Run Simulation" button // Enable "Run Simulation" button
$("#run_simulation").button().click( $("#xxrun_simulation").button().click(
function (e) { function (e) {
$("#loading_spinner").show(); $("#loading_spinner").show();
$("#run_simulation").button('disable'); $("#run_simulation").button('disable');
...@@ -276,5 +276,56 @@ ...@@ -276,5 +276,56 @@
$("#shift_spreadsheet").hide(); $("#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); })(jQuery);
...@@ -360,6 +360,13 @@ ...@@ -360,6 +360,13 @@
$("#" + element_id).text(data["name"]).append('<div class="ep"></div></div>'); $("#" + element_id).text(data["name"]).append('<div class="ep"></div></div>');
priv.node_container[node_id].name = data['name']; 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']; var new_id = data['id'];
delete(data['id']); delete(data['id']);
$.extend(priv.node_container[node_id], data.data); $.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 ...@@ -25,12 +25,12 @@ Created on 8 Nov 2012
carries some global variables carries some global variables
''' '''
#from SimPy.Simulation import *
from Machine import Machine from Machine import Machine
from Queue import Queue from Queue import Queue
from Repairman import Repairman from Repairman import Repairman
import xlwt import xlwt
import xlrd import xlrd
import json
from random import Random, expovariate, gammavariate, normalvariate from random import Random, expovariate, gammavariate, normalvariate
from SimPy.Simulation import now from SimPy.Simulation import now
...@@ -254,7 +254,6 @@ def countQueueMetrics(argumentDict={}): ...@@ -254,7 +254,6 @@ def countQueueMetrics(argumentDict={}):
if isinstance(obj, Queue): if isinstance(obj, Queue):
obj.wip_stat_list.append((now(), len(obj.Res.activeQ))) obj.wip_stat_list.append((now(), len(obj.Res.activeQ)))
# ======================================================================= # =======================================================================
# Helper function to calculate the confidence intervals of a serie. # Helper function to calculate the confidence intervals of a serie.
# ======================================================================= # =======================================================================
...@@ -272,3 +271,24 @@ def getConfidenceIntervals(value_list): ...@@ -272,3 +271,24 @@ def getConfidenceIntervals(value_list):
'ub': ub, 'ub': ub,
'avg': numpy.mean(value_list) } '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( ...@@ -9,6 +9,8 @@ setup(
package_dir={'': '.', 'simulation': 'simulation'}, package_dir={'': '.', 'simulation': 'simulation'},
install_requires=[ install_requires=[
'flask', 'flask',
'gunicorn',
'gevent-websocket',
'SimPy>=2,<3', 'SimPy>=2,<3',
'xlrd', 'xlrd',
'xlwt', '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