-
Notifications
You must be signed in to change notification settings - Fork 6
/
View_Instrument.cpp
425 lines (343 loc) · 15 KB
/
View_Instrument.cpp
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
// View_Instrument.cpp : implementation file
//
#include "stdafx.h"
#include "NovacMasterProgram.h"
#include "View_Instrument.h"
#include "Configuration/Configuration.h"
extern CConfigurationSetting g_settings;
using namespace Graph;
// CView_Instrument dialog
IMPLEMENT_DYNAMIC(CView_Instrument, CPropertyPage)
CView_Instrument::CView_Instrument()
: CPropertyPage(CView_Instrument::IDD)
{
m_evalDataStorage = nullptr;
m_commDataStorage = nullptr;
}
CView_Instrument::~CView_Instrument()
{
m_evalDataStorage = nullptr;
m_commDataStorage = nullptr;
// Clear the labels
POSITION pos = m_serialLegend.GetHeadPosition();
while (pos != nullptr) {
CLegend* leg = m_serialLegend.GetNext(pos);
delete leg;
}
}
void CView_Instrument::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CView_Instrument, CPropertyPage)
// Messages from other parts of the program
ON_MESSAGE(WM_EVAL_SUCCESS, OnUpdateGraphs)
ON_MESSAGE(WM_EVAL_FAILURE, OnUpdateGraphs)
END_MESSAGE_MAP()
// CView_Instrument message handlers
BOOL CView_Instrument::OnInitDialog()
{
CPropertyPage::OnInitDialog();
CString serialString[50];
CRect thisRect, batteryGraphRect, tempGraphRect, expTimeGraphRect, linkSpeedGraphRect;
CRect labelRect, textRect;
int margin = 4; // the margin between the graphs
int labelWidth = 80; // the width of each label
int labelHeight = 15; // the height of each label
int nSpectrometers = g_settings.scannerNum;
COLORREF colors[] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(255, 255, 0), RGB(255, 0, 255), RGB(0, 255, 255), RGB(0, 0, 255) };
int nColors = 6;
// The size of the window.
this->GetWindowRect(thisRect);
// The legends are arranged in a matrix with up to 'nLegends' in each row
// and as many rows as are needed
const int nLegendsPerRow = 8;
int nRows = 1 + (int)(nSpectrometers / nLegendsPerRow);
// The number of graps;
int nGraphs = 4;
// The height of each graph
int graphHeight = (thisRect.Height() - nRows * labelHeight - margin) / nGraphs - margin;
// Calculate the size of the graphs
batteryGraphRect.left = margin;
batteryGraphRect.right = thisRect.Width() - 2 * margin;
batteryGraphRect.top = margin;
batteryGraphRect.bottom = batteryGraphRect.top + graphHeight;
tempGraphRect.left = margin;
tempGraphRect.right = thisRect.Width() - 2 * margin;
tempGraphRect.top = batteryGraphRect.bottom + margin;
tempGraphRect.bottom = tempGraphRect.top + graphHeight;
expTimeGraphRect.left = margin;
expTimeGraphRect.right = thisRect.Width() - 2 * margin;
expTimeGraphRect.top = tempGraphRect.bottom + margin;
expTimeGraphRect.bottom = expTimeGraphRect.top + graphHeight;
linkSpeedGraphRect.left = margin;
linkSpeedGraphRect.right = thisRect.Width() - 2 * margin;
linkSpeedGraphRect.top = expTimeGraphRect.bottom + margin;
linkSpeedGraphRect.bottom = linkSpeedGraphRect.top + graphHeight;
// The font we want to use
CFont* font = new CFont();
font->CreateFont((int)(16 - 0.2 * nSpectrometers), 0, 0, 0, FW_BOLD,
FALSE, FALSE, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, "Arial");
// Create the graphs
// 1. The battery voltage graph
m_batteryGraph.SetXUnits(m_common.GetString(AXIS_UTCTIME));
m_batteryGraph.HideXScale();
m_batteryGraph.Create(WS_VISIBLE | WS_CHILD, batteryGraphRect, this);
m_batteryGraph.SetFontHeight((int)(14 - 0.3 * nSpectrometers));
m_batteryGraph.SetXAxisNumberFormat(FORMAT_DATETIME);
m_batteryGraph.EnableGridLinesX(true);
m_batteryGraph.SetYUnits("Battery [V]");
m_batteryGraph.SetLineWidth(2); // Increases the line width to 2 pixels
m_batteryGraph.SetMinimumRangeY(1.0);
m_batteryGraph.SetGridColor(RGB(255, 255, 255));
m_batteryGraph.SetBackgroundColor(RGB(0, 0, 0));
//m_batteryGraph.SetRange(0, 24*3600-1, 0, 0, 20, 0);
m_batteryGraph.HideXScale();
SetRange(m_batteryGraph, 20);
// 2. The temperature graph
m_temperatureGraph.SetXUnits(m_common.GetString(AXIS_UTCTIME));
m_temperatureGraph.HideXScale();
m_temperatureGraph.Create(WS_VISIBLE | WS_CHILD, tempGraphRect, this);
m_temperatureGraph.SetFontHeight((int)(14 - 0.3 * nSpectrometers));
m_temperatureGraph.SetXAxisNumberFormat(FORMAT_DATETIME);
m_temperatureGraph.EnableGridLinesX(true);
m_temperatureGraph.SetYUnits("Temp [°C]");
m_temperatureGraph.SetLineWidth(2); // Increases the line width to 2 pixels
m_temperatureGraph.SetMinimumRangeY(1.0);
m_temperatureGraph.SetGridColor(RGB(255, 255, 255));
m_temperatureGraph.SetBackgroundColor(RGB(0, 0, 0));
//m_temperatureGraph.SetRange(0, 24*3600-1, 0, 0, 60, 0);
SetRange(m_temperatureGraph, 60);
// 3. The exposure time graph
m_expTimeGraph.SetXUnits(m_common.GetString(AXIS_UTCTIME));
m_expTimeGraph.HideXScale();
m_expTimeGraph.Create(WS_VISIBLE | WS_CHILD, expTimeGraphRect, this);
m_expTimeGraph.SetFontHeight((int)(14 - 0.3 * nSpectrometers));
m_expTimeGraph.SetXAxisNumberFormat(FORMAT_DATETIME);
m_expTimeGraph.EnableGridLinesX(true);
m_expTimeGraph.SetYUnits("Exp. time [ms]");
m_expTimeGraph.SetLineWidth(2); // Increases the line width to 2 pixels
m_expTimeGraph.SetMinimumRangeY(1.0);
m_expTimeGraph.SetGridColor(RGB(255, 255, 255));
m_expTimeGraph.SetBackgroundColor(RGB(0, 0, 0));
//m_expTimeGraph.SetRange(0, 24*3600-1, 0, 0, 1000, 0);
SetRange(m_expTimeGraph, 1000);
// 4. The data-link speed graph
m_linkSpeedGraph.SetXUnits(m_common.GetString(AXIS_UTCTIME));
m_linkSpeedGraph.Create(WS_VISIBLE | WS_CHILD, linkSpeedGraphRect, this);
m_linkSpeedGraph.SetFontHeight((int)(14 - 0.3 * nSpectrometers));
m_linkSpeedGraph.SetXAxisNumberFormat(FORMAT_DATETIME);
m_linkSpeedGraph.EnableGridLinesX(true);
m_linkSpeedGraph.SetYUnits("Link [kb/s]");
m_linkSpeedGraph.SetLineWidth(2); // Increases the line width to 2 pixels
m_linkSpeedGraph.SetMinimumRangeY(1.0);
m_linkSpeedGraph.SetGridColor(RGB(255, 255, 255));
m_linkSpeedGraph.SetBackgroundColor(RGB(0, 0, 0));
//m_linkSpeedGraph.SetRange(0, 24*3600-1, 0, 0, 1000, 0);
SetRange(m_linkSpeedGraph, 1000);
// if there are no spectrometers then we don't have anything more to do
if (nSpectrometers == 0)
return TRUE;
// Create the legends
for (unsigned int index = 0; index < g_settings.scannerNum; ++index) {
// the size and position of the colored square
labelRect.top = linkSpeedGraphRect.bottom + margin / 2;
labelRect.bottom = labelRect.top + labelHeight;
labelRect.left = linkSpeedGraphRect.left + (index % nLegendsPerRow) * (labelWidth + labelHeight);
labelRect.right = labelRect.left + labelHeight;
// The size and position of the text label containing the serial-number
textRect.top = labelRect.top;
textRect.bottom = labelRect.bottom;
textRect.left = labelRect.right + 2;
textRect.right = textRect.left + labelWidth;
// Create it all...
CLegend* legend = new CLegend();
legend->m_color = colors[index % nColors];
legend->m_serial.Format(g_settings.scanner[index].spec[0].serialNumber);
legend->m_label.Create("", WS_VISIBLE | WS_CHILD | WS_BORDER, labelRect, this);
legend->m_label.SetBackgroundColor(legend->m_color);
legend->m_text.Create(legend->m_serial, WS_VISIBLE | WS_CHILD, textRect, this);
legend->m_text.SetFont(font);
m_serialLegend.AddTail(legend);
}
// Enable the tool tips
if (!m_toolTip.Create(this)) {
TRACE0("Failed to create tooltip control\n");
}
m_toolTip.AddTool(&m_batteryGraph, "Variation in battery voltage of the connected instruments today");
m_toolTip.AddTool(&m_temperatureGraph, "Variation in temperature in the connected instruments today");
m_toolTip.AddTool(&m_expTimeGraph, "Variation in exposure-times of the connected instruments today");
m_toolTip.AddTool(&m_linkSpeedGraph, "The speed of the downloads done today");
m_toolTip.SetMaxTipWidth(INT_MAX);
m_toolTip.Activate(TRUE);
return TRUE; // return TRUE unless you set the focus to a control
}
BOOL CView_Instrument::OnSetActive()
{
// Redraw the screen
DrawGraphs();
return CPropertyPage::OnSetActive();
}
BOOL CView_Instrument::PreTranslateMessage(MSG* pMsg) {
m_toolTip.RelayEvent(pMsg);
return CPropertyPage::PreTranslateMessage(pMsg);
}
LRESULT CView_Instrument::OnUpdateGraphs(WPARAM wParam, LPARAM lParam) {
// Re-draw the screen
DrawGraphs();
return 0;
}
void CView_Instrument::DrawGraphs() {
DrawTempGraph();
DrawBatteryGraph();
DrawExpTimeGraph();
DrawLinkSpeedGraph();
}
/** Draws the temperature graph */
void CView_Instrument::DrawTempGraph() {
const int BUFFER_SIZE = 200;
double timeBuffer[BUFFER_SIZE];
double tempBuffer[BUFFER_SIZE];
CString serialString;
// Clear the plot
m_temperatureGraph.CleanPlot();
SetRange(m_temperatureGraph, 60);
// loop through all double-spectrometers
if (m_serialLegend.GetCount() == 0)
return;
POSITION pos = m_serialLegend.GetHeadPosition();
while (pos != nullptr) {
CLegend* legend = m_serialLegend.GetNext(pos);
// get the serial of the spectrometer
CString& serial = legend->m_serial;
// Get the data
int dataLength = m_evalDataStorage->GetTemperatureData(serial, timeBuffer, tempBuffer, BUFFER_SIZE);
// ---------- Plot the data ------------
// Draw the wind-measurements as function of time
if (0 != dataLength) {
m_temperatureGraph.SetCircleColor(legend->m_color);
m_temperatureGraph.XYPlot(timeBuffer, tempBuffer, dataLength, CGraphCtrl::PLOT_CIRCLES | CGraphCtrl::PLOT_FIXED_AXIS);
}
}
}
/** Draws the battery-voltage graph */
void CView_Instrument::DrawBatteryGraph() {
const int BUFFER_SIZE = 200;
double timeBuffer[BUFFER_SIZE];
double batteryBuffer[BUFFER_SIZE];
CString serialString;
// Clear the plot
m_batteryGraph.CleanPlot();
SetRange(m_batteryGraph, 20);
// loop through all double-spectrometers
POSITION pos = m_serialLegend.GetHeadPosition();
while (pos != nullptr) {
CLegend* legend = m_serialLegend.GetNext(pos);
// get the serial of the spectrometer
CString& serial = legend->m_serial;
// Get the data
int dataLength = m_evalDataStorage->GetBatteryVoltageData(serial, timeBuffer, batteryBuffer, BUFFER_SIZE);
// ---------- Plot the data ------------
// Draw the wind-measurements as function of time
if (0 != dataLength) {
m_batteryGraph.SetCircleColor(legend->m_color);
m_batteryGraph.XYPlot(timeBuffer, batteryBuffer, dataLength, CGraphCtrl::PLOT_FIXED_AXIS | CGraphCtrl::PLOT_CIRCLES);
}
}
}
/** Draws the exposure-time graph */
void CView_Instrument::DrawExpTimeGraph() {
const int BUFFER_SIZE = 200;
double timeBuffer[BUFFER_SIZE];
double expTimeBuffer[BUFFER_SIZE];
CString serialString;
// Clear the plot
m_expTimeGraph.CleanPlot();
SetRange(m_expTimeGraph, 1000);
// loop through all double-spectrometers
POSITION pos = m_serialLegend.GetHeadPosition();
while (pos != nullptr) {
CLegend* legend = m_serialLegend.GetNext(pos);
// get the serial of the spectrometer
CString& serial = legend->m_serial;
// Get the data
int dataLength = m_evalDataStorage->GetExposureTimeData(serial, timeBuffer, expTimeBuffer, BUFFER_SIZE);
// ---------- Plot the data ------------
// Draw the wind-measurements as function of time
if (0 != dataLength) {
m_expTimeGraph.SetCircleColor(legend->m_color);
m_expTimeGraph.XYPlot(timeBuffer, expTimeBuffer, dataLength, CGraphCtrl::PLOT_FIXED_AXIS | CGraphCtrl::PLOT_CIRCLES);
}
}
}
/** Draws the link-speed graph */
void CView_Instrument::DrawLinkSpeedGraph() {
const int BUFFER_SIZE = 1024;
double* timeBuffer = new double[BUFFER_SIZE];
double* linkSpeed = new double[BUFFER_SIZE];
double divisor = 1.0;
CString serialString;
int dataLength;
// Clear the plot
m_linkSpeedGraph.CleanPlot();
// First find the range for the graph
double maxDataRate = 1.0; //kb/s
POSITION pos = m_serialLegend.GetHeadPosition();
while (pos != nullptr) {
CLegend* legend = m_serialLegend.GetNext(pos);
// get the serial of the spectrometer
CString& serial = legend->m_serial;
// Get the data
dataLength = this->m_commDataStorage->GetLinkSpeedData(serial, timeBuffer, linkSpeed, BUFFER_SIZE);
maxDataRate = max(maxDataRate, Max(linkSpeed, dataLength));
}
maxDataRate = 2 * ceil(maxDataRate / 2); // to make the max-rate a factor of two...
// decide on a unit...
if (maxDataRate > 1024) {
// Mb/s
divisor = 1024.0;
m_linkSpeedGraph.SetYUnits("Link [MB/s]");
}
else {
m_linkSpeedGraph.SetYUnits("Link [kB/s]");
}
maxDataRate /= divisor;
//m_linkSpeedGraph.SetRangeY(0, maxDataRate, 0);
SetRange(m_linkSpeedGraph, maxDataRate + 5);
// loop through all spectrometers
pos = m_serialLegend.GetHeadPosition();
while (pos != nullptr) {
CLegend* legend = m_serialLegend.GetNext(pos);
// get the serial of the spectrometer
CString& serial = legend->m_serial;
// Get the data
int dataLength = this->m_commDataStorage->GetLinkSpeedData(serial, timeBuffer, linkSpeed, BUFFER_SIZE);
// Shold we scale to MB/s?
if (divisor > 1.5) {
for (int k = 0; k < dataLength; ++k) {
linkSpeed[k] /= divisor;
}
}
// ---------- Plot the data ------------
// Draw the wind-measurements as function of time
if (0 != dataLength) {
m_linkSpeedGraph.SetCircleColor(legend->m_color);
m_linkSpeedGraph.XYPlot(timeBuffer, linkSpeed, dataLength, CGraphCtrl::PLOT_FIXED_AXIS | CGraphCtrl::PLOT_CIRCLES);
}
}
delete[] timeBuffer;
delete[] linkSpeed;
}
void CView_Instrument::SetRange(Graph::CGraphCtrl& graph, int maxy) {
struct tm* tm;
time_t t;
time(&t);
tm = gmtime(&t);
time_t endtime = t;
time_t starttime = endtime - 86400;
graph.SetRange(starttime, endtime, 0, 0, maxy, 0);
}