Node-red-contrib-home-assistant-websocket

I logged in directly via Docker cli. Edited the file, restarted nodered via s6. In-line editing, baby. :wink:

Unfortunate (or fortunately?) HA’s Addon “Restart” downs and recreates the container - blowing away any local changes.

It would appear the err object is not an error object. That’s why it’s difficult to pin-down, nothing is shown. It’s an HaWebsocket object. :confused:

Still no clue as to why the connection is closing.

The best I can figure out, at some point a reconnect-error is triggered by the polling tick. This then starts a down-stream of errors, not captured anywhere. The best I can see is this might be a home-assistant-js-websocket bug – failing to properly pass the resulting error? However, I can’t trace that as it’s all uncompiled .ts libraries on the filesystem. :confused:

root@a0d7b954-nodered:/var/run/s6/services$ ls -l /opt/node_modules/home-assistant-js-websocket/lib/connection.ts
ls: /opt/node_modules/home-assistant-js-websocket/lib/connection.ts: No such file or directory
root@a0d7b954-nodered:/var/run/s6/services$ ls -l /opt/node_modules/home-assistant-js-websocket/
total 40
-rw-r--r--    1 root     root         10480 Oct 26  1985 LICENSE.md
-rw-r--r--    1 root     root         17875 Oct 26  1985 README.md
drwxr-xr-x    1 root     root          4096 Jan  1 13:05 dist
-rw-r--r--    1 root     root          2365 Dec 17 05:20 package.json
root@a0d7b954-nodered:/var/run/s6/services$ ls -l /opt/node_modules/home-assistant-js-websocket/dist
total 308
-rw-r--r--    1 root     root          1177 Oct 26  1985 auth.d.ts
-rw-r--r--    1 root     root           832 Oct 26  1985 collection.d.ts
-rw-r--r--    1 root     root           597 Oct 26  1985 commands.d.ts
-rw-r--r--    1 root     root           217 Oct 26  1985 config.d.ts
-rw-r--r--    1 root     root          2409 Oct 26  1985 connection.d.ts
-rw-r--r--    1 root     root           330 Oct 26  1985 entities.d.ts
-rw-r--r--    1 root     root           240 Oct 26  1985 errors.d.ts
-rw-r--r--    1 root     root         12025 Oct 26  1985 haws.es.js
-rw-r--r--    1 root     root         70597 Oct 26  1985 haws.es.js.map
-rw-r--r--    1 root     root         12076 Oct 26  1985 haws.js
-rw-r--r--    1 root     root         70307 Oct 26  1985 haws.js.map
-rw-r--r--    1 root     root         12120 Oct 26  1985 haws.umd.js
-rw-r--r--    1 root     root         70301 Oct 26  1985 haws.umd.js.map
-rw-r--r--    1 root     root           446 Oct 26  1985 index.d.ts
-rw-r--r--    1 root     root          1184 Oct 26  1985 messages.d.ts
-rw-r--r--    1 root     root           223 Oct 26  1985 services.d.ts
-rw-r--r--    1 root     root           133 Oct 26  1985 socket.d.ts
-rw-r--r--    1 root     root           628 Oct 26  1985 store.d.ts
-rw-r--r--    1 root     root          2569 Oct 26  1985 types.d.ts
-rw-r--r--    1 root     root            64 Oct 26  1985 util.d.ts

Here’s a full trace of the onClientError() event trigger:

