Node-red writing on InfluxDB

Hey guys I currently have a REST sensor that gets energy consumption and HA automatically puts it into InfluxDB. It looks something like the screenshot I’m attaching. As you can see HA does it so it’s under “W”, then entity_id and then the entity name (shelly_usage_watts)

However now I want to write from node-red to that same table/path but I’m not sure how to setup node-red to do that. I have a “Measurement” field where I’m using W, but I’m not sure how to get “inside” to write into the shelly_usage_watts
Screenshot 2021-07-14 at 17.58.07

Anyone got an example of that I can look at and learn from it? Thanks a lot!

First you should create a separate db and user in influxdb to practice with. Sending the wrong values to a measurement can really screw things up. I have this flow that checks message structure. It’s a matter of routing what you save in a change node to the correct message position.

[{"id":"b47174e3.35aef8","type":"group","z":"3d343940.cf7566","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["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","d282f435.07c18"],"x":334,"y":539,"w":1172,"h":502},{"id":"7273324f.7f53ac","type":"inject","z":"3d343940.cf7566","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":990,"y":680,"wires":[["d282f435.07c18"]]},{"id":"a000bc32.2dc19","type":"function","z":"3d343940.cf7566","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":"","libs":[],"x":860,"y":780,"wires":[["2dbcfbbd.b61f44","d282f435.07c18"]],"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":"3d343940.cf7566","g":"b47174e3.35aef8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1175,"y":800,"wires":[],"l":false},{"id":"4c6ac117.8bbe6","type":"inject","z":"3d343940.cf7566","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":480,"y":580,"wires":[["a000bc32.2dc19"]]},{"id":"d16b6be1.138148","type":"inject","z":"3d343940.cf7566","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":510,"y":880,"wires":[["a000bc32.2dc19"]]},{"id":"a13fc0ed.df4e","type":"inject","z":"3d343940.cf7566","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":510,"y":620,"wires":[["a000bc32.2dc19"]]},{"id":"dc063c13.07848","type":"inject","z":"3d343940.cf7566","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":470,"y":660,"wires":[["a000bc32.2dc19"]]},{"id":"e0d6c61d.faee48","type":"inject","z":"3d343940.cf7566","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":510,"y":700,"wires":[["a000bc32.2dc19"]]},{"id":"91c03b02.b2c198","type":"inject","z":"3d343940.cf7566","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":520,"y":740,"wires":[["a000bc32.2dc19"]]},{"id":"312b8552.1db4ea","type":"inject","z":"3d343940.cf7566","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":520,"y":780,"wires":[["a000bc32.2dc19"]]},{"id":"b7c7c8cb.4003d8","type":"inject","z":"3d343940.cf7566","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":520,"y":820,"wires":[["a000bc32.2dc19"]]},{"id":"79bbe9aa.3a2408","type":"inject","z":"3d343940.cf7566","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":490,"y":920,"wires":[["a000bc32.2dc19"]]},{"id":"4025e7d.27e6c18","type":"inject","z":"3d343940.cf7566","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":520,"y":960,"wires":[["a000bc32.2dc19"]]},{"id":"913cf8ef.65c9f8","type":"inject","z":"3d343940.cf7566","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":500,"y":1000,"wires":[["a000bc32.2dc19"]]},{"id":"54b3c063.c132b","type":"comment","z":"3d343940.cf7566","g":"b47174e3.35aef8","name":"Test validation function for influxdb-out","info":"","x":930,"y":620,"wires":[]},{"id":"d282f435.07c18","type":"influxdb out","z":"3d343940.cf7566","g":"b47174e3.35aef8","influxdb":"35db8db.37760f2","name":"","measurement":"measure1","precision":"ms","retentionPolicy":"7d","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"organisation","bucket":"bucket","x":1310,"y":740,"wires":[]},{"id":"35db8db.37760f2","type":"influxdb","hostname":"192.168.0.101","port":"8086","protocol":"http","database":"nodered","name":"","usetls":false,"tls":"24a4158b.d8e9ca","influxdbVersion":"1.x","url":"https://192.168.0.101:8086","rejectUnauthorized":false},{"id":"24a4158b.d8e9ca","type":"tls-config","name":"","cert":"","key":"","ca":"","certname":"fullchain.pem","keyname":"privkey.pem","caname":"","servername":"","verifyservercert":false}]

Thanks a lot! I will check this out soon and give it a try

I forgot to add that numbers, if using the events all node, sends a string. Multiply by one to change to float.

[{"id":"9f562806.43eb78","type":"server-events","z":"3d343940.cf7566","name":"","server":"6b1110b5.183a4","version":1,"event_type":"state_changed","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"waitForRunning":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"}],"x":180,"y":140,"wires":[["bfba911d.a827d8"]]},{"id":"bfba911d.a827d8","type":"switch","z":"3d343940.cf7566","name":"","property":"payload.entity_id","propertyType":"msg","rules":[{"t":"eq","v":"sensor.2a_main_01_amps","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":390,"y":140,"wires":[["9d0b539.a92233"]]},{"id":"9d0b539.a92233","type":"function","z":"3d343940.cf7566","name":"","func":"var st = msg.payload.event.new_state.state*1;\nvar name = msg.payload.entity_id;\nmsg.measurement = name;\nmsg.payload = st;\nreturn msg;\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":140,"wires":[["26ccff6.a48c9"]]},{"id":"26ccff6.a48c9","type":"influxdb out","z":"3d343940.cf7566","influxdb":"35db8db.37760f2","name":"","measurement":"","precision":"ms","retentionPolicy":"7d","database":"nodered","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"nodered","bucket":"nodered","x":940,"y":140,"wires":[]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":1,"legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true},{"id":"35db8db.37760f2","type":"influxdb","hostname":"192.168.0.101","port":"8086","protocol":"http","database":"nodered","name":"","usetls":false,"tls":"24a4158b.d8e9ca","influxdbVersion":"1.x","url":"https://192.168.0.101:8086","rejectUnauthorized":false},{"id":"24a4158b.d8e9ca","type":"tls-config","name":"","cert":"","key":"","ca":"","certname":"fullchain.pem","keyname":"privkey.pem","caname":"","servername":"","verifyservercert":false}]

oh wow, this is more complicated than what I anticipated! I need to learn a few things before getting into it!. Thanks Mikefila!

There are two main parts, whatever is in msg.payload will be stored as the value. Then msg.measurement will be the heading its stored under. That’s all I use.