@gapit/node-red-contrib-gapit-modbus
Version:
A Node-RED node witch reads Modbus registers based on gapit code JSON schema
311 lines (267 loc) • 11.2 kB
Markdown
# node-red-contrib-gapit-modbus
The _gapit-modbus_ <a href="http://nodered.org" target="_new">Node-RED</a>
node reads modbus register and decode modbus registers acording to data types specified in the _Gapit code_.
The _Gapit code_ structures and names data, preparing it for
insertion into a database. The complementary _gapit-results-to-influx-batch_
node transforms the output of this node to the format required by the
_influx batch_ node (from `node-red-contrib-influxdb`).
So to read a standard set of data and insert it into InfluxDB, a flow
like this is all you need:

Here's a fragment of a _Gapit code_:
```json
{
"objects": [
{
"group_name": "EB Current Bar",
"read_priority": 0,
"address_type": "dec",
"register_type": "holding",
"group": [
{
"address": 8200,
"description": "Breaker 1",
"scaling_factor": 1,
"unit": "A",
"byte_type": "SINT16"
},
{
"address": 8201,
"description": "Breaker 2",
"scaling_factor": 0.1,
"unit": "A",
"byte_type": "SINT32"
}
]
}
]
}
```
This would get inserted into a InfluxDB measurement called "EB Current Bar" (from the _group_name_ field),
with fields called "Breaker 1" and "Breaker 2" (from the _description_ field).
The output of `gapit-modbus`, which is parsed by `gapit-results-to-influx-batch`,
is `msg.gapit_results`. This has the same structure as the _Gapit code_,
except with `.value` added for each address.
### Other destinations/databases?
If you want to insert the data into a different database, you can parse
the `msg.gapit_results` structure, and transform it into the required
format.
### gapit-results-to-influx-batch node
The gapit-results-to-influx-batch node is packaged as a separate module,
`node-red-contrib-gapit-results`, which is automatically installed with
this module. It is a packaged as a separate module to enable sharing with
other nodes which yield results in the same `msg.gapit_results` structure.
The `node-red-contrib-gapit-results` module may be expanded with new
nodes in the future.
## Installation
### Install from the Node-RED interface
Install using _Manage palette_ -> _Install_.
You need to refresh your browser for the `gapit-results-to-influx-batch`
node to be available in the node palette. If you are running Node-RED 1.2
or older, you will need to restart Node-RED for it to be visible.
If you are using an ancient version of NPM, you will need to manually install
`node-red-contrib-gapit-results`.
### Install using the command line
Run the following command in your Node-RED user directory - typically `~/.node-red`
npm install /node-red-contrib-gapit-modbus
and then restart Node-RED.
## Usage
### Example flow
This is the JSON for the flow pictured above.
```json
[
{
"id": "4baf4f334b779050",
"type": "tab",
"label": "gapit modbus",
"disabled": false,
"info": ""
},
{
"id": "738d78ca6f672b59",
"type": "influxdb batch",
"z": "4baf4f334b779050",
"influxdb": "99e22e92c3be98de",
"precision": "",
"retentionPolicy": "",
"name": "",
"database": "modbus",
"precisionV18FluxV20": "ms",
"retentionPolicyV18Flux": "",
"org": "organisation",
"bucket": "bucket",
"x": 1240,
"y": 280,
"wires": []
},
{
"id": "f1a98ce54346cd03",
"type": "gapit-modbus",
"z": "4baf4f334b779050",
"name": "",
"host": "nodered",
"port": "502",
"deviceName": "123-123-123",
"deviceNameDbTag": "uid",
"unitId": "1",
"gapitCode": "{\"objects\":[{\"group_name\":\"EB Current Bar\",\"read_priority\":0,\"address_type\":\"dec\",\"register_type\":\"holding\",\"group\":[{\"address\":8200,\"description\":\"Breaker 1\",\"scaling_factor\":1,\"unit\":\"A\",\"byte_type\":\"SINT16\"},{\"address\":8201,\"description\":\"Breaker 2\",\"scaling_factor\":0.1,\"unit\":\"A\",\"byte_type\":\"SINT32\"}]}]}",
"customTags": "{\"foo\":\"test\",\"baar\":10}",
"scalingType": "general",
"x": 420,
"y": 280,
"wires": [["d32ef3b037c73222", "3438922f9c6b25ca"]]
},
{
"id": "c80bd9f665e8a5b9",
"type": "debug",
"z": "4baf4f334b779050",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1010,
"y": 220,
"wires": []
},
{
"id": "d32ef3b037c73222",
"type": "debug",
"z": "4baf4f334b779050",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 590,
"y": 220,
"wires": []
},
{
"id": "3438922f9c6b25ca",
"type": "gapit-results-to-influx-batch",
"z": "4baf4f334b779050",
"use_timestamp_from_msg": false,
"timestamp_property": "ts",
"name": "",
"x": 760,
"y": 280,
"wires": [["738d78ca6f672b59", "c80bd9f665e8a5b9"]]
},
{
"id": "28060540b4b95271",
"type": "inject",
"z": "4baf4f334b779050",
"name": "",
"props": [],
"repeat": "1",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 170,
"y": 280,
"wires": [["f1a98ce54346cd03"]]
},
{
"id": "99e22e92c3be98de",
"type": "influxdb",
"hostname": "127.0.0.1",
"port": "8086",
"protocol": "http",
"database": "database",
"name": "modbus-test",
"usetls": false,
"tls": "8b3094b6.5fc088",
"influxdbVersion": "1.8-flux",
"url": "http://influx:8086",
"rejectUnauthorized": false
},
{
"id": "8b3094b6.5fc088",
"type": "tls-config",
"name": "",
"cert": "",
"key": "",
"ca": "",
"certname": "GapitBroker.crt",
"keyname": "",
"caname": "",
"servername": "",
"verifyservercert": false
}
]
```
### Supported data types
The _Gapit-modbus_ supports these data types.
| Parameter | Description |
| --------- | ------------------------------------------------------------------------------------------------------ |
| BIT1 | Decodes a single bit register to integer value |
| BIT16 | Decodes a single bit register to integer value depending on witch bit is selected in the gapit code |
| BIT16-SW | Decodes a single bit SW register to integer value depending on witch bit is selected in the gapit code |
| BIT32 | Decodes a single bit register to integer value depending on witch bit is selected in the gapit code |
| BIT32-SW | Decodes a single bit SW register to integer value depending on witch bit is selected in the gapit code |
| UINT8 | Decodes a 8 bit register to unsigned integer value |
| UINT16 | Decodes a 16 bit register to unsigned integer value |
| UINT32 | Decodes a 32 bit register to unsigned integer value |
| UINT64 | Decodes a 16 bit register to unsigned integer value |
| SINT16 | Decodes a 16 bit register to signed integer value |
| SINT32 | Decodes a 32 bit register to signed integer value |
| SINT64 | Decodes a 16 bit register to signed integer value |
| FLOAT32 | Decodes a 32 bit register to floating point value |
| FLOAT64 | Decodes a 64 bit register to floating point value |
| DUMMY16 | Skipping a 16 bit register |
| DUMMY32 | Skipping a 32 bit register |
| DUMMY64 | Skipping a 64 bit register |
| HEX | Decodes a register depending on length specified in the gapit code to a hex decimal value |
| ASCII | Decodes a register depending on length specified in the gapit code to a ASCII value |
| ASCII-SW | Decodes a SW register depending on length specified in the gapit code to a ASCII value |
### Gapit codes
A library of ready-made _Gapit codes_ is forthcoming.
### gapit-modbus
The node needs to be configured with, at a minimum:
- MODBUS config (IP address, port, Unit ID etc.)
- Gapit code
| Parameter | Description |
| ------------------ | ------------------------------------------------------------------ |
| Name | Node name |
| Host | Modbus host |
| Port | Modbus port |
| Device name | The device name database records will be tagged with (e.g. "ups1") |
| Device name db-tag | The database tag for device name (e.g. "devname") |
| Unit ID | The ID modbus uses to select which unit to read |
| Custom tags | Extra tags to add to database records, see below |
| Gapit code | The Gapit code JSON |
| Scaling | _Specify scaling type_ |
#### Custom tags
Add database tags, formatted as JSON with `tag_name: value`.
Example:
```json
{
"floor": "1",
"room": "101"
}
```
### gapit-results-to-influx-batch
To use a Node-RED timestamp with influxdb (enabled by default),
add a property containing a timestamp in your inject node. The
default name is `msg.ts`.
| Parameter | Description |
| -------------------------- | -------------------------------------------------------------- |
| Name | Node name |
| Use timestamp from Message | Use a timestamp injected in the flow (_default on_) |
| Timestamp property | The `msg` property to get the timestamp from (_default: "ts"_) |
#### N.B.! Check the InfluxDB time precision
If using timestamps from Node-RED, note that while this works "out-of-the-box"
with InfluxDB v2, you will have to set the `influx batch` node to match the
millisecond resolution of Node-RED if you're using InfluxDB v1. You can do this
by checking `Advanced Query Options` on the `influx batch` node, and then
choosing `Milliseconds (ms)` from the `Time Precision` popup menu.