-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
466 lines (357 loc) · 16 KB
/
server.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
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
// /////////////////////////THIẾT LẬP KẾT NỐI WEB/////////////////////////
var express = require("express"); //gọi thư viện express
var app = express(); //gọi ứng dụng express
var mqtt = require('mqtt')
/////////////////////////app login
const bcrypt = require('bcrypt')
const passport = require('passport')
const flash = require('express-flash')
const session = require('express-session')
const methodOverride = require('method-override')
/////////////////////////
app.use(express.static("public")); // pulic thư viện express
app.set("view engine", "ejs"); //gọi file ejs (đã tạo home.ejs) , // để có thể sử dụng cú pháp của ejs ( {name: 'K_zyred'} => <%= name %> )
app.set("views", "./views"); // gọi thư mục view đã tạo
var server = require("http").Server(app); // gọi liên kết kết nối dạng http
var io = require("socket.io")(server); // gọi chương trình đọc dữ liệu theo thời gian thực socket.io
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
///////////////////////////////LOGIN/////////////////////////////////////////////
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}
///////////////////////
const initializePassport = require('./passport-config')
initializePassport(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
)
const users = [] // biến toàn cục lưu user người dùng
users.push({ // đẩy thông tin vào mảng user đăng nhập
id: "1",
name: "admin",
email: "[email protected]", // lấy được email đã đăng kí từ thẻ cha (register) phải dùng app.use(express.urlencoded({ extended: false }))
password: "admin"
},
{ // đẩy thông tin vào mảng user đăng nhập
id: "2",
name: "1@1",
email: "1@1", // lấy được email đã đăng kí từ thẻ cha (register) phải dùng app.use(express.urlencoded({ extended: false }))
password: "admin"
},
)
// For parsing application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: false }))
app.use(flash())
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))
/////////////////////////////////////////////////////////////////////////////
app.get('/', checkAuthenticated, (req, res) => {
res.render('home.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/tramTQ', checkAuthenticated, (req, res) => {
res.render('3DtramTQ.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/dashBoard', checkAuthenticated, (req, res) => {
res.render('dashBoard.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/tram1', checkAuthenticated, (req, res) => {
res.render('tram1.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/tram2', checkAuthenticated, (req, res) => {
res.render('tram2.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/tram3', checkAuthenticated, (req, res) => {
res.render('tram3.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/CSDL', checkAuthenticated, (req, res) => {
res.render('CSDL.ejs', { name: req.user.name })
})
/////////////////////////////////////////////////////////////////////////////
app.get('/login', checkNotAuthenticated, (req, res) => {
res.render('login.ejs')
})
app.post('/login', checkNotAuthenticated, passport.authenticate('local', {
successRedirect: '/', //thỏa mãn về trang / home
failureRedirect: '/login', // không thỏa mãn thì ở lại trang login
failureFlash: true
}))
/////////////////////////////////////////////////////////////////////////////
app.get('/register', checkNotAuthenticated, (req, res) => {
res.render('register.ejs')
})
app.post('/register', checkNotAuthenticated, async (req, res) => {
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10) // 10 biểu thị độ mạnh của lần quy đổi mảng băm
users.push({ // đẩy thông tin vào mảng user đăng nhập
id: Date.now().toString(),
name: req.body.name,
email: req.body.email, // lấy được email đã đăng kí từ thẻ cha (register) phải dùng app.use(express.urlencoded({ extended: false }))
password: hashedPassword
})
res.redirect('/login') // hàm chuyển hướng đến login
} catch {
res.redirect('/register') // chẳng may gặp lỗi chuyển lại trang đăng kí
}
console.log(users)
})
/////////////////////////////////////////////////////////////////////////////
app.delete('/logout', (req, res, next) => {
req.logOut((err) => {
if (err) {
return next(err);
}
res.redirect('/login');
});
});
/////////////////////////////////////////////////////////////////////////////
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next()
}
res.redirect('/login')
}
function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/')
}
next()
}
// Port that the web server should listen on
var port = process.env.PORT || 3000;
server.listen(port); // cổng này phải giống cổng lên home.ejs // var socket = io("http://192.168.0.1:3000")
///////////////////////////////LOGIN/////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
///////////////////////////////MQTT/////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Chúng ta cần xử lý các ký tự đại diện tương ứng như topic, vì vậy không thể chỉ so sánh đơn giản
// Hàm này trả về true nếu chúng khớp nhau và false nếu không
// topic1 có thể bao gồm các ký tự ...và topic2 không thể
var topicMatch = function (topic1, topic2) {
// Switch our wildcards from MQTT style to Regexp style
var matchStr = topic1.replace(/#/g, ".*")
return (topic2.match("^" + matchStr + "$") != null)
}
// tùy chọn kết nối với Broker
var options = {
// Clean session
clean: true,
connectTimeout: 4000,
host: process.env.host_MQTT,
port: 8883,
protocol: 'mqtts',
username: process.env.username_MQTT,
password: process.env.password_MQTT,
clientId: 'AAA++++++++'
}
// thiết lập kết nối với Broker
var client = mqtt.connect(options);
// nếu kết nối thành công
client.on('connect', function () {
console.log('Connected_MQTT');
});
client.on('error', function (error) {
console.log(error);
});
// kết nối với topic,... trả ra payload
client.on('message', function (topic, payload) {
// console.log("topic: "+topic)
// console.log("payload: "+payload)
// Gửi nó đến bất kỳ socket nào đang theo dõi hoặc quan tâm
// như vậy là gõ # thì nó nhận tất cả cá topic
// gõ bất kì thì chỉ nhận từ topic đó thôi
// lưu ý ấn ctrl+S để reset
Object.keys(io.sockets.adapter.rooms).map(function (room_name) {
// Xem phòng (socket room) này có phù hợp với topic đã đề nghị theo dõi ko
if (topicMatch(room_name, topic)) {
// Nếu có. Gửi tin nhắn (server)->client
for (var clientId in io.sockets.adapter.rooms[room_name].sockets) {
//emit mqtt
io.sockets.connected[clientId].emit('mqtt', { 'topic': topic, 'payload': payload.toString() })
}
}
})
});
////////////////////////////////////////////////////////////////////////
// thiết lập các bản tin client và server trao đổi khi muốn server public hoặc subscribe
io.sockets.on('connection', function (sock) {
// New connection, listen for...
console.log("New connection from " + sock.id) //sock.id
// ...subscribe messages
sock.on('subscribe', function (msg) {
console.log("Asked to subscribe to " + msg.topic)
if (msg.topic !== undefined) {
sock.join(msg.topic)
if (io.sockets.adapter.rooms[msg.topic].length == 1) {
//// Máy đầu là người đầu tiên trong phòng, đăng ký topic MQTT
client.subscribe(msg.topic)
}
//// nếu có máy khác đã ở đây, vì vậy chúng tôi sẽ có đăng ký MQTT rồi
}
//////////////////////////////////
//////////////////////////////////
//////////////////////////////////
//////////////////////////////////
// FIXME else It'd be nice to report the error back to the user
//// FIXME other Sẽ rất tốt nếu báo lỗi lại cho người dùng rằng đã có máy đang dùng rồi
//////////////////////////////////
//////////////////////////////////
//////////////////////////////////
//////////////////////////////////
})
// ...publish messages
sock.on('publish', function (msg) {
console.log("socket published [" + msg.topic + "] >>" + msg.payload + "<<")
client.publish(msg.topic, msg.payload)
})
// ...and disconnections
sock.on('disconnect', function (reason) {
console.log("disconnect from " + sock.id)
// socket sẽ rời khỏi tất cả các phòng của nó bây giờ, vì vậy hãy xem liệu có
// là bất kỳ cái phòng trống nào (hủy kết nối khi cảm thấy phòng chống)
for (var sub in client._resubscribeTopics) {
if (io.sockets.adapter.rooms[sub] == undefined) {
// Không có "phòng" cho đăng ký này,
// vì vậy không có khách hàng đang xem nên hủy đăng ký
console.log("Unsubscribing from " + sub)
client.unsubscribe(sub)
}
// nếu người khác đang xem, vì vậy vẫn subscribe MQTT này
}
})
})
///////////////////////////////MQTT/////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Khai báo SQL
var mysql = require('mysql');
var sqlcon
// var tableName = "PLC_thuc"
var tableName = process.env.tableName
function handleDisconnect() {
sqlcon = mysql.createConnection({
host: process.env.host_SQL,
user: process.env.user_SQL,
password: process.env.password_SQL,
database: process.env.database_SQL,
dateStrings: true
}) // Recreate the connection, since
// the old one cannot be reused.
sqlcon.connect(function (err) { // The server is either down
if (err) { // or restarting (takes a while sometimes).
console.log('error when connecting to db:', err);
setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
} // to avoid a hot loop, and to allow our node script to
console.log("Connected DB!");
}); // process asynchronous requests in the meantime.
// If you're also serving http, display a 503 error.
sqlcon.on('error', function (err) {
console.log('db error', err);
if (err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
handleDisconnect(); // lost due to either server restart, or a
} else { // connnection idle timeout (the wait_timeout
throw err; // server variable configures this)
}
});
sqlcon.on('end', function () {
console.log('end My SQL server connection');
});
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
handleDisconnect();
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// reload dữ liệu
io.on("connection", function (socket) {
socket.on("reConnect_mySQL", function (data) {
sqlcon.end()
handleDisconnect();
console.log("hi reconnect DB!")
socket.emit('reConnect_mySQL_toClient', "true");
});
});
// Đọc dữ liệu từ SQL
io.on("connection", function (socket) {
socket.on("msg_SQL_Show", function (data) {
var sqltable_Name = tableName;
var query = "SELECT * FROM " + sqltable_Name + ";"
sqlcon.query(query, function (err, results, fields) {
if (err) {
console.log(err);
} else {
const objectifyRawPacket = row => ({ ...row });
const convertedResponse = results.map(objectifyRawPacket);
socket.emit('SQL_Show', convertedResponse);
}
});
});
});
// Tìm kiếm dữ liệu SQL theo khoảng thời gian
io.on("connection", function (socket) {
socket.on("msg_SQL_ByTime", function (data) {
var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset time Việt Nam (GMT7+)
// var tzoffset = (new Date()).getTimezoneOffset() * 0; //offset time Việt Nam (GMT7+)
// Lấy thời gian tìm kiếm từ date time piker
var timeS = new Date(data[0]); // Thời gian bắt đầu
var timeE = new Date(data[1]); // Thời gian kết thúc
// Quy đổi thời gian ra định dạng cua MySQL
var timeS1 = "'" + (new Date(timeS - tzoffset)).toISOString().slice(0, -1).replace("T", " ") + "'";
var timeE1 = "'" + (new Date(timeE - tzoffset)).toISOString().slice(0, -1).replace("T", " ") + "'";
var timeR = timeS1 + "AND" + timeE1; // Khoảng thời gian tìm kiếm (Time Range)
var sqltable_Name = tableName; // Tên bảng
var dt_col_Name = "_TIMESTAMP"; // Tên cột thời gian
var Query1 = "SELECT * FROM " + sqltable_Name + " WHERE " + dt_col_Name + " BETWEEN ";
var Query = Query1 + timeR + ";";
sqlcon.query(Query, function (err, results, fields) {
if (err) {
console.log(err);
} else {
const objectifyRawPacket = row => ({ ...row });
const convertedResponse = results.map(objectifyRawPacket);
socket.emit('SQL_ByTime', convertedResponse);
}
});
});
});
// Tìm kiếm dữ liệu SQL theo _NAME và _VALUE
io.on("connection", function (socket) {
socket.on("msg_SQL_By_NAME_VALUE", async function (data) {
var sqltable_Name = tableName; // Tên bảng
var tram1 = `'TCP_IP_tram.tramChu.Tram01_CBXLDay','TCP_IP_tram.tramChu.Tram01_CBXLThu','TCP_IP_tram.tramChu.Tram01_CBHTNhaPhoi','TCP_IP_tram.tramChu.Tram01_CBHTVTHutPhoi'`
var tram2 = `'TCP_IP_tram.tram2.Tram02_CbXLDuoi','TCP_IP_tram.tram2.Tram02_CbXLtren','TCP_IP_tram.tram2.Tram02_XLDanPhoi','TCP_IP_tram.tram2.Tram02_XLDay'`
var tram3 = `'TCP_IP_tram.tramChu.tram03_KhoanDiXuong','TCP_IP_tram.tramChu.Tram03_DapPhoi','TCP_IP_tram.tramChu.Tram03_GatPhoi','TCP_IP_tram.tramChu.Tram03_KepPhoi','TCP_IP_tram.tramChu.Tram03_BanXoay'`
var _Group_Names = `(${tram1},${tram2},${tram3})`; // Tên cột thời gian
var Query = "Select _NAME,COUNT(_NAME) From " + sqltable_Name + " Where _NAME in " + _Group_Names + " Group by _NAME,_VALUE HAVING _VALUE = 0; ";
await sqlcon.query(Query, function (err, results, fields) {
if (err) {
console.log(err);
} else {
const objectifyRawPacket = row => ({ ...row });
const convertedResponse = results.map(objectifyRawPacket);
socket.emit('SQL_By_NAME_VALUE', convertedResponse);
}
});
});
});