Node-red-contrib-home-assistant-websocket

While I’m here, I thought I’d ask if there’s a way of dealing with conversation/intents in Node-Red: https://developers.home-assistant.io/docs/intent_index, or if that is just stuff handled natively.

I just glanced through the docs and no this is not something that can be handled by NR out of the box. It would need to be added to the NR custom integration.

New Release 0.30.0 (2021-01-10)

Features

  • call-service: Add load example data button (2ef840b)
  • entity: Add ability to have the switch entity output on state change (703568e), closes #228

Documentation

  • cookbook: Update vacation example (f6080ca)
  • guide: Add call-service tips and tricks (499ad96)
  • Update holiday lights export to include autogeneration of HA helpers (ddb5741)
  • Update README.md (#325) (9fe6023)

0.30.1 (2021-01-10)

Bug Fixes

  • entity: update getValue name change (0531b86)

Buy me a coffee For those that enjoy my work.

3 Likes

Not sure if it is right place to ask this question: is it possible to create HA entities by somehow passing their names to Entity node, using payload attributes for example? Right now it seems the entity must be parametrized in Entity node in fixed way.

Or if it’s not possible (I cannot se it in node description) does such feature make sense? Should I create FR then?

Hello
I’m just trying to use this feature and I really cannot understand why the approach taken for the switch mode is not consistent with others.

Even binary_sensor has only one output, pushing out current state (on or off values)
switch however, has two outputs, but both pushes the same, fixed value, set in node config.

Now I found, that regardless of “output on state change” every message except of one containing msg.enable is passed to first or second output node depending on switch state. But message which enables or disables the switch (msg.enable) is never passed through.

In addition if “output on state change” is enabled there is option to set a value returned to first or second output. The same value for both states. However I found incidentally that after switching to J:expression a value $entity().state ? "on": "off" is set. I thought this is the solution but it doesn’t work. no way to push current state of switch out from node output.

obrazek

Using the API node and the custom WebSocket endpoints it’s possible. At the moment it is not going to be added to the entity node as the node needs to register itself with HA when you deploy.

Examples of use the API node to register and update entities:

Follow my conversation with swiftlyfalling
https://community.home-assistant.io/t/custom-component-for-node-red-contrib-home-assistant-websocket/150736/7?u=kermit

https://community.home-assistant.io/t/help-merging-2-node-red-flows-in-1/154642/23?u=kermit

https://community.home-assistant.io/t/help-merging-2-node-red-flows-in-1/154642/32?u=kermit

The sensor entities are very different than a switch entity. A sensor is only one way from NR to HA whereas a switch needs to have two-way communication between NR and HA. The entity node is going to include any custom entity types that are added. So each type could have a vastly different config and output methods.

I think it’s a pretty standard practice in NR that reset/enable/disable messages only act on the node and don’t cause any output.

Newly created node default to this, I guess I didn’t add it to existing nodes.

I don’t think I fulling understand the issue you’re having. If you want the state of the switch in HA use a current state node. The main purpose of this node is to act as an NR switch redirecting the flow based on the state of the HA switch.

Thank you for instant reply.
I think my problem is the different view on that. Till now I thought those nodes are dedicated only for ability to control HA entities and feeding them with data. So they functionality is limited to:

  1. creating/removing entities
  2. setting its values with payload passed to input
  3. optionally redirecting state changes to output

I cannot see why switch couldn’t work this way even if there are differences in communication with HA.

Switch functionality is pretty different having additionally built-in routing of all messages which hit input, not only those which caused its state change. To me it seems that it duplicates the functionality of current state node, isn’t it?
Anyway seems that this feature led to a need of moving control messages to msg.enable instead of payload.
Then if I want to follow control messages only, I have to join both outputs (also change/hardcode values because currently the node doesn’t output its state), and filter-out other messages which possibly come to the input.

Actually it doesn’t work if I want to intercept switch state change caused by the flow. Something I can achieve with binary_sensor type of entity node as for example

It all seems cumbersome to me;

But if this behaviour is intentional and someone feels it’s useful then I have to accept that as a feature and live with it.

thank you for your work. I really enjoy playing with NR, which wouldn’t be possible without your contribution.

1 Like

@Kermit may i ask some help? im trying to compare climate max temp with current temp via current state node

[{"id":"10ce7169.c8fbdf","type":"api-current-state","z":"dc0cfe23.744d3","name":"","server":"b6b3d766.fc28f8","version":1,"outputs":2,"halt_if":"$entity().state > $entities(\"sensor.tempmax_{{topic}}\").state","halt_if_type":"jsonata","halt_if_compare":"jsonata","override_topic":false,"entity_id":"sensor.magala_temperatuur","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":350,"y":4560,"wires":[["6f337226.749ebc"],["3e7a42.04e815be"]]},{"id":"b6b3d766.fc28f8","type":"server","z":"","name":"hassio","legacy":false,"addon":false,"rejectUnauthorizedCerts":false,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]
$entity().state > $entities("sensor.tempmax_" & topic).state

edit:
probably need to cast them to numbers

$number($entity().state) > $number($entities("sensor.tempmax_" & topic).state)
1 Like

Love this implementation a lot :smiley:

I am using node ha-entity to create and update sensor value.

I can not figure out, how to handle updates if the sensor repeats the previous value. When checked in HA, it shows as not being updated since the last state change.
I guess somehow I’d need to touch last_changed…

Here is my flow:

[{"id":"e97b2a4b.ab2348","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"491fc415.621e9c","type":"change","z":"e97b2a4b.ab2348","name":"battery level, oregon_th_outside","rules":[{"t":"move","p":"payload.bat","pt":"msg","to":"oregon_th_outside","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1250,"y":260,"wires":[[]]},{"id":"5f1fb3ee.6b80ac","type":"ha-entity","z":"e97b2a4b.ab2348","name":"Outside temp","server":"e447d17a.16a64","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Outside temp"},{"property":"device_class","value":"temperature"},{"property":"icon","value":"hass:thermometer"},{"property":"unit_of_measurement","value":"°C"}],"state":"payload.temp","stateType":"msg","attributes":[{"property":"batery level","value":"oregon_th_outside","valueType":"flow"}],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"","outputPayloadType":"str","x":1220,"y":180,"wires":[[]]},{"id":"2f1374fd.cf772c","type":"function","z":"e97b2a4b.ab2348","name":"Oregon TempHygro, 128B7, outside","func":"if ( msg.payload.name==\"Oregon TempHygro\"\n        && msg.payload.id==\"128B7\" )\n{\n    return msg;\n}\nelse\n    return null;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":860,"y":180,"wires":[["5f1fb3ee.6b80ac","491fc415.621e9c"]]},{"id":"92eb03c6.3d0eb","type":"function","z":"e97b2a4b.ab2348","name":"RFLink decode","func":"var the433 = {}; \nmsg.payload = msg.payload.replace(/(\\r\\n|\\n|\\r)/gm,\"\"); \n// node.warn(msg.payload);\nvar parts433 = msg.payload.split(\";\"); \nthe433.p1 = parts433[0];\nthe433.p2 = parts433[1]; \nthe433.name = parts433[2];\nvar a = 3; \nwhile (a < parts433.length)\n{\n\tvar bits433 = parts433[a].split(\"=\"); \n\tswitch (bits433[0]) \n\t{ \n\t\tcase \"ID\": the433.id = bits433[1]; break; \n\t\tcase \"SWITCH\": the433.switch = bits433[1]; break; \n\t\tcase \"CMD\": the433.cmd = bits433[1]; break; \n\t\tcase \"SET_LEVEL\":\n\t\tthe433.set_level = parseInt(bits433[1], 10); break; \n\t\tcase \"TEMP\":\n\t\tvar int=parseInt(bits433[1],16);\n\t\tif ((int & 0x8000) >0) {\n\t\t\tthe433.temp=-(int & 0x7fff) / 10;\n\t\t} else {\n\t\t\tthe433.temp = int / 10;\n\t\t}\n\t\tbreak; \n\t\tcase \"HUM\": the433.hum = parseInt(bits433[1], 10); break; \n\t\tcase \"BARO\": the433.baro = parseInt(bits433[1], 16); break; \n\t\tcase \"HSTATUS\": the433.hstatus = parseInt(bits433[1], 10); break; \n\t\tcase \"BFORECAST\": the433.bforecast = parseInt(bits433[1], 10); break; \n\t\tcase \"UV\": the433.uv = parseInt(bits433[1], 16); break; \n\t\tcase \"LUX\": the433.lux = parseInt(bits433[1], 16); break; \n\t\tcase \"BAT\": the433.bat = bits433[1]; break; case \"RAIN\":\n\t\tthe433.rain = parseInt(bits433[1], 16) / 10; break; \n\t\tcase \"RAIN\":\n\t\tthe433.rainrate = parseInt(bits433[1], 16) / 10; break; \n\t\tcase \"WINSP\":\n\t\tthe433.winsp = parseInt(bits433[1], 16) / 10; break; \n\t\tcase \"AWINSP\":\n\t\tthe433.awinsp = parseInt(bits433[1], 16) / 10; break; \n\t\tcase \"WINGS\": the433.wings = parseInt(bits433[1], 16); break; \n\t\tcase \"WINDIR\":\n\t\tthe433.windir = parseInt(bits433[1], 10); break; \n\t\tcase \"WINCHL\":\n\t\tthe433.winchl = parseInt(bits433[1], 16); break; \n\t\tcase \"WINTMP\":\n\t\tthe433.wintmp = parseInt(bits433[1], 16); break; \n\t\tcase \"CHIME\": the433.chime = parseInt(bits433[1], 10); break; \n\t\tcase \"SMOKEALERT\": the433.smokealert = bits433[1]; break; \n\t\tcase \"PIR\": the433.pir = bits433[1]; break; \n\t\tcase \"CO2\": the433.co2 = parseInt(bits433[1], 10); break; \n\t\tcase \"SOUND\": the433.sound = parseInt(bits433[1], 10); break; \n\t\tcase \"KWATT\": the433.kwatt = parseInt(bits433[1], 16); break; \n\t\tcase \"WATT\": the433.watt = parseInt(bits433[1], 16); break; \n\t\tcase \"CURRENT\":\n\t\tthe433.current = parseInt(bits433[1], 10); break; \n\t\tcase \"CURRENT2\":\n\t\tthe433.current2 = parseInt(bits433[1], 10); break; \n\t\tcase \"CURRENT3\":\n\t\tthe433.current3 = parseInt(bits433[1], 10); break; \n\t\tcase \"DIST\": the433.dist = parseInt(bits433[1], 10); break; \n\t\tcase \"METER\": the433.meter = parseInt(bits433[1], 10); break; \n\t\tcase \"VOLT\": the433.volt = parseInt(bits433[1], 10); break; \n\t\tcase \"RGBW\":\n\t\tthe433.rgbc = parseInt(bits433[1].substring(0, 2), 16); \n\t\tthe433.rgbw = parseInt(bits433[1].substring(2, 4), 16);\n\t\tbreak;\n\t} \n\ta++; \n}\n\nmsg1 = {};\nmsg1.payload=the433;\nreturn msg1;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":540,"y":180,"wires":[["2f1374fd.cf772c"]]},{"id":"845c4873.c466d8","type":"serial in","z":"e97b2a4b.ab2348","name":"RFLink","serial":"f4d1890d.229258","x":290,"y":180,"wires":[["92eb03c6.3d0eb"]]},{"id":"e447d17a.16a64","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true},{"id":"f4d1890d.229258","type":"serial-port","serialport":"/dev/serial/by-id/usb-Arduino__www.arduino.cc__0042_559363430343517001B0-if00","serialbaud":"57600","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"\\n","bin":"false","out":"char","addchar":"","responsetimeout":"10000"}]

