-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
119 lines (98 loc) · 3.73 KB
/
app.js
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
const express = require('express');
const app = express();
const httpServer = require('http').Server(app);
const io = require('socket.io')(httpServer);
const mqtt = require('mqtt');
const config = require('./config');
const realtimeRouter = require('./routes/realtime');
const historyRouter = require('./routes/history');
const brokerURL = `mqtt://${config.mqtt.host}:${config.mqtt.port}`;
Array.prototype.flat = function (depth = 1) {
return this.reduce(function (flat, toFlatten) {
return flat.concat((Array.isArray(toFlatten) && (depth - 1)) ? toFlatten.flat(depth - 1) : toFlatten);
}, []);
}
Object.prototype.getNestedPropertyValue = function (property) {
return property.split('.').reduce((a, b) => a[b], this);
}
let charts = [];
config.visuals.charts.forEach((chart, i) => {
charts.push({
id: i,
fieldsOfData: chart.fieldsOfData,
type: chart.chartOptions.type,
maxNumberOfPoints: chart.chartOptions.maxNumberOfPoints,
options: { ...config.visuals.globalChartOptions, ...chart.chartOptions.options },
measurementsOfDevices: {}
});
});
let mqttClient = mqtt.connect(brokerURL, {
clientId: config.mqtt.clientId,
username: config.mqtt.username,
password: config.mqtt.password
});
mqttClient.on('error', (error) => console.error(error));
mqttClient.on('close', () => console.log('Disconnecting from mqtt broker'));
mqttClient.on('reconnect', () => console.log('Reconnecting to mqtt broker'));
mqttClient.on('connect', (connack) => {
console.log(`Connected to mqtt broker on url ${brokerURL}`);
mqttClient.subscribe(config.mqtt.topic, (err, granted) => {
if (err) console.error(err);
console.log(`Subscribed to ${config.mqtt.topic}`);
});
});
mqttClient.on('message', (topic, message) => {
const json = JSON.parse(message.toString());
charts.forEach((chart) => {
for (const field of chart.fieldsOfData) {
const value = json.getNestedPropertyValue(field);
if (!isNaN(value)) {
const device = json.deviceId || 'Default device';
chart.measurementsOfDevices[device] = [value];
io.emit('data', {
id: chart.id,
date: json.date || new Date(),
measurementsOfDevices: chart.measurementsOfDevices
});
break;
}
};
});
});
app.set('view engine', 'ejs');
app.set('config', config)
app.set('charts', charts);
app.use(express.static('public'));
app.use('/', realtimeRouter);
app.use('/history', historyRouter);
app.get('/scripts/chart.js', (req, res) => res.status(200).sendFile(`${__dirname}/node_modules/chart.js/dist/Chart.bundle.min.js`));
app.get('/scripts/palette.js', (req, res) => res.status(200).sendFile(`${__dirname}/node_modules/google-palette/palette.js`));
app.get('/chartoptions/:id', (req, res) => {
let id = parseInt(req.params.id);
let chart = charts.find((c) => c.id === id);
if (chart) {
res.status(200).json({
type: chart.type,
maxNumberOfPoints: chart.maxNumberOfPoints,
options: chart.options
});
} else {
res.status(404).end();
}
});
// app.use((req, res) => {
// res.redirect('/');
// });
httpServer.listen(config.port, () => {
console.log(`IoTDataVisualizer is running on port ${config.port}!`);
});
process.on('SIGUSR1', () => process.exit());
process.on('SIGUSR2', () => process.exit());
process.on('SIGINT', () => process.exit());
process.on('exit', () => {
Promise.all([
new Promise((resolve) => io.close(resolve)),
new Promise((resolve) => httpServer.close(resolve)),
new Promise((resolve) => mqttClient.end(undefined, resolve))
]);
});