我使用node.js的应用程序出了问题。 我写了一个小应用程序,允许网页和PLC之间的通信。 与网页的通信基于socket.io,与PLC的通信基于net.createConnection。
我的应用程序从网页接收命令,然后使用标准的提取/写入协议创建消息并将这些消息发送到PLC。 PLC响应也基于F / W协议,当从我的应用程序收到响应消息时,它应解码并仅向网页发送少量信息。
所有过程都在运行但我看到每次操作后(如果获取或写入都不重要),来自PLC的消息将再次被复制。 例如:
Fetch operation -> Response: Data
Fetch operation -> Response: Data Data
Fetch operation -> Response: Data Data Data
...
我已经使用wireshark检查这是否是PLC问题,但消息是正确的,只有一个。 我认为node.js缓冲区存在问题或类似的问题。
有什么建议吗?
以下是代码:
/***
Fetch-Write protocol in Node.js
Massimo Milluzzo - massimo.milluzzo@gmail.com
***/
// 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');
});
}
});
!!!更新!!!
我做了一些其他测试,结果是没有真正的消息队列,测试的结果是:
Data
Data1 Data1
Data Data Data
Data2 Data2 Data2 Data2
Data3 Data3 Data3 Data3 Data3
Data1 Data1 Data1 Data1 Data1 Data1
等等
答案 0 :(得分:0)
<强>解决强>
最后,我找到了一个解决方案并且非常简单:问题是每次有操作时,都会添加 new “data”监听器。
为了避免这种情况,我不得不改变代码:
conn.on('data', function(data) {
...
}
为:
conn.once('data', function(data) {
...
}