1 Jan 13:23:10 - [debug] [server:Home Assistant] config server event listener connecting
Trace: o {
  options:
   { setupRetry: 0,
     createSocket: [Function: createSocket],
     self:
      HaWebsocket {
        _events: [Object],
        _eventsCount: 13,
        _maxListeners: 0,
        config: [Object],
        connectionState: 0,
        states: [Object],
        services: [Object],
        statesLoaded: false,
        client: [Circular],
        subscribedEvents: [Set],
        unsubCallback: [Object],
        integrationVersion: 0,
        servicesLoaded: false } },
  commandId: 11,
  commands:
   Map {
     2 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] },
     3 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] },
     5 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] },
     6 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] },
     8 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] },
     9 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] },
     11 => { resolve: [Function],
       reject: [Function],
       callback: [Function],
       subscribe: [Function: subscribe],
       unsubscribe: [Function: unsubscribe] } },
  eventListeners:
   Map {
     'ready' => [ [Function: bound onClientOpen],
       [Function: u],
       [Function: u],
       [Function: u] ],
     'disconnected' => [ [Function: bound onClientClose] ],
     'reconnect-error' => [ [Function: bound onClientError] ] },
  closeRequested: false,
  socket:
   WebSocket {
     _events:
      [Object: null prototype] { message: [Function], close: [Function] },
     _eventsCount: 2,
     _maxListeners: undefined,
     readyState: 3,
     protocol: '',
     _binaryType: 'nodebuffer',
     _closeFrameReceived: true,
     _closeFrameSent: true,
     _closeMessage: '',
     _closeTimer:
      Timeout {
        _called: false,
        _idleTimeout: -1,
        _idlePrev: null,
        _idleNext: null,
        _idleStart: 74563,
        _onTimeout: null,
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: false,
        [Symbol(unrefed)]: false,
        [Symbol(asyncId)]: 1783,
        [Symbol(triggerId)]: 1358 },
     _closeCode: 1000,
     _extensions: { 'permessage-deflate': [PerMessageDeflate] },
     _receiver:
      Receiver {
        _writableState: [WritableState],
        writable: false,
        _events: [Object: null prototype] {},
        _eventsCount: 0,
        _maxListeners: undefined,
        _binaryType: 'nodebuffer',
        _extensions: [Object],
        _maxPayload: 104857600,
        _bufferedBytes: 0,
        _buffers: [],
        _compressed: true,
        _payloadLength: 2,
        _mask: undefined,
        _fragmented: 0,
        _masked: false,
        _fin: true,
        _opcode: 8,
        _totalPayloadLength: 0,
        _messageLength: 0,
        _fragments: [],
        _state: 0,
        _loop: false,
        [Symbol(websocket)]: [Circular] },
     _sender:
      Sender {
        _extensions: [Object],
        _socket: [Socket],
        _firstFragment: true,
        _compress: false,
        _bufferedBytes: 0,
        _deflating: false,
        _queue: [] },
     _socket:
      Socket {
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'hassio',
        _readableState: [ReadableState],
        readable: false,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: null,
        _server: null,
        parser: null,
        _httpMessage: null,
        timeout: 0,
        write: [Function: writeAfterFIN],
        [Symbol(asyncId)]: 1358,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 40143,
        [Symbol(kBytesWritten)]: 1010,
        [Symbol(websocket)]: undefined },
     _bufferedAmount: 0,
     _isServer: false,
     _redirects: 0,
     url: 'ws://hassio/homeassistant/websocket',
     _req: null },
  _ent:
   { state: [Getter],
     refresh: [Function: c],
     subscribe: [Function: subscribe] },
  _srv:
   { state: [Getter],
     refresh: [Function: c],
     subscribe: [Function: subscribe] },
  _cnf:
   { state: [Getter],
     refresh: [Function: c],
     subscribe: [Function: subscribe] } }
    at HaWebsocket.callback [as onClientError] (/opt/node_modules/node-red-contrib-home-assistant-websocket/lib/ha-websocket.js:266:10)
    at forEach (/opt/node_modules/home-assistant-js-websocket/lib/connection.ts:153:7)
    at Array.forEach (<anonymous>)
    at o.fireEvent (/opt/node_modules/home-assistant-js-websocket/lib/connection.ts:152:48)
    at /opt/node_modules/home-assistant-js-websocket/lib/connection.ts:327:18
    at process._tickCallback (internal/process/next_tick.js:68:7)

This is a dump of the result of this addition:
@node_modules/node-red-contrib-home-assistant-websocket/lib/ha-websocket.js:266

    onClientError(data) {
        console.trace(data);
        this.closeClient(
            data,
            'events connection error, cleaning up connection'
        );
    }

The websocket object has a closeCode 1000, and according to the docs: this is a perfectly normal closure – https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent

So, something else is broken. :frowning:

Hi all,

Just a few days ago I noticed some weird behavior in my Node-Red and I cannot pin-point what the problem is (driving me mad :stuck_out_tongue: ). So hoping someone can help me troubleshoot (Hass logs are not saying anything as well as Node-Red…).

Running Hass and Node-Red in a separate Docker.

