I'm running 2.x as well and haven't seen anything that would absolutely push me to upgrade (other than my impatience). The new function UI is nice, but not necessary as is the debugging tool. Other than that, I don't see too many differences.
No soecific reason to upgrade today.
That said, I do use the new debugging tools and the Monaco editor in 2.x, and like them.
There are inject node improvements around 1.2.x that I find very useful.
Same, updated to NR2.05 and works without issue.
Anyone have an idea what is causing this error or how to fix it? It looks like it's happening on power node for influxdb. It seems to have appeared after the recent Hubitat platform updates as I've had no other changes for weeks.

I'm guessing something in this function node to get the data into influxdb no longer works with the recent hub update?
As it's the only thing in the sequence between the devices sending the data and the node going into influxdb.

No idea what is happening but take a look at this link:
Thanks for the pointer, I tried a few things with no success but don't really know what I'm doing. So I'll probably just not look at the debug errors until something starts causing a problem.
I'm looking for some help please.
I've got a flow that keeps track of my zigbee2mqtt devices, and when they last meshed with the mesh. However, after a reinstall recently, they only seem to update the flow, if the dashboard is Open somewhere. How would I go about making it update when the dash is closed, and then show an up-to-date listing when I open my dash. Here is the flow.
[{"id":"87af4aff.b17178","type":"change","z":"8c249630.076968","name":"Make table update","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"command\":\"updateOrAddData\",\t \"arguments\":[\t [\t {\t \"id\":msg.device.friendly_name,\t \"value\":msg.payload,\t \"name\":msg.device.friendly_name\t }\t ]\t ],\t \"returnPromise\":true\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1750,"y":1640,"wires":[["2c22ee36.5a7e52","e32ca362.ba5fa"]]},{"id":"e32ca362.ba5fa","type":"function","z":"8c249630.076968","name":"table recorder","func":"var status = {fill:\"red\",shape:\"ring\",text:\"an error occured\"};\nvar success = (msg.topic && msg.topic===\"success\") || false;\nvar tableData2 = flow.get(\"tableData2\");\nif (tableData2 === undefined) {\n tableData2 = [];\n flow.set(\"tableData2\",tableData2);\n}\n\n// find the index for a row in tableData2 for a given index (id)\nfunction checkIndex(id) {\n let matchRow=-1;\n tableData2.forEach(function (row,index){\n if (row.id === id){\n matchRow=index;\n return matchRow;\n }\n });\n return matchRow;\n}\n\n// flat merge one row \nfunction mergeRow(dest,source) {\n Object.keys(source).forEach(function(key) {\n dest[key]=source[key];\n });\n}\n\n//merge or add one or many rows into tableData2 \nfunction mergeData(newData,toTop) {\n newData.forEach(function (item,index) {\n // node.warn([\"findIndex\",item]);\n let row=checkIndex(item.id);\n if (row<0) { // row do not existst in tableData2\n if (toTop) {\n tableData2.push(item);\n status.text+=\"newRow @ top\";\n } else {\n tableData2.unshift(item);\n status.text+=\"newRow @ bottom\";\n }\n return;\n } else { // row exists so update\n mergeRow(tableData2[row],item);\n status.text+=\"row updated\";\n return;\n }\n if (status.text!==\"\") node.status(status);\n });\n}\n\nswitch (typeof msg.payload){\n case \"string\":\n // node.warn([\"[table recorder] \",(typeof msg.payload),msg.payload]);\n switch (msg.payload){\n case \"change\":\n status={fill:\"green\",shape:\"dot\",text:\"table restored \"+tableData2.length+\" rows\"};\n msg.payload=tableData2;\n break;\n }\n break;\n case \"object\":\n // node.warn([\"[table recorder] \",(typeof msg.payload),msg.payload]);\n if (Array.isArray(msg.payload)) { // replace all tableData2\n status={fill:\"green\",shape:\"dot\",text:\"table replaced \"+msg.payload.length+\" rows\"};\n tableData2=RED.util.cloneMessage(msg.payload); \n } else {\n switch (msg.payload.command) { // clearData does not return a promise!\n case \"clearData\":\n status={fill:\"green\",shape:\"dot\",text:\"clearData: done\"};\n tableData2=[];\n flow.set(\"lastId\",0);\n break; \n }\n }\n break;\n default: // likely a msg fom a ui-table command or callback\n if (msg.hasOwnProperty(\"topic\")&&\n msg.hasOwnProperty(\"ui_control\") && \n msg.ui_control.hasOwnProperty(\"callback\") &&\n msg.hasOwnProperty(\"return\")) { // message originates from a ui-table callback\n if (success) {\n switch(msg.return.command) {\n case \"addRow\":\n status.text=\"addRow: \";\n mergeData(msg.return.arguments[0],msg.return.arguments[1]);\n status.shape=\"dot\";\n break;\n case \"updateOrAddData\":\n status.text=\"updateOrAddData: \";\n mergeData(msg.return.arguments[0]);\n break;\n case \"deleteRow\":\n let row=checkIndex(msg.return.arguments[0]);\n tableData2.splice(row,1);\n status.shape=\"dot\";\n status.text=\"deleteRow: \"+row+\" deleted\";\n break;\n default:\n status={fill:\"yellow\",shape:\"dot\",text:msg.return.command + \" unknown!\"};\n break; \n }\n } else {\n status.text=msg.topic+\" \"+msg.error;\n }\n }\n break;\n}\nif (success) status.fill=\"green\";\nflow.set(\"tableData2\",tableData2);\nnode.status(status);\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2080,"y":1700,"wires":[["2c22ee36.5a7e52"]],"icon":"font-awesome/fa-database","info":"# simple ui-table handler\n## abstract\nUsing ui-table with commands offer the hole flexibilty of tabulator. The table can be manipulated down to cell level.\nAs the ui-table node only passes the commands to tabulator and receives promises back the node does not hold the table data. If the data should be available after refresh, tab change, new connections the flow is responsible to cache the data and all the manipulations.\nThis node takes care of most simple data manipulation commands and holds a copy of the data in `flow.context.tabledata`\n\n## details\n\n### row index (id)\n\nTo identify a [row a index](http://tabulator.info/docs/4.5/data#overview) column has to be defined. This colum defaults to `id` but can be changed by specifing a **field** by using `msg.ui_control`. In this example the row index is a simple counter adding up by one if a new line is added.\n\n### addRow command\n\n[details @ tabulator addRow docs](http://tabulator.info/docs/4.5/update#alter-add)\n\nYou can add a row by sending the `addRow` command. You can decide if the row adds on the top or at the bottom of table.\n\n### addOrUpdate command\n\n[details @ tabulator addOrUpdate docs](http://tabulator.info/docs/4.5/update#alter-update)\n\nTo update data the best way is to use the `addOrUpdate` command. If the row indetified by the index is not exeisting a new row will be added automatically\n\n### deleteRow command\n\n[details @ tabulator deleteRow docs](http://tabulator.info/docs/4.5/update#row)\n\nDelete one or more rows (passing an array always results in \"row not found error\"! I think there is an issue in tabulator)\n\n### clearData\n\n[details @ tabulator clearData docs](http://tabulator.info/docs/4.5/update#alter-empty)\n\nunfortunately this command (currently) do not send a promise back! So we have to pass it directly to the table handler"},{"id":"2c22ee36.5a7e52","type":"ui_table","z":"8c249630.076968","group":"aa839120.af379","name":"Table","order":2,"width":"7","height":"34","columns":[{"field":"name","title":"Name","width":"50%","align":"left","formatter":"plaintext","formatterParams":{"target":"_blank"}},{"field":"value","title":"Last Seen","width":"50%","align":"left","formatter":"plaintext","formatterParams":{"target":"_blank"}}],"outputs":1,"cts":true,"x":2090,"y":1620,"wires":[["e32ca362.ba5fa"]]},{"id":"627f575b.807ba8","type":"ui_ui_control","z":"8c249630.076968","name":"","events":"all","x":1860,"y":1700,"wires":[["e32ca362.ba5fa"]]},{"id":"7809fd85.767624","type":"moment","z":"8c249630.076968","name":"Format","topic":"","input":"payload","inputType":"msg","inTz":"Australia/Sydney","adjAmount":0,"adjType":"days","adjDir":"add","format":"LLL","locale":"en-US","output":"payload","outputType":"msg","outTz":"Australia/Sydney","x":1580,"y":1640,"wires":[["87af4aff.b17178"]]},{"id":"23d0d89d.ce8c78","type":"change","z":"8c249630.076968","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"device.friendly_name","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"$now()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1260,"y":1640,"wires":[["be50a728cbf07ce7"]]},{"id":"27ccfd14.9342e2","type":"zigbee2mqtt-in","z":"8c249630.076968","name":"","server":"7b626d8c.6f0df4","friendly_name":"Temp - Kitchen","device_id":"0x00158d00016c6081","state":"0","outputAtStartup":true,"x":940,"y":1640,"wires":[["23d0d89d.ce8c78"]],"info":"Not working, as the profile is not setup in zibgee2mqtt"},{"id":"b32ac3e1.6b7dc","type":"zigbee2mqtt-in","z":"8c249630.076968","name":"","server":"7b626d8c.6f0df4","friendly_name":"Temp - Outside Down","device_id":"0x00158d0004876b5e","state":"0","outputAtStartup":true,"x":920,"y":1700,"wires":[["23d0d89d.ce8c78"]],"info":"Not working, as the profile is not setup in zibgee2mqtt"},{"id":"be50a728cbf07ce7","type":"switch","z":"8c249630.076968","name":"","property":"topic","propertyType":"msg","rules":[{"t":"cont","v":"0x00","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1430,"y":1640,"wires":[[],["7809fd85.767624"]]},{"id":"aa839120.af379","type":"ui_group","name":"Last Update","tab":"1862e313.45ffad","order":19,"disp":true,"width":"7","collapse":true},{"id":"7b626d8c.6f0df4","type":"zigbee2mqtt-server","name":"zigbee2mqtt","host":"localhost","mqtt_port":"1883","mqtt_username":"","mqtt_password":"","tls":"","usetls":false,"base_topic":"zigbee2mqtt"},{"id":"1862e313.45ffad","type":"ui_tab","name":"Mike","icon":"dashboard","order":2,"disabled":false,"hidden":false}]
Flow was appropriated from here, and modified.
I've got another question, if someone could please help.
[{"id":"b2c3e7e69d7a5dfe","type":"inject","z":"d4b869aa.fe5808","name":"closed","props":[{"p":"payload.contact","v":"true","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":1500,"wires":[["487678c2488205ca"]]},{"id":"b79e442b4fc936b4","type":"inject","z":"d4b869aa.fe5808","name":"open","props":[{"p":"payload.contact","v":"false","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":1540,"wires":[["487678c2488205ca"]]},{"id":"487678c2488205ca","type":"switch","z":"d4b869aa.fe5808","name":"","property":"true","propertyType":"jsonata","rules":[{"t":"eq","v":"payload.contact = \"false\" or \"true\"","vt":"jsonata"},{"t":"eq","v":"payload.temperature != null","vt":"jsonata"},{"t":"eq","v":"payload.tamper = \"false\" or \"true\"","vt":"jsonata"}],"checkall":"true","repair":false,"outputs":3,"x":370,"y":1400,"wires":[["4b0ccf6b048f47b4"],["1cef9ddf39d64272"],["7ccdfc8491aa401c"]]}]
I'm probably misunderstanding Jsonata, but why does the injected payload go out both the first and third switch. The injected payload only contains payload.contact information.
You can't do the comparison like that. The 3rd item will always evaluate as "true" because what you are actually doing is:
(payload.tamper = "false") OR "true" -- which will always=true
You could do it like this:
1st: (payload.contact = "name1") or (payload.contact = "name2")
3rd: (payload.tamper = "false") or (payload.tamper = "true")
Thanks for keeping at it. I'm still working with it. What was strange was everything worked before I added in the third line. Then the third line seems to pick up the true and false from the first line, despite the payload.tamper being empty.
It isn't picking up anything from the 1st one. Your comparison is literally just "true", which will always be "true".
What you wrote originally does:
(payload.tamper = "false")
OR
"true"
^^^^^^ which is not payload.tamper = "true" as you intended... It is just "true", which will always be "true", obviously.
Your 1st one doesn't work either, as it is the same issue. It will ALWAYS be "true" even if payload.contact is empty/missing.
Yes, I want it to be true, if there is a payload.contact of either true or false. I dont want to have 5 different switches, one working on payload.contact, a second payload.temperature, a third on payload.tamper, and so on. But you've given me an idea. I'll modify it somewhat.
All you really need to do is change:
payload.contact = "false" or "true"
to
payload.contact = "false" or payload.contact = "true"
And then the same on the 3rd.
Does it evaluate left to right? I'd always put parenthesis to make it do the eval the way I want.
It does. In his case though since it is an OR it doesn't matter anyway. Well, it wouldn't have mattered if it was AND either, now that I think about it.
It obviously does matter in some cares when you have more than 2 comparators though.
What would tamper be otherwise? null? Maybe test for "exists" or something like that instead... i.e. $exists()
I have Node-Red installed on a pi and have everything running well... as long as I hit Deploy that is. Node-red doesn't refresh at all except 1 node. This node has the standard "http://127.0.0.1:1880" /hubitat/webhook.
All the other nodes have an underscore appended to the /hubitat/webhook (ex: /hubitat/webhook_ or __ or ___ or ____ . The nodes don't refresh and if I try to delete the "_" it just comes back.
Maker API is configured as : http://192.168.102.155:1880/hubitat/webhook
So to be clear - are you running on a Pi, docker or under HomeAssistant - it makes a difference. If you are running on a Pi or non-docker vm then the make app config should be like this:
URL to send device events to by POST:
http://[your node-red IP address with port usually :1880]/hubitat/webhook
With "Include location events sent by POST?" set ON
In Node-RED config you need:
Server: [Hubitat IP Address]
Port: [Hubitat Port, usually 80]
Application Id: [Application ID of the Maker App instance]
Webhook configuration:
Node-RED: [Node Red IP address with port usually :1880]/hubitat/webhook
Also make sure you have the maker api instance token included AND use Websocket checked OFF (at least initially).
If you have running under Docker or HomeAssistant then there are some other adjustments you need to make.. not sure as I don't run Node-RED on those.
edit: I have 4 configs of HE Nodes in Node-RED - meaning 4 separate Maker API instances on 3 different hubs. Have 2 instances on one hub for testing. Everything working well and responding as it should.
I'm running Node-Red on a Rapberry pi4. Maker API is exacly like your exemple.
Token is included and Websocket is OFF.
"Include location events sent by POST?" set ON
I dont understand why the Node-Red Hubitat app is forcing the underscore. It seems this is causing the problem. If I add more Hubitat nodes, it generate more _ until it gets to ____ then it starts back at _
I've tried stopping and restarting Node-Red, shutdown the pi. I've removed Maker Api and reinstalled it. Nothing seems to work. The only Node that auto updates is the one node that has no "_". (/hubitat/webhook)