Is this correct approach, or should I do it differently?

Currently, there is no “force_update” on the NR entity node.

You can fake it by adding another attribute to the entity that could be named anything with the value as timestamp.

1 Like

Thanks for reply. Unfortunately, this didn’t do the trick.
Screenshot_1

I added attribute updated, assigned it to timestamp and it is indeed changing, however, since the temperature value doesn’t change, it’s reporting as “dead sensor”.

Perhaps I’d need to rethink the whole concept. Any ideas, how to approach this?

I’ve gotten the new Philips Hue Dimmer Switch that has a Power button instead of On/Off buttons so I want to create a logic for toggling the lights using just one button. The button has to toggle two (or more) lights so the logic can’t be as simple as using “homeassistant.toggle”.

The logic should be:

  • if any light is on then the Power button turns off all of them
  • if none of the lights are on then the Power button turns on all of them

For implementing that I would need to get the state of all related lights and based on their ON/OFF states determine what to do.

I wonder if anyone has suggestions on how to do that. It seems like the “Current state” node can only get the state of one entity so that seems the biggest blocker for me.

Once I get the state I guess I can write some custom JS logic using the “Function” node since I don’t think this addon has anything so specific to my use case.

Use a HA group with all the lights. If it’s on there’s at least one light on the group is on and if they are all off the group is off

