zachowj / hass-node-red

Companion Component for node-red-contrib-home-assistant-websocket to help integrate Node-RED with Home Assistant Core
MIT License
465 stars 182 forks source link

trigger service not exposed #12

Closed manonstreet closed 4 years ago

manonstreet commented 4 years ago

Release v0.3.0 notes that:

New service added nodered.trigger to trigger an exposed node.

After upgrading and restarting, I'm looking in the Developer Tools->Services and do not see nodered.trigger service available. I can confirm that I do see a services.yaml file in my $config/custom_components/nodered directory; however the service details are not registered/exposed to Home Assistant.

I can also confirm that the component is being loaded successfully:

2020-02-12 19:19:51 INFO (MainThread) [homeassistant.setup] Setting up nodered
2020-02-12 19:19:51 INFO (MainThread) [homeassistant.setup] Setup of domain nodered took 0.0 seconds.
2020-02-12 19:19:51 INFO (MainThread) [custom_components.nodered] 
-------------------------------------------------------------------
nodered
Version: 0.3.0
This is a custom integration
If you have any issues with this you need to open an issue here:
https://github.com/zachowj/hass-node-red/issues
-------------------------------------------------------------------
zachowj commented 4 years ago

Do you have any event nodes exposed to HA? The service won't get loaded until there is a nodered switch registered in HA.

manonstreet commented 4 years ago

Creating an Event Node with "Expose to Home Assistant" enabled did the trick. So there is no bug.

Separately, the use case for this option is a little confusing to me. If I'm not mistaken, the option to expose to HA can only be done on an event node (events: all and events: state change). So NR will first need to be setup to listen for particular event types and this service gives the user an additional way to trigger the flow? Is there a way to do the same without the dependency of listening for an event?

I've seen lots of implementations where users integrate HA with NR by creating an input_boolean and then watching for state change in NR. Or by creating a script with no contents, and listening for the event of the script being fired. If there was a simpler method to just call a service to fire off the flow, that would be much cleaner. Almost like a specialized inject node that could be exposed to HA.

zachowj commented 4 years ago

Yes, you are correct in the way I intended this current implementation to be used for.

In the next non-bugfix release, the sensor node will be renamed to entity and a switch type will be added to it. These will work the same way as the exposed event nodes work now expect they won't listen for any events and will only output when the nodered.trigger service is used. When the switch is off/disabled using the service call will do nothing. There will also be a new service data property, data, added that will be passed as the payload when the switch is triggered.

Well, that's the plan at least for now. Any other recommendations or changes?

zachowj commented 4 years ago

Also, your wanted use case can be achieved in the current implementation with a little trickery.

Using a placeholder entity id will cause the event: state node to never trigger by an event and only be triggered by a service call.

image

