Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Commit

Permalink
fix: wait for initial entities to be loaded (#153)
Browse files Browse the repository at this point in the history
related to: #55
  • Loading branch information
t0bst4r authored Jul 13, 2024
1 parent 823572c commit d1b2878
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 15 deletions.
31 changes: 18 additions & 13 deletions src/home-assistant/home-assistant-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,34 @@ export class HomeAssistantClient {
url = url.replace(/\/$/, '');
const auth = createLongLivedTokenAuth(url, accessToken);
const connection = await createConnection({ auth });
const client = new HomeAssistantClient(connection);
await client.init();
return client;
return new HomeAssistantClient(connection);
}

private readonly entityCollection: Collection<HassEntities>;
private readonly registryCollection: Collection<HassRegistryEntities>;
private states: HassEntities = {};
private registry: HassRegistryEntities = {};
private states: HassEntities | undefined = undefined;
private registry: HassRegistryEntities | undefined = undefined;
private entities: Record<string, Entity> = {};
private readonly subscribers = new Set<SubscribeFn>();
private readonly update: () => Promise<void>;

private _isInitialized: boolean = false;
public get isInitialized(): boolean {
return this._isInitialized;
}

private constructor(private readonly connection: Connection) {
this.update = debounce(this.expensiveUpdate.bind(this), 100);
this.entityCollection = entitiesColl(connection);
this.registryCollection = entityRegistryColl(connection);
}

private async init() {
this.entityCollection.subscribe((states) => {
this.entityCollection.subscribe(async (states) => {
this.states = states;
this.update();
await this.update();
});
this.registryCollection.subscribe((registry) => {
this.registryCollection.subscribe(async (registry) => {
this.registry = registry;
this.update();
await this.update();
});
}

Expand All @@ -57,17 +58,21 @@ export class HomeAssistantClient {
}

private async expensiveUpdate() {
if (!this.states || !this.registry) {
return;
}
this.entities = Object.fromEntries(
Object.keys(this.states)
.map<Entity>((entityId) => ({
...this.states[entityId],
hidden: !!this.registry[entityId]?.hidden_by,
...this.states![entityId],
hidden: !!this.registry?.[entityId]?.hidden_by,
}))
.map((entity) => [entity.entity_id, entity]),
);
for (const subscriber of this.subscribers) {
await subscriber(this.entities);
}
this._isInitialized = true;
}

callService(
Expand Down
6 changes: 6 additions & 0 deletions src/home-assistant/home-assistant-matter-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,13 @@ export class HomeAssistantMatterAdapter {
private readonly ignoreEntities = new Set<string>();
private readonly hiddenEntities = new Set<string>();
private readonly devices = new Map<string, HomeAssistantDevice>();
private _isInitialized: boolean = false;
public readonly close: UnsubscribeFn;

public get isInitialized(): boolean {
return this._isInitialized;
}

constructor(
private readonly client: HomeAssistantClient,
private readonly platform: MatterbridgeDynamicPlatform,
Expand All @@ -58,6 +63,7 @@ export class HomeAssistantMatterAdapter {
for (const removedEntity of removed) {
await this.remove(removedEntity);
}
this._isInitialized = true;
}

async create(entity: Entity) {
Expand Down
15 changes: 13 additions & 2 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,29 @@ export class HomeAssistantPlatform extends MatterbridgeDynamicPlatform {

override async onStart(reason?: string) {
const config = this.validateConfig();
this.log.info('onStart called with reason:', reason ?? 'none');
this.log.debug('onStart called with reason:', reason ?? 'none');

const client = await HomeAssistantClient.create(config.homeAssistantUrl, config.homeAssistantAccessToken);
this.adapter = new HomeAssistantMatterAdapter(
client,
this,
new PatternMatcher(config.homeAssistantClientConfig ?? {}),
);

await new Promise<void>((resolve) => {
const handle = setInterval(() => {
if (client.isInitialized && this.adapter.isInitialized) {
clearInterval(handle);
resolve();
}
}, 10);
});

this.log.debug('onStart finished');
}

override async onShutdown(reason?: string) {
this.log.info('onShutdown called with reason:', reason ?? 'none');
this.log.debug('onShutdown called with reason:', reason ?? 'none');
this.adapter.close();
if (this.config.unregisterOnShutdown === true) await this.unregisterAllDevices();
}
Expand Down

0 comments on commit d1b2878

Please sign in to comment.