-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathMessage.js
113 lines (89 loc) · 3.05 KB
/
Message.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
const crc = require('crc');
const { MESSAGE_OFFSET } = require('./const');
class Message {
setCheckSum() {
const checksum = crc.crc16xmodem(this.data.slice(0x64));
this.data.writeUInt32BE(checksum, MESSAGE_OFFSET.CHECK_SUM);
}
encrypt() {
if (this.body.length === 0 || !this.device) {
return;
}
const password = Buffer.allocUnsafe(20);
const mac = this.device.mac.split(':');
for (let i=0; i<password.length; i++) {
password.writeUInt8(parseInt(mac[i % mac.length], 16), i);
}
this.body.forEach((v, i) => this.data.writeUInt8(v ^ password.readUInt8(i % password.length), i + MESSAGE_OFFSET.BODY));
}
decrypt() {
this.encrypt();
}
getRequestSN() {
return this.data.readInt32BE(MESSAGE_OFFSET.REQ_SERIAL_NUM);
}
getResponseSN() {
return this.data.readInt32BE(MESSAGE_OFFSET.RES_SERIAL_NUM);
}
toBuffer() {
return this.data;
}
}
function dataToBuffer(data) {
if (data instanceof Buffer) {
return data;
} else if (Array.isArray(data)) {
return Buffer.from(data);
} else if (typeof data === 'number') {
let buf;
if (data < 0x100) {
buf = Buffer.allocUnsafe(1);
buf.writeUInt8(data, 0);
} else if (data < 0x10000) {
buf = Buffer.allocUnsafe(2);
buf.writeUInt16BE(data, 0);
} else {
buf = Buffer.allocUnsafe(4);
buf.writeUInt32BE(data, 0);
}
return buf;
} else {
return Buffer.alloc(0);
}
}
Message.build = function(messageType, body = null, device = null) {
const message = new Message();
message.body = dataToBuffer(body);
message.device = device;
message.messageType = messageType;
message.data = Buffer.alloc(MESSAGE_OFFSET.BODY + message.body.length);
message.sn = Math.floor(Math.random() * 1000 + 1);
message.data.writeUInt32BE(0x3f2, MESSAGE_OFFSET.L2_TYPE);
message.data.writeUInt32BE(0x2775, MESSAGE_OFFSET.L3_VERSION);
message.data.writeUInt32BE(0x1, MESSAGE_OFFSET.L3_ID);
message.data.writeUInt32BE(0x2, MESSAGE_OFFSET.OFFSET);
message.data.writeUInt32BE(0x3, MESSAGE_OFFSET.TTL);
message.data.writeUInt32BE(0x5, MESSAGE_OFFSET.L3_CHECKSUM);
message.data.writeUInt32BE(0x1, MESSAGE_OFFSET.DEST_OBJ_TYPE);
message.data.writeUInt32BE(0x6A68, MESSAGE_OFFSET.SRC_ID);
if (message.device) {
message.data.writeUInt32BE(message.device.localPort, MESSAGE_OFFSET.DEST_PORT);
message.data.writeUInt32BE(message.device.id, MESSAGE_OFFSET.DEST_ID);
}
message.data.writeUInt32BE(message.sn, MESSAGE_OFFSET.REQ_SERIAL_NUM);
message.data.writeUInt32BE(message.messageType, MESSAGE_OFFSET.MSG_TYPE);
message.data.writeUInt32BE(message.body.length + 0x68, MESSAGE_OFFSET.PKG_LENGTH);
message.data.writeUInt32BE(message.body.length + 0x18, MESSAGE_OFFSET.MSG_LENGTH);
message.body.copy(message.data, MESSAGE_OFFSET.BODY);
message.setCheckSum();
message.encrypt();
return message;
};
Message.from = function(data) {
const message = new Message();
message.data = data;
message.body = data.slice(MESSAGE_OFFSET.BODY);
message.decrypt();
return message;
};
module.exports = Message;