1

我的应用程序使用 node.js 时遇到问题。我编写了一个小应用程序,允许网页和 PLC 之间的通信。与web页面的通信基于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

等等

4

1 回答 1

0

解决了

最后,我找到了一个解决方案,而且非常简单:问题是每次有操作时,都会添加一个的“数据”监听器。

为避免这种情况,我不得不将代码更改为:

conn.on('data', function(data) {
    ...
}

到:

conn.once('data', function(data) {
    ...
}
于 2013-01-23T09:21:29.423 回答