I've a problem with my application using node.js. I've wrote a little application that allow the comunication between a web page and a PLC. The communication with the web page is based on socket.io, the communication with PLC is based on net.createConnection.
My application receive a command from the web page, then it creates the message with a standard fetch/write protocol and sent those message to the PLC. The PLC response is based on the F/W protocol too, when the response message is received from my application it should decode and sent only few information to the web page.
All the process is working but I see that after every operation (not important if fetch or write) the message from the PLC is replicated one more time. For example:
Fetch operation -> Response: Data
Fetch operation -> Response: Data Data
Fetch operation -> Response: Data Data Data
...
I've used wireshark to check if this is a PLC problem but the message is correct and is only one. I think there's a problem with node.js buffer or something like that.
Any suggestion?
Here's the code:
/***
Fetch-Write protocol in Node.js
Massimo Milluzzo - [email protected]
***/
// Packages needed
var httpd = require('http').createServer(handler);
var io = require('socket.io').listen(httpd);
var fs = require('fs');
var net = require('net');
// Connection variables
var host = "192.168.0.220"; // Ip of PLC
var port = 2002; // Port for the comunication with PLC
httpd.listen(4000); // Listening the browser on port 4000
var conn = null; // Manage the connection
var message = null; // Message
// Manage HTML request
function handler(req, res) {
fs.readFile(__dirname + '/index.html',
function(err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
}
);
}
// When is created the connection of the socket
io.sockets.on('connection', function (socket) {
console.log('connected');
// Test function
socket.on('message', function(content) {
console.log(content);
socket.emit('serverMessage', 'I\'m here');
});
// Need to write -> set the message
socket.on('write', function(content){
// See fetch-write protocol documentation
message = new Uint8Array([83,53,16,1,3,3,3,8,0x01,content[0],0,content[1],0,content[2],255,2,0,content[3]]);
connect(content);
});
socket.on('fetch', function(content) {
// See fetch-write protocol documentation
message = new Uint8Array([83,53,16,1,3,5,3,8,0x01,content[0],0,content[1],0,content[2],255,2]);
connect(content);
});
// Main function for the communication with PLC
function connect(content){
// Console writing
console.log(content);
socket.emit('serverMessage', 'Message received...try to comunicate with PLC');
// If there isn't a connection create one
if(conn == null)
conn = net.createConnection(port,host);
// If gets an error print it
conn.on('error', function(err) {
console.log('Error in connection:', err);
socket.emit('error',""+err);
});
// On connection close write it
conn.on('close', function() {
console.log('connection got closed');
socket.emit('serverMessage','connection got closed');
});
// When data is received decode the message
conn.on('data', function(data) {
console.log('some data has arrived:', ""+data);
// See fetch-write protocol documentation
if((data[0] == 0x53) &&
(data[1] == 0x35) &&
(data[2] == 0x10) &&
(data[3] == 0x01) &&
(data[4] == 0x03) &&
((data[5] == 0x06) || (data[5] == 0x04)) && // 06: fetch | 04: write
(data[6] == 0x0F) &&
(data[7] == 0x03) &&
((data[8] == 0x00) || (data[8] == 0x02) || (data[8] == 0x03) || (data[8] == 0x06)) && // Error code, see fetch-write protocol documentation
(data[9] == 0xFF) &&
(data[10] == 0x07))
{
switch(data[8]){
// No error
case 0x00:
// Fetch
if(data[5] == 0x06){
// Get the response of PLC
var i;
var mex = "";
for(i = 16; i<data.length; i=i+2){
mex = mex + "[" + data[i].toString(16) + " " + data[i+1].toString(16) + "]";
}
// Write it
socket.emit('serverMessage','Value read: ' + mex);
mex = "";
}
// Write
else if(data[5] == 0x06){
socket.emit('serverMessage','PLC updated');
}
break;
// Error 02: Requested block does not exist
case 0x02:
socket.emit('error','Requested block does not exist');
break;
// Error 03: Requested block is to small
case 0x03:
socket.emit('error','Requested block is to small');
break;
// Error 06: No valid ORG ID
case 0x06:
socket.emit('error','No valid ORG ID');
break;
// Any other code, warning because not exist in the protocol
default:
var temp = ""+data[8];
socket.emit('error','Unknown error ID ['+temp+']');
break;
}
}
// The message doesn't correspond to the Fetch/Write protocol
else{
socket.emit('error','Error while talking with PLC');
}
data = "";
});
// Write the client message on the socket
conn.write(new Buffer(message,'ascii'), function() {
console.log('data was written out');
socket.emit('serverMessage','data was written out');
});
}
});
!!! Update !!!
I've made some other tests, the result is that there isn't a real enqueue of the messages, the result of the tests are:
Data
Data1 Data1
Data Data Data
Data2 Data2 Data2 Data2
Data3 Data3 Data3 Data3 Data3
Data1 Data1 Data1 Data1 Data1 Data1
and so on
Solved
Finally, I found a solution and it is pretty simple: the problem was that every time there was an operation, a new "data" listener was added.
To avoid this, I had to change the code from:
conn.on('data', function(data) {
...
}
to:
conn.once('data', function(data) {
...
}