Handle (invalid) null hass objects.
This commit is contained in:
@@ -16,7 +16,7 @@ export class HASSManager {
|
|||||||
return this._hass;
|
return this._hass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setHASS(hass: ExtendedHomeAssistant): void {
|
public setHASS(hass?: ExtendedHomeAssistant | null): void {
|
||||||
const getSelectedCameraConfig = (): CameraConfig | null => {
|
const getSelectedCameraConfig = (): CameraConfig | null => {
|
||||||
const view = this._api.getViewManager().getView();
|
const view = this._api.getViewManager().getView();
|
||||||
const cameraManager = this._api.getCameraManager();
|
const cameraManager = this._api.getCameraManager();
|
||||||
@@ -26,13 +26,8 @@ export class HASSManager {
|
|||||||
: null;
|
: null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const oldHass = this._hass;
|
if (hasHAConnectionStateChanged(this._hass, hass)) {
|
||||||
this._hass = hass;
|
if (!hass?.connected) {
|
||||||
|
|
||||||
const selectedCamera = getSelectedCameraConfig();
|
|
||||||
|
|
||||||
if (hasHAConnectionStateChanged(oldHass, hass)) {
|
|
||||||
if (!this._hass?.connected) {
|
|
||||||
this._api.getMessageManager().setMessageIfHigherPriority({
|
this._api.getMessageManager().setMessageIfHigherPriority({
|
||||||
message: localize('error.reconnecting'),
|
message: localize('error.reconnecting'),
|
||||||
icon: 'mdi:lan-disconnect',
|
icon: 'mdi:lan-disconnect',
|
||||||
@@ -40,9 +35,18 @@ export class HASSManager {
|
|||||||
dotdotdot: true,
|
dotdotdot: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this._api.getViewManager().setViewDefault();
|
this._api.getMessageManager().resetType('connection');
|
||||||
}
|
}
|
||||||
} else if (
|
}
|
||||||
|
|
||||||
|
if (!hass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldHass = this._hass;
|
||||||
|
this._hass = hass;
|
||||||
|
|
||||||
|
if (
|
||||||
// Home Assistant pumps a lot of updates through. Re-rendering the card is
|
// Home Assistant pumps a lot of updates through. Re-rendering the card is
|
||||||
// necessary at times (e.g. to update the 'clip' view as new clips
|
// necessary at times (e.g. to update the 'clip' view as new clips
|
||||||
// arrive), but also is a jarring experience for the user (e.g. if they
|
// arrive), but also is a jarring experience for the user (e.g. if they
|
||||||
@@ -52,7 +56,7 @@ export class HASSManager {
|
|||||||
this._isAutomatedViewUpdateAllowed() &&
|
this._isAutomatedViewUpdateAllowed() &&
|
||||||
isHassDifferent(this._hass, oldHass, [
|
isHassDifferent(this._hass, oldHass, [
|
||||||
...(this._api.getConfigManager().getConfig()?.view.update_entities ?? []),
|
...(this._api.getConfigManager().getConfig()?.view.update_entities ?? []),
|
||||||
...(selectedCamera?.triggers.entities ?? []),
|
...(getSelectedCameraConfig()?.triggers.entities ?? []),
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
// If entities being monitored have changed then reset the view to the
|
// If entities being monitored have changed then reset the view to the
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FrigateCardError, MESSAGE_TYPE_PRIORITIES, Message } from '../types';
|
import { FrigateCardError, MESSAGE_TYPE_PRIORITIES, Message, MessageType } from '../types';
|
||||||
import { errorToConsole } from '../utils/basic';
|
import { errorToConsole } from '../utils/basic';
|
||||||
import { CardMessageAPI } from './types';
|
import { CardMessageAPI } from './types';
|
||||||
|
|
||||||
@@ -31,6 +31,12 @@ export class MessageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public resetType(type: MessageType): void {
|
||||||
|
if (this._message?.type === type) {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public setErrorIfHigherPriority(error: unknown): void {
|
public setErrorIfHigherPriority(error: unknown): void {
|
||||||
// This object should accept unknown objects to be able to seamlessly
|
// This object should accept unknown objects to be able to seamlessly
|
||||||
// process arguments to catch() which can only be unknown/any.
|
// process arguments to catch() which can only be unknown/any.
|
||||||
|
|||||||
@@ -375,8 +375,5 @@ export const hasHAConnectionStateChanged = (
|
|||||||
oldHass: HomeAssistant | undefined | null,
|
oldHass: HomeAssistant | undefined | null,
|
||||||
newHass: HomeAssistant | undefined | null,
|
newHass: HomeAssistant | undefined | null,
|
||||||
): boolean => {
|
): boolean => {
|
||||||
return (
|
return oldHass?.connected !== newHass?.connected;
|
||||||
(!oldHass && !newHass?.connected) ||
|
|
||||||
(!!oldHass && oldHass.connected !== !!newHass?.connected)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -130,7 +130,29 @@ describe('HASSManager', () => {
|
|||||||
const reconnectedHASS = createHASS();
|
const reconnectedHASS = createHASS();
|
||||||
manager.setHASS(reconnectedHASS);
|
manager.setHASS(reconnectedHASS);
|
||||||
|
|
||||||
expect(api.getViewManager().setViewDefault).toBeCalled();
|
expect(api.getMessageManager().resetType).toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hass is null', () => {
|
||||||
|
const api = createAPIWithoutMediaPlayers();
|
||||||
|
const manager = new HASSManager(api);
|
||||||
|
const connectedHASS = createHASS();
|
||||||
|
connectedHASS.connected = true;
|
||||||
|
|
||||||
|
manager.setHASS(connectedHASS);
|
||||||
|
manager.setHASS(null);
|
||||||
|
|
||||||
|
expect(api.getMessageManager().setMessageIfHigherPriority).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
message: 'Reconnecting',
|
||||||
|
icon: 'mdi:lan-disconnect',
|
||||||
|
type: 'connection',
|
||||||
|
dotdotdot: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
manager.setHASS(connectedHASS);
|
||||||
|
expect(api.getMessageManager().resetType).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,22 @@ describe('MessageManager', () => {
|
|||||||
expect(api.getCardElementManager().update).toBeCalled();
|
expect(api.getCardElementManager().update).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should reset message that matches type', () => {
|
||||||
|
const api = createCardAPI();
|
||||||
|
const manager = new MessageManager(api);
|
||||||
|
|
||||||
|
const message = createMessage({ type: 'connection' });
|
||||||
|
manager.setMessageIfHigherPriority(message);
|
||||||
|
expect(manager.getMessage()).toBe(message);
|
||||||
|
|
||||||
|
manager.resetType('error');
|
||||||
|
expect(manager.getMessage()).toBe(message);
|
||||||
|
|
||||||
|
manager.resetType('connection');
|
||||||
|
expect(manager.getMessage()).toBeNull();
|
||||||
|
expect(manager.hasMessage()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should respect priority', () => {
|
it('should respect priority', () => {
|
||||||
const api = createCardAPI();
|
const api = createCardAPI();
|
||||||
const manager = new MessageManager(api);
|
const manager = new MessageManager(api);
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { HomeAssistant } from 'custom-card-helpers';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { hasHAConnectionStateChanged } from '../../../src/utils/ha/index.js';
|
||||||
|
import { createHASS } from '../../test-utils.js';
|
||||||
|
|
||||||
|
const createConnected = (connected: boolean): HomeAssistant => {
|
||||||
|
const hass = createHASS();
|
||||||
|
hass.connected = connected;
|
||||||
|
return hass;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('hasHAConnectionStateChanged', () => {
|
||||||
|
it('initially connected', () => {
|
||||||
|
expect(hasHAConnectionStateChanged(null, createConnected(true))).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('initially disconnected', () => {
|
||||||
|
expect(hasHAConnectionStateChanged(null, createConnected(false))).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('disconnected', () => {
|
||||||
|
expect(
|
||||||
|
hasHAConnectionStateChanged(createConnected(true), createConnected(false)),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('disconnected via absence', () => {
|
||||||
|
expect(hasHAConnectionStateChanged(createConnected(true), null)).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('connected', () => {
|
||||||
|
expect(
|
||||||
|
hasHAConnectionStateChanged(createConnected(false), createConnected(true)),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('still disconnected', () => {
|
||||||
|
expect(
|
||||||
|
hasHAConnectionStateChanged(createConnected(false), createConnected(false)),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('still connected', () => {
|
||||||
|
expect(
|
||||||
|
hasHAConnectionStateChanged(createConnected(true), createConnected(true)),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('still absent', () => {
|
||||||
|
expect(hasHAConnectionStateChanged(null, null)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user