UNPKG

node-red-contrib-hasskit

Version:

hasskit for node-red

197 lines (181 loc) 5.27 kB
"use strict"; /* var events = require("events"); var EventEmitter = events.EventEmitter || events; */ var net = require("net"); const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); const Lock = require('async-lock') /** * Simulate a modbus-RTU port using TCP connection * @module TcpRTUBufferedPort * * @param {string} ip - ip address * @constructor */ class TcpBufferedPort { constructor(ip, port,node, timeout) { this.openFlag = false; this.callback = null; this.timeout = timeout this.heartbeatInterval = 0 this.heartbeatTime = 120000 //心跳间隔 this.heartbeatPack = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00]) //心跳包 this._client = null this._onData = [] this._onError = null this._onConnect = null this._onClose = null this.node = node this.reconnectTime = 0 this.lock = new Lock() this.connectOptions = { host: ip || "", port: port || 8666, }; } get isOpen() { return this.openFlag; } /** * 消息回调 */ set onData(cb) { this._onData.push(cb) } set onClose(cb) { this._onClose = cb } set onConnect(cb) { this._onConnect = cb } set onError(cb) { this._onError = cb } write_lock(data) { let self = this self.lock.acquire('key', function (done) { self.write(data,function(){ setTimeout(done,25); }) }, function () { }) } _listener() { var self = this; this._client = new net.Socket(); var handleCallback = function (had_error) { if (self.callback) { self.callback(had_error); self.callback = null; } }; this._client.on('data', function (data) { for(let it of self._onData){ it[0].call(it[1],data) } }) if (this.timeout) this._client.setTimeout(this.timeout); this._client.on("connect", function () { self.openFlag = true; handleCallback(); if (self._onConnect) self._onConnect() }); this._client.on("close", function (had_error) { self.openFlag = false; handleCallback(had_error); if (self._onClose) self._onClose() }); this._client.on("error", function (had_error) { self.openFlag = false; handleCallback(had_error); if (self._onError) self._onError() }); this._client.on("timeout", function () { handleCallback(new Error("TcpRTUBufferedPort Connection Timed Out")); }); } /** * TCP心跳方法 * @param {*} dev */ _heartbeat() { let self = this this.heartbeatInterval = setInterval(() => { self.write(self.heartbeatPack) }, this.heartbeatTime); } /** * 重连方法 * @param {*} */ async reconnect() { let self = this this.close() await sleep(1000) if (!self.isOpen) self.connect() } connect() { let self = this this._listener() // this._onData = [] //console.log(self.node.__proto__) this.open(function (err) { if (!err) { //self.node.('TCP连接成功') self.node.error('TCP连接成功') self._heartbeat()//心跳启动 } else { self.node.error("TCP连接错误") self.reconnectTime = setTimeout(() => { self.close() self.connect() }, 10000) } }) } /** * Simulate successful port open. * * @param callback */ open(callback) { if (this.openFlag) { console.log("TcpRTUBuffered port: external socket is opened"); callback(); // go ahead to setup existing socket } else { this.callback = callback; this._client.connect(this.connectOptions); } } close(callback) { this.callback = callback; this._client.end(callback); if (this.heartbeatInterval) clearInterval(this.heartbeatInterval) if (this.reconnectTime) clearTimeout(this.reconnectTime) } destroy(callback) { this.callback = callback; if (!this._client.destroyed) { this._client.destroy(); } }; write(data, cb) { let self = this this._client.write(data, function (err) { if (err) { console.log(err) if (cb) cb(true) self.reconnect() } else { if (cb) cb() } }); }; } module.exports = TcpBufferedPort;