osiota-app-modbus 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -34
- package/busscan.js +7 -1
- package/busscan_tcp.js +52 -0
- package/helper_modbus.js +44 -22
- package/index.js +63 -17
- package/package.json +4 -4
- package/schema.json +20 -4
package/README.md
CHANGED
|
@@ -16,19 +16,19 @@ Please edit schema.json or
|
|
|
16
16
|
|
|
17
17
|
This application connects devices via Modbus.
|
|
18
18
|
|
|
19
|
-
**Additional Properties:**
|
|
19
|
+
**Additional Properties:** not allowed<br/>
|
|
20
20
|
<br>**Option 1 (alternative):**
|
|
21
21
|
Modbus Serial Interface
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
**Properties**
|
|
25
25
|
|
|
26
|
-
|Name|Description|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|[
|
|
31
|
-
|[
|
|
26
|
+
|Name|Type|Description|Required|
|
|
27
|
+
|----|----|-----------|--------|
|
|
28
|
+
|**connect\_type**<br/>(Connection Type)|`string`|Enum: `"RTU"`, `"C701"`, `"RTUBuffered"`, `"AsciiSerial"`<br/>|yes|
|
|
29
|
+
|**connect\_path**|`string`|i.e. device path<br/>|yes|
|
|
30
|
+
|[**connect\_options**](#option1connect_options)<br/>(Serial Connect Options)|`object`|Additional options for connecting to modbus, i.e. the baud rate settings<br/>|no|
|
|
31
|
+
|[**map**](#option1map)<br/>(Modbus devices)|`object[]`||no|
|
|
32
32
|
|
|
33
33
|
**Example**
|
|
34
34
|
|
|
@@ -49,12 +49,12 @@ Modbus Network Interface
|
|
|
49
49
|
|
|
50
50
|
**Properties**
|
|
51
51
|
|
|
52
|
-
|Name|Description|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|[
|
|
57
|
-
|[
|
|
52
|
+
|Name|Type|Description|Required|
|
|
53
|
+
|----|----|-----------|--------|
|
|
54
|
+
|**connect\_type**<br/>(Connection Type)|`string`|Enum: `"TCP"`, `"Telnet"`<br/>|yes|
|
|
55
|
+
|**connect\_path**<br/>(Host)|`string`|i.e. an IP address or host name<br/>|yes|
|
|
56
|
+
|[**connect\_options**](#option2connect_options)<br/>(Network Connect Options)|`object`|Additional options for connecting to modbus, i.e. the port settings<br/>|no|
|
|
57
|
+
|[**map**](#option2map)<br/>(Modbus devices)|`object[]`||no|
|
|
58
58
|
|
|
59
59
|
**Example**
|
|
60
60
|
|
|
@@ -72,29 +72,33 @@ Modbus Network Interface
|
|
|
72
72
|
<a name="option1connect_options"></a>
|
|
73
73
|
### Option 1: connect\_options: Serial Connect Options
|
|
74
74
|
|
|
75
|
+
Additional options for connecting to modbus, i.e. the baud rate settings
|
|
76
|
+
|
|
77
|
+
See [SerialPort options](https://serialport.io/docs/api-stream#openoptions)
|
|
78
|
+
|
|
79
|
+
|
|
75
80
|
**Properties**
|
|
76
81
|
|
|
77
|
-
|Name|Description|
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
|Name|Type|Description|Required|
|
|
83
|
+
|----|----|-----------|--------|
|
|
84
|
+
|**baudRate**<br/>(Baud rate)|`number`||no|
|
|
80
85
|
|
|
81
|
-
<a name="
|
|
82
|
-
###
|
|
86
|
+
<a name="option1map"></a>
|
|
87
|
+
### Option 1: map: Modbus devices
|
|
83
88
|
|
|
84
|
-
**Items**
|
|
89
|
+
**Items: Modbus device**
|
|
85
90
|
|
|
86
91
|
**Item Properties**
|
|
87
92
|
|
|
88
|
-
|Name|Description|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|[
|
|
93
|
+
|Name|Type|Description|Required|
|
|
94
|
+
|----|----|-----------|--------|
|
|
95
|
+
|**node**<br/>(Node to map to)|`string`||no|
|
|
96
|
+
|**id**<br/>(Modbus Client ID)|`number`|Minimum: `0`<br/>|yes|
|
|
97
|
+
|**address**<br/>(Modbus Field Address)|`number`|Minimum: `0`<br/>|yes|
|
|
98
|
+
|**type**<br/>(Modbus Field Type)|`string`|Enum: `"input boolean"`, `"input register"`, `"output boolen"`, `"output register"`<br/>|no|
|
|
99
|
+
|**datatype**<br/>(Field Data Type)|`string`|Default: `"uint16"`<br/>Enum: `"boolean"`, `"uint16"`<br/>|yes|
|
|
100
|
+
|[**metadata**](#option1mapmetadata)<br/>(Node Metadata)|`object`||no|
|
|
96
101
|
|
|
97
|
-
**Item Required Properties:** id,address,datatype<br/>
|
|
98
102
|
**Example**
|
|
99
103
|
|
|
100
104
|
```json
|
|
@@ -112,19 +116,69 @@ Modbus Network Interface
|
|
|
112
116
|
]
|
|
113
117
|
```
|
|
114
118
|
|
|
115
|
-
<a name="
|
|
116
|
-
####
|
|
119
|
+
<a name="option1mapmetadata"></a>
|
|
120
|
+
#### Option 1: map\.metadata: Node Metadata
|
|
117
121
|
|
|
118
|
-
**Additional Properties:**
|
|
122
|
+
**Additional Properties:** allowed<br/>
|
|
119
123
|
<a name="option2connect_options"></a>
|
|
120
124
|
### Option 2: connect\_options: Network Connect Options
|
|
121
125
|
|
|
126
|
+
Additional options for connecting to modbus, i.e. the port settings
|
|
127
|
+
|
|
128
|
+
See [Connect options](https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener)
|
|
129
|
+
|
|
130
|
+
|
|
122
131
|
**Properties**
|
|
123
132
|
|
|
124
|
-
|Name|Description|
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
|Name|Type|Description|Required|
|
|
134
|
+
|----|----|-----------|--------|
|
|
135
|
+
|**port**|`number`|Modbus Port<br/>Default: `502`<br/>|no|
|
|
136
|
+
|
|
137
|
+
**Example**
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"port": 502
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
<a name="option2map"></a>
|
|
146
|
+
### Option 2: map: Modbus devices
|
|
147
|
+
|
|
148
|
+
**Items: Modbus device**
|
|
149
|
+
|
|
150
|
+
**Item Properties**
|
|
151
|
+
|
|
152
|
+
|Name|Type|Description|Required|
|
|
153
|
+
|----|----|-----------|--------|
|
|
154
|
+
|**node**<br/>(Node to map to)|`string`||no|
|
|
155
|
+
|**id**<br/>(Modbus Client ID)|`number`|Minimum: `0`<br/>|yes|
|
|
156
|
+
|**address**<br/>(Modbus Field Address)|`number`|Minimum: `0`<br/>|yes|
|
|
157
|
+
|**type**<br/>(Modbus Field Type)|`string`|Enum: `"input boolean"`, `"input register"`, `"output boolen"`, `"output register"`<br/>|no|
|
|
158
|
+
|**datatype**<br/>(Field Data Type)|`string`|Default: `"uint16"`<br/>Enum: `"boolean"`, `"uint16"`<br/>|yes|
|
|
159
|
+
|[**metadata**](#option2mapmetadata)<br/>(Node Metadata)|`object`||no|
|
|
160
|
+
|
|
161
|
+
**Example**
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
[
|
|
165
|
+
{
|
|
166
|
+
"node": "/Lamp Switch",
|
|
167
|
+
"id": 0,
|
|
168
|
+
"address": 10,
|
|
169
|
+
"type": "output boolean",
|
|
170
|
+
"datatype": "boolean",
|
|
171
|
+
"metadata": {
|
|
172
|
+
"power": 60
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
<a name="option2mapmetadata"></a>
|
|
179
|
+
#### Option 2: map\.metadata: Node Metadata
|
|
127
180
|
|
|
181
|
+
**Additional Properties:** allowed<br/>
|
|
128
182
|
|
|
129
183
|
## How to setup
|
|
130
184
|
|
package/busscan.js
CHANGED
|
@@ -15,13 +15,19 @@ var app_config = {
|
|
|
15
15
|
var m = new modbus.modbus(app_config);
|
|
16
16
|
m.onerror = function(err) {
|
|
17
17
|
if (err.name === "TransactionTimedOutError") {
|
|
18
|
+
m.client._port.openFlag = true;
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
21
|
console.log("modbus, error:", err.stack || err);
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
m.connect(app_config.connect_type, app_config.connect_path, app_config.connect_options, function() {
|
|
25
|
+
m.connect(app_config.connect_type, app_config.connect_path, app_config.connect_options, function(err) {
|
|
26
|
+
if (err) {
|
|
27
|
+
console.error("Error:", err);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.log("Connected");
|
|
25
31
|
scan();
|
|
26
32
|
});
|
|
27
33
|
|
package/busscan_tcp.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
var modbus = require("./helper_modbus.js");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var app_config = {
|
|
7
|
+
"connect_type": "Telnet",
|
|
8
|
+
"connect_path": "192.168.2.111",
|
|
9
|
+
"connect_options": {
|
|
10
|
+
"port": 12345
|
|
11
|
+
},
|
|
12
|
+
"packet_timeout": 200
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
var m = new modbus.modbus(app_config);
|
|
16
|
+
m.onerror = function(err) {
|
|
17
|
+
if (err.name === "TransactionTimedOutError") {
|
|
18
|
+
m.client._port.openFlag = true;
|
|
19
|
+
//m.client.openFlag = true;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.log("modbus, error:", err.stack || err);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
m.connect(app_config.connect_type, app_config.connect_path, app_config.connect_options, function(err) {
|
|
27
|
+
if (err) {
|
|
28
|
+
console.error("Error:", err);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
console.log("Connected");
|
|
32
|
+
scan();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
var cid = 1;
|
|
36
|
+
var scan = function() {
|
|
37
|
+
if (cid > 255) {
|
|
38
|
+
m.close();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
m.send_set("writeFC1", cid, 0, 1, function(err) {
|
|
43
|
+
if (err) {
|
|
44
|
+
console.log(cid, "No Client");
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(cid, "Found");
|
|
48
|
+
}
|
|
49
|
+
cid++;
|
|
50
|
+
scan();
|
|
51
|
+
});
|
|
52
|
+
};
|
package/helper_modbus.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
var ModbusRTU = require("modbus-serial");
|
|
3
3
|
|
|
4
|
-
var read_data = function(client_items, address_min, data) {
|
|
4
|
+
var read_data = function(client_items, address_min, data, buffer) {
|
|
5
5
|
client_items.forEach(function(c) {
|
|
6
6
|
c.callback(data.slice(c.address-address_min,
|
|
7
|
-
c.address-address_min+c.length)
|
|
7
|
+
c.address-address_min+c.length),
|
|
8
|
+
buffer.slice(2*(c.address-address_min),
|
|
9
|
+
2*(c.address-address_min+c.length)));
|
|
8
10
|
});
|
|
9
11
|
};
|
|
10
12
|
|
|
@@ -28,6 +30,10 @@ exports.modbus = function(config) {
|
|
|
28
30
|
this.packet_delay = config.packet_delay;
|
|
29
31
|
this.circle_delay = config.circle_delay;
|
|
30
32
|
this.client.setTimeout(config.packet_timeout);
|
|
33
|
+
this.max_payload = 60;
|
|
34
|
+
if (typeof config.max_payload === "number") {
|
|
35
|
+
this.max_payload = config.max_payload;
|
|
36
|
+
}
|
|
31
37
|
|
|
32
38
|
this.commands = {
|
|
33
39
|
"output boolean": {
|
|
@@ -54,7 +60,7 @@ exports.modbus = function(config) {
|
|
|
54
60
|
this.set_commands = [];
|
|
55
61
|
|
|
56
62
|
this.onerror = function(err) {
|
|
57
|
-
console.
|
|
63
|
+
console.error("modbus, run:", err.stack || err);
|
|
58
64
|
return false;
|
|
59
65
|
};
|
|
60
66
|
|
|
@@ -95,12 +101,16 @@ exports.modbus.prototype.client_add = function(type, cid, config) {
|
|
|
95
101
|
throw new Error("type undefined: " + type);
|
|
96
102
|
return;
|
|
97
103
|
}
|
|
104
|
+
var gid = config.address - (config.address % this.max_payload);
|
|
98
105
|
if (typeof this.commands[type].clients[cid] !== "object" ||
|
|
99
|
-
|
|
100
|
-
this.commands[type].clients[cid] = [];
|
|
106
|
+
this.commands[type].clients[cid] === null) {
|
|
107
|
+
this.commands[type].clients[cid] = {"groups": []};
|
|
108
|
+
}
|
|
109
|
+
if (!Array.isArray(this.commands[type].clients[cid].groups[gid])) {
|
|
110
|
+
this.commands[type].clients[cid].groups[gid] = [];
|
|
101
111
|
}
|
|
102
112
|
|
|
103
|
-
this.commands[type].clients[cid].push(config);
|
|
113
|
+
this.commands[type].clients[cid].groups[gid].push(config);
|
|
104
114
|
};
|
|
105
115
|
|
|
106
116
|
exports.modbus.prototype.client_can_set = function(type) {
|
|
@@ -146,7 +156,7 @@ exports.modbus.prototype.send_poll = function(command, cid, address, length, cli
|
|
|
146
156
|
length,
|
|
147
157
|
function(err, data) {
|
|
148
158
|
if (already_called) {
|
|
149
|
-
console.
|
|
159
|
+
console.warn("Warn: Called callback twice. Command: POLL", command, cid, address, data, "\nThis happens after a timeout. Please increase the packet timeout.");
|
|
150
160
|
return;
|
|
151
161
|
}
|
|
152
162
|
already_called = true;
|
|
@@ -161,11 +171,11 @@ exports.modbus.prototype.send_poll = function(command, cid, address, length, cli
|
|
|
161
171
|
if (_this.onerror(err))
|
|
162
172
|
return;
|
|
163
173
|
} else {
|
|
164
|
-
read_data(client_items, address, data.data);
|
|
174
|
+
read_data(client_items, address, data.data, data.buffer);
|
|
165
175
|
}
|
|
166
176
|
callback();
|
|
167
177
|
}
|
|
168
|
-
|
|
178
|
+
);
|
|
169
179
|
};
|
|
170
180
|
exports.modbus.prototype.send_set = function(command, cid, address, data, callback) {
|
|
171
181
|
var _this = this;
|
|
@@ -179,7 +189,7 @@ exports.modbus.prototype.send_set = function(command, cid, address, data, callba
|
|
|
179
189
|
data,
|
|
180
190
|
function(err, new_data) {
|
|
181
191
|
if (already_called) {
|
|
182
|
-
console.
|
|
192
|
+
console.warn("Warn: Called callback twice. Command: SET", command, cid, address, data, "\nThis happens after a timeout. Please increase the packet timeout.");
|
|
183
193
|
return;
|
|
184
194
|
}
|
|
185
195
|
already_called = true;
|
|
@@ -222,11 +232,14 @@ exports.modbus.prototype.connect = function(connect_type, path, options,
|
|
|
222
232
|
}
|
|
223
233
|
});
|
|
224
234
|
|
|
225
|
-
|
|
226
|
-
for (
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
235
|
+
this.poll_commands = [];
|
|
236
|
+
for (let type in this.commands) {
|
|
237
|
+
for (let cid in this.commands[type].clients) {
|
|
238
|
+
for (let gid in this.commands[type].clients[cid].groups) {
|
|
239
|
+
let address_min = null;
|
|
240
|
+
let address_max = null;
|
|
241
|
+
this.commands[type].clients[cid].groups[gid].
|
|
242
|
+
forEach(function(c) {
|
|
230
243
|
if (address_min === null || c.address < address_min) {
|
|
231
244
|
address_min = c.address;
|
|
232
245
|
}
|
|
@@ -238,13 +251,22 @@ exports.modbus.prototype.connect = function(connect_type, path, options,
|
|
|
238
251
|
//commands[type].clients[cid].address = address_min;
|
|
239
252
|
//commands[type].clients[cid].length = address_max-address_min;
|
|
240
253
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
254
|
+
let command = this.commands[type].command_poll;
|
|
255
|
+
let address = address_min;
|
|
256
|
+
let length = address_max-address_min;
|
|
257
|
+
let client_items = this.commands[type].clients[cid].groups[gid];
|
|
258
|
+
|
|
259
|
+
this.poll_commands.push(function(next) {
|
|
260
|
+
_this.send_poll(
|
|
261
|
+
command,
|
|
262
|
+
+cid,
|
|
263
|
+
address_min,
|
|
264
|
+
length,
|
|
265
|
+
client_items,
|
|
266
|
+
next
|
|
267
|
+
);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
248
270
|
}
|
|
249
271
|
}
|
|
250
272
|
|
package/index.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
|
|
2
2
|
var modbus = require("./helper_modbus.js");
|
|
3
3
|
|
|
4
|
-
var map_value = function(datatype, data) {
|
|
4
|
+
var map_value = function(datatype, data, buffer) {
|
|
5
5
|
if (datatype == "uint16") {
|
|
6
|
+
//return buffer.readUInt16BE(0);
|
|
6
7
|
return data[0];
|
|
7
8
|
}
|
|
9
|
+
else if (datatype == "floatBE") {
|
|
10
|
+
return buffer.readFloatBE(0);
|
|
11
|
+
}
|
|
12
|
+
else if (datatype == "floatLE") {
|
|
13
|
+
return buffer.readFloatLE(0);
|
|
14
|
+
}
|
|
15
|
+
else if (datatype == "floatBE-swap") {
|
|
16
|
+
buffer.swap16();
|
|
17
|
+
return buffer.readFloatBE(0);
|
|
18
|
+
}
|
|
19
|
+
else if (datatype == "floatLE-swap") {
|
|
20
|
+
buffer.swap16();
|
|
21
|
+
return buffer.readFloatLE(0);
|
|
22
|
+
}
|
|
8
23
|
else if (datatype == "boolean") {
|
|
9
24
|
return data[0] != 0;
|
|
10
25
|
}
|
|
@@ -15,6 +30,30 @@ var remap_value = function(datatype, value) {
|
|
|
15
30
|
if (datatype == "uint16") {
|
|
16
31
|
return [ value*1 ];
|
|
17
32
|
}
|
|
33
|
+
if (datatype == "floatBE") {
|
|
34
|
+
let buffer = Buffer.alloc(4);
|
|
35
|
+
buffer.writeFloatBE(value);
|
|
36
|
+
return buffer;
|
|
37
|
+
//return new Uint16Array(buffer.buffer,buffer.byteOffset,buffer.length/2);
|
|
38
|
+
//return [ buffer.readUInt16BE(0), buffer.readUInt16BE(2) ];
|
|
39
|
+
}
|
|
40
|
+
else if (datatype == "floatLE") {
|
|
41
|
+
let buffer = Buffer.alloc(4);
|
|
42
|
+
buffer.writeFloatLE(value);
|
|
43
|
+
return buffer;
|
|
44
|
+
}
|
|
45
|
+
else if (datatype == "floatBE-swap") {
|
|
46
|
+
let buffer = Buffer.alloc(4);
|
|
47
|
+
buffer.writeFloatBE(value);
|
|
48
|
+
buffer.swap16();
|
|
49
|
+
return buffer;
|
|
50
|
+
}
|
|
51
|
+
else if (datatype == "floatLE-swap") {
|
|
52
|
+
let buffer = Buffer.alloc(4);
|
|
53
|
+
buffer.writeFloatLE(value);
|
|
54
|
+
buffer.swap16();
|
|
55
|
+
return buffer;
|
|
56
|
+
}
|
|
18
57
|
else if (datatype == "boolean") {
|
|
19
58
|
return [ value*1 ];
|
|
20
59
|
}
|
|
@@ -22,11 +61,6 @@ var remap_value = function(datatype, value) {
|
|
|
22
61
|
};
|
|
23
62
|
|
|
24
63
|
exports.init = function(node, app_config, main, host_info) {
|
|
25
|
-
|
|
26
|
-
var baudrate = 38400;
|
|
27
|
-
|
|
28
|
-
var models = {};
|
|
29
|
-
|
|
30
64
|
if (typeof app_config !== "object") {
|
|
31
65
|
app_config = {};
|
|
32
66
|
}
|
|
@@ -41,7 +75,7 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
41
75
|
|
|
42
76
|
var m = new modbus.modbus(app_config);
|
|
43
77
|
m.onerror = function(err) {
|
|
44
|
-
console.
|
|
78
|
+
console.error("modbus, error:", err.stack || err);
|
|
45
79
|
|
|
46
80
|
if (typeof err.message === "string" &&
|
|
47
81
|
err.message.match(/^Timed out/))
|
|
@@ -52,7 +86,7 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
52
86
|
if (this.close)
|
|
53
87
|
this.close();
|
|
54
88
|
|
|
55
|
-
console.
|
|
89
|
+
console.info("modbus, restarting ...");
|
|
56
90
|
_this._reinit_delay(5000);
|
|
57
91
|
return true;
|
|
58
92
|
};
|
|
@@ -60,13 +94,13 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
60
94
|
var map_itemtype = function(type) {
|
|
61
95
|
if (typeof type !== "string")
|
|
62
96
|
return "output boolean";
|
|
63
|
-
if (type.match(
|
|
97
|
+
if (type.match(/^FC(1|5|15)$/i))
|
|
64
98
|
return "output boolean";
|
|
65
|
-
if (type.match(
|
|
99
|
+
if (type.match(/^FC2$/i))
|
|
66
100
|
return "input boolean";
|
|
67
|
-
if (type.match(
|
|
101
|
+
if (type.match(/^FC(3|6|16)$/i))
|
|
68
102
|
return "output register";
|
|
69
|
-
if (type.match(
|
|
103
|
+
if (type.match(/^FC4$/i))
|
|
70
104
|
return "input register";
|
|
71
105
|
|
|
72
106
|
if (type.match(/coil/))
|
|
@@ -84,6 +118,10 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
84
118
|
return "output boolean";
|
|
85
119
|
};
|
|
86
120
|
|
|
121
|
+
node.announce({
|
|
122
|
+
"type": "modbus.app"
|
|
123
|
+
});
|
|
124
|
+
|
|
87
125
|
var map = node.map(app_config.map, null, true, null,
|
|
88
126
|
function(n,metadata,config) {
|
|
89
127
|
var command = map_itemtype(config.type);
|
|
@@ -92,7 +130,11 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
92
130
|
var length = config.length;
|
|
93
131
|
if (typeof length !== "number") {
|
|
94
132
|
var tmp = remap_value(config.datatype, 0);
|
|
95
|
-
|
|
133
|
+
if (Buffer.isBuffer(tmp)) {
|
|
134
|
+
length = tmp.length / 2;
|
|
135
|
+
} else {
|
|
136
|
+
length = tmp.length;
|
|
137
|
+
}
|
|
96
138
|
}
|
|
97
139
|
|
|
98
140
|
var type = "number";
|
|
@@ -104,8 +146,8 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
104
146
|
m.client_add(command, cid, {
|
|
105
147
|
"address": config.address || 0,
|
|
106
148
|
"length": length || 1,
|
|
107
|
-
"callback": function(data) {
|
|
108
|
-
var value = map_value(config.datatype, data);
|
|
149
|
+
"callback": function(data, buffer) {
|
|
150
|
+
var value = map_value(config.datatype, data, buffer);
|
|
109
151
|
// better name: reset
|
|
110
152
|
if (config.erase && value) {
|
|
111
153
|
// uninitialized?
|
|
@@ -141,6 +183,9 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
141
183
|
}
|
|
142
184
|
});
|
|
143
185
|
};
|
|
186
|
+
n.rpc_toggle = function(reply, time) {
|
|
187
|
+
return n.rpc_set(reply, !n.value, time);
|
|
188
|
+
};
|
|
144
189
|
n.rpc_publish = function(reply, time, value) {
|
|
145
190
|
return n.rpc_set(reply, value, time);
|
|
146
191
|
};
|
|
@@ -163,7 +208,8 @@ exports.init = function(node, app_config, main, host_info) {
|
|
|
163
208
|
});
|
|
164
209
|
|
|
165
210
|
// open connection to a port
|
|
166
|
-
m.connect(app_config.connect_type, app_config.connect_path,
|
|
211
|
+
m.connect(app_config.connect_type, app_config.connect_path,
|
|
212
|
+
JSON.parse(JSON.stringify(app_config.connect_options || {})));
|
|
167
213
|
|
|
168
|
-
return [map, m];
|
|
214
|
+
return [node, map, m];
|
|
169
215
|
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "osiota-app-modbus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "This application connects devices via Modbus",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"modbus-serial": "^
|
|
8
|
-
"serialport": "^
|
|
7
|
+
"modbus-serial": "^8.0.23",
|
|
8
|
+
"serialport": "^13.0.0"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"osiota-dev": "^1.
|
|
11
|
+
"osiota-dev": "^1.x"
|
|
12
12
|
},
|
|
13
13
|
"author": "Simon Walz and others",
|
|
14
14
|
"license": "MIT",
|
package/schema.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "object",
|
|
3
|
-
"title": "osiota
|
|
3
|
+
"title": "osiota Application Modbus",
|
|
4
4
|
"description": "This application connects devices via Modbus.",
|
|
5
5
|
"oneOf": [{
|
|
6
6
|
"description": "Modbus Serial Interface",
|
|
@@ -17,18 +17,24 @@
|
|
|
17
17
|
},
|
|
18
18
|
"connect_options": {
|
|
19
19
|
"title": "Serial Connect Options",
|
|
20
|
+
"description": "Additional options for connecting to modbus, i.e. the baud rate settings\n\nSee [SerialPort options](https://serialport.io/docs/api-stream#openoptions)",
|
|
20
21
|
"type": "object",
|
|
21
22
|
"properties": {
|
|
22
23
|
"baudRate": {
|
|
23
24
|
"title": "Baud rate",
|
|
24
25
|
"type": "number"
|
|
25
26
|
}
|
|
26
|
-
}
|
|
27
|
+
},
|
|
28
|
+
"required": []
|
|
27
29
|
},
|
|
28
30
|
"map": {
|
|
29
31
|
"$ref": "#/definitions/map"
|
|
30
32
|
}
|
|
31
33
|
},
|
|
34
|
+
"required": [
|
|
35
|
+
"connect_type",
|
|
36
|
+
"connect_path"
|
|
37
|
+
],
|
|
32
38
|
"examples": [{
|
|
33
39
|
"connect_type": "RTUBuffered",
|
|
34
40
|
"connect_path": "/dev/ttyUSB0",
|
|
@@ -51,18 +57,26 @@
|
|
|
51
57
|
},
|
|
52
58
|
"connect_options": {
|
|
53
59
|
"title": "Network Connect Options",
|
|
60
|
+
"description": "Additional options for connecting to modbus, i.e. the port settings\n\nSee [Connect options](https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener)",
|
|
54
61
|
"type": "object",
|
|
55
62
|
"properties": {
|
|
56
63
|
"port": {
|
|
57
64
|
"title": "Port",
|
|
65
|
+
"description": "Modbus Port",
|
|
66
|
+
"default": 502,
|
|
58
67
|
"type": "number"
|
|
59
68
|
}
|
|
60
|
-
}
|
|
69
|
+
},
|
|
70
|
+
"required": []
|
|
61
71
|
},
|
|
62
72
|
"map": {
|
|
63
73
|
"$ref": "#/definitions/map"
|
|
64
74
|
}
|
|
65
75
|
},
|
|
76
|
+
"required": [
|
|
77
|
+
"connect_type",
|
|
78
|
+
"connect_path"
|
|
79
|
+
],
|
|
66
80
|
"examples": [{
|
|
67
81
|
"connect_type": "Telnet",
|
|
68
82
|
"connect_path": "192.168.1.101",
|
|
@@ -79,6 +93,7 @@
|
|
|
79
93
|
"title": "Modbus devices",
|
|
80
94
|
"items": {
|
|
81
95
|
"type": "object",
|
|
96
|
+
"title": "Modbus device",
|
|
82
97
|
"properties": {
|
|
83
98
|
"node": {
|
|
84
99
|
"title": "Node to map to",
|
|
@@ -97,7 +112,7 @@
|
|
|
97
112
|
"type": {
|
|
98
113
|
"title": "Modbus Field Type",
|
|
99
114
|
"type": "string",
|
|
100
|
-
"enum": [ "input boolean", "input register", "output
|
|
115
|
+
"enum": [ "input boolean", "input register", "output boolean", "output register" ]
|
|
101
116
|
},
|
|
102
117
|
"datatype": {
|
|
103
118
|
"title": "Field Data Type",
|
|
@@ -121,6 +136,7 @@
|
|
|
121
136
|
"power": 60
|
|
122
137
|
}
|
|
123
138
|
}],
|
|
139
|
+
"additionalProperties": false,
|
|
124
140
|
"required": [ "id", "address", "datatype" ]
|
|
125
141
|
}
|
|
126
142
|
}
|