@@ -19,6 +19,8 @@ function getTimeParameter(){
19
19
}
20
20
21
21
async function drawRealtime ( ) {
22
+ var minutes_to_show = 2 ;
23
+ var max_minutes_to_show = 10 ;
22
24
23
25
var min_time = new Date ( ) ;
24
26
min_time . setSeconds ( 0 ) ;
@@ -42,15 +44,17 @@ async function drawRealtime(){
42
44
} ]
43
45
} ,
44
46
options : {
47
+ tooltips : {
48
+ enabled : false ,
49
+ } ,
45
50
scales : {
46
51
xAxes : [ {
47
52
type : "time" ,
48
53
position : "bottom" ,
49
54
time : {
50
55
unit : 'minute' ,
51
56
stepSize : 1 ,
52
- min : min_time
53
- }
57
+ } ,
54
58
} ] ,
55
59
yAxes : [ {
56
60
scaleLabel : {
@@ -65,6 +69,15 @@ async function drawRealtime(){
65
69
}
66
70
} ) ;
67
71
72
+ function adjustAxisForTimeProgression ( chart , minutes_to_show ) {
73
+ var ticks = chart . options . scales . xAxes [ 0 ] . ticks ;
74
+ ticks . max = new Date ( ) ;
75
+ ticks . min = new Date ( ticks . max . getTime ( ) - minutes_to_show * 60000 ) ;
76
+ chart . update ( ) ;
77
+ }
78
+
79
+ setInterval ( function ( ) { adjustAxisForTimeProgression ( chart , minutes_to_show ) ; } , 50 ) ;
80
+
68
81
async function processData ( data ) {
69
82
var records = data . split ( "\n" ) ;
70
83
@@ -85,16 +98,20 @@ async function drawRealtime(){
85
98
return [ in_power , out_power ] ;
86
99
}
87
100
88
- async function updateChart ( chart , in_power , out_power ) {
89
- for ( const value of in_power ) {
90
- data = chart . data . datasets [ 0 ] . data ;
91
- data . push ( value ) ;
92
- }
93
- for ( const value of out_power ) {
94
- data = chart . data . datasets [ 1 ] . data ;
95
- data . push ( value ) ;
101
+ function addToRecentData ( data , new_data ) {
102
+ data . push ( ...new_data ) ;
103
+
104
+ // Removing data that won't be shown anymore:
105
+ var current_time = new Date ( ) ;
106
+ while ( data . length > 0 && ( current_time - data [ 0 ] . x . getTime ( ) ) / 1000 / 60 > max_minutes_to_show ) {
107
+ data . shift ( ) ;
96
108
}
97
- chart . update ( ) ;
109
+ }
110
+
111
+ async function updateChart ( chart , in_power , out_power ) {
112
+ addToRecentData ( chart . data . datasets [ 0 ] . data , in_power ) ;
113
+ addToRecentData ( chart . data . datasets [ 1 ] . data , out_power ) ;
114
+ chart . update ( 0 ) ;
98
115
}
99
116
100
117
var socket = new WebSocket ( WS_URL ) ;
@@ -127,35 +144,58 @@ async function drawRealtime(){
127
144
}
128
145
129
146
async function drawPowerUsage ( ) {
130
- function processLogResponse ( response_text , meta ) {
147
+ function processLogResponse ( response_text , offset ) {
131
148
var data = [ ] ;
132
149
var records = response_text . split ( "\n" ) ;
133
150
for ( const record of records ) {
134
151
var values = record . split ( "," ) ;
135
- values [ 0 ] = Number ( values [ 0 ] ) + meta [ "start_time_offset" ] ;
152
+ values [ 0 ] = Number ( values [ 0 ] ) + offset ;
136
153
values [ 1 ] = Number ( values [ 1 ] ) ;
137
154
values [ 2 ] = Number ( values [ 2 ] ) ;
138
155
data . push ( values ) ;
139
156
}
140
157
return data ;
141
158
}
142
159
143
- async function getData ( ) {
160
+ async function * getData ( ) {
144
161
var response = await fetch ( API_URL + '/data/meta.json' ) ;
145
162
var meta = await response . json ( ) ;
146
- var data = [ ] ;
147
163
148
- for ( const [ key , value ] of Object . entries ( meta [ "logs" ] ) ) {
149
- console . log ( "Downloading " + key + '.csv' ) ;
150
- var response = await fetch ( API_URL + '/data/' + key + '.csv' ) ;
151
- var response_text = await response . text ( ) ;
152
- data = data . concat ( await processLogResponse ( response_text , value ) ) ;
164
+ var logs = [ ] ;
165
+ for ( const [ log_number , log_meta ] of Object . entries ( meta [ "logs" ] ) ) {
166
+ logs . push ( {
167
+ number : log_number ,
168
+ start_time_offset : log_meta . start_time_offset ,
169
+ start_time : log_meta . start_time ,
170
+ } )
153
171
}
172
+ console . log ( "Number of log files:" ) ;
173
+ console . log ( logs . length ) ;
154
174
155
- return data ;
175
+
176
+ // Skip data that doesn't have complete time information:
177
+ logs = logs . filter ( function ( a ) {
178
+ return ! ( a . start_time_offset === null ) ;
179
+ } ) ;
180
+
181
+ // Load the newest data first as that's most likely to be viewed first:
182
+ logs . sort ( function ( a , b ) {
183
+ var a_value = a . start_time_offset + a . start_time ;
184
+ var b_value = b . start_time_offset + b . start_time ;
185
+ return b_value - a_value ;
186
+ } )
187
+
188
+ // Download the data:
189
+ for ( const log of logs ) {
190
+ console . log ( `Downloading ${ log . number } .csv (${ new Date ( log . start_time_offset + log . start_time ) } )` ) ;
191
+
192
+ var response = await fetch ( API_URL + '/data/' + log . number + '.csv' ) ;
193
+ var response_text = await response . text ( ) ;
194
+ yield await processLogResponse ( response_text , log . start_time_offset ) ;
195
+ }
156
196
}
157
197
158
- async function processData ( data , bucketize ) {
198
+ function processData ( data , bucketize ) {
159
199
var buckets = { } ;
160
200
var in_energy = [ ] ;
161
201
var out_energy = [ ] ;
@@ -167,7 +207,7 @@ async function drawPowerUsage(){
167
207
var bucket = bucketize ( time ) ;
168
208
var bucket_value = buckets [ bucket ] ;
169
209
if ( typeof ( bucket_value ) == "undefined" ) {
170
- console . log ( "Initializing bucket " + new Date ( bucket ) ) ;
210
+ // console.log("Initializing bucket " + new Date(bucket));
171
211
bucket_value = { "in" : 0 , "out" : 0 } ;
172
212
buckets [ bucket ] = bucket_value ;
173
213
}
@@ -178,12 +218,10 @@ async function drawPowerUsage(){
178
218
}
179
219
}
180
220
181
- console . log ( buckets ) ;
182
-
183
221
for ( const key of Object . keys ( buckets ) . sort ( ) ) {
184
222
var time = new Date ( Number ( key ) ) ;
185
- in_energy . push ( { x : time , y : buckets [ key ] [ "in" ] } ) ;
186
- out_energy . push ( { x : time , y : - buckets [ key ] [ "out" ] } ) ;
223
+ in_energy . push ( { x : time , y : Math . round ( buckets [ key ] [ "in" ] ) } ) ;
224
+ out_energy . push ( { x : time , y : Math . round ( - buckets [ key ] [ "out" ] ) } ) ;
187
225
}
188
226
189
227
return [ in_energy , out_energy ] ;
@@ -198,66 +236,107 @@ async function drawPowerUsage(){
198
236
return bucket_date . getTime ( ) ;
199
237
}
200
238
201
- var data = await getData ( ) ;
202
- var [ in_energy , out_energy ] = await processData ( data , bucketize_15_min ) ;
239
+ function createChart ( ctx , in_energy , out_energy ) {
240
+ var min_time = new Date ( ) ;
241
+ min_time . setHours ( 0 ) ;
242
+ min_time . setMinutes ( 0 ) ;
243
+ min_time . setSeconds ( 0 ) ;
244
+ min_time . setMilliseconds ( 0 ) ;
203
245
204
- var min_time = new Date ( ) ;
205
- min_time . setHours ( 0 ) ;
206
- min_time . setMinutes ( 0 ) ;
207
- min_time . setSeconds ( 0 ) ;
208
- min_time . setMilliseconds ( 0 ) ;
246
+ var max_time = new Date ( min_time ) ;
247
+ max_time . setDate ( min_time . getDate ( ) + 1 ) ;
209
248
210
- var max_time = new Date ( min_time ) ;
211
- max_time . setDate ( min_time . getDate ( ) + 1 ) ;
212
249
213
- var ctx = document . getElementById ( 'today_power' ) . getContext ( '2d' ) ;
214
- var chart = new Chart ( ctx , {
215
- type : 'bar' ,
216
- data : {
217
- datasets : [ {
218
- label : "In" ,
219
- data : in_energy ,
220
- fill : false ,
221
- borderColor : "blue" ,
222
- backgroundColor : "blue" ,
223
- } , {
224
- label : "Out" ,
225
- data : out_energy ,
226
- fill : false ,
227
- borderColor : "orange" ,
228
- backgroundColor : "orange" ,
229
- } ]
230
- } ,
231
- options : {
232
- scales : {
233
- xAxes : [ {
234
- type : "time" ,
235
- position : "bottom" ,
236
- stacked : true ,
237
- gridLines : {
238
- offsetGridLines : false
239
- } ,
240
- // barThickness: 2,
241
- time : {
242
- unit : 'hour' ,
243
- stepSize : 3 ,
244
- min : min_time ,
245
- max : max_time ,
246
- }
247
- } ] ,
248
- yAxes : [ {
249
- stacked : true ,
250
- scaleLabel : {
251
- display : true ,
252
- labelString : "Energy [Wh]"
253
- } ,
254
- ticks : {
255
- beginAtZero : true
256
- }
250
+ var chart = new Chart ( ctx , {
251
+ type : 'bar' ,
252
+ data : {
253
+ datasets : [ {
254
+ label : "In" ,
255
+ data : [ ] ,
256
+ fill : false ,
257
+ borderColor : "blue" ,
258
+ backgroundColor : "blue" ,
259
+ } , {
260
+ label : "Out" ,
261
+ data : [ ] ,
262
+ fill : false ,
263
+ borderColor : "orange" ,
264
+ backgroundColor : "orange" ,
257
265
} ]
266
+ } ,
267
+ options : {
268
+ scales : {
269
+ xAxes : [ {
270
+ type : "time" ,
271
+ position : "bottom" ,
272
+ stacked : true ,
273
+ gridLines : {
274
+ offsetGridLines : false
275
+ } ,
276
+ time : {
277
+ unit : 'hour' ,
278
+ stepSize : 3 ,
279
+ } ,
280
+ ticks : {
281
+ min : min_time ,
282
+ max : max_time ,
283
+ }
284
+ } ] ,
285
+ yAxes : [ {
286
+ stacked : true ,
287
+ scaleLabel : {
288
+ display : true ,
289
+ labelString : "Energy [Wh]"
290
+ } ,
291
+ ticks : {
292
+ beginAtZero : true
293
+ }
294
+ } ]
295
+ }
296
+ }
297
+ } ) ;
298
+
299
+ energy_chart = chart ;
300
+
301
+ return chart ;
302
+ }
303
+
304
+ function updateDataInPlace ( existing_data , new_data ) {
305
+ for ( const new_value of new_data ) {
306
+ var found = false ;
307
+ for ( var existing_value of existing_data ) {
308
+ if ( existing_value . x . getTime ( ) == new_value . x . getTime ( ) ) {
309
+ found = true ;
310
+ existing_value . y = new_value . y ;
311
+ break ;
312
+ }
313
+ }
314
+ if ( ! found ) {
315
+ existing_data . push ( new_value ) ;
258
316
}
259
317
}
260
- } ) ;
318
+ }
319
+
320
+ function updateChart ( chart , in_energy , out_energy ) {
321
+ updateDataInPlace ( chart . data . datasets [ 0 ] . data , in_energy ) ;
322
+ updateDataInPlace ( chart . data . datasets [ 1 ] . data , out_energy ) ;
323
+ chart . update ( ) ;
324
+ }
325
+
326
+ var ctx = document . getElementById ( 'today_power' ) . getContext ( '2d' ) ;
327
+ var chart = createChart ( ctx ) ;
328
+
329
+ var all_data = [ ] ;
330
+
331
+
332
+ for await ( const data of getData ( ) ) {
333
+ all_data . push ( ...data ) ;
334
+ var [ in_energy , out_energy ] = processData ( all_data , bucketize_15_min ) ;
335
+ updateChart ( chart , in_energy , out_energy )
336
+ }
337
+
338
+ console . log ( "Done updating chart with with all the data!" ) ;
339
+
261
340
}
262
341
263
342
async function drawDiskUsage ( ) {
@@ -303,9 +382,9 @@ async function drawDiskUsage(){
303
382
async function main ( ) {
304
383
// await fetch(API_URL + "/set_time?" + getTimeParameter(), {"method": "POST"});
305
384
306
- await drawRealtime ( ) ;
307
- await drawDiskUsage ( ) ;
308
- await drawPowerUsage ( ) ;
385
+ drawRealtime ( ) ;
386
+ drawDiskUsage ( ) ;
387
+ drawPowerUsage ( ) ;
309
388
}
310
389
311
390
console . log ( 'Loading...' ) ;
0 commit comments