[{"id":"2d32c7a6.7651a8","type":"api-call-service","z":"311deaea.efb306","name":"","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"switch.test","data":"{\"trigger_entity_id\":\"sun.sun\",\"skip_condition\":true}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":388,"y":240,"wires":[[]]},{"id":"ac653c18.04cfd","type":"inject","z":"311deaea.efb306","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":156,"y":240,"wires":[["2d32c7a6.7651a8"]]},{"id":"8a8f32e9.453dc","type":"server-state-changed","z":"311deaea.efb306","name":"","version":1,"exposeToHomeAssistant":true,"haConfig":[{"property":"name","value":"test"},{"property":"icon","value":""}],"entityidfilter":"placeholder","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":200,"y":288,"wires":[["d81208b2.b354f8"]]},{"id":"d81208b2.b354f8","type":"debug","z":"311deaea.efb306","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":462,"y":288,"wires":[]}]
bambi73 commented 4 years ago

@zachowj : I have to agree with @manonstreet that current exposing event nodes into HA is quite confusing. It works, but ... For example, switch exposed to HA is used to call nodered.trigger service but when toggled manually it disables event node. From my point of view, it's quite dangerous that it completely disables node (not only service call but regular events too). I have to bury that switch somewhere deep :smile:

If you plan to extend entity node then could you please think about adding script type too (even if it isn't entity :smile:)? Basically its functionality should be quite simmilar as switch type but without exposing new entity and be directly callable (without nodered.trigger) from HA (automations or UI).

My current use-case is to call HA services/scripts from ESPHome devices so I would appreciate possibility to directly call NodeRed flows too. It's working with current event node implementation but it's bit cumbersome.

manonstreet commented 4 years ago

I think the plan to expose a switch entity (for enabling / disabling the flow) and allowing a trigger service on the switch for easy firing from HA makes sense. The downside I suppose it that there may be needless switches created -- most of my flows I have no intention of ever disabling. I personally also use Home Assistant Cloud with Alexa integration. So each switch created gets automatically exposed to Alexa unless I specifically setup exclusions - which is somewhat annoying. But I can't think of a better approach. Perhaps a script or automation type as noted by @bami73. Creation of a new entity should probably cause the appropriate entities (script or automations) to automatically be reloaded as well so they show up immediately.

I was considering the same workaround using a fake entity. However I already have everything wired up using empty scripts and watching for the event of the script being fired. I'll wait to refactor until after the new release.

zachowj commented 4 years ago

When I first started the custom component I wanted to extend the automation class instead of switches but from what I found you can't extend it or scripts for integrations. It could be my lack of knowledge of the Home Assistant code base.

The entity switch is up on the dev branch of https://github.com/zachowj/node-red-contrib-home-assistant-websocket along with the latest release of this package version 0.4.0.

You can install the dev nodes using

npm install node-red-contrib-home-assistant-websocket@next

Here's a sample flow

image

[{"id":"5f1ea7f6.3b9c38","type":"inject","z":"311deaea.efb306","name":"Toggle Switch","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":854,"y":192,"wires":[["1c4a2fc3.7893b"]]},{"id":"1c4a2fc3.7893b","type":"api-call-service","z":"311deaea.efb306","name":"Toggle Switch On/Off","version":1,"debugenabled":false,"service_domain":"switch","service":"toggle","entityId":"switch.nodered_entity_switch","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1060,"y":192,"wires":[[]]},{"id":"fb53b970.12ce18","type":"inject","z":"311deaea.efb306","name":"Trigger Switch","topic":"","payload":"{\"data\": {\"entity_id\": \"switch.nodered_entity_switch\"}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":854,"y":240,"wires":[["ea36ec1a.73db4"]]},{"id":"ea36ec1a.73db4","type":"api-call-service","z":"311deaea.efb306","name":"nodered.trigger switch no payload","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1100,"y":240,"wires":[["9bec4817.a954a8"]]},{"id":"97c4610d.aab57","type":"ha-entity","z":"311deaea.efb306","name":"","server":"9c202bd8.b64db8","version":1,"debugenabled":false,"outputs":2,"entityType":"switch","config":[{"property":"name","value":"nodered_entity_switch"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:airplane"},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":1030,"y":128,"wires":[["487f8f3.e60e77"],["a4832f29.edfe4"]]},{"id":"487f8f3.e60e77","type":"debug","z":"311deaea.efb306","name":"on","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1186,"y":112,"wires":[]},{"id":"34cd8f4f.e7f09","type":"inject","z":"311deaea.efb306","name":"Input to Switch","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":864,"y":128,"wires":[["97c4610d.aab57"]]},{"id":"a4832f29.edfe4","type":"debug","z":"311deaea.efb306","name":"off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1186,"y":144,"wires":[]},{"id":"9bec4817.a954a8","type":"api-call-service","z":"311deaea.efb306","name":"nodered.trigger switch object payload","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"","data":"{\"payload\": {\"abc\": 123}}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1110,"y":288,"wires":[["7a3c3a8b.2c4804"]]},{"id":"7a3c3a8b.2c4804","type":"api-call-service","z":"311deaea.efb306","name":"nodered.trigger switch string payload","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"","data":"{\"payload\": \"abc\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1110,"y":336,"wires":[["3c27bdbc.b357e2"]]},{"id":"3c27bdbc.b357e2","type":"api-call-service","z":"311deaea.efb306","name":"nodered.trigger switch boolean payload","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"","data":"{\"payload\": true }","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1120,"y":384,"wires":[["cf7a296.cb159d8"]]},{"id":"cf7a296.cb159d8","type":"api-call-service","z":"311deaea.efb306","name":"nodered.trigger switch number payload","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"","data":"{\"payload\": 123 }","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1110,"y":432,"wires":[[]]}]
bambi73 commented 4 years ago

It's kind of unfortunate that you can't do it "correctly" :expressionless: Anyway current solution works (didn't tried parameters from 0.4.0 yet) so thank you for hard work.

zachowj commented 4 years ago

The switch entity is now released in version v0.21.0