Skip to content

Commit

Permalink
fix: Wait until integration is loaded before attempting to register e…
Browse files Browse the repository at this point in the history
…ntities

With version HA 0.111.0 websocket connects before all integrations are
loaded. This puts checks in place to wait until the NR integration is
loaded before attempting to register entities.

Closes #247
  • Loading branch information
zachowj committed Jun 24, 2020
1 parent 60143b7 commit 1d8eb04
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 47 deletions.
7 changes: 7 additions & 0 deletions lib/base-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,13 @@ class BaseNode {
);
}

get isIntegrationLoaded() {
return (
this.websocketClient.isConnected &&
this.websocketClient.isIntegrationLoaded
);
}

getPrettyDate() {
return new Date().toLocaleDateString('en-US', {
month: 'short',
Expand Down
22 changes: 12 additions & 10 deletions lib/events-ha-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class EventsHaNode extends EventsNode {
async init() {
await this.loadPersistedData();

if (this.isConnected) {
if (this.isIntegrationLoaded) {
this.registerEntity();
this.removeFromHomeAssistant();
}
Expand All @@ -50,7 +50,10 @@ class EventsHaNode extends EventsNode {
super.onClose(removed);

if (removed) {
if (this.isConnected && this.nodeConfig.exposeToHomeAssistant) {
if (
this.isIntegrationLoaded &&
this.nodeConfig.exposeToHomeAssistant
) {
this.removeFromHomeAssistant(true);
}
await this.removeNodeData();
Expand All @@ -59,17 +62,16 @@ class EventsHaNode extends EventsNode {
this.removeSubscription();
}

async onHaConfigUpdate() {
this.registerEntity();
this.removeFromHomeAssistant();
}

onHaIntegration(type) {
async onHaIntegration(type) {
if (type === 'loaded') {
this.registerEntity();
if (this.registered) {
// Update the state of exposed nodes because when the HA client
// resubscribes it registers the entity with the original state
setTimeout(() => this.updateHomeAssistant(), 300);
}
await this.registerEntity();
} else if (type === 'unloaded') {
this.isEnabled = true;
this.registered = false;
if (this.subscription) {
this.subscription();
this.subscription = null;
Expand Down
16 changes: 8 additions & 8 deletions lib/events-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ class EventsNode extends BaseNode {
if (err.message) this.error(err.message);
}

onHaConfigUpdate() {
this.registerEntity();
}

onHaIntegration(type) {
if (type === 'loaded') {
this.registerEntity();
} else if (type === 'unloaded') {
this.registered = false;
switch (type) {
case 'loaded':
case 'notloaded':
this.registerEntity();
break;
case 'unloaded':
this.registered = false;
break;
}
}

Expand Down
63 changes: 48 additions & 15 deletions lib/ha-websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const MSG_TYPE_AUTH_REQUIRED = 'auth_required';
const MSG_TYPE_AUTH_INVALID = 'auth_invalid';
const MSG_TYPE_AUTH_OK = 'auth_ok';
const connectionStates = ['CONNECTING', 'CONNECTED', 'DISCONNECTED', 'ERROR'];
const INTEGRATION_EVENT = 'nodered';
const INTEGRATION_NOT_LOADED = 'notloaded';
const INTEGRATION_LOADED = 'loaded';
const INTEGRATION_UNLOADED = 'unloaded';

class HaWebsocket extends EventEmitter {
constructor(config) {
Expand Down Expand Up @@ -47,6 +51,10 @@ class HaWebsocket extends EventEmitter {
return HaWebsocket.ERROR;
}

get isIntegrationLoaded() {
return this.integrationVersion !== 0;
}

async connect() {
this.client = await homeassistant
.createConnection({
Expand Down Expand Up @@ -104,6 +112,11 @@ class HaWebsocket extends EventEmitter {
this.onStatesLoadedAndRunning();

// Home Assistant Events
await this.client.subscribeEvents(
(evt) => this.integrationEvent(evt),
INTEGRATION_EVENT
);

homeassistant.subscribeConfig(this.client, (config) =>
this.onClientConfigUpdate(config)
);
Expand All @@ -125,6 +138,27 @@ class HaWebsocket extends EventEmitter {
if (!this.isHomeAssistantRunning) {
this.isHomeAssistantRunning = true;
this.emit('ha_client:running');
if (!this.isIntegrationLoaded) {
this.createIntegrationEvent(INTEGRATION_NOT_LOADED);
}
}
}

integrationEvent(evt) {
const oldVersion = this.integrationVersion;
switch (evt.data.type) {
case INTEGRATION_LOADED:
this.integrationVersion = evt.data.version;
break;
case INTEGRATION_UNLOADED:
this.integrationVersion = 0;
break;
case INTEGRATION_NOT_LOADED:
this.emit(`integration`, evt.data.type);
return;
}
if (oldVersion !== this.integrationVersion) {
this.emit(`integration`, evt.data.type);
}
}

Expand Down Expand Up @@ -169,7 +203,6 @@ class HaWebsocket extends EventEmitter {

// Always need the state_changed event
currentEvents.add('state_changed');
currentEvents.add('nodered');

const add = new Set(
[...currentEvents].filter((x) => !this.subscribedEvents.has(x))
Expand Down Expand Up @@ -240,16 +273,6 @@ class HaWebsocket extends EventEmitter {
const eventType = msg.event_type;
const entityId = msg.data && msg.data.entity_id;

if (eventType === 'nodered') {
if (msg.data.type === 'loaded') {
this.integrationVersion = msg.data.version;
} else if (msg.data.type === 'unloaded') {
this.integrationVersion = 0;
}
this.emit(`integration`, msg.data.type);
return;
}

const emitEvent = {
event_type: eventType,
entity_id: entityId,
Expand Down Expand Up @@ -293,12 +316,22 @@ class HaWebsocket extends EventEmitter {
this.integrationVersion === 0
) {
try {
this.integrationVersion = await this.send({
type: 'nodered/version',
});
const version = await this.getIntegrationVersion();
this.createIntegrationEvent(INTEGRATION_LOADED, version);
} catch (e) {}
}
this.emit('ha_events:config_update');
}

async getIntegrationVersion() {
return this.send({
type: 'nodered/version',
});
}

createIntegrationEvent(type, version) {
this.integrationEvent({
data: { type, version },
});
}

onClientOpen() {
Expand Down
17 changes: 4 additions & 13 deletions nodes/entity/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ module.exports = function (RED) {
class EntityNode extends EventsHaNode {
constructor(nodeDefinition) {
super(nodeDefinition, RED, nodeOptions);
this.registered = false;

this.init();
}

async init() {
await this.loadPersistedData();
}

setConnectionStatus(additionalText) {
Expand Down Expand Up @@ -124,11 +117,9 @@ module.exports = function (RED) {
onHaEventsClose() {
super.onHaEventsClose();

this.registered = false;
}

async onConfigUpdate() {
this.registerEntity();
if (this.nodeConfig.entityType !== 'switch') {
this.registered = false;
}
}

onHaIntegration(type) {
Expand All @@ -148,7 +139,7 @@ module.exports = function (RED) {
if (
this.nodeConfig.entityType !== 'switch' &&
this.registered &&
this.isConnected &&
this.isIntegrationLoaded &&
removed
) {
const payload = {
Expand Down
2 changes: 1 addition & 1 deletion nodes/webhook/webhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = function (RED) {
constructor(nodeDefinition) {
super(nodeDefinition, RED, nodeOptions);

if (this.isConnected) {
if (this.isIntegrationLoaded) {
this.registerEntity();
}
}
Expand Down

0 comments on commit 1d8eb04

Please sign in to comment.