I have this input_boolean in home-assistant to indicate if we are sleeping or not. It always has worked perfectly:

image

In some Node-Red flows I check the state of this Switch like so:

However, recently I’m getting the result “Initializing at: …” constantly on this boolean:

image

Does not matter if it’s On/Off, always the same result and treated as “false” by the node…

The debug shows as follows, the first line is the payload before it enters this node, second is the result “initializing”.

image

Am I missing something obvious??

@flamingm0e - according to HA Websocket’s documents, reconnect-error is supposed to be only called on ERR_INVALID_AUTH

Looks like somewhere, somehow, the auth token is expiring? However, there is a bug in the websocket’s implementation. According to the docs reconnect-error is supposed to pass the code not a websocket object.

This may very well be an HA bug (maybe?). NR hasn’t changed from what I can tell.

Kind of… :slight_smile:

input_boolean.sleeping_global is a boolean and you are comparing its value to a string.
So, you are comparing “true” with “on” and it is always “false”.
Choose boolean in the drop down menu “if state”. It should be better.
GV

Turns out this IS due an auth error! – The debug() messages within ha-websocket aren’t showing up in the logs, making it hard to debug this issue. I added my own commands and here we go:

[Auth Phase] New connection ws://hassio/homeassistant/websocket
1 Jan 14:08:38 - [debug] [server:Home Assistant] WebSocket Connecting http://hassio/homeassistant
1 Jan 14:08:38 - [debug] [server:Home Assistant] config server event listener connecting
[Auth Phase] Received { type: 'auth_required', ha_version: '0.103.5' }
[Auth Phase] Received { type: 'auth_ok', ha_version: '0.103.5' }
1 Jan 14:08:38 - [info] [server:Home Assistant] WebSocket Connected to http://hassio/homeassistant
1 Jan 14:08:38 - [debug] [server:Home Assistant] config server event listener connected
1 Jan 14:13:05 - [info] [server:Home Assistant] WebSocket Closed http://hassio/homeassistant
1 Jan 14:13:05 - [debug] [server:Home Assistant] config server event listener closed
events connection closed, cleaning up connection
1 Jan 14:13:05 - [debug] [server:Home Assistant] config server event listener closed
[Auth Phase] Initializing ws://hassio/homeassistant/websocket
[Auth Phase] New connection ws://hassio/homeassistant/websocket
1 Jan 14:13:10 - [debug] [server:Home Assistant] WebSocket Connecting http://hassio/homeassistant
1 Jan 14:13:10 - [debug] [server:Home Assistant] config server event listener connecting
[Auth Phase] New connection ws://hassio/homeassistant/websocket
1 Jan 14:13:15 - [debug] [server:Home Assistant] WebSocket Connecting http://hassio/homeassistant
1 Jan 14:13:15 - [debug] [server:Home Assistant] config server event listener connecting
[Auth Phase] Received { type: 'auth_required', ha_version: '0.103.5' }
[Auth Phase] Received { type: 'auth_ok', ha_version: '0.103.5' }
1 Jan 14:13:15 - [info] [server:Home Assistant] WebSocket Connected to http://hassio/homeassistant
1 Jan 14:13:15 - [debug] [server:Home Assistant] config server event listener connected
1 Jan 14:18:05 - [info] [server:Home Assistant] WebSocket Closed http://hassio/homeassistant
1 Jan 14:18:05 - [debug] [server:Home Assistant] config server event listener closed
events connection closed, cleaning up connection
1 Jan 14:18:05 - [debug] [server:Home Assistant] config server event listener closed
[Auth Phase] Initializing ws://hassio/homeassistant/websocket
[Auth Phase] New connection ws://hassio/homeassistant/websocket
1 Jan 14:18:10 - [debug] [server:Home Assistant] WebSocket Connecting http://hassio/homeassistant
1 Jan 14:18:10 - [debug] [server:Home Assistant] config server event listener connecting
[Auth Phase] Received { type: 'auth_required', ha_version: '0.103.5' }
[Auth Phase] Received { type: 'auth_invalid', message: 'Invalid access' }
events connection error, cleaning up connection

I’ve opened up two tickets on this, first one is a real bug, other may be resolved some other way (?):

