Skip to content

Commit d04ae01

Browse files
committed
feat(www): show transfer rate while uploading
Signed-off-by: Cedric Hombourger <[email protected]>
1 parent 429948a commit d04ae01

File tree

4 files changed

+56
-9
lines changed

4 files changed

+56
-9
lines changed

mtda-www

+2-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ class StorageCloseHandler(BaseHandler):
177177
if mtda is not None:
178178
sid = self.get_argument('session')
179179
result = mtda.storage_close(session=sid)
180-
del self.application.settings['sockets'][sid]
180+
if sid in self.application.settings['sockets']:
181+
del self.application.settings['sockets'][sid]
181182
self.result_as_json({"result": result})
182183

183184

mtda/constants.py

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class STORAGE:
7373
LOCKED = "LOCKED"
7474
UNLOCKED = "UNLOCKED"
7575
OPENED = "OPENED"
76+
WRITING = "WRITING"
7677
CORRUPTED = "CORRUPTED"
7778
INITIALIZED = "INITIALIZED"
7879
UNKNOWN = "???"
@@ -86,3 +87,4 @@ class WRITER:
8687
RECV_TIMEOUT = 5
8788
READ_SIZE = 1*1024*1024
8889
WRITE_SIZE = 1*1024*1024
90+
NOTIFY_SECONDS = 1

mtda/storage/writer.py

+12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import bz2
1313
import threading
1414
import mtda.constants as CONSTS
15+
import time
1516
import zlib
1617
import zstandard as zstd
1718
import lzma
@@ -132,6 +133,8 @@ def worker(self):
132133
self.mtda.debug(3, "storage.writer.worker()")
133134

134135
mtda = self.mtda
136+
last_notification = time.monotonic()
137+
last_read = 0
135138
received = 0
136139
tries = CONSTS.WRITER.RECV_RETRIES
137140
self._exiting = False
@@ -147,6 +150,15 @@ def worker(self):
147150
"transfer complete")
148151
break
149152
received += len(chunk)
153+
154+
now = time.monotonic()
155+
if (now - last_notification) >= CONSTS.WRITER.NOTIFY_SECONDS:
156+
speed = (received - last_read) / (now - last_notification)
157+
mtda._storage_event(f'{CONSTS.STORAGE.WRITING} '
158+
f'{received} {speed}')
159+
last_notification = now
160+
last_read = received
161+
150162
tries = CONSTS.WRITER.RECV_RETRIES
151163
mtda.session_ping(self._session)
152164
self._write(chunk)

mtda/templates/index.html

+40-8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<link rel="stylesheet" href="./assets/modern.min.css">
1414
<link rel="stylesheet" href="novnc/app/styles/base.css">
1515
<script type="module" crossorigin="anonymous" src="./assets/vnc.js"></script>
16+
<script src="./assets/smoothie.js"></script>
1617
<link rel="preload" href="./assets/winbox.bundle.min.js" as="script">
1718
<title>Multi-Tenant Device Access</title>
1819
<link rel="stylesheet" href="./assets/xterm.css"/>
@@ -95,22 +96,31 @@
9596
class: ["no-close", "no-full", "no-max", "modern"],
9697
width: "640px",
9798
height: "480px",
98-
hidden: true,
99+
hidden: true
99100
});
100101
videoWindow = new WinBox("Video", {
101102
html: "<div id=video></div>",
102103
class: ["no-close", "no-full", "no-max", "modern"],
103104
width: "1360px",
104105
height: "768px",
105-
hidden: true,
106+
hidden: true
106107
});
107108
uploadWindow = new WinBox("Upload", {
108109
html: "<div id=dropzone>Drag and drop your file here</div><button id='upload' disabled></button>",
109110
class: ["no-full", "no-max", "modern"],
110111
width: "600px",
111112
height: "340px",
112-
hidden: true,
113+
hidden: true
113114
});
115+
xferWindow = new WinBox("Transferring", {
116+
html: "<canvas id='xferCanvas' width='320' height='200'></canvas>",
117+
class: ["no-full", "no-max", "modern"],
118+
width: "320px",
119+
height: "200px",
120+
hidden: true
121+
});
122+
var xferChart;
123+
var xferSeries = new TimeSeries();
114124
consoleWindow.focus()
115125
</script>
116126
<script src="./assets/jquery.min.js"></script>
@@ -192,9 +202,9 @@
192202
$(function() {
193203
$('#upload').bind('click', function() {
194204
$.getJSON('./storage-open', {
195-
file: selectedFile.name,
196-
session: localStorage.getItem('session')
197-
}, function(data) {
205+
file: selectedFile.name,
206+
session: localStorage.getItem('session')
207+
}, function(data) {
198208
// do nothing
199209
});
200210
return false;
@@ -290,7 +300,8 @@
290300
function storage_event(data) {
291301
data = data.event.split(" ");
292302
event = data[0];
293-
data = data.splice(1).join(" ");
303+
let args = data.splice(1);
304+
data = args.join(" ");
294305
if (event == 'UNLOCKED') {
295306
event = data;
296307
}
@@ -316,6 +327,25 @@
316327
}
317328
}
318329
break;
330+
case 'WRITING':
331+
let speed = args[1] / 1024 / 1024;
332+
if (xferWindow.hidden) {
333+
uploadWindow.hide();
334+
xferWindow.move('center', 'center');
335+
xferWindow.toggleClass('modal');
336+
xferWindow.show();
337+
xferWindow.focus();
338+
xferChart = new SmoothieChart({
339+
millisPerPixel: 100,
340+
maxValueScale: 1.2,
341+
minValueScale: 1.2,
342+
grid: { strokeStyle: 'rgba(0, 0, 0, 0.2)', verticalSections: 4 },
343+
});
344+
xferChart.streamTo(document.getElementById("xferCanvas"), 1000);
345+
xferChart.addTimeSeries(xferSeries, { strokeStyle: 'rgb(0, 255, 0)', lineWidth: 2 });
346+
}
347+
xferSeries.append(Date.now(), speed);
348+
break;
319349
case 'CORRUPTED':
320350
case 'INITIALIZED':
321351
$.getJSON('./storage-close', {
@@ -325,6 +355,8 @@
325355
}).fail(function(jqXHR, textStatus, errorThrown) {
326356
console.error('Upload failed:', textStatus, errorThrown);
327357
});
358+
xferChart.stop();
359+
xferWindow.hide();
328360
break;
329361
case 'QLOW':
330362
maySend = true;
@@ -354,7 +386,7 @@
354386
const files = event.dataTransfer.files;
355387
if (files.length) {
356388
selectedFile = files[0];
357-
console.log('will upload '+selectedFile.name);
389+
console.log('will upload '+selectedFile.name);
358390
dropzone.textContent = `${selectedFile.name}`;
359391
upload.disabled = false;
360392
}

0 commit comments

Comments
 (0)