forked from haydendonald/node-red-contrib-panasonicprojector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpanasonicprojector.js
215 lines (194 loc) · 8.06 KB
/
panasonicprojector.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
var crypto = require('crypto');
var debug = require('debug')('node-red-contrib-panasonicprojector');
var tcp = require('net');
var eventEmitter = require("events");
var timeoutPeriod = 1500;
class EventEmitter extends eventEmitter{}
module.exports = function(RED)
{
//Main Function
function PanasonicProjector(config)
{
const emitter = new EventEmitter();
RED.nodes.createNode(this, config);
var projectorId = config.projectorId;
var ipAddress = config.ipAddress;
var port = config.port;
var username = config.username;
var password = config.password;
var server = new tcp.Socket();
var node = this;
var md5Hash;
server.on("close", function()
{
server.destroy();
});
server.on("error", function(error)
{
RED.log.error("Socket Error: " + error);
node.status({fill:"red",shape:"dot",text:"Internal Error, Check Debug"});
msg = {"payload":{}};
msg.payload.response = error;
});
//When a request is received on the input
this.on("input", function(msg) {
if(typeof msg.payload.ipAddress === "string") {
ipAddress = msg.payload.ipAddress;
}
if(typeof msg.payload.port === "string") {
port = msg.payload.port;
}
if(typeof msg.payload.username === "string") {
username = msg.payload.username;
}
if(typeof msg.payload.password === "string") {
password = msg.payload.password;
}
if(typeof msg.payload.projectorId === "string") {
projectorId = msg.payload.projectorId;
}
var done = false;
handShake(server, emitter, ipAddress, port, username, password, function(state, description, md5)
{
switch(state) {
case "handshakesuccess":
md5Hash = md5;
var command = msg.payload.command;
var subcommand = msg.payload.subcommand;
var parameter = msg.payload.parameter;
//Check
if(!command){
node.status({fill:"yellow",shape:"dot",text:"No msg.payload.command Parameter"});
return;
}
if(!parameter){parameter = "";}
//If there is a subcommand
if(subcommand){
var tempParameter = subcommand + "E" + parameter;
sendData(command, tempParameter, server, username, password, projectorId, md5Hash);
}
else {
sendData(command, parameter, server, username, password, projectorId, md5Hash);
}
//Response handler
var handler = function(data) {
var data = getData(data, command);
if(data != "error") {
if(data.includes("ER")){
if(data != "ER401") {
RED.log.error("An Error Occurred: Error Returned " + data);
node.status({fill:"red",shape:"dot",text:"Error: " + data});
}
else {
node.status({fill:"yellow",shape:"dot",text:"Returned Cannot Execute"});
}
}
else {
node.status({fill:"green",shape:"dot",text:"Sent!"});
}
msg.payload.response = data.toString('utf8');
//Return the data and disconnect
server.removeListener("data", handler);
server.destroy();
node.send(msg);
done = true;
}
else {
RED.log.error("An Error Occurred: Unexpected Response");
node.status({fill:"red",shape:"dot",text:"Error: Unexpected Response"});
done = true;
}
};
server.on("data", handler);
//Timeout
setTimeout(function() {
if(!done) {
RED.log.error("An Error Occurred While Waiting For A Response: Timeout");
node.status({fill:"red",shape:"dot",text:"Error: Timeout"});
server.removeListener("data", handler);
server.destroy();
}
}, timeoutPeriod);
}
});
});
}
RED.nodes.registerType("panasonicprojector-panasonicprojector", PanasonicProjector);
}
//Return the data, returns false if failed, true if successful, and data if there is any
function getData(data, expectedCommand)
{
if(!data[0] == 0x30){return false;}
if(!data[1] == 0x30){return false;}
//If there is data return it, else return true
if (data.length - 3 > 0) {
var returnData = new Buffer(data.length - 3);
for(i = 0; i < data.length - 3; i++) {
returnData[i] = data[2 + i];
}
return returnData;
}
else {
return "error";
}
}
//Send the data
function sendData(command, parameter, server, username, password, projectorId, md5Hash)
{
var hashValue = new Buffer(md5Hash);
var start=new Buffer(2);
start.writeUInt8(0x30, 0);
start.writeUInt8(0x30, 1);
/*var start = new Buffer(7);
start.writeUInt8(0x30, 0);
start.writeUInt8(0x30, 1);
start.write("A", 2);
start.write("D", 3);
start.write(projectorId[0].toUpperCase(), 4);
start.write(projectorId[1].toUpperCase(), 5);
start.writeUInt8(0x3b, 6);*/
var commandBuff = new Buffer(command);
var parameterBuff = new Buffer(parameter);
var endBit = new Buffer(1);
endBit.writeUInt8(0x0d, 0);
if(parameter != "") {
var buffer = Buffer.concat([hashValue, start, commandBuff, new Buffer(":"), parameterBuff, endBit]);
}
else {
var buffer = Buffer.concat([hashValue, start, commandBuff, endBit]);
}
server.write(buffer);
}
//Hand shake with the projector
function handShake(server, emitter, ipAddress, port, username, password, callback)
{
server.connect(port, ipAddress);
var processHandshakeData = function(data)
{
//Get in the request, checking that it's correct as well as getting the random number
var randomNumber = new Buffer(8);
if(data[0] != 0x4E){return;}
if(data[1] != 0x54){return;}
if(data[2] != 0x43){return;}
if(data[3] != 0x4F){return;}
if(data[4] != 0x4E){return;}
if(data[5] != 0x54){return;}
if(data[6] != 0x52){return;}
if(data[7] != 0x4F){return;}
if(data[8] != 0x4C){return;}
if(data[9] != 0x20){return;}
if(data[10] != 0x31){return;}
if(data[11] != 0x20){return;}
for(i = 0; i < 8; i++) {
randomNumber.writeInt8(data[12 + i], 0 + i);
}
if(data[20] != 0x0d){return;}
emitter.emit("generate32ByteHash", randomNumber);
}
server.once("data", processHandshakeData);
//Got a correct response, generate and reply
emitter.once("generate32ByteHash", function(randomNumber) {
emitter.emit("connection", "handshakesuccess", "", crypto.createHash('md5').update(username + ":" + password + ":" + randomNumber).digest("hex"));
});
emitter.once("connection", callback);
}