Thanks. That would work nicely but I want to depend as little as possible on HA configuration in NodeRed so as to not have to maintain two moving pieces at the same time.

I’ve implemented that using the “Get entities” node (apparently it can get states of multiple entities using regexp) + a custom function node that returns a payload formatted for the “Call service” node.

Hi,

I’ve just posted this topic about a problem with the service homeassistant set_location which is demanding a lot of memory (until my Pi freezes).

I’m just linking from here, since I’ve got the feeling people are reading here, who can help me out.

Thanks!

Hi,

I’ve a problem with using global variable in render template node.
This example doesn’t work:

[{"id":"4da1c3b6.ecf84c","type":"change","z":"1497555b.20160b","name":"","rules":[{"t":"set","p":"var1","pt":"global","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":1580,"wires":[["15b0ee15.17c1f2"]]},{"id":"15b0ee15.17c1f2","type":"api-render-template","z":"1497555b.20160b","name":"test","server":"f52dc269.9226a","template":"{{ global.var1 }}","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"template","templateLocationType":"msg","x":610,"y":1580,"wires":[["a8c839d6.c4f668"]]},{"id":"aee883ee.441c","type":"inject","z":"1497555b.20160b","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":210,"y":1580,"wires":[["4da1c3b6.ecf84c"]]},{"id":"a8c839d6.c4f668","type":"debug","z":"1497555b.20160b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":1580,"wires":[]},{"id":"f52dc269.9226a","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Help, plz.

Hi,
The home-assistant template doesn’t see node-red scoped variables. You can get around this by stringing together a node-red template then a home-assistant template. Here’s your example with an additional node-red template node. The node-red template makes a string that will be expanded by the home-assistant template, so 1. I had to change the delimiter so that the {{ }}'s were preserved in the output, 2. I added a home-assistant variable to expand (assuming you have a sun sensor).

[{"id":"aee883ee.441c","type":"inject","z":"1c7b6f3e.2903c9","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":140,"wires":[["4da1c3b6.ecf84c"]]},{"id":"4da1c3b6.ecf84c","type":"change","z":"1c7b6f3e.2903c9","name":"","rules":[{"t":"set","p":"var1","pt":"global","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":140,"wires":[["9d37cf2c.baae78"]]},{"id":"9d37cf2c.baae78","type":"template","z":"1c7b6f3e.2903c9","name":"","field":"template","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{=<% %>=}}\n{{ (10.5 * <% global.var1 %>)|int }}\n{{ states.sun.sun.state }}","output":"str","x":470,"y":140,"wires":[["937938be.5629e8","15b0ee15.17c1f2"]]},{"id":"937938be.5629e8","type":"debug","z":"1c7b6f3e.2903c9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"template","targetType":"msg","statusVal":"","statusType":"auto","x":620,"y":100,"wires":[]},{"id":"15b0ee15.17c1f2","type":"api-render-template","z":"1c7b6f3e.2903c9","name":"test","server":"f52dc269.9226a","template":"","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"template","templateLocationType":"msg","x":650,"y":140,"wires":[["a8c839d6.c4f668"]]},{"id":"a8c839d6.c4f668","type":"debug","z":"1c7b6f3e.2903c9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":140,"wires":[]},{"id":"f52dc269.9226a","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Hope that helps,
Benjamin

3 Likes

Firstly, thanks Kermit for all your hard work on this, really appreciated.

Can anyone point me to some instructions on using the trigger-state node? I thought I had it figured out, but no matter what I try I keep messing it up, so I feel I need some ELI5 explanation and my Google searches have failed me.

I’m just trying to test it out with something simple where when a light in my office is turned on it outputs a custom boolean message of true, as below. Sadly the debug shows multiple lines of the state of the office light, not the true message I was expecting. :confused: I’m sure I’m doing something wrong and that it’s dead simple but I just can’t figure it out.