Now, I’m dead in the water. … NR can’t stay connected. :frowning:
(*note: I can reconnect NR simply by manually redeploying the flows … but it won’t stay connected)

Sensor nodes identify themself to HA by a combination of the server-config node id and the node id of the sensor node. So when that changes in NR Home Assistant thinks it’s a brand new sensor.

A possible solution is to go into the entity registry and delete the original sensor entity_id then rename the entity_id of the new sensor.

Thanks but that is unfortunately not the problem. I’ve tried and it always returns false, furthermore, the configuration node is by default set-up like this:

The On/Off does also work on all my other input_booleans.

Also in the same flow if I make an input on a event change for the sleeping boolean, it detects it correctly:

I’m really lost :frowning:

What does the state of the input Boolean show in home assistant?

Hi Kermit,

Just on or off, in home-assistant seems to all work OK.

image

Drop a debug right before the current state node. Does it contain a msg.payload.entity_id? If so it’s overwriting the current state nodes entity id and is actually looking up that entity’s state.

Check the Block Input Overrides box in the current state node.

Edit:
I can pretty much say that’s your issue based off the screenshot of the debug window.

New Release 0.19.1

Documentation for the Node-RED information panel is now automatically generated from the markdown documentation.

If you see errors or items that need better clarification. All you have to do it click on the link at the bottom of any of the documentation pages.

image

All examples found in the cookbook are now available directly from the examples tab on the import menu in Node-RED.

Bug Fixes

  • include correct files when publishing to npm (8f8eb6f)
  • point changelog to new documentation (0c1a93e)
  • run correct task for convert docs action (b9b3ee4)
  • Catch rejection for lost connection when unsubbing (0008406)

Features

  • docs: Markdown docs will be automatically converted to NR help files (5abfb62)
  • api: Add debug ouput option (72cf55b)
  • sensor: Add the ability to choose how input values are handled (cbd48b9)

0.19.2 (2020-01-06)

Bug Fixes

  • get-history: Don’t send an enddate when using relative time (d536c3c), closes #183
  • get-history: Fix for using flatten results with output type split (38b9c9c)

Buy me a coffee For those that enjoy my work.

4 Likes

Hi.
Please can you help me. Im unable to transfer data from any sensor (i.e. temperature) to Hass.io.

I have a simple flow,


get data from UDP (from arduino temp. sensor) and transfer it to Hass.io.

Output from function block is this:

OneWire/2699EFE501000090 : msg.payload : Object
{ temperature: 23.843 }

But there is a problem with API node, which is unable to connect to Hass.io.

It show me this log:

5 Jan 23:12:27 - [info] [server:http://hassio/homeassistant] WebSocket Connected to http://hassio/homeassistant
5 Jan 23:12:35 - [error] [ha-api:3b52fbe5.c96594] Error Message: Request failed with status code 404

That is the config of this API node:


API_3

Where is a problem?

{{entity_id}} in the path field assumes that msg.entity_id will contain a value. I’m assuming it doesn’t based on the 404 coded returned by HA.

https://developers.home-assistant.io/docs/en/external_api_rest.html#post-apistatesltentity_id
POST /api/states/<entity_id> expects the data field to contain at least state to be set. You’re passing { temperature: 23.843} as just msg.payload it expects it to be in msg.payload.data.

https://zachowj.github.io/node-red-contrib-home-assistant-websocket/node/API.html#input

Change your function node to out the temperature value to msg.payload.data.state

msg.payload =

{
    "data": {
        "state": 23.843
    }
}

Checking the Show Debug Information will give you the output of what the node is sending to HA.

So you’re running home assistant on port 80? Or running a reverse proxy?

Why are you pointing to a path? It should just point to your hassio instance.

No, I use default port 8123 (and no proxy). Should I set it somewhere?

When I set Path (in API node) to /api/states/msg.payload and correct function node as you describe it works ok.
It create in Hass.io new entity msg.payload.
But when I want to rename it (i.e. on onewire2ha_temperature_livingroom) it doesnt work :frowning:
I simply change the Path to /api/states/onewire2ha_temperature_livingroom

/api/states/sensor.onewire2ha_temperature_livingroom

1 Like

Thanks. It works perfect!

Sorry. Your server name (terrible choice BTW) had me mistaken to be the URL you were connecting to.