|
[ |
|
{ |
|
"id": "b47174e3.35aef8", |
|
"type": "group", |
|
"z": "33700a61.0a0d46", |
|
"style": { |
|
"stroke": "#999999", |
|
"stroke-opacity": "1", |
|
"fill": "none", |
|
"fill-opacity": "1", |
|
"label": true, |
|
"label-position": "nw", |
|
"color": "#a4a4a4" |
|
}, |
|
"nodes": [ |
|
"1bb27551.b13a6b", |
|
"7273324f.7f53ac", |
|
"a000bc32.2dc19", |
|
"2dbcfbbd.b61f44", |
|
"4c6ac117.8bbe6", |
|
"d16b6be1.138148", |
|
"a13fc0ed.df4e", |
|
"dc063c13.07848", |
|
"e0d6c61d.faee48", |
|
"91c03b02.b2c198", |
|
"312b8552.1db4ea", |
|
"b7c7c8cb.4003d8", |
|
"79bbe9aa.3a2408", |
|
"4025e7d.27e6c18", |
|
"913cf8ef.65c9f8", |
|
"54b3c063.c132b" |
|
], |
|
"x": 54, |
|
"y": 1159, |
|
"w": 1132, |
|
"h": 502 |
|
}, |
|
{ |
|
"id": "1bb27551.b13a6b", |
|
"type": "influxdb out", |
|
"z": "33700a61.0a0d46", |
|
"d": true, |
|
"g": "b47174e3.35aef8", |
|
"influxdb": "c4e91fa4.30ca7", |
|
"name": "", |
|
"measurement": "measure1", |
|
"precision": "s", |
|
"retentionPolicy": "one_week", |
|
"database": "database", |
|
"precisionV18FluxV20": "ms", |
|
"retentionPolicyV18Flux": "", |
|
"org": "organisation", |
|
"bucket": "bucket", |
|
"x": 1020, |
|
"y": 1380, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "7273324f.7f53ac", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "", |
|
"props": [ |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"payload": "[{\"field1\":100,\"value\":101},{\"tagname1\":\"tag1val\"}]", |
|
"payloadType": "json", |
|
"x": 730, |
|
"y": 1360, |
|
"wires": [ |
|
[ |
|
"1bb27551.b13a6b" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "a000bc32.2dc19", |
|
"type": "function", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "Validate Input", |
|
"func": "/**\n * Validate input suitable for the influxdb-out node.\n * We will ALWAYS use the \"array containing two objects\" payload\n * OR the singe Object payload (if no tags being used).\n * See the Description tab for more details.\n */\n\n// check measurement field is set - if not exit with error\nif ( ! msg.measurement ) {\n node.error('msg.measurement is missing')\n return\n}\n\nlet fields,tags\n\n// if payload is an object, assume that it contains fieldName:fieldValue pairs\nif ( msg.payload!== null && msg.payload.constructor.name === 'Object' ) {\n fields = msg.payload\n} else if ( msg.payload!== null && msg.payload.constructor.name === 'Array' ) {\n node.error('msg.payload cannot be an array. It must be an object containing fieldName:fieldValue pairs or a single value (which would be written to the `value` field name).')\n return\n} else {\n // Otherwise, we always use 'value' as the default field name\n fields = {'value': msg.payload}\n}\n\nconst lstFields = Object.keys(fields)\n\n// check to make sure that there is a value field name - if not, continue but with a warning\nif ( ! lstFields.includes('value') ) {\n // Lets us turn off the warning if we know what we are doing :-)\n if ( msg.noValueField !== true )\n node.warn('Default field name \"vaue\" not present, was that deliberate? Set msg.noValueField=true or use the `value` field name to avoid this msg')\n}\n\n// check to make sure that all field values are numeric - if not, exit with a warning\nlet allNumeric = true\nlstFields.forEach( key => {\n // I use On/Off for simple switch values in MQTT but these are not useful\n // in InfluxDB, so translate them to ON=1 and OFF=0 (ignoring case).\n try {\n if ( fields[key].toLowerCase() === 'on' ) fields[key] = 1\n if ( fields[key].toLowerCase() === 'off' ) fields[key] = 0\n } catch (e) {}\n\n // then check to make sure the field is actually a number\n if ( parseFloat(fields[key]) !== fields[key] ) {\n node.error(`Field msg.payload.${key} is not numeric. Only use numbers for field values, text should go in tags.`)\n allNumeric = false\n return\n }\n})\nif ( allNumeric === false ) {\n return\n}\n\n// check to make sure that if msg.tags is present, it is an object - if not, exit with a warning\nif ( msg.tags ) {\n if ( !(msg.tags!== null && msg.tags.constructor.name === 'Object') ) {\n node.error('msg.tags is not an object - it must contain tagName:tagValue pairs')\n return\n }\n tags = msg.tags\n}\n\n// Format the output to go to the InfluxDB out node\nif ( msg.tags ) {\n msg.payload = [\n fields,\n tags,\n ]\n} else {\n msg.payload = fields\n}\n\n\nreturn msg;", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"x": 580, |
|
"y": 1400, |
|
"wires": [ |
|
[ |
|
"1bb27551.b13a6b", |
|
"2dbcfbbd.b61f44" |
|
] |
|
], |
|
"info": "This function validates msg input to ensure that it is suitable for the influxdb-out node.\n\nUse the following input msg schema:\n\n* `msg.payload`: **MUST** be an object containing fieldName:fieldValue pairs; OR a single value that will be written to the `value` field which is the default field name for InfluxDB.\n* `msg.measurement`: **MUST** be a valid measurement name for the database being written to.\n* `msg.tags`: Is _OPTIONAL_. If present, it **MUST** be an object containing tagName:tagValue pairs.\n\nWe will ALWAYS use the \"array containing two objects\" payload\nOR the singe Object payload (if no tags being used).\n\n## Tests\n* _SUCCESS_: \n `msg={\"payload\":{\"fieldName1\":10,\"value\":15},\"tags\":{\"tagName1\":\"tagname1Value\"},\"measure\":\"myMeasure1\"}`\n* _SUCCESS_ (payload converted to `{\"value\":16}`): \n `msg={\"payload\":16,\"tags\":{\"tagName1\":\"tagname1Value\"},\"measure\":\"myMeasure2\"}`\n* _SUCCESS_ (no tags): \n `msg={\"payload\":16,\"measure\":\"myMeasure2\"}`\n* _SUCCESS_ (but warning issued, no value field): \n `msg={\"payload\":{\"fieldName2\":17},\"tags\":{\"tagName1\":\"tagname1Value\"},\"measure\":\"myMeasure3\"}`\n* _SUCCESS_ (value \"On\" converted to 1): \n `msg={\"payload\":\"On\",\"measure\":\"myMeasure4\"}`\n* _???_ (missing tags for a measure with tags): \n `msg={\"payload\":\"On\",\"measure\":\"myMeasure1\"}`\n* _FAIL_: No `msg.measure`\n* _FAIL_: `msg.payload` is an array\n* _FAIL_: 1 or more fields have non-numeric values\n* _FAIL_: msg.tags exists but is not an object\n\n## Expected output formats\n```\nmsg.payload = [\n objFields,\n objTags\n]\n```\nOR (if no tags)\n```\nmsg.payload = {\n \"fieldName1\":123,\n \"fieldName2\":23,\n \"value\":3,\n}\n```" |
|
}, |
|
{ |
|
"id": "2dbcfbbd.b61f44", |
|
"type": "debug", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "", |
|
"active": true, |
|
"tosidebar": true, |
|
"console": false, |
|
"tostatus": false, |
|
"complete": "true", |
|
"targetType": "full", |
|
"statusVal": "", |
|
"statusType": "auto", |
|
"x": 895, |
|
"y": 1420, |
|
"wires": [], |
|
"l": false |
|
}, |
|
{ |
|
"id": "4c6ac117.8bbe6", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/Valid Input", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/Valid Input", |
|
"payload": "{\"field1\":10,\"value\":15}", |
|
"payloadType": "json", |
|
"x": 200, |
|
"y": 1200, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "d16b6be1.138148", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "FAIL/msg.measurement missing", |
|
"props": [ |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "FAIL/msg.measurement missing", |
|
"payload": "{\"field1\":10,\"value\":15}", |
|
"payloadType": "json", |
|
"x": 230, |
|
"y": 1500, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "a13fc0ed.df4e", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/single value payload", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/single value payload", |
|
"payload": "16", |
|
"payloadType": "num", |
|
"x": 230, |
|
"y": 1240, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "dc063c13.07848", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/no tags", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/no tags", |
|
"payload": "16", |
|
"payloadType": "num", |
|
"x": 190, |
|
"y": 1280, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "e0d6c61d.faee48", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/no value field/warning", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/but warning issued, no value field", |
|
"payload": "{\"fieldname2\":17}", |
|
"payloadType": "json", |
|
"x": 230, |
|
"y": 1320, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "91c03b02.b2c198", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/no value field/no warning", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
}, |
|
{ |
|
"p": "noValueField", |
|
"v": "true", |
|
"vt": "bool" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/no value field, no warning", |
|
"payload": "{\"fieldname2\":17}", |
|
"payloadType": "json", |
|
"x": 240, |
|
"y": 1360, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "312b8552.1db4ea", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/value \"On\" converted to 1", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/On converted to 1", |
|
"payload": "On", |
|
"payloadType": "str", |
|
"x": 240, |
|
"y": 1400, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "b7c7c8cb.4003d8", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "SUCCESS/value \"Off\" converted to 1", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "SUCCESS/Off converted to 1", |
|
"payload": "{\"fieldname3\":\"Off\",\"value\":\"ON\"}", |
|
"payloadType": "json", |
|
"x": 240, |
|
"y": 1440, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "79bbe9aa.3a2408", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "FAIL/payload is an array", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "FAIL/payload is an array", |
|
"payload": "[10,15]", |
|
"payloadType": "json", |
|
"x": 210, |
|
"y": 1540, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "4025e7d.27e6c18", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "FAIL/Field with non-numeric value", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "json" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "FAIL/Field with non-numeric value", |
|
"payload": "{\"field1\":\"hello\",\"value\":true}", |
|
"payloadType": "json", |
|
"x": 240, |
|
"y": 1580, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "913cf8ef.65c9f8", |
|
"type": "inject", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "FAIL/tags exists but not object", |
|
"props": [ |
|
{ |
|
"p": "topic", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "payload" |
|
}, |
|
{ |
|
"p": "measurement", |
|
"v": "measure1", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "tags", |
|
"v": "{\"tagname1\":\"tagname1Value\"}", |
|
"vt": "str" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "FAIL/msg.tags exists but is not an object", |
|
"payload": "{\"field1\":10,\"value\":15}", |
|
"payloadType": "json", |
|
"x": 220, |
|
"y": 1620, |
|
"wires": [ |
|
[ |
|
"a000bc32.2dc19" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "54b3c063.c132b", |
|
"type": "comment", |
|
"z": "33700a61.0a0d46", |
|
"g": "b47174e3.35aef8", |
|
"name": "Test validation function for influxdb-out", |
|
"info": "", |
|
"x": 650, |
|
"y": 1240, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "c4e91fa4.30ca7", |
|
"type": "influxdb", |
|
"hostname": "127.0.0.1", |
|
"port": "8086", |
|
"protocol": "http", |
|
"database": "test", |
|
"name": "", |
|
"usetls": false, |
|
"tls": "", |
|
"influxdbVersion": "1.x", |
|
"url": "http://localhost:8086", |
|
"rejectUnauthorized": true |
|
} |
|
] |