feat: Add hardened error handling and retries (#2451)

- Closes #1830
 - Closes #2099
This commit is contained in:
Dermot Duffy
2026-06-30 17:45:12 -07:00
committed by dermotduffy
parent 4bc787e2b7
commit 47bcce93d3
182 changed files with 7877 additions and 4043 deletions
+28 -34
View File
@@ -1,6 +1,5 @@
import { hasHAConnectionStateChanged } from '../../ha/has-hass-connection-changed';
import { STATE_RUNNING } from 'home-assistant-js-websocket';
import { HomeAssistant } from '../../ha/types';
import { localize } from '../../localize/localize';
import { log } from '../../utils/debug';
import { InitializationAspect } from '../initialization-manager';
import { CardHASSAPI } from '../types';
@@ -28,39 +27,30 @@ export class HASSManager {
}
public setHASS(hass?: HomeAssistant | null): void {
if (hasHAConnectionStateChanged(this._hass, hass)) {
if (!hass?.connected) {
this._api.getMessageManager().setMessageIfHigherPriority({
message: localize('error.reconnecting'),
icon: 'mdi:lan-disconnect',
type: 'connection',
dotdotdot: true,
});
} else {
this._api.getMessageManager().resetType('connection');
// When HA transitions from "not ready" to "ready" (WebSocket reconnected
// AND all integrations finished loading), reinitialize cameras and the
// view. This is necessary because event subscriptions (e.g. Frigate
// WebSocket subscriptions via hass.connection.subscribeMessage) are tied to
// the old connection and are lost when it drops. Without reinitialization,
// triggers and thumbnail updates stop working.
//
// We deliberately wait for hass.config.state === STATE_RUNNING rather than
// just hass.connected, because HA exposes the WebSocket before integrations
// have finished loading. Triggering re-init too early would race against
// integration startup and fail with "Unknown command" on
// integration-specific WS calls.
if (this._hass && !this._isReady(this._hass) && this._isReady(hass)) {
log(
this._api.getConfigManager().getCardWideConfig(),
'Advanced Camera Card: HA fully ready, reinitializing...',
);
// When the HA WebSocket connection is restored after a drop,
// reinitialize cameras and the view. This is necessary because
// event subscriptions (e.g. Frigate WebSocket subscriptions via
// hass.connection.subscribeMessage) are tied to the old connection
// and are lost when it drops. Without reinitialization, triggers
// and thumbnail updates stop working.
if (this._hass) {
log(
this._api.getConfigManager().getCardWideConfig(),
'Advanced Camera Card: HA connection restored, reinitializing...',
);
this._api
.getInitializationManager()
.uninitialize(InitializationAspect.CAMERAS);
this._api.getCameraManager().destroy();
this._api.getInitializationManager().uninitialize(InitializationAspect.VIEW);
this._api
.getInitializationManager()
.uninitialize(InitializationAspect.INITIAL_TRIGGER);
}
}
this._api.getInitializationManager().uninitialize(InitializationAspect.CAMERAS);
this._api.getCameraManager().destroy();
this._api.getInitializationManager().uninitialize(InitializationAspect.VIEW);
this._api
.getInitializationManager()
.uninitialize(InitializationAspect.INITIAL_TRIGGER);
}
if (!hass) {
@@ -79,4 +69,8 @@ export class HASSManager {
this._stateWatcher.setHASS(oldHass, hass);
}
private _isReady(hass?: HomeAssistant | null): boolean {
return !!hass?.connected && hass.config?.state === STATE_RUNNING;
}
}