Compare commits

...
Author SHA1 Message Date
Claude 0b81845af3 Correct entity domain and helper API types in the frontend
Compare the entity domain and helper data modules with the domains
that produce the attributes, and fix the mismatches.

Add supported feature flags the domains define and the frontend did
not list, and add attributes the domains report. Remove attributes
that are service fields rather than state, and the light colour
temperature keys core replaced with the kelvin forms.

Correct the weather forecast, where the event carries the whole list
and the wind speed is a number, and correct the image update command,
which sent the wrong id.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK
2026-09-21 05:38:14 +00:00
25 changed files with 53 additions and 39 deletions
@@ -11,7 +11,6 @@ export const mockPersistentNotification = (hass: MockHomeAssistant) => {
message: "There was motion detected in the backyard.",
notification_id: "demo-1",
title: "Motion Detected!",
status: "unread",
},
},
} as PersistentNotificationMessage);
+2
View File
@@ -217,6 +217,8 @@ export interface CalendarEventApiData {
uid?: string | null;
recurrence_id?: string | null;
rrule?: string | null;
status?: "confirmed" | "tentative" | null;
all_day?: boolean;
}
export interface CalendarEventSubscription {
+3 -4
View File
@@ -16,11 +16,10 @@ export type StreamType = typeof STREAM_TYPE_HLS | typeof STREAM_TYPE_WEB_RTC;
export { CameraEntityFeature } from "./feature/camera_entity_feature";
interface CameraEntityAttributes extends HassEntityAttributeBase {
model_name: string;
model_name?: string;
access_token?: string;
brand: string;
motion_detection: boolean;
frontend_stream_type: string;
brand?: string;
motion_detection?: boolean;
}
export interface CameraEntity extends HassEntityBase {
+2 -3
View File
@@ -39,13 +39,12 @@ export type HvacAction =
export type ClimateEntity = HassEntityBase & {
attributes: HassEntityAttributeBase & {
hvac_mode: HvacMode;
hvac_modes: HvacMode[];
hvac_action?: HvacAction;
current_temperature: number;
current_temperature?: number;
min_temp: number;
max_temp: number;
temperature: number;
temperature?: number;
target_temp_step?: number;
target_temp_high?: number;
target_temp_low?: number;
+2 -2
View File
@@ -6,8 +6,8 @@ export interface Counter {
icon?: string;
initial?: number;
restore?: boolean;
minimum?: number;
maximum?: number;
minimum?: number | null;
maximum?: number | null;
step?: number;
}
+1
View File
@@ -106,6 +106,7 @@ export function canStopTilt(stateObj: CoverEntity): boolean {
interface CoverEntityAttributes extends HassEntityAttributeBase {
current_position?: number;
current_tilt_position?: number;
supported_speeds?: string[];
}
export interface CoverEntity extends HassEntityBase {
+1
View File
@@ -7,4 +7,5 @@ export enum CoverEntityFeature {
CLOSE_TILT = 32,
STOP_TILT = 64,
SET_TILT_POSITION = 128,
SPEED = 256,
}
@@ -19,4 +19,7 @@ export enum MediaPlayerEntityFeature {
BROWSE_MEDIA = 131072,
REPEAT_SET = 262144,
GROUPING = 524288,
MEDIA_ANNOUNCE = 1048576,
MEDIA_ENQUEUE = 2097152,
SEARCH_MEDIA = 4194304,
}
+1 -1
View File
@@ -75,7 +75,7 @@ export const updateImage = (
) =>
hass.callWS<Image>({
type: "image/update",
media_id: id,
image_id: id,
...updates,
});
+1
View File
@@ -9,6 +9,7 @@ export interface InputText {
max?: number;
pattern?: string;
mode?: "text" | "password";
unit_of_measurement?: string;
}
export interface InputTextMutableParams {
-3
View File
@@ -69,12 +69,9 @@ export const getLightCurrentModeRgbColor = (
interface LightEntityAttributes extends HassEntityAttributeBase {
min_color_temp_kelvin?: number;
max_color_temp_kelvin?: number;
min_mireds?: number;
max_mireds?: number;
brightness?: number;
xy_color?: [number, number];
hs_color?: [number, number];
color_temp?: number;
color_temp_kelvin?: number;
rgb_color?: [number, number, number];
rgbw_color?: [number, number, number, number];
+4
View File
@@ -48,10 +48,14 @@ interface MediaPlayerEntityAttributes extends HassEntityAttributeBase {
media_content_id?: string;
media_content_type?: string;
media_artist?: string;
media_album_name?: string;
media_album_artist?: string;
media_track?: number;
media_playlist?: string;
media_series_title?: string;
media_season?: any;
media_episode?: any;
app_id?: string;
app_name?: string;
media_position_updated_at?: string | number | Date;
media_duration?: number;
+1 -2
View File
@@ -15,8 +15,7 @@ export interface PersistentNotification {
created_at: string;
message: string;
notification_id: string;
title: string;
status: "read" | "unread";
title: string | null;
}
export type PersistentNotifications = Record<string, PersistentNotification>;
+1 -2
View File
@@ -14,8 +14,7 @@ export const subscribePreviewGeneric = (
hass: HomeAssistant,
domain: string,
flow_id: string,
flow_type:
"config_flow" | "options_flow" | "config_subentries_flow" | "repair_flow",
flow_type: "config_flow" | "options_flow",
user_input: Record<string, any>,
callback: (preview: GenericPreview) => void
): Promise<UnsubscribeFunc> =>
+2 -2
View File
@@ -11,8 +11,8 @@ export enum RemoteEntityFeature {
export type RemoteEntity = HassEntityBase & {
attributes: HassEntityAttributeBase & {
current_activity: string | null;
activity_list: string[] | null;
current_activity?: string | null;
activity_list?: string[] | null;
[key: string]: any;
};
};
+1
View File
@@ -13,6 +13,7 @@ export const weekdays = [
export interface ScheduleDay {
from: string;
to: string;
data?: Record<string, boolean | string | number>;
}
type ScheduleDays = Partial<Record<(typeof weekdays)[number], ScheduleDay[]>>;
+1 -1
View File
@@ -79,7 +79,7 @@ export const subscribeItems = (
entity_id: string,
callback: (update: TodoItems) => void
) =>
hass.connection.subscribeMessage<any>(callback, {
hass.connection.subscribeMessage<TodoItems>(callback, {
type: "todo/item/subscribe",
entity_id,
});
+1 -1
View File
@@ -67,7 +67,7 @@ export function canReturnHome(stateObj: VacuumEntity): boolean {
export interface Segment {
id: string;
name: string;
group?: string;
group: string | null;
}
export const getVacuumSegments = (
+1 -2
View File
@@ -68,8 +68,7 @@ export function canStop(stateObj: ValveEntity): boolean {
}
interface ValveEntityAttributes extends HassEntityAttributeBase {
current_position?: number;
position?: number;
current_position?: number | null;
}
export interface ValveEntity extends HassEntityBase {
+5 -2
View File
@@ -7,6 +7,7 @@ export enum WaterHeaterEntityFeature {
TARGET_TEMPERATURE = 1,
OPERATION_MODE = 2,
AWAY_MODE = 4,
ON_OFF = 8,
}
export const OPERATION_MODES = [
@@ -28,8 +29,10 @@ export type WaterHeaterEntity = HassEntityBase & {
max_temp: number;
current_temperature?: number;
temperature?: number;
operation_mode: OperationMode;
operation_list: OperationMode[];
target_temp_high?: number;
target_temp_low?: number;
operation_mode?: OperationMode;
operation_list?: OperationMode[];
away_mode?: "on" | "off";
};
};
+14 -3
View File
@@ -56,13 +56,19 @@ export interface ForecastAttribute {
temperature: number;
datetime: string;
templow?: number;
apparent_temperature?: number;
dew_point?: number;
precipitation?: number;
precipitation_probability?: number;
humidity?: number;
cloud_coverage?: number;
uv_index?: number;
condition?: string;
is_daytime?: boolean;
pressure?: number;
wind_speed?: string;
wind_bearing?: number | string;
wind_gust_speed?: number;
wind_speed?: number;
}
export type ForecastPrecipitationType = "amount" | "probability";
@@ -77,13 +83,18 @@ export const getForecastPrecipitation = (
interface WeatherEntityAttributes extends HassEntityAttributeBase {
attribution?: string;
apparent_temperature?: number;
cloud_coverage?: number;
dew_point?: number;
humidity?: number;
forecast?: ForecastAttribute[];
is_daytime?: boolean;
ozone?: number;
pressure?: number;
temperature?: number;
uv_index?: number;
visibility?: number;
wind_bearing?: number | string;
wind_gust_speed?: number;
wind_speed?: number;
precipitation_unit: string;
pressure_unit: string;
@@ -94,7 +105,7 @@ interface WeatherEntityAttributes extends HassEntityAttributeBase {
export interface ForecastEvent {
type: "hourly" | "daily" | "twice_daily";
forecast: [ForecastAttribute] | null;
forecast: ForecastAttribute[] | null;
}
export interface WeatherEntity extends HassEntityBase {
@@ -82,12 +82,7 @@ export class FlowPreviewGeneric extends LitElement {
(await this._unsub)();
this._unsub = undefined;
}
if (
this.flowType !== "config_flow" &&
this.flowType !== "options_flow" &&
this.flowType !== "config_subentries_flow" &&
this.flowType !== "repair_flow"
) {
if (this.flowType !== "config_flow" && this.flowType !== "options_flow") {
return;
}
this._error = undefined;
@@ -46,8 +46,8 @@ const OPTION_MIN_WIDTH = 30;
type NumericFavoriteEntity = HassEntity & {
attributes: HassEntity["attributes"] & {
current_position?: number;
current_tilt_position?: number;
current_position?: number | null;
current_tilt_position?: number | null;
};
};
@@ -22,7 +22,8 @@ const valvePositionFavoriteCardFeatureDefinition: NumericFavoriteCardFeatureDefi
domain: "valve",
supportsPosition: valveSupportsPosition,
getFavoritePositions: (entry) => entry?.options?.valve?.favorite_positions,
getCurrentValue: (stateObj) => stateObj.attributes.current_position,
getCurrentValue: (stateObj) =>
stateObj.attributes.current_position ?? undefined,
normalizeFavoritePositions,
defaultFavoritePositions: DEFAULT_VALVE_FAVORITE_POSITIONS,
setPositionService: "set_valve_position",
+1 -1
View File
@@ -115,7 +115,7 @@ describe("image_upload", () => {
await updateImage(hass, "12345", updates);
expect(hass.callWS).toHaveBeenCalledWith({
type: "image/update",
media_id: "12345",
image_id: "12345",
...updates,
});
});