Skip to content

Commit 4fd1b18

Browse files
committed
reconnect, itemNames
1 parent b0b80c3 commit 4fd1b18

File tree

7 files changed

+234
-29
lines changed

7 files changed

+234
-29
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ENV NODE_ENV=production
33

44
# install openssl
55
RUN apk update \
6-
&& apk add --no-cache openssl\
6+
&& apk add --no-cache openssl python3 make g++\
77
&& rm -rf /var/lib/apt/lists/* \
88
&& rm -rf /var/cache/apk/*
99

NetReconnect.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* https://github.com/Cloud-Automation/node-net-reconnect
3+
* Copyright (C) 2017 Stefan Poeter (Stefan.Poeter[at]cloud-automation.de)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10+
11+
*/
12+
let debug = require('debug')('net-reconnect')
13+
let NetKeepAlive = require('net-keepalive')
14+
15+
class NetReconnect {
16+
17+
constructor (socket, options) {
18+
this._socket = socket
19+
this._options = options
20+
this._retryTime = options.retryTime || 1000
21+
this._retryAlways = options.retryAlways || false
22+
this._keepAliveDelay = Math.max(options.keepAliveDelay, 1000) || 1000
23+
this._keepAliveInterval = Math.max(options.keepAliveInterval, 1000) || 1000
24+
this._keepAliveProbes = Math.max(Math.min(options.keepAliveProbes, 1), 20) || 1
25+
this._closing = false
26+
27+
this._socket.on('connect', this._onConnect.bind(this))
28+
this._socket.on('close', this._onClose.bind(this))
29+
this._socket.on('error', this._onError.bind(this))
30+
}
31+
32+
static apply (socket, options) {
33+
return new NetReconnect(socket, options)
34+
}
35+
36+
_reconnect () {
37+
debug('reconnecting in %d', this._retryTime)
38+
setTimeout(function () {
39+
this._socket.connect(this._options)
40+
}.bind(this), this._retryTime)
41+
}
42+
43+
_onConnect () {
44+
if (this._closing) {
45+
return
46+
}
47+
48+
this._socket.setKeepAlive(true, this._keepAliveDelay)
49+
NetKeepAlive.setKeepAliveInterval(this._socket, this._keepAliveInterval)
50+
NetKeepAlive.setKeepAliveProbes(this._socket, this._keepAliveProbes)
51+
52+
debug('online')
53+
}
54+
55+
_onClose (hadError) {
56+
if (this._closing) {
57+
return
58+
}
59+
debug('offline')
60+
this._state = 'offline'
61+
if (!hadError) {
62+
debug('connection closed on purpose')
63+
if (this._retryAlways) {
64+
debug('retryAlways flag active, reconnecting')
65+
this._reconnect()
66+
return
67+
} else {
68+
debug('not reconnecting')
69+
return
70+
}
71+
}
72+
73+
debug('connection closed with errors, reconnecting')
74+
75+
this._reconnect()
76+
}
77+
78+
_onError () {
79+
if (this._closing) {
80+
return
81+
}
82+
83+
debug('error')
84+
}
85+
86+
end () {
87+
debug('closing socket permanently')
88+
this._closing = true
89+
this._socket.removeListener('connect', this._onConnect)
90+
this._socket.removeListener('close', this._onClose)
91+
this._socket.removeListener('error', this._onError)
92+
return this._socket.end.apply(this._socket, arguments)
93+
}
94+
95+
}
96+
97+
module.exports = NetReconnect

modbushandler.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
`use strict`;
22

3+
var modbus = require('jsmodbus');
34
const opcua = require("node-opcua");
4-
const Reconnect = require('node-net-reconnect')
5+
const Reconnect = require('./NetReconnect')
56
const net = require('net');
67
const { errorCodeToMessage } = require('jsmodbus/dist/codes');
78

@@ -79,16 +80,28 @@ var modbushandler = {
7980
'host': host,
8081
'port': port,
8182
'autoReconnect': true,
82-
'retryAlways' : true,
83+
'retryAlways': true,
8384
'retryTime': 1000,
8485
'timeout': 5000,
8586
'keepAlive': 5000
8687
};
87-
let recon = new Reconnect( this.socket, options);
88+
let recon = new Reconnect(this.socket, options);
8889
this.socket.connect(options);
8990

90-
console.log("Created a Modbus device on " + host + ":" + port + " " + unit);
91+
console.log("Created a Modbus device on %s:%d %s",host,port,unit);
9192
this.modbusclient = mclient;
93+
let connectionState = false;
94+
this.socket.on('error', () => {
95+
if (connectionState)
96+
console.warn("Lost connection to Modbus device on %s:%d %s",host,port,unit);
97+
connectionState = false;
98+
});
99+
this.socket.on('connect', () => {
100+
if (!connectionState) {
101+
console.info("Connection established to Modbus device on %s:%d %s",host,port,unit);
102+
}
103+
connectionState = true;
104+
});
92105
}
93106
};
94107

package-lock.json

Lines changed: 94 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
"jsmodbus": "~4.0",
1515
"lodash": "~4.17",
1616
"node-opcua": "~2.50",
17-
"net-keepalive" : "~3.0",
18-
"node-net-reconnect" : "~0.2"
17+
"net-keepalive": "~3.0"
1918
}
2019
}

sample/docker-compose.yaml

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
# opcua-server:
2-
# container_name: opcua-server
3-
# image: ghcr.io/bobiene/opcmodbusuaserver
4-
# ports:
5-
# - 8080:8080
6-
# command: >
7-
# --modbus-host modbus-server
8-
# --modbus-port 5020
9-
# --modbus-not-onebased
10-
# --modbus-holdingregister 0:100
11-
# --modbus-inputregisters 0:2 3 5:5 426:6 456:6
12-
modbus-server:
13-
container_name: modbus-server
14-
image: oitc/modbus-server
15-
restart: always
16-
command: -f /server_config.json
17-
ports:
18-
- 5020:5020
19-
volumes:
20-
- ./modbus-server.json:/server_config.json:ro
1+
version: "2.4"
2+
services:
3+
opcua-server:
4+
container_name: opcua-server
5+
image: ghcr.io/bobiene/opcmodbusuaserver
6+
ports:
7+
- 8080:8080
8+
command: >
9+
--modbus-host modbus-server
10+
--modbus-port 5020
11+
--modbus-not-onebased
12+
--modbus-holdingregister 0:100
13+
--modbus-inputregisters 0:2 3 5:5 426:6 456:6
14+
modbus-server:
15+
container_name: modbus-server
16+
image: oitc/modbus-server
17+
restart: always
18+
command: -f /server_config.json
19+
ports:
20+
- 5020:5020
21+
volumes:
22+
- ./modbus-server.json:/server_config.json:ro

server.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ function create_modbus_variables(server, modbushandler, rootname, register, type
7474
modbushandler.StartPoll(rootname, type, StartAddress, count, device.pollrate);
7575
const addressSpace = server.engine.addressSpace;
7676
const namespace = addressSpace.getOwnNamespace();
77-
77+
7878
for (var i = 0; i < count; i++) {
7979
//console.log("creating variable: " + (address + count).toString());
8080
var node = function (register, type, address, i) {
8181
var servernode = {
8282
componentOf: register,
83-
browseName: (address + i).toString(),
83+
browseName: (address + i).toString().padStart(5, 0),
8484
minimumSamplingInterval: device.pollrate,
8585
dataType: modbushandler.GetDataTypeString(type),
8686
value: {

0 commit comments

Comments
 (0)