Intial Commit

This commit is contained in:
valki
2020-10-17 18:42:50 +02:00
commit 664c6d8ca3
5892 changed files with 759183 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
# node-red-contrib-influxdb
A <a href="http://nodered.org" target="_new">Node-RED</a> node to write and query data from an influxdb time series database. These nodes use the <a href="https://www.npmjs.com/package/influx" target="_new">influxDB 1.x client</a> for node.js, specifically calling the **writePoints()**, and **query()** methods. Currently these nodes can only communicate with one influxdb host. These nodes do not support InfluxDb 2.0 yet.
## Prerequisites
To run this you'll need access to an influxdb database version 1.x. See the <a href="https://influxdb.com/" target="_new">influxdb site</a> for more information. The last release of this node has been tested with InfluxDb 1.8.
## Install
Run the following command in the root directory of your Node-RED install.
Usually this is `~/.node-red` .
npm install node-red-contrib-influxdb
## Usage
Nodes to write and query data from an influxdb time series database.
### Input Node
Queries one or more measurements in an influxdb database. The query is specified in the node configuration or in the ***msg.query*** property. Setting it in the node will override the ***msg.query***. The result is returned in ***msg.payload***.
For example, here is a simple flow to query all of the points in the `test` measurement of the `aTimeSeries` database, where the query is in the configuration of the influxdb input node (copy and paste to your NR editor).
[{"id":"eba91e98.1456e","type":"influxdb","z":"b061b303.4f9e5","hostname":"127.0.0.1","port":"8086","database":"aTimeSeries","name":"aTimeSeries"},{"id":"9641241a.69bed8","type":"influxdb in","z":"b061b303.4f9e5","influxdb":"eba91e98.1456e","name":"time query","query":"select * from test;","x":259,"y":416,"wires":[["ef40525d.10bfb"]]},{"id":"99338e00.66cc7","type":"inject","z":"b061b303.4f9e5","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":108,"y":416,"wires":[["9641241a.69bed8"]]},{"id":"ef40525d.10bfb","type":"debug","z":"b061b303.4f9e5","name":"","active":true,"console":"false","complete":"false","x":441,"y":416,"wires":[]}]
This flow performs the same, but using a query in the msg.payload:
[{"id":"eba91e98.1456e","type":"influxdb","z":"b061b303.4f9e5","hostname":"127.0.0.1","port":"8086","database":"aTimeSeries","name":"aTimeSeries"},{"id":"c8b8604d.3747a","type":"inject","z":"b061b303.4f9e5","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":113,"y":496,"wires":[["affa0a63.5005f8"]]},{"id":"affa0a63.5005f8","type":"function","z":"b061b303.4f9e5","name":"simple query","func":"msg.query=\"select * from test;\";\nreturn msg;","outputs":1,"noerr":0,"x":273,"y":496,"wires":[["30a428ee.cf5bd8"]]},{"id":"30a428ee.cf5bd8","type":"influxdb in","z":"b061b303.4f9e5","influxdb":"eba91e98.1456e","name":"time query","query":"","x":436,"y":496,"wires":[["eee2af7a.111d5"]]},{"id":"eee2af7a.111d5","type":"debug","z":"b061b303.4f9e5","name":"","active":true,"console":"false","complete":"false","x":594,"y":496,"wires":[]}]
The function node in this flow sets the `msg.query` property as follows:
msg.query="select * from test;";
return msg;
### Output Node
Writes one or more points (fields and tags) to a measurement.
The fields and tags to write are in ***msg.payload***. If the message is a string, number, or boolean, it will be written as a single value to the specified measurement (called *value*).
For example, the following flow injects a single random field called `value` into the measurement `test` in the database `aTimeSeries` with the current timestamp.
[{"id":"eba91e98.1456e","type":"influxdb","z":"b061b303.4f9e5","hostname":"127.0.0.1","port":"8086","database":"aTimeSeries","name":"aTimeSeries"},{"id":"17bd4566.e842bb","type":"influxdb out","z":"b061b303.4f9e5","influxdb":"eba91e98.1456e","name":"","measurement":"test","x":428,"y":36,"wires":[]},{"id":"be93bfeb.416c4","type":"function","z":"b061b303.4f9e5","name":"single value","func":"msg.payload = Math.random()*10;\nreturn msg;","outputs":1,"noerr":0,"x":245,"y":64,"wires":[["17bd4566.e842bb"]]},{"id":"31f9f174.ce060e","type":"inject","z":"b061b303.4f9e5","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":101,"y":39,"wires":[["be93bfeb.416c4"]]}]
The function node consists of the following:
msg.payload = Math.random()*10;
return msg;
If ***msg.payload*** is an object containing multiple properties, the fields will be written to the measurement.
For example, the following flow injects three fields, `numValue`, `randomValue` and `strValue` into the same measurement with the current timestamp.
[{"id":"eba91e98.1456e","type":"influxdb","z":"b061b303.4f9e5","hostname":"127.0.0.1","port":"8086","database":"aTimeSeries","name":"aTimeSeries"},{"id":"baee675c.451198","type":"inject","z":"b061b303.4f9e5","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":103,"y":177,"wires":[["827180cf.7d8e8"]]},{"id":"827180cf.7d8e8","type":"function","z":"b061b303.4f9e5","name":"Fields","func":"msg.payload = {\n numValue: 123.0,\n strValue: \"message\",\n randomValue: Math.random()*10\n}\nreturn msg;","outputs":1,"noerr":0,"x":251,"y":177,"wires":[["c36cb4d6.3c9348"]]},{"id":"c36cb4d6.3c9348","type":"influxdb out","z":"b061b303.4f9e5","influxdb":"eba91e98.1456e","name":"","measurement":"test","x":421,"y":177,"wires":[]}]
The function node in the flow above consists of the following:
msg.payload = {
numValue: 123.0,
strValue: "message",
randomValue: Math.random()*10
}
return msg;
If ***msg.payload*** is an array containing two objects, the first object will be written as the set of named fields, the second is the set of named tags.
For example, the following simple flow injects three fields as above, along with two tags, `tag1` and `tag2`:
[{"id":"eba91e98.1456e","type":"influxdb","z":"b061b303.4f9e5","hostname":"127.0.0.1","port":"8086","database":"aTimeSeries","name":"aTimeSeries"},{"id":"7f25337e.80dacc","type":"inject","z":"b061b303.4f9e5","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":101,"y":248,"wires":[["bb0ff0.ff44f01"]]},{"id":"bb0ff0.ff44f01","type":"function","z":"b061b303.4f9e5","name":"Fields and Tags","func":"msg.payload = [{\n numValue: 12,\n randomValue: Math.random()*10,\n strValue: \"message2\"\n},\n{\n tag1:\"sensor1\",\n tag2:\"device2\"\n}];\nreturn msg;","outputs":1,"noerr":0,"x":272,"y":248,"wires":[["8e2713fa.71d8f"]]},{"id":"8e2713fa.71d8f","type":"influxdb out","z":"b061b303.4f9e5","influxdb":"eba91e98.1456e","name":"","measurement":"test","x":460,"y":248,"wires":[]}]
The function node consists of the following code:
msg.payload = [{
numValue: 12,
randomValue: Math.random()*10,
strValue: "message2"
},
{
tag1:"sensor1",
tag2:"device2"
}];
return msg;
Finally, if ***msg.payload*** is an array of arrays, it will be written as a series of points containing fields and tags.
For example, the following flow injects two points with timestamps specified.
[{"id":"eba91e98.1456e","type":"influxdb","z":"b061b303.4f9e5","hostname":"127.0.0.1","port":"8086","database":"aTimeSeries","name":"aTimeSeries"},{"id":"9555a67c.6aaa58","type":"function","z":"b061b303.4f9e5","name":"multiple readings","func":"msg.payload = [\n [{\n numValue: 10,\n randomValue: Math.random()*10,\n strValue: \"message1\",\n time: new Date(\"2015-12-28T19:41:13Z\").getTime()\n },\n {\n tag1:\"sensor1\",\n tag2:\"device2\"\n }],\n [{\n numValue: 20,\n randomValue: Math.random()*10,\n strValue: \"message2\",\n time: new Date(\"2015-12-28T19:41:14Z\").getTime()\n },\n {\n tag1:\"sensor1\",\n tag2:\"device2\"\n }]\n];\nreturn msg;","outputs":1,"noerr":0,"x":278,"y":335,"wires":[["f485378d.0b7ac8"]]},{"id":"68b911d9.9746f","type":"inject","z":"b061b303.4f9e5","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":104,"y":335,"wires":[["9555a67c.6aaa58"]]},{"id":"f485378d.0b7ac8","type":"influxdb out","z":"b061b303.4f9e5","influxdb":"eba91e98.1456e","name":"","measurement":"test","x":479,"y":334,"wires":[]}]
The function node in the above flow looks as follows:
msg.payload = [
[{
numValue: 10,
randomValue: Math.random()*10,
strValue: "message1",
time: new Date("2015-12-28T19:41:13Z").getTime()
},
{
tag1:"sensor1",
tag2:"device2"
}],
[{
numValue: 20,
randomValue: Math.random()*10,
strValue: "message2",
time: new Date("2015-12-28T19:41:14Z").getTime()
},
{
tag1:"sensor1",
tag2:"device2"
}]
];
return msg;
Note how timestamps are specified - the number of milliseconds since 1 January 1970 00:00:00 UTC. In this case do not forget to set "ms" in "Time Precision" (Advanced Query Options) of the "Influx Out Node".
### The Batch Output Node
The batch output node (influx batch) sends a list of *points* together in a batch to InfluxDB in a slightly different format from the output node, more in line with the underlying node.js [influx library version 5.x](https://www.npmjs.com/package/influx). In each point you must specify the measurement name to write into as well as a list of tag and field values. Optionally, you can specify the time to tag that point at, defaulting to the current time.
Under the hood we are calling the node influxdb 5.x library **writePoints()** call as documented [here](https://node-influx.github.io/class/src/index.js~InfluxDB.html#instance-method-writePoints).
By default the node will write timestamps using ms precision since that's what JavaScript gives us. if you specify the timestamp as a Date object, we'll convert it to milliseconds.
If you provide a string or number as the timestamp, we'll pass it straight into Influx to parse using the specified precision, or the default precision in nanoseconds if it is left unspecified.
>>**Note** that the default precision is *nanoseconds*, so if you pass in a number such as date.getTime(), and do not specify millisecond precision, your timestamp will be orders of magnitude incorrect.
The following example flow writes two points to two measurements, setting the timestamp to the current date.
[{"id":"4a271a88.499184","type":"function","z":"87205ed6.329bc","name":"multiple measurement points","func":"msg.payload = [\n {\n measurement: \"weather_sensor\",\n fields: {\n temp: 5.5,\n light: 678,\n humidity: 51\n },\n tags:{\n location:\"garden\"\n },\n timestamp: new Date()\n },\n {\n measurement: \"alarm_sensor\",\n fields: {\n proximity: 999,\n temp: 19.5\n },\n tags:{\n location:\"home\"\n },\n timestamp: new Date()\n }\n];\nreturn msg;","outputs":1,"noerr":0,"x":400,"y":280,"wires":[["748a06bd.675ed8"]]},{"id":"6493a442.1cdcbc","type":"inject","z":"87205ed6.329bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":140,"y":220,"wires":[["4a271a88.499184"]]},{"id":"748a06bd.675ed8","type":"influxdb batch","z":"87205ed6.329bc","influxdb":"6ca8bde.9eb2f44","name":"","x":670,"y":220,"wires":[]},{"id":"6ca8bde.9eb2f44","type":"influxdb","z":"","hostname":"localhost","port":"8086","protocol":"https","database":"new_db","name":"","usetls":true,"tls":"f7f39f4e.896ae"},{"id":"f7f39f4e.896ae","type":"tls-config","z":"","name":"local-tls","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","verifyservercert":false}]
The function node generates sample points as follows:
msg.payload = [
{
measurement: "weather_sensor",
fields: {
temp: 5.5,
light: 678,
humidity: 51
},
tags:{
location:"garden"
},
timestamp: new Date()
},
{
measurement: "alarm_sensor",
fields: {
proximity: 999,
temp: 19.5
},
tags:{
location:"home"
},
timestamp: new Date()
}
];
return msg;
### Catching Failed Reads and Writes
Errors in reads and writes can be caught using the node-red `catch` node as usual.
Standard error information is availlable in the default `msg.error` field; additional
information about the underlying error is in the `msg.influx_error` field. Currently,
this includes the HTTP status code returned from the influxdb server. The `influx-read`
node will always throw a `503`, whereas the write nodes will include other status codes
as detailed in the
[Influx API documentation](https://docs.influxdata.com/influxdb/v1.8/tools/api/#status-codes-and-responses-2).

View File

@@ -0,0 +1,153 @@
reporting-disabled = false
bind-address = "127.0.0.1:8088"
[meta]
dir = "/var/lib/influxdb/meta"
retention-autocreate = true
logging-enabled = true
[data]
dir = "/var/lib/influxdb/data"
index-version = "inmem"
wal-dir = "/var/lib/influxdb/wal"
wal-fsync-delay = "0s"
validate-keys = false
query-log-enabled = true
cache-max-memory-size = 1073741824
cache-snapshot-memory-size = 26214400
cache-snapshot-write-cold-duration = "10m0s"
compact-full-write-cold-duration = "4h0m0s"
compact-throughput = 50331648
compact-throughput-burst = 50331648
max-series-per-database = 1000000
max-values-per-tag = 100000
max-concurrent-compactions = 0
max-index-log-file-size = 1048576
series-id-set-cache-size = 100
trace-logging-enabled = false
tsm-use-madv-willneed = false
[coordinator]
write-timeout = "10s"
max-concurrent-queries = 0
query-timeout = "0s"
log-queries-after = "0s"
max-select-point = 0
max-select-series = 0
max-select-buckets = 0
[retention]
enabled = true
check-interval = "30m0s"
[shard-precreation]
enabled = true
check-interval = "10m0s"
advance-period = "30m0s"
[monitor]
store-enabled = true
store-database = "_internal"
store-interval = "10s"
[subscriber]
enabled = true
http-timeout = "30s"
insecure-skip-verify = true
ca-certs = ""
write-concurrency = 40
write-buffer-size = 1000
[http]
enabled = true
bind-address = ":8086"
auth-enabled = false
log-enabled = true
suppress-write-log = false
write-tracing = false
flux-enabled = false
flux-log-enabled = false
pprof-enabled = true
debug-pprof-enabled = false
https-enabled = false
https-certificate = "/etc/ssl/influxdb.pem"
https-private-key = ""
max-row-limit = 0
max-connection-limit = 0
shared-secret = ""
realm = "InfluxDB"
unix-socket-enabled = false
unix-socket-permissions = "0777"
bind-socket = "/var/run/influxdb.sock"
max-body-size = 25000000
access-log-path = ""
max-concurrent-write-limit = 0
max-enqueued-write-limit = 0
enqueued-write-timeout = 30000000000
[logging]
format = "auto"
level = "info"
suppress-logo = false
[[graphite]]
enabled = false
bind-address = ":2003"
database = "graphite"
retention-policy = ""
protocol = "tcp"
batch-size = 5000
batch-pending = 10
batch-timeout = "1s"
consistency-level = "one"
separator = "."
udp-read-buffer = 0
[[collectd]]
enabled = false
bind-address = ":25826"
database = "collectd"
retention-policy = ""
batch-size = 5000
batch-pending = 10
batch-timeout = "10s"
read-buffer = 0
typesdb = "/usr/share/collectd/types.db"
security-level = "none"
auth-file = "/etc/collectd/auth_file"
parse-multivalue-plugin = "split"
[[opentsdb]]
enabled = false
bind-address = ":4242"
database = "opentsdb"
retention-policy = ""
consistency-level = "one"
tls-enabled = false
certificate = "/etc/ssl/influxdb.pem"
batch-size = 1000
batch-pending = 5
batch-timeout = "1s"
log-point-errors = true
[[udp]]
enabled = false
bind-address = ":8089"
database = "udp"
retention-policy = ""
batch-size = 5000
batch-pending = 10
read-buffer = 0
batch-timeout = "1s"
precision = ""
[continuous_queries]
log-enabled = true
enabled = true
query-stats-enabled = false
run-interval = "1s"
[tls]
min-version = ""
max-version = ""

View File

@@ -0,0 +1,4 @@
docker run --name influxdb -p 8086:8086 \
-v $PWD/influxdb.conf:/etc/influxdb/influxdb.conf:ro \
-v influxdb:/var/lib/influxdb \
influxdb -config /etc/influxdb/influxdb.conf

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

View File

@@ -0,0 +1,397 @@
<script type="text/x-red" data-template-name="influxdb">
<div class="form-row">
<label for="node-config-input-hostname"><i class="fa fa-server"></i> <span data-i18n="influxdb.label.host"></span></label>
<input class="input-append-left" type="text" id="node-config-input-hostname" placeholder="localhost" style="width: 40%;" >
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> <span data-i18n="influxdb.label.port"></span></label>
<input type="text" id="node-config-input-port" style="width:45px">
</div>
<div class="form-row">
<label for="node-config-input-database"><i class="fa fa-database"></i> <span data-i18n="influxdb.label.database"></span></label>
<input type="text" id="node-config-input-database">
</div>
<div class="form-row">
<label for="node-config-input-username"><i class="fa fa-user"></i> <span data-i18n="node-red:common.label.username"></span></label>
<input type="text" id="node-config-input-username">
</div>
<div class="form-row">
<label for="node-config-input-password"><i class="fa fa-lock"></i> <span data-i18n="node-red:common.label.password"></span></label>
<input type="password" id="node-config-input-password">
</div>
<div class="form-row">
<input type="checkbox" id="node-config-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-config-input-usetls" style="width: auto" data-i18n="influxdb.label.use-tls"></label>
<div id="node-config-row-tls" class="hide">
<label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-config-input-tls"><span data-i18n="influxdb.label.tls-config"></span></label>
<input style="width: 300px;" type="text" id="node-config-input-tls">
</div>
</div>
<div class="form-row">
<label for="node-config-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-config-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('influxdb', {
category: 'config',
color: "rgb(218, 196, 180)",
defaults: {
hostname: {value: "127.0.0.1", required: true},
port: {value: 8086, required: true},
protocol: {value: "http", required: true},
database: {value: "", required: true},
name: {value: ""},
usetls: {value: false},
tls: {type:"tls-config",required: false}
},
credentials: {
username: {type: "text"},
password: {type: "password"}
},
label: function() {
return this.name || this.hostname + ":" + this.port + "/" + this.database;
},
oneditprepare: function() {
if (typeof this.usetls === 'undefined') {
this.usetls = false;
$("#node-config-input-usetls").prop("checked",false);
}
function updateTLSOptions() {
if ($("#node-config-input-usetls").is(':checked')) {
$("#node-config-row-tls").show();
} else {
$("#node-config-row-tls").hide();
}
}
updateTLSOptions();
$("#node-config-input-usetls").on("click",function() {
updateTLSOptions();
});
}
});
</script>
<script type="text/x-red" data-template-name="influxdb out">
<div class="form-row">
<label for="node-input-influxdb"><i class="fa fa-server"></i> <span data-i18n="influxdb.label.server"></span></label>
<input type="text" id="node-input-influxdb">
</div>
<div class="form-row">
<label for="node-input-measurement"><i style="width: 10px;" class="fa fa-rss"></i> <span data-i18n="influxdb.label.measurement"></span></label>
<input type="text" id="node-input-measurement">
</div>
<div class="form-row">
<input type="checkbox" id="advanced-options-checkbox" style="display: inline-block; width: auto; vertical-align: top;">
<label for="advanced-options-checkbox" style="width: 70%;"><span data-i18n="influxdb.label.use-advanced-query"></span></label>
<div id="advanced-options-div" class="hide" style="margin-left: 20px; margin-top: 10px;">
<div class="form-row">
<label for="node-input-precision" style="width:35%"><i class="fa fa-clock-o"></i> <span data-i18n="influxdb.label.time-precision"></span></label>
<select type="text" id="node-input-precision" style="width:55%">
<option value="">Default</option>
<option value="n">Nanoseconds (n)</option>
<option value="u">Microseconds (u)</option>
<option value="ms">Milliseconds (ms)</option>
<option value="s">Seconds (s)</option>
<option value="m">Minute (m)</option>
<option value="h">Hour (h)</option>
<option value="d">Day (d)</option>
<option value="w">Week (w)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-retentionPolicy" style="width:35%"><i class="fa fa-gavel"></i> <span data-i18n="influxdb.label.retention-policy"></span></label>
<input type="text" style="width:55%" id="node-input-retentionPolicy">
</div>
</div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-tips" id="node-warning" style="display: none"><span data-i18n="[html]influxdb.tip"></span></div>
</script>
<script type="text/x-red" data-help-name="influxdb out">
<p>A simple influxdb output node to write values and tags to an influxdb measurement.</p>
<p>The fields and tags to write are in <b>msg.payload</b>. If <b>msg.payload</b> is a string, number, or boolean,
it will be written as a single value to the specified measurement (called <i>value</i>).</p>
<p>If <b>msg.payload</b> is an object containing multiple properties, the fields will be written to the measurement.</p>
<p>If <b>msg.payload</b> is an array containing two objects, the first object will be written as the set of named fields,
the second is the set of named tags.</p>
<p>Finally, if <b>msg.payload</b> is an array of arrays, it will be written as a series of points containing fields and tags.</p>
<p>If the <i>measurement</i> field is not set in the node configuration, the user can send in data with a specified
measurement name in <b>msg.measurement</b> to overwrite the <i>measurement</i> field in the configuration of the node.</p>
<p>Check <i>Advanced Query Options</i> to specify a time precision and retention policy for the insertion.<p>
<p>The advanced query options <i>Time Precision</i> and <i>Retention Policy</i> can be overwritten using
message properties <b>msg.precision</b> and <b>msg.retentionPolicy</b>.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('influxdb out', {
category: 'storage-output',
color: "rgb(218, 196, 180)",
defaults: {
influxdb: {type: "influxdb", required: true},
name: {value: ""},
measurement: {value: ""},
precision: {value: ""},
retentionPolicy: {value: ""}
},
inputs: 1,
outputs: 0,
icon: "influxdb.png",
align: "right",
label: function() {
var influxNode = RED.nodes.node(this.influxdb);
return this.name || (influxNode ? influxNode.label() + " " + this.measurement: "influxdb");
},
labelStyle: function() {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function() {
$("#node-input-measurement").change(function () {
if($("#node-input-measurement").val() === "") {
$("#node-warning").show();
} else {
$("#node-warning").hide();
}
});
$("#advanced-options-checkbox").change( function () {
if ($('#advanced-options-checkbox').is(":checked")) {
$("#advanced-options-div").show();
} else {
$("#advanced-options-div").hide();
}
});
// show advanced options if a query option is set on startup
if (($('#node-input-precision').val() === "")
&& ($('#node-input-retentionPolicy').val() === "")) {
$("#advanced-options-div").hide();
} else {
$('#advanced-options-checkbox').prop('checked', true);
$("#advanced-options-div").show();
}
},
oneditsave: function() {
// reset inputs if we are not using advanced options
if (!$("#advanced-options-checkbox").is(':checked')) {
$("#node-input-precision").val("");
$("#node-input-retentionPolicy").val("");
}
}
});
</script>
<script type="text/x-red" data-template-name="influxdb batch">
<div class="form-row">
<label for="node-input-influxdb"><i class="fa fa-server"></i> <span data-i18n="influxdb.label.server"></span></label>
<input type="text" id="node-input-influxdb">
</div>
<div class="form-row">
<input type="checkbox" id="advanced-options-checkbox" style="display: inline-block; width: auto; vertical-align: top;">
<label for="advanced-options-checkbox" style="width: 70%;"><span data-i18n="influxdb.label.use-advanced-query"></span></label>
<div id="advanced-options-div" class="hide" style="margin-left: 20px; margin-top: 10px;">
<div class="form-row">
<label for="node-input-precision" style="width:35%"><i class="fa fa-clock-o"></i> <span data-i18n="influxdb.label.time-precision"></span></label>
<select type="text" id="node-input-precision" style="width:55%">
<option value="">Default</option>
<option value="n">Nanoseconds (n)</option>
<option value="u">Microseconds (u)</option>
<option value="ms">Milliseconds (ms)</option>
<option value="s">Seconds (s)</option>
<option value="m">Minute (m)</option>
<option value="h">Hour (h)</option>
<option value="d">Day (d)</option>
<option value="w">Week (w)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-retentionPolicy" style="width:35%"><i class="fa fa-gavel"></i> <span data-i18n="influxdb.label.retention-policy"></span></label>
<input type="text" style="width:55%" id="node-input-retentionPolicy">
</div>
</div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-tips" id="node-warning" style="display: none"><span data-i18n="[html]influxdb.tip"></span></div>
</script>
<script type="text/x-red" data-help-name="influxdb batch">
<p>A influxdb output node to write multiple points (fields and tags) to multiple influxdb measurements.</p>
<p>The <b>msg.payload</b> needs to be an array of <i>point</i> objects.</p>
<p>The <b>measurement</b> property of a point contains the name of the measurement for the point. The <b>fields</b> property will contain the
fields of the point. If supplied, the <b>tags</b> property will contain the tags for the point. To set the time
for the point, supply a <b>timestamp</b> property.</p>
<p>Check <i>Advanced Query Options</i> to specify a time precision and retention policy for the insertion.<p>
<p>The advanced query options <i>Time Precision</i> and <i>Retention Policy</i> can be overwritten using
message properties <b>msg.precision</b> and <b>msg.retentionPolicy</b>.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('influxdb batch', {
category: 'storage-output',
color: "rgb(218, 196, 180)",
paletteLabel: 'influx batch',
defaults: {
influxdb: {type: "influxdb", required: true},
precision: {value: ""},
retentionPolicy: {value: ""},
name: {value: ""}
},
inputs: 1,
outputs: 0,
icon: "influxdb.png",
align: "right",
label: function() {
var influxNode = RED.nodes.node(this.influxdb);
return this.name || (influxNode ? influxNode.label() : "influxdb batch");
},
labelStyle: function() {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function() {
$("#advanced-options-checkbox").change( function () {
if ($('#advanced-options-checkbox').is(":checked")) {
$("#advanced-options-div").show();
} else {
$("#advanced-options-div").hide();
}
});
// show advanced options if a query option is set on startup
if (($('#node-input-precision').val() === "")
&& ($('#node-input-retentionPolicy').val() === "")) {
$("#advanced-options-div").hide();
} else {
$('#advanced-options-checkbox').prop('checked', true);
$("#advanced-options-div").show();
}
},
oneditsave: function() {
// reset inputs if we are not using advanced options
if (!$("#advanced-options-checkbox").is(':checked')) {
$("#node-input-precision").val("");
$("#node-input-retentionPolicy").val("");
}
}
});
</script>
<script type="text/x-red" data-template-name="influxdb in">
<div class="form-row">
<label for="node-input-influxdb"><i class="fa fa-server"></i> <span data-i18n="influxdb.label.server"></span></label>
<input type="text" id="node-input-influxdb">
</div>
<div class="form-row">
<label for="node-input-query"><i class="fa fa-briefcase"></i> <span data-i18n="influxdb.label.query"></span></label>
<input type="text" id="node-input-query">
</div>
<div class="form-row">
<input type="checkbox" id="node-input-rawOutput" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-rawOutput"><span data-i18n="influxdb.label.use-raw-output"></span></label>
</div>
<div class="form-row">
<input type="checkbox" id="advanced-options-checkbox" style="display: inline-block; width: auto; vertical-align: top;">
<label for="advanced-options-checkbox" style="width: 70%;"><span data-i18n="influxdb.label.use-advanced-query"></span></label>
<div id="advanced-options-div" class="hide" style="margin-left: 20px; margin-top: 10px;">
<div class="form-row">
<label for="node-input-precision" style="width:35%"><i class="fa fa-clock-o"></i> <span data-i18n="influxdb.label.time-precision"></span></label>
<select type="text" id="node-input-precision" style="width:55%">
<option value="">Default</option>
<option value="n">Nanoseconds (n)</option>
<option value="u">Microseconds (u)</option>
<option value="ms">Milliseconds (ms)</option>
<option value="s">Seconds (s)</option>
<option value="m">Minute (m)</option>
<option value="h">Hour (h)</option>
<option value="d">Day (d)</option>
<option value="w">Week (w)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-retentionPolicy" style="width:35%"><i class="fa fa-gavel"></i> <span data-i18n="influxdb.label.retention-policy"></span></label>
<input type="text" style="width:55%" id="node-input-retentionPolicy">
</div>
</div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-tips" id="node-warning" style="display: none"><span data-i18n="[html]influxdb.querytip"></span></div>
</script>
<script type="text/x-red" data-help-name="influxdb in">
<p>Allows basic queries to be made to an influxdb time series database.</p>
<p>The query can be specified in the configuration property or using the property
<b>msg.query</b>. The results will be returned in <b>msg.payload</b>.</p>
<p>To output the results of the query in the raw output format returned by InfluxDb,
check the <i>Raw Output</i> checkbox.</p>
<p>Check <i>Advanced Query Options</i> to specify a time precision and retention policy for the query.<p>
<p>The raw output configuration can be overwritten by the message property <b>msg.rawOutput</b>. </p>
<p>The advanced query options <i>Time Precision</i> and <i>Retention Policy</i> can be overwritten using
message properties <b>msg.precision</b> and <b>msg.retentionPolicy</b>.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('influxdb in', {
category: 'storage-input',
color: "rgb(218, 196, 180)",
defaults: {
influxdb: {type: "influxdb", required: true},
name: {value: ""},
query: {value: ""},
rawOutput: {value: false},
precision: {value: ""},
retentionPolicy: {value: ""}
},
inputs: 1,
outputs: 1,
icon: "influxdb.png",
label: function() {
var influxNode = RED.nodes.node(this.influxdb);
return this.name || (influxNode ? influxNode.label() + " " + this.query: "influxdb");
},
labelStyle: function() {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function() {
$("#node-input-query").change(function () {
if($("#node-input-query").val() === "") {
$("#node-warning").show();
} else {
$("#node-warning").hide();
}
});
$("#advanced-options-checkbox").change( function () {
if ($('#advanced-options-checkbox').is(":checked")) {
$("#advanced-options-div").show();
} else {
$("#advanced-options-div").hide();
}
});
// show advanced options if a query option is set on startup
if (($('#node-input-precision').val() === "")
&& ($('#node-input-retentionPolicy').val() === "")) {
$("#advanced-options-div").hide();
} else {
$('#advanced-options-checkbox').prop('checked', true);
$("#advanced-options-div").show();
}
},
oneditsave: function() {
// reset inputs if we are not using advanced options
if (!$("#advanced-options-checkbox").is(':checked')) {
$("#node-input-precision").val("");
$("#node-input-retentionPolicy").val("");
}
}
});
</script>

View File

@@ -0,0 +1,255 @@
var _ = require('lodash');
module.exports = function(RED) {
"use strict";
var Influx = require('influx');
/**
* Config node. Currently we only connect to one host.
*/
function InfluxConfigNode(n) {
RED.nodes.createNode(this,n);
this.hostname = n.hostname;
this.port = n.port;
this.database= n.database;
this.name = n.name;
this.usetls = n.usetls;
if (typeof this.usetls === 'undefined') {
this.usetls = false;
}
// for backward compatibility with old 'protocol' setting
if (n.protocol === 'https') {
this.usetls = true;
}
if (this.usetls && n.tls) {
var tlsNode = RED.nodes.getNode(n.tls);
if (tlsNode) {
this.hostOptions = {};
tlsNode.addTLSOptions(this.hostOptions);
}
}
this.client = new Influx.InfluxDB({
hosts: [ {
host: this.hostname,
port: this.port,
protocol: this.usetls ? "https" : "http",
options: this.hostOptions
}
],
database: this.database,
username: this.credentials.username,
password: this.credentials.password
});
}
RED.nodes.registerType("influxdb",InfluxConfigNode,{
credentials: {
username: {type:"text"},
password: {type: "password"}
}
});
/**
* Output node to write to an influxdb measurement
*/
function InfluxOutNode(n) {
RED.nodes.createNode(this,n);
this.measurement = n.measurement;
this.influxdb = n.influxdb;
this.precision = n.precision;
this.retentionPolicy = n.retentionPolicy;
this.influxdbConfig = RED.nodes.getNode(this.influxdb);
if (this.influxdbConfig) {
var node = this;
var client = this.influxdbConfig.client;
node.on("input",function(msg) {
var measurement;
var writeOptions = {};
var measurement = msg.hasOwnProperty('measurement') ? msg.measurement : node.measurement;
if (!measurement) {
node.error(RED._("influxdb.errors.nomeasurement"),msg);
return;
}
var precision = msg.hasOwnProperty('precision') ? msg.precision : node.precision;
var retentionPolicy = msg.hasOwnProperty('retentionPolicy') ? msg.retentionPolicy : node.retentionPolicy;
if (precision) {
writeOptions.precision = precision;
}
if (retentionPolicy) {
writeOptions.retentionPolicy = retentionPolicy;
}
// format payload to match new writePoints API
var points = [];
var point;
var timestamp;
if (_.isArray(msg.payload) && msg.payload.length > 0) {
// array of arrays
if (_.isArray(msg.payload[0]) && msg.payload[0].length > 0) {
msg.payload.forEach(function(nodeRedPoint) {
point = {
measurement: measurement,
fields: nodeRedPoint[0],
tags: nodeRedPoint[1]
}
if (point.fields.time) {
point.timestamp = point.fields.time;
delete point.fields.time;
}
points.push(point);
});
} else {
// array of non-arrays, assume one point with both fields and tags
point = {
measurement: measurement,
fields: msg.payload[0],
tags: msg.payload[1]
};
if (point.fields.time) {
point.timestamp = point.fields.time;
delete point.fields.time;
}
points.push(point);
}
} else {
if (_.isPlainObject(msg.payload)) {
point = {
measurement: measurement,
fields: msg.payload
};
} else {
// just a value
point = {
measurement: measurement,
fields: {value:msg.payload}
};
}
if (point.fields.time) {
point.timestamp = point.fields.time;
delete point.fields.time;
}
points.push(point);
}
client.writePoints(points, writeOptions).catch(function(err) {
msg.influx_error = {
statusCode : err.res ? err.res.statusCode : 503
}
node.error(err,msg);
});
});
} else {
this.error(RED._("influxdb.errors.missingconfig"));
}
}
RED.nodes.registerType("influxdb out",InfluxOutNode);
/**
* Output node to write batches of points to influxdb
*/
function InfluxBatchNode(n) {
RED.nodes.createNode(this,n);
this.influxdb = n.influxdb;
this.precision = n.precision;
this.retentionPolicy = n.retentionPolicy;
this.influxdbConfig = RED.nodes.getNode(this.influxdb);
if (this.influxdbConfig) {
var node = this;
var client = this.influxdbConfig.client;
node.on("input",function(msg) {
var writeOptions = {};
var precision = msg.hasOwnProperty('precision') ? msg.precision : node.precision;
var retentionPolicy = msg.hasOwnProperty('retentionPolicy') ? msg.retentionPolicy : node.retentionPolicy;
if (precision) {
writeOptions.precision = precision;
}
if (retentionPolicy) {
writeOptions.retentionPolicy = retentionPolicy;
}
client.writePoints(msg.payload, writeOptions).catch(function(err) {
msg.influx_error = {
statusCode : err.res ? err.res.statusCode : 503
}
node.error(err,msg);
});
});
} else {
this.error(RED._("influxdb.errors.missingconfig"));
}
}
RED.nodes.registerType("influxdb batch",InfluxBatchNode);
/**
* Input node to make queries to influxdb
*/
function InfluxInNode(n) {
RED.nodes.createNode(this, n);
this.influxdb = n.influxdb;
this.query = n.query;
this.precision = n.precision;
this.retentionPolicy = n.retentionPolicy;
this.rawOutput = n.rawOutput;
this.influxdbConfig = RED.nodes.getNode(this.influxdb);
if (this.influxdbConfig) {
var node = this;
var client = this.influxdbConfig.client;
node.on("input", function (msg) {
var query;
var rawOutput;
var queryOptions = {};
var precision;
var retentionPolicy;
query = msg.hasOwnProperty('query') ? msg.query : node.query;
if (!query) {
node.error(RED._("influxdb.errors.noquery"), msg);
return;
}
rawOutput = msg.hasOwnProperty('rawOutput') ? msg.rawOutput : node.rawOutput;
precision = msg.hasOwnProperty('precision') ? msg.precision : node.precision;
retentionPolicy = msg.hasOwnProperty('retentionPolicy') ? msg.retentionPolicy : node.retentionPolicy;
if (precision) {
queryOptions.precision = precision;
}
if (retentionPolicy) {
queryOptions.retentionPolicy = retentionPolicy;
}
if (rawOutput) {
var queryPromise = client.queryRaw(query, queryOptions);
} else {
var queryPromise = client.query(query, queryOptions);
}
queryPromise.then(function (results) {
msg.payload = results;
node.send(msg);
}).catch(function (err) {
msg.influx_error = {
statusCode : err.res ? err.res.statusCode : 503
}
node.error(err, msg);
});
});
} else {
this.error(RED._("influxdb.errors.missingconfig"));
}
}
RED.nodes.registerType("influxdb in",InfluxInNode);
}

View File

@@ -0,0 +1,24 @@
{
"influxdb": {
"label": {
"host": "Host",
"port": "Port",
"database": "Database",
"measurement":"Measurement",
"server":"Server",
"query":"Query",
"use-tls": "Enable secure (SSL/TLS) connection",
"tls-config":"TLS Configuration",
"use-raw-output":"Raw Output",
"time-precision":"Time Precision",
"retention-policy":"Retention Policy",
"use-advanced-query":"Advanced Query Options"
},
"errors":{
"nomeasurement":"No measurement specified",
"missingconfig":"Configuration missing"
},
"tip":"<b> Tip:</b> If no measurement is specified, ensure <b>msg.measurement</b> contains the measurement name",
"querytip":"<b> Tip:</b> If no query is set, ensure <b>msg.query</b> contains a query."
}
}

View File

@@ -0,0 +1,62 @@
{
"_from": "node-red-contrib-influxdb@0.4.1",
"_id": "node-red-contrib-influxdb@0.4.1",
"_inBundle": false,
"_integrity": "sha512-OdWM/mq1MfnyxW/HNzWEkPLuM+vZkqQAwxF/JQI5hNl/HeDy1kwoHMohsOBMhZul/47JxrJrrZnpFLcrH1tw5w==",
"_location": "/node-red-contrib-influxdb",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "node-red-contrib-influxdb@0.4.1",
"name": "node-red-contrib-influxdb",
"escapedName": "node-red-contrib-influxdb",
"rawSpec": "0.4.1",
"saveSpec": null,
"fetchSpec": "0.4.1"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/node-red-contrib-influxdb/-/node-red-contrib-influxdb-0.4.1.tgz",
"_shasum": "d02985b5b3ba924a511d4448792a385779abac07",
"_spec": "node-red-contrib-influxdb@0.4.1",
"_where": "/data",
"author": {
"name": "Mike Blackstock",
"email": "mikeblackstock@gmail.com",
"url": "http://mblackstock.com"
},
"bugs": {
"url": "https://github.com/mblackstock/node-red-contrib-influxdb/issues"
},
"bundleDependencies": false,
"dependencies": {
"influx": "5.5.2",
"lodash": "4.17.15"
},
"deprecated": false,
"description": "Node-RED nodes to save and query data from an influxdb 1.x time series database",
"homepage": "https://github.com/mblackstock/node-red-contrib-influxdb#readme",
"keywords": [
"node-red",
"influxdb"
],
"license": "Apache-2.0",
"main": "influxdb.js",
"name": "node-red-contrib-influxdb",
"node-red": {
"nodes": {
"influxdb": "influxdb.js"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/mblackstock/node-red-contrib-influxdb.git"
},
"scripts": {
"test": "echo \"Error: no test specified yet!\" && exit 1"
},
"version": "0.4.1"
}

View File

@@ -0,0 +1,41 @@
# Test Flows README
To test this node, we use influxdb running in a docker container. Currently testing with influxdb 1.6.3
Set up influxdb using docker. See documentation at https://hub.docker.com/_/influxdb/
## Generating influxdb configuration
We have a configuration file already set up for use with a self signed cert. To generate a new, fresh config file locally:
docker run --rm influxdb:1.8 influxd config > influxdb.conf
## Set up self signed certificate
From the [influxdb admim documentation](https://docs.influxdata.com/influxdb/v1.6/administration/https_setup/) you can set up
self signed SSL cert as follows:
sudo openssl req -x509 -nodes -newkey rsa:2048 -keyout ./keys/influxdb-selfsigned.key -out ./keys/influxdb-selfsigned.crt
Answer the questions as you like.
## Running influxdb for tests
To run influxdb using the config file in the current directory:
docker run --name=influxdb -p 8086:8086 \
-v $PWD/influxdb.conf:/etc/influxdb/influxdb.conf:ro \
-v $PWD/ssl:/etc/ssl \
influxdb:1.8 -config /etc/influxdb/influxdb.conf
To run the influxdb CLI against this container using a self-signed cert:
docker run --rm --link=influxdb -it influxdb influx -ssl -unsafeSsl -host influxdb
You can then execute CLI commands to create databases, make queries, etc..
First, create a `test database to use by the test flows.
create database test
Then import the test flows into Node-RED and ensure they work.

View File

@@ -0,0 +1,152 @@
reporting-disabled = false
bind-address = "127.0.0.1:8088"
[meta]
dir = "/var/lib/influxdb/meta"
retention-autocreate = true
logging-enabled = true
[data]
dir = "/var/lib/influxdb/data"
index-version = "inmem"
wal-dir = "/var/lib/influxdb/wal"
wal-fsync-delay = "0s"
query-log-enabled = true
cache-max-memory-size = 1073741824
cache-snapshot-memory-size = 26214400
cache-snapshot-write-cold-duration = "10m0s"
compact-full-write-cold-duration = "4h0m0s"
max-series-per-database = 1000000
max-values-per-tag = 100000
max-concurrent-compactions = 0
max-index-log-file-size = 1048576
trace-logging-enabled = false
tsm-use-madv-willneed = false
[coordinator]
write-timeout = "10s"
max-concurrent-queries = 0
query-timeout = "0s"
log-queries-after = "0s"
max-select-point = 0
max-select-series = 0
max-select-buckets = 0
[retention]
enabled = true
check-interval = "30m0s"
[shard-precreation]
enabled = true
check-interval = "10m0s"
advance-period = "30m0s"
[monitor]
store-enabled = true
store-database = "_internal"
store-interval = "10s"
[subscriber]
enabled = true
http-timeout = "30s"
insecure-skip-verify = false
ca-certs = ""
write-concurrency = 40
write-buffer-size = 1000
[http]
enabled = true
bind-address = ":8086"
auth-enabled = false
log-enabled = true
suppress-write-log = false
write-tracing = false
pprof-enabled = true
debug-pprof-enabled = false
https-enabled = true
https-certificate = "/etc/ssl/influxdb-selfsigned.crt"
https-private-key = "/etc/ssl/influxdb-selfsigned.key"
max-row-limit = 0
max-connection-limit = 0
shared-secret = ""
realm = "InfluxDB"
unix-socket-enabled = false
unix-socket-permissions = "0777"
bind-socket = "/var/run/influxdb.sock"
max-body-size = 25000000
access-log-path = ""
max-concurrent-write-limit = 0
max-enqueued-write-limit = 0
enqueued-write-timeout = 30000000000
[logging]
format = "auto"
level = "info"
suppress-logo = false
[ifql]
enabled = false
log-enabled = true
bind-address = ":8082"
[[graphite]]
enabled = false
bind-address = ":2003"
database = "graphite"
retention-policy = ""
protocol = "tcp"
batch-size = 5000
batch-pending = 10
batch-timeout = "1s"
consistency-level = "one"
separator = "."
udp-read-buffer = 0
[[collectd]]
enabled = false
bind-address = ":25826"
database = "collectd"
retention-policy = ""
batch-size = 5000
batch-pending = 10
batch-timeout = "10s"
read-buffer = 0
typesdb = "/usr/share/collectd/types.db"
security-level = "none"
auth-file = "/etc/collectd/auth_file"
parse-multivalue-plugin = "split"
[[opentsdb]]
enabled = false
bind-address = ":4242"
database = "opentsdb"
retention-policy = ""
consistency-level = "one"
tls-enabled = false
certificate = "/etc/ssl/influxdb.pem"
batch-size = 1000
batch-pending = 5
batch-timeout = "1s"
log-point-errors = true
[[udp]]
enabled = false
bind-address = ":8089"
database = "udp"
retention-policy = ""
batch-size = 5000
batch-pending = 10
read-buffer = 0
batch-timeout = "1s"
precision = ""
[continuous_queries]
log-enabled = true
enabled = true
query-stats-enabled = false
run-interval = "1s"
[tls]
min-version = ""
max-version = ""

View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDBDCCAewCCQCDcrNep3/xPDANBgkqhkiG9w0BAQsFADBEMQswCQYDVQQGEwJD
QTELMAkGA1UECAwCQkMxEjAQBgNVBAcMCVZhbmNvdXZlcjEUMBIGA1UECgwLU2Vu
c2VUZWNuaWMwHhcNMTgwOTI5MjMyMDIwWhcNMTgxMDI5MjMyMDIwWjBEMQswCQYD
VQQGEwJDQTELMAkGA1UECAwCQkMxEjAQBgNVBAcMCVZhbmNvdXZlcjEUMBIGA1UE
CgwLU2Vuc2VUZWNuaWMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
45td3PIAhNuzoPFKIhvxoWAAmLV4U1S9d2bby51J1/XfcHPLAQB7H8jRQyBV5z1b
APhTWZKxrM9tseRbBrABzN9VlS+FfzQRW/RyOKUCa5clepgHoeP0I8RIX4cMAA4c
63RxobqIdw6WgSoUSY8Z/t+DNhqJkWyK2UaMyTmS9k9L/kxVXTSi+5QeaEW7wAW+
aUHvsBiNqb1RzPKDNYfwvlrbYvUyC2ymI684yN0l7tq7XOgMDbyLbVE1+9k/L+9a
QgsqM3462q13GyOZpURvsNYZhIT+BeArB17kDlYQvn0+/nFKGy6jGcLUawfg8RW5
sr2z4IuVKxUGBUs71oKLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD58NMK5VDoN
w6P4XDx/L6BDl9j6lPV9Qg3F8BqAfFeW080oy/DTaXaE0zZZPijREGoaxk6eI85d
BtU4YWBkBC5jxAVITx/jE99GkklQOzU+Ppzjp51wX/zlsw3WCjusEhh4v2AKBH/8
y3z7Sdwo58/QNqGSOjH5YxbjndPbehJsUbHkVsi1y0jfaAGFP7rkkFKFs0xtuSiw
v8/J2THuG7idWozddeWyDufrrLAsAHve+y9n/J7IoayDshmAhR6Noa2TyZS4rvpB
zMs2Wq5tzY/EXhJIOaPMYb+b+ca7njfN7zH0DgCjklqHhWQyHe2MQdHMVWVl9u1e
e80MdJjhlko=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC245td3PIAhNuz
oPFKIhvxoWAAmLV4U1S9d2bby51J1/XfcHPLAQB7H8jRQyBV5z1bAPhTWZKxrM9t
seRbBrABzN9VlS+FfzQRW/RyOKUCa5clepgHoeP0I8RIX4cMAA4c63RxobqIdw6W
gSoUSY8Z/t+DNhqJkWyK2UaMyTmS9k9L/kxVXTSi+5QeaEW7wAW+aUHvsBiNqb1R
zPKDNYfwvlrbYvUyC2ymI684yN0l7tq7XOgMDbyLbVE1+9k/L+9aQgsqM3462q13
GyOZpURvsNYZhIT+BeArB17kDlYQvn0+/nFKGy6jGcLUawfg8RW5sr2z4IuVKxUG
BUs71oKLAgMBAAECggEABoQfgf2gRbJ2HXVLg4eplTdZs0u9k3bsmv+JE6WyifH+
2aIpDf+QI9LjFcmdelIN1pM3Rcj4OApfLZpb935KgRXqkyMImWoJ0eCD2hn4jxiE
PxqaFhOHiqhHkwiMSDosRo2BDZdkjP4o7+XUOPrR9WwmTId99I7Q3jWVlOiKe5jp
mO/6WpQNfUzQDeCw+dajb5V+CK7BdRg71oN0VYkh4TDRJu20mgdoful747HX46Tl
dc+exFLIhohJrQUaRVDmb992hu3GJXQuDdQVFA5AIs5royLR4ZyVie+s/jF42cxM
YBowtvcGxZ2X/q8/XQwfRRE3jlB1xpjVHj8jfOtioQKBgQDanchewW/QStHcprog
7mQtEwV3BoGDljUtULxWi1IztpuYSdOE5p054LFIFsEhxoEVBaBOut3RG3B5w+rn
kFggClUp8eg907BtdixZ2mBWhCEo6saMAm9tcQ7wmzXIIQs6IhAW94tGXwaIaPFe
80oGzoogXC0QdBSP6o6A71CcuwKBgQDWKdEkAYTKtKmffbz17faDPRqZAd+E3dWZ
BaM1kcQJh5JxBv79bN5MZBelYvbIseYIEl7L+aMp5TWAJD+6DTiJK4mBdvkEMBeO
ZHefvc7UlohIQaiziS+z5x3vHwYMbTeS4lLMp+MmW++HkrLGY1kulSaSpk7vVk3q
1z4HI/i8cQKBgBamXkoi9Hi6J8AarhIXYN2iqOBKFkUR3PSS9tBoot2kv74pd/a/
Be8nLnbvlJbxQBJzgMZnae/uTdrvx3iyZc78AxLTc2JkelT8919f1rdf/SeGG4gK
AI1wN0IKcqoHcmhVeyFGCHIECmM7rDZQMo09/OWZZznbLP40KQuGv+1dAoGAYKwJ
ovYoihPZCYyJkn2zK/SWIAEvc1trgqJ/1LuSwTZ4TRr6WU0eX19DKT2t5lQfYP9h
2TM7irrTVp+GQKadIZYMgOtCZriKuZTyRqI4TdARfoRc8YX4iX3HDlxzr4JRdrVA
6O7T40nWqtz2ZAUOia979PCravALRfmZH0IGkpECgYA0xvtg2jhDLQGPUEl/ft3W
jenP1RkYAuOEpBK3traqed6Rb5IT75h8JKlqo9N6wX2xUuUZtdUrct1mvRgmanv1
29WS9a+dGx7NBycKrkMMDbaHVEshiP0kA8bpnOD0ssCoKrMOyOJRJw+ZVaXhFnt+
ulVCZQW6fWqtCHtRGZ4BMQ==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,271 @@
[
{
"id": "99bf88cf.4254c8",
"type": "influxdb in",
"z": "e7ce51cb.4244",
"influxdb": "730dac77.69ca34",
"name": "",
"query": "select * from test",
"rawOutput": false,
"precision": "",
"retentionPolicy": "",
"x": 450,
"y": 400,
"wires": [
[
"fa349e8c.f740a"
]
]
},
{
"id": "d1adae5b.bca4",
"type": "inject",
"z": "e7ce51cb.4244",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 200,
"y": 400,
"wires": [
[
"99bf88cf.4254c8"
]
]
},
{
"id": "fa349e8c.f740a",
"type": "debug",
"z": "e7ce51cb.4244",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 710,
"y": 400,
"wires": []
},
{
"id": "eac189ce.f28be8",
"type": "inject",
"z": "e7ce51cb.4244",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"x": 360,
"y": 100,
"wires": [
[
"b397e971.522bd8"
]
]
},
{
"id": "b397e971.522bd8",
"type": "function",
"z": "e7ce51cb.4244",
"name": "Fields",
"func": "msg.payload = {\n numValue: 123.0,\n strValue: \"message\",\n randomValue: Math.random()*10\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 508,
"y": 100,
"wires": [
[
"51fc70d6.dc65b"
]
]
},
{
"id": "51fc70d6.dc65b",
"type": "influxdb out",
"z": "e7ce51cb.4244",
"influxdb": "730dac77.69ca34",
"name": "",
"measurement": "test",
"precision": "",
"retentionPolicy": "",
"x": 698,
"y": 100,
"wires": []
},
{
"id": "a9d0f3cc.bbceb",
"type": "inject",
"z": "e7ce51cb.4244",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"x": 340,
"y": 160,
"wires": [
[
"a284e9c0.969b08"
]
]
},
{
"id": "a284e9c0.969b08",
"type": "function",
"z": "e7ce51cb.4244",
"name": "Fields and Tags",
"func": "msg.payload = [{\n numValue: 12,\n randomValue: Math.random()*10,\n strValue: \"message2\"\n},\n{\n tag1:\"sensor1\",\n tag2:\"device2\"\n}];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 511,
"y": 160,
"wires": [
[
"2056b637.2cdf8a"
]
]
},
{
"id": "2056b637.2cdf8a",
"type": "influxdb out",
"z": "e7ce51cb.4244",
"influxdb": "730dac77.69ca34",
"name": "",
"measurement": "test",
"precision": "",
"retentionPolicy": "",
"x": 719,
"y": 160,
"wires": []
},
{
"id": "b70228ff.b5c1c8",
"type": "function",
"z": "e7ce51cb.4244",
"name": "multiple readings",
"func": "msg.payload = [\n [{\n numValue: 10,\n randomValue: Math.random()*10,\n strValue: \"message1\",\n time: new Date(\"2015-12-28T19:41:13Z\").getTime()\n },\n {\n tag1:\"sensor1\",\n tag2:\"device2\"\n }],\n [{\n numValue: 20,\n randomValue: Math.random()*10,\n strValue: \"message2\",\n time: new Date(\"2015-12-28T19:41:14Z\").getTime()\n },\n {\n tag1:\"sensor1\",\n tag2:\"device2\"\n }]\n];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 490,
"y": 240,
"wires": [
[
"f77ae03a.c8af"
]
]
},
{
"id": "cc5a4f6c.7ca5",
"type": "inject",
"z": "e7ce51cb.4244",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"x": 316,
"y": 240,
"wires": [
[
"b70228ff.b5c1c8"
]
]
},
{
"id": "f77ae03a.c8af",
"type": "influxdb out",
"z": "e7ce51cb.4244",
"influxdb": "730dac77.69ca34",
"name": "",
"measurement": "test",
"precision": "",
"retentionPolicy": "",
"x": 711,
"y": 239,
"wires": []
},
{
"id": "b005e63a.2cde38",
"type": "function",
"z": "e7ce51cb.4244",
"name": "multiple measurement points",
"func": "msg.payload = [\n {\n measurement: \"weather_sensor\",\n fields: {\n temp: 5.5,\n light: 678,\n humidity: 51\n },\n tags:{\n location:\"garden\"\n },\n timestamp: new Date()\n },\n {\n measurement: \"alarm_sensor\",\n fields: {\n proximity: 999,\n temp: 19.5\n },\n tags:{\n location:\"home\"\n },\n timestamp: new Date()\n }\n];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 440,
"y": 320,
"wires": [
[
"ea1abed6.da87d"
]
]
},
{
"id": "fb899d8a.42d35",
"type": "inject",
"z": "e7ce51cb.4244",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"x": 220,
"y": 320,
"wires": [
[
"b005e63a.2cde38"
]
]
},
{
"id": "ea1abed6.da87d",
"type": "influxdb batch",
"z": "e7ce51cb.4244",
"influxdb": "730dac77.69ca34",
"precision": "",
"retentionPolicy": "",
"name": "",
"x": 690,
"y": 320,
"wires": []
},
{
"id": "730dac77.69ca34",
"type": "influxdb",
"z": "",
"hostname": "127.0.0.1",
"port": "8086",
"protocol": "http",
"database": "test",
"name": "",
"usetls": true,
"tls": "8086d718.bcda28"
},
{
"id": "8086d718.bcda28",
"type": "tls-config",
"z": "",
"name": "",
"cert": "",
"key": "",
"ca": "",
"certname": "",
"keyname": "",
"caname": "",
"servername": "",
"verifyservercert": false
}
]