-
Notifications
You must be signed in to change notification settings - Fork 3
/
SimUI.py
121 lines (100 loc) · 4.32 KB
/
SimUI.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# built-in
import threading
import webbrowser
import time
# third-party
import bottle
# local
import SimEngine
import SimVersion
class SimUI(object):
'''
Web-based User Interface of the simulator.
'''
TCPPORT = 8080
def __init__(self,floorplan,dotbots,orchestrator):
# store params
self.floorplan = floorplan
self.dotbots = dotbots
self.orchestrator = orchestrator
# local variables
self.simEngine = SimEngine.SimEngine()
# start web server
self.websrv = bottle.Bottle()
self.websrv.route('/', 'GET', self._webhandle_root_GET)
self.websrv.route('/static/<filename>', 'GET', self._webhandle_static_GET)
self.websrv.route('/floorplan.json', 'GET', self._webhandle_floorplan_GET)
self.websrv.route('/dotbots.json', 'GET', self._webhandle_dotbots_GET)
self.websrv.route('/frameforward', 'POST', self._webhandle_frameforward_POST)
self.websrv.route('/play', 'POST', self._webhandle_play_POST)
self.websrv.route('/fastforward', 'POST', self._webhandle_fastforward_POST)
self.websrv.route('/pause', 'POST', self._webhandle_pause_POST)
webthread = threading.Thread(
target = self._bottle_try_running_forever,
args = (self.websrv.run,),
kwargs = {
'host' : '127.0.0.1',
'port' : self.TCPPORT,
'quiet' : True,
'debug' : False,
}
)
webthread.name = 'WebServer'
webthread.daemon = True
webthread.start()
# open browser
webbrowser.open('http://127.0.0.1:{0}'.format(self.TCPPORT))
#======================== public ==========================================
#======================== private =========================================
#=== web handles
def _webhandle_root_GET(self):
return bottle.template(
'SimUI',
pagetitle = 'DotBot Simulator',
version = SimVersion.formatVersion(),
)
def _webhandle_static_GET(self,filename):
return bottle.static_file(filename, root='static/')
def _webhandle_floorplan_GET(self):
return self.floorplan.getJSON()
def _webhandle_dotbots_GET(self):
simulatedTime = self.simEngine.currentTime()
orchestratorView = self.orchestrator.getView()
returnVal = {
'mode': self.simEngine.mode(),
'simulatedTime': self.simEngine.formatSimulatedTime(),
'dotbots': [],
'discomap': orchestratorView['discomap'],
}
for dotbot in self.dotbots:
returnVal['dotbots'] += [dotbot.getAttitude()]
for (dotbot,orchestratorview) in zip(returnVal['dotbots'],orchestratorView['dotbots']):
dotbot['orchestratorview_x'] = orchestratorview['x']
dotbot['orchestratorview_y'] = orchestratorview['y']
return returnVal
def _webhandle_frameforward_POST(self):
self.simEngine.commandFrameforward()
def _webhandle_play_POST(self):
rxjson = bottle.request.json
self.simEngine.commandPlay(rxjson['speed'])
def _webhandle_fastforward_POST(self):
self.simEngine.commandFastforward()
def _webhandle_pause_POST(self):
self.simEngine.commandPause()
#=== web server admin
def _bottle_try_running_forever(self,*args,**kwargs):
RETRY_PERIOD = 3
while True:
try:
args[0](**kwargs) # blocking
except Exception as err:
if False: # how to get socket.error? if err[0] == 10013:
print('FATAL: cannot open TCP port {0}.'.format(kwargs['port']))
print(' Is another application running on that port?')
else:
print(err)
print(' Trying again in {0} seconds'.format(RETRY_PERIOD))
for _ in range(RETRY_PERIOD):
time.sleep(1)
print('.')
print('')