node-red-contrib-home-assistant-websocket icon indicating copy to clipboard operation
node-red-contrib-home-assistant-websocket copied to clipboard

custom component switch gets unavailable after changing the state in HA

Open tmp-e opened this issue 11 months ago • 2 comments

Describe the bug

Creating a switch with API: nodered/discovery works as expected. Also changing the state in nodered through API: nodered/entity works well, the switch is shown in homeassistant dashboards and the state is reflected correctly.

But when changing the switch state in homeassistant, it immediately gets "unavailable". Then, also any further change through API: nodered/entity has no effect.

To Reproduce

  1. Create a switch with API: nodered/discovery:
msg.payload = {
    data: {
        type: "nodered/discovery",
        component: "switch",
        server_id: "home",
        node_id: "my_test_switch",
        
        config: {
            name: "My Test Switch"
        }
    }
}
  1. Change switch state in homeassistant

Expected behavior

The switch should schange the state and be available

Screenshots

Switch in homeassistant after registering with nodered/discovery on

Switch after trying to change state in HA Note: "German "nicht verfügbar" = "not available" off

Example Flow

[
    {
        "id": "3e8d201af9b3ab92",
        "type": "function",
        "z": "fe6d6eb28ba94acb",
        "name": "register \"My Test Switch\"",
        "func": "\nmsg.payload = {\n    data: {\n        type: \"nodered/discovery\",\n        component: \"switch\",\n        server_id: \"home\",\n        node_id: \"my_test_switch\",\n        \n        config: {\n            name: \"My Test Switch\"\n        }\n    }\n}\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 1920,
        "wires": [
            [
                "f2f11101b98595ba"
            ]
        ]
    },
    {
        "id": "f2f11101b98595ba",
        "type": "ha-api",
        "z": "fe6d6eb28ba94acb",
        "name": "",
        "server": "acfbfb24.12e808",
        "version": 1,
        "debugenabled": false,
        "protocol": "websocket",
        "method": "get",
        "path": "",
        "data": "",
        "dataType": "jsonata",
        "responseType": "json",
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "results"
            }
        ],
        "x": 590,
        "y": 1920,
        "wires": [
            [
                "1fc2b3eef146b652"
            ]
        ]
    },
    {
        "id": "f4c278ef467f984b",
        "type": "inject",
        "z": "fe6d6eb28ba94acb",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 150,
        "y": 1920,
        "wires": [
            [
                "3e8d201af9b3ab92"
            ]
        ]
    },
    {
        "id": "1fc2b3eef146b652",
        "type": "debug",
        "z": "fe6d6eb28ba94acb",
        "name": "output",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 750,
        "y": 1920,
        "wires": []
    },
    {
        "id": "acfbfb24.12e808",
        "type": "server",
        "name": "Home Assistant",
        "addon": true
    }
]

Environment Information

Version: 0.74.2

Home Assistant version: 2024.12.5 Companion version: 4.1.2

Node-RED version: 4.0.3 Docker: yes Add-on: 18.1.1

Node.js version: v18.20.4 arm64 linux OS: Linux 6.6.62-haos-raspi arm64

Additional context

No response

tmp-e avatar Dec 26 '24 20:12 tmp-e

Is there a reason you're not using the switch node which will handle all the background tasks for you?

The issue with the switch entity lies in the communication protocol. The discovery call, intended to be a subscription call, should establish a two-way path. This path would allow Home Assistant to send data back to Node-RED, such as updates on the switch's state. However, the API node in Node-RED can only make one-way calls and cannot receive subscriptions.

Consequently, when the switch's state changes in Home Assistant and this information is sent to Node-RED, Node-RED expects a response. Since the two-way communication was never established and Node-RED never received the update from Home Assistant, it cannot update Home Assistant accordingly. Home Assistant then interprets this lack of response as the switch becoming unavailable.

zachowj avatar Dec 26 '24 20:12 zachowj

Hi @zachowj , thank you for your quick response. I really appreciate your detailed explanations.

I'm using the switch node a lot, as well as the other nodes (binary sensor, sensor, number ...), for instance to process data from my entities within nodered and have the possibility to view the result and interact from HA dashboards.

At some point in time, as flows got bigger, I started to generalize the functionality by introducing a dummy subflow that handles any input datatype (numeric, binary, strings), optionally allows to configure a measurement type and exposes the data as a HA entity. That works well for viewing data, but not for switches.

As a core functionality for my dummy I needed a way to create the HA entities from the flow and env context data, e.g. the data type, name, unit etc. In old discussions I've seen the possibility to use the nodered/discovery API for that.

In principle I'm trying to re-produce the ha-entity-config on my own, as I was not able to use/call it within my dummy subflow, having parameters passed to it. If there would be a way to re-use ha-entity-config and populate the parameters from my flow and env context data, I guess that would also solve my issue.

Anoher solution could be to listen for switch changes by the call-service event, which shows the turn_off event (I suppose it's from HA). But I did not find out how to forward this event back to Node-RED / back to HA, as you explained.

{"event_type":"call_service","event":{"domain":"switch","service":"turn_off","service_data":{"entity_id":"switch.my_test_switch"}},"origin":"LOCAL","time_fired":"2024-12-27T08:25:42.643794+00:00","context":{"id":"01JG3KHBFKCY9TYFDYTWWPAZRC","parent_id":null,"user_id":"c8e4c9953ad04f4c9fc85274b99b9790"}}

Do you see any workaround that I could implement?

Thank you a lot in advance.

tmp-e avatar Dec 27 '24 08:12 tmp-e