More demo stubs (#2529)
* More demo stubs * History stub actually generates mocks * More tweaks * Add more entitiespull/2530/head
parent
547f829f5b
commit
24b0eb8ce4
|
@ -19,6 +19,7 @@ export const demoThemeJimpower = () => ({
|
|||
"paper-grey-200": "#414A59",
|
||||
"label-badge-background-color": "#2E333A",
|
||||
"paper-card-header-color": "var(--accent-color)",
|
||||
"sidebar-icon-color": "var(--paper-item-icon-color)",
|
||||
"paper-listbox-background-color": "#2E333A",
|
||||
"table-row-background-color": "#353840",
|
||||
"paper-grey-50": "var(--primary-text-color)",
|
||||
|
|
|
@ -93,7 +93,7 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
type: "icon",
|
||||
tap_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "/lovelace/traffic",
|
||||
navigation_path: "/lovelace/home_info",
|
||||
},
|
||||
icon: "mdi:car",
|
||||
},
|
||||
|
@ -192,6 +192,12 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
],
|
||||
type: "horizontal-stack",
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
},
|
||||
{
|
||||
type: "vertical-stack",
|
||||
cards: [
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
|
@ -225,248 +231,180 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
type: "horizontal-stack",
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
"light.outdoor_lights",
|
||||
{
|
||||
name: "Yard net",
|
||||
entity: "light.outdoor_yard_light_net",
|
||||
},
|
||||
"light.bedroom_ceiling_light",
|
||||
"light.bedside_lamp",
|
||||
"light.dining_area_ceiling_light_level",
|
||||
"light.kitchen_ceiling_spotlights_level",
|
||||
"light.floorlamp_reading_light",
|
||||
"light.floorlamp_uplight",
|
||||
"light.hallway_window_light",
|
||||
"light.isa_ceiling_light",
|
||||
"light.living_room_ceiling_light_level",
|
||||
"light.living_room_spotlights_level",
|
||||
"light.passage_ceiling_spotlights_level",
|
||||
"light.stairs_lights_lights",
|
||||
"light.walk_in_closet_lights",
|
||||
"light.upstairs_hallway_ceiling_light_level",
|
||||
"light.gateway_light_34ce008bfc4b",
|
||||
],
|
||||
show_empty: false,
|
||||
type: "entity-filter",
|
||||
card: {
|
||||
type: "glance",
|
||||
show_state: false,
|
||||
},
|
||||
state_filter: ["on"],
|
||||
},
|
||||
{
|
||||
type: "shopping-list",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
{
|
||||
entity: "switch.livingroom_tv",
|
||||
name: "Tv",
|
||||
icon: "mdi:television-classic",
|
||||
},
|
||||
// {
|
||||
// hide_power: true,
|
||||
// group: true,
|
||||
// icon: "mdi:television-classic",
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.livingroom_tv",
|
||||
// },
|
||||
{
|
||||
entity: "switch.livingroom_movie_system",
|
||||
name: "Movie system",
|
||||
icon: "mdi:movie",
|
||||
},
|
||||
// {
|
||||
// hide_power: true,
|
||||
// group: true,
|
||||
// name: "Movie system",
|
||||
// icon: "mdi:movie",
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.livingroom_movie_system",
|
||||
// },
|
||||
// {
|
||||
// hide_power: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.shield",
|
||||
// group: true,
|
||||
// icon: "mdi:cast",
|
||||
// },
|
||||
// {
|
||||
// group: true,
|
||||
// icon: "mdi:speaker-wireless",
|
||||
// power_color: true,
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.sonos",
|
||||
// },
|
||||
// {
|
||||
// group: true,
|
||||
// name: "Chromecast Bedroom",
|
||||
// icon: "mdi:cast",
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.sovrum",
|
||||
// },
|
||||
],
|
||||
type: "entities",
|
||||
},
|
||||
|
||||
{
|
||||
image: "/assets/teachingbirds/plants.png",
|
||||
elements: [
|
||||
{
|
||||
style: {
|
||||
top: "7%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "2%",
|
||||
transform: "none",
|
||||
},
|
||||
type: "state-badge",
|
||||
entity: "sensor.small_chili_moisture",
|
||||
},
|
||||
{
|
||||
style: {
|
||||
top: "7%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "17%",
|
||||
transform: "none",
|
||||
},
|
||||
type: "state-badge",
|
||||
entity: "sensor.big_chili_moisture",
|
||||
},
|
||||
{
|
||||
style: {
|
||||
top: "7%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "32%",
|
||||
transform: "none",
|
||||
},
|
||||
type: "state-badge",
|
||||
entity: "sensor.herbs_moisture",
|
||||
},
|
||||
{
|
||||
style: {
|
||||
top: "12%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "92%",
|
||||
},
|
||||
type: "state-label",
|
||||
entity: "sensor.greenhouse_temperature",
|
||||
},
|
||||
],
|
||||
type: "picture-elements",
|
||||
},
|
||||
{
|
||||
// show_name: false,
|
||||
// entity: "camera.stockholm_meteogram",
|
||||
// type: "picture-entity",
|
||||
// show_state: false,
|
||||
type: "picture",
|
||||
image: "/assets/teachingbirds/meteogram.png",
|
||||
},
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
cards: [
|
||||
// {
|
||||
// entities: [
|
||||
// {
|
||||
// name: "Front door lock",
|
||||
// entity: "sensor.front_door_lock",
|
||||
// },
|
||||
// {
|
||||
// name: "Yard door lock",
|
||||
// entity: "sensor.yard_door_lock",
|
||||
// },
|
||||
// "sensor.front_door",
|
||||
// "sensor.back_door",
|
||||
// "sensor.backyard_door",
|
||||
// "sensor.balcony_door",
|
||||
// "sensor.yard_door",
|
||||
// {
|
||||
// name: "Dining area",
|
||||
// entity: "sensor.dining_area_window",
|
||||
// },
|
||||
// {
|
||||
// name: "Bedroom",
|
||||
// entity: "sensor.bedroom_window",
|
||||
// },
|
||||
// {
|
||||
// name: "Ring motion",
|
||||
// entity: "sensor.front_door_outdoor_movement",
|
||||
// },
|
||||
// "sensor.hallway_movement",
|
||||
// "sensor.passage_movement",
|
||||
// "sensor.upstairs_hallway_movement",
|
||||
// "sensor.living_room_movement",
|
||||
// "sensor.back_door_camera_movement",
|
||||
// {
|
||||
// name: "Storage door",
|
||||
// entity: "sensor.yard_storage_door",
|
||||
// },
|
||||
// "sensor.water_heater",
|
||||
// "sensor.kitchen_sink",
|
||||
// "binary_sensor.smoke_sensor_158d0001d37bdd",
|
||||
// "binary_sensor.smoke_sensor_158d0001d37be5",
|
||||
// "binary_sensor.smoke_sensor_158d0001d37c82",
|
||||
// ],
|
||||
// show_empty: false,
|
||||
// type: "entity-filter",
|
||||
// card: {
|
||||
// type: "glance",
|
||||
// show_state: false,
|
||||
// },
|
||||
// state_filter: [
|
||||
// "Open",
|
||||
// "Movement detected",
|
||||
// "Leaking",
|
||||
// "Unlocked",
|
||||
// "on",
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
entities: [
|
||||
"light.outdoor_lights",
|
||||
{
|
||||
name: "Yard net",
|
||||
entity: "light.outdoor_yard_light_net",
|
||||
},
|
||||
"light.bedroom_ceiling_light",
|
||||
"light.bedside_lamp",
|
||||
"light.dining_area_ceiling_light_level",
|
||||
"light.kitchen_ceiling_spotlights_level",
|
||||
"light.floorlamp_reading_light",
|
||||
"light.floorlamp_uplight",
|
||||
"light.hallway_window_light",
|
||||
"light.isa_ceiling_light",
|
||||
"light.living_room_ceiling_light_level",
|
||||
"light.living_room_spotlights_level",
|
||||
"light.passage_ceiling_spotlights_level",
|
||||
"light.stairs_lights_lights",
|
||||
"light.walk_in_closet_lights",
|
||||
"light.upstairs_hallway_ceiling_light_level",
|
||||
"light.gateway_light_34ce008bfc4b",
|
||||
],
|
||||
show_empty: false,
|
||||
type: "entity-filter",
|
||||
card: {
|
||||
type: "glance",
|
||||
show_state: false,
|
||||
},
|
||||
state_filter: ["on"],
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
type: "gauge",
|
||||
severity: {
|
||||
green: 0,
|
||||
yellow: 2,
|
||||
red: 3,
|
||||
},
|
||||
min: 0,
|
||||
max: 6,
|
||||
title: "Downstairs",
|
||||
measurement: "visits",
|
||||
entity: "counter.litterbox_downstairs_visits",
|
||||
},
|
||||
{
|
||||
type: "shopping-list",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
{
|
||||
entity: "switch.livingroom_tv",
|
||||
name: "Tv",
|
||||
icon: "mdi:television-classic",
|
||||
},
|
||||
// {
|
||||
// hide_power: true,
|
||||
// group: true,
|
||||
// icon: "mdi:television-classic",
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.livingroom_tv",
|
||||
// },
|
||||
{
|
||||
entity: "switch.livingroom_movie_system",
|
||||
name: "Movie system",
|
||||
icon: "mdi:movie",
|
||||
},
|
||||
// {
|
||||
// hide_power: true,
|
||||
// group: true,
|
||||
// name: "Movie system",
|
||||
// icon: "mdi:movie",
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.livingroom_movie_system",
|
||||
// },
|
||||
// {
|
||||
// hide_power: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.shield",
|
||||
// group: true,
|
||||
// icon: "mdi:cast",
|
||||
// },
|
||||
// {
|
||||
// group: true,
|
||||
// icon: "mdi:speaker-wireless",
|
||||
// power_color: true,
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.sonos",
|
||||
// },
|
||||
// {
|
||||
// group: true,
|
||||
// name: "Chromecast Bedroom",
|
||||
// icon: "mdi:cast",
|
||||
// artwork_border: true,
|
||||
// type: "custom:mini-media-player",
|
||||
// entity: "media_player.sovrum",
|
||||
// },
|
||||
],
|
||||
type: "entities",
|
||||
type: "gauge",
|
||||
severity: {
|
||||
green: 0,
|
||||
yellow: 2,
|
||||
red: 3,
|
||||
},
|
||||
min: 0,
|
||||
max: 6,
|
||||
title: "Upstairs",
|
||||
measurement: "visits",
|
||||
entity: "counter.litterbox_upstairs_visits",
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
},
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
image: "/assets/teachingbirds/plants.png",
|
||||
elements: [
|
||||
{
|
||||
style: {
|
||||
top: "30%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "10%",
|
||||
},
|
||||
type: "state-badge",
|
||||
entity: "sensor.small_chili_moisture",
|
||||
},
|
||||
{
|
||||
style: {
|
||||
top: "30%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "25%",
|
||||
},
|
||||
type: "state-badge",
|
||||
entity: "sensor.big_chili_moisture",
|
||||
},
|
||||
{
|
||||
style: {
|
||||
top: "30%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "40%",
|
||||
},
|
||||
type: "state-badge",
|
||||
entity: "sensor.herbs_moisture",
|
||||
},
|
||||
{
|
||||
style: {
|
||||
top: "12%",
|
||||
"--ha-label-badge-font-size": "1em",
|
||||
left: "92%",
|
||||
},
|
||||
type: "state-label",
|
||||
entity: "sensor.greenhouse_temperature",
|
||||
},
|
||||
],
|
||||
type: "picture-elements",
|
||||
},
|
||||
{
|
||||
// show_name: false,
|
||||
// entity: "camera.stockholm_meteogram",
|
||||
// type: "picture-entity",
|
||||
// show_state: false,
|
||||
type: "picture",
|
||||
image: "/assets/teachingbirds/meteogram.png",
|
||||
},
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
type: "gauge",
|
||||
severity: {
|
||||
green: 0,
|
||||
yellow: 2,
|
||||
red: 3,
|
||||
},
|
||||
min: 0,
|
||||
max: 6,
|
||||
title: "Downstairs",
|
||||
measurement: "visits",
|
||||
entity: "counter.litterbox_downstairs_visits",
|
||||
},
|
||||
{
|
||||
type: "gauge",
|
||||
severity: {
|
||||
green: 0,
|
||||
yellow: 2,
|
||||
red: 3,
|
||||
},
|
||||
min: 0,
|
||||
max: 6,
|
||||
title: "Upstairs",
|
||||
measurement: "visits",
|
||||
entity: "counter.litterbox_upstairs_visits",
|
||||
},
|
||||
],
|
||||
type: "horizontal-stack",
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
type: "horizontal-stack",
|
||||
},
|
||||
],
|
||||
path: "home",
|
||||
|
@ -478,75 +416,75 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
{
|
||||
cards: [
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
entity: "script.air_cleaner_quiet",
|
||||
type: "entity-button",
|
||||
name: "AC bed",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.air_cleaner_quiet",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan-off",
|
||||
entity: "script.air_cleaner_quiet",
|
||||
type: "entity-button",
|
||||
name: "AC bed",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.air_cleaner_quiet",
|
||||
},
|
||||
{
|
||||
entity: "script.air_cleaner_auto",
|
||||
type: "entity-button",
|
||||
name: "AC bed",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.air_cleaner_auto",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan",
|
||||
},
|
||||
{
|
||||
entity: "script.air_cleaner_turbo",
|
||||
type: "entity-button",
|
||||
name: "AC bed",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.air_cleaner_turbo",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:run-fast",
|
||||
},
|
||||
{
|
||||
entity: "script.ac_off",
|
||||
type: "entity-button",
|
||||
name: "AC",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.ac_off",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan-off",
|
||||
},
|
||||
{
|
||||
entity: "script.ac_on",
|
||||
type: "entity-button",
|
||||
name: "AC",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.ac_on",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan",
|
||||
},
|
||||
],
|
||||
type: "horizontal-stack",
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan-off",
|
||||
},
|
||||
{
|
||||
entity: "script.air_cleaner_auto",
|
||||
type: "entity-button",
|
||||
name: "AC bed",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.air_cleaner_auto",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan",
|
||||
},
|
||||
{
|
||||
entity: "script.air_cleaner_turbo",
|
||||
type: "entity-button",
|
||||
name: "AC bed",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.air_cleaner_turbo",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:run-fast",
|
||||
},
|
||||
{
|
||||
entity: "script.ac_off",
|
||||
type: "entity-button",
|
||||
name: "AC",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.ac_off",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan-off",
|
||||
},
|
||||
{
|
||||
entity: "script.ac_on",
|
||||
type: "entity-button",
|
||||
name: "AC",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "script.ac_on",
|
||||
},
|
||||
service: "script.turn_on",
|
||||
},
|
||||
icon: "mdi:fan",
|
||||
},
|
||||
],
|
||||
type: "horizontal-stack",
|
||||
},
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
|
@ -595,91 +533,100 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
],
|
||||
type: "horizontal-stack",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
{
|
||||
name: "Vacation",
|
||||
entity: "input_boolean.vacation_mode",
|
||||
},
|
||||
"input_boolean.cleaning_day",
|
||||
"input_boolean.guest_mode",
|
||||
{
|
||||
name: "Isa Mode",
|
||||
tap_action: {
|
||||
action: "toggle",
|
||||
},
|
||||
entity: "input_boolean.isa_mode",
|
||||
},
|
||||
],
|
||||
show_header_toggle: false,
|
||||
type: "glance",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
"sensor.pollen_bjork",
|
||||
"sensor.pollen_gras",
|
||||
"sensor.pollen_grabo",
|
||||
],
|
||||
type: "glance",
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
},
|
||||
{
|
||||
cards: [
|
||||
entities: [
|
||||
{
|
||||
states: ["arm_home", "arm_away", "arm_night"],
|
||||
type: "alarm-panel",
|
||||
entity: "alarm_control_panel.house",
|
||||
name: "Vacation",
|
||||
entity: "input_boolean.vacation_mode",
|
||||
tap_action: {
|
||||
action: "toggle",
|
||||
},
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
{
|
||||
entity: "sensor.front_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.back_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.yard_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.balcony_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.dining_area_window",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.bedroom_window",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.passage_movement",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.upstairs_hallway_movement",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "binary_sensor.stefans_room_motion",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.ring_front_door_last_motion",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
],
|
||||
type: "entities",
|
||||
entity: "input_boolean.cleaning_day",
|
||||
tap_action: {
|
||||
action: "toggle",
|
||||
},
|
||||
},
|
||||
{
|
||||
entity: "input_boolean.guest_mode",
|
||||
tap_action: {
|
||||
action: "toggle",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Isa Mode",
|
||||
tap_action: {
|
||||
action: "toggle",
|
||||
},
|
||||
entity: "input_boolean.isa_mode",
|
||||
},
|
||||
],
|
||||
type: "vertical-stack",
|
||||
show_header_toggle: false,
|
||||
type: "glance",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
"sensor.pollen_bjork",
|
||||
"sensor.pollen_gras",
|
||||
"sensor.pollen_grabo",
|
||||
],
|
||||
type: "glance",
|
||||
},
|
||||
{
|
||||
states: ["arm_home", "arm_away", "arm_night"],
|
||||
type: "alarm-panel",
|
||||
entity: "alarm_control_panel.house",
|
||||
},
|
||||
{
|
||||
entities: [
|
||||
{
|
||||
entity: "sensor.front_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.back_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.yard_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.balcony_door",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.dining_area_window",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.bedroom_window",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.passage_movement",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.upstairs_hallway_movement",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "binary_sensor.stefans_room_motion",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
{
|
||||
entity: "sensor.ring_front_door_last_motion",
|
||||
secondary_info: "last-changed",
|
||||
},
|
||||
],
|
||||
type: "entities",
|
||||
},
|
||||
|
||||
{
|
||||
cards: [
|
||||
{
|
||||
|
@ -729,19 +676,16 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
cards: [
|
||||
{
|
||||
entity: "scene.morning_lights",
|
||||
hold_action: {
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: "script.goodnight",
|
||||
},
|
||||
type: "entity-button",
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
icon: "mdi:weather-night",
|
||||
},
|
||||
{
|
||||
entity: "scene.morning_lights",
|
||||
hold_action: {
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "scene.morning_lights",
|
||||
|
@ -749,14 +693,11 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
service: "scene.turn_on",
|
||||
},
|
||||
type: "entity-button",
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
icon: "mdi:coffee-outline",
|
||||
},
|
||||
{
|
||||
entity: "scene.movie_time",
|
||||
hold_action: {
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "scene.movie_time",
|
||||
|
@ -764,9 +705,6 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
service: "scene.turn_on",
|
||||
},
|
||||
type: "entity-button",
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
icon: "mdi:television-classic",
|
||||
},
|
||||
],
|
||||
|
@ -820,32 +758,26 @@ export const demoLovelaceTeachingbirds: () => LovelaceConfig = () => ({
|
|||
cards: [
|
||||
{
|
||||
entity: "light.downstairs_lights",
|
||||
hold_action: {
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "light.downstairs_lights",
|
||||
},
|
||||
service: "light.turn_off",
|
||||
service: "light.toggle",
|
||||
},
|
||||
type: "entity-button",
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
icon: "mdi:page-layout-footer",
|
||||
},
|
||||
{
|
||||
entity: "light.upstairs_lights",
|
||||
hold_action: {
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service_data: {
|
||||
entity_id: "light.upstairs_lights",
|
||||
},
|
||||
service: "light.turn_off",
|
||||
service: "light.toggle",
|
||||
},
|
||||
type: "entity-button",
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
icon: "mdi:page-layout-header",
|
||||
},
|
||||
],
|
||||
|
|
|
@ -7,6 +7,9 @@ import { selectedDemoConfig } from "./configs/demo-configs";
|
|||
import { mockTranslations } from "./stubs/translations";
|
||||
import { mockHistory } from "./stubs/history";
|
||||
import { mockShoppingList } from "./stubs/shopping_list";
|
||||
import { mockSystemLog } from "./stubs/system_log";
|
||||
import { mockTemplate } from "./stubs/template";
|
||||
import { mockEvents } from "./stubs/events";
|
||||
|
||||
class HaDemo extends HomeAssistant {
|
||||
protected async _handleConnProm() {
|
||||
|
@ -24,6 +27,9 @@ class HaDemo extends HomeAssistant {
|
|||
mockTranslations(hass);
|
||||
mockHistory(hass);
|
||||
mockShoppingList(hass);
|
||||
mockSystemLog(hass);
|
||||
mockTemplate(hass);
|
||||
mockEvents(hass);
|
||||
selectedDemoConfig.then((conf) => {
|
||||
hass.addEntities(conf.entities());
|
||||
if (conf.theme) {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
|
||||
export const mockEvents = (hass: MockHomeAssistant) => {
|
||||
hass.mockAPI("events", () => []);
|
||||
};
|
|
@ -1,5 +1,138 @@
|
|||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
|
||||
export const mockHistory = (hass: MockHomeAssistant) => {
|
||||
hass.mockAPI(new RegExp("history/period/.+"), () => []);
|
||||
interface HistoryQueryParams {
|
||||
filter_entity_id: string;
|
||||
end_time: string;
|
||||
}
|
||||
|
||||
const parseQuery = <T>(queryString: string) => {
|
||||
const query: any = {};
|
||||
const items = queryString.split("&");
|
||||
for (const item of items) {
|
||||
const parts = item.split("=");
|
||||
const key = decodeURIComponent(parts[0]);
|
||||
const value = parts.length > 1 ? decodeURIComponent(parts[1]) : undefined;
|
||||
query[key] = value;
|
||||
}
|
||||
return query as T;
|
||||
};
|
||||
|
||||
const getTime = (minutesAgo) => {
|
||||
const ts = new Date(Date.now() - minutesAgo * 60 * 1000);
|
||||
return ts.toISOString();
|
||||
};
|
||||
|
||||
const randomTimeAdjustment = (diff) => Math.random() * diff - diff / 2;
|
||||
|
||||
const maxTime = 1440;
|
||||
|
||||
const generateHistory = (state, deltas) => {
|
||||
const changes =
|
||||
typeof deltas[0] === "object"
|
||||
? deltas
|
||||
: deltas.map((st) => ({ state: st }));
|
||||
|
||||
const timeDiff = 900 / changes.length;
|
||||
|
||||
return changes.map((change, index) => {
|
||||
let attributes;
|
||||
if (!change.attributes && !state.attributes) {
|
||||
attributes = {};
|
||||
} else if (!change.attributes) {
|
||||
attributes = state.attributes;
|
||||
} else if (!state.attributes) {
|
||||
attributes = change.attributes;
|
||||
} else {
|
||||
attributes = { ...state.attributes, ...change.attributes };
|
||||
}
|
||||
|
||||
const time =
|
||||
index === 0
|
||||
? getTime(maxTime)
|
||||
: getTime(maxTime - index * timeDiff + randomTimeAdjustment(timeDiff));
|
||||
|
||||
return {
|
||||
attributes,
|
||||
entity_id: state.entity_id,
|
||||
state: change.state || state.state,
|
||||
last_changed: time,
|
||||
last_updated: time,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const incrementalUnits = ["clients", "queries", "ads"];
|
||||
|
||||
export const mockHistory = (mockHass: MockHomeAssistant) => {
|
||||
mockHass.mockAPI(new RegExp("history/period/.+"), (
|
||||
hass,
|
||||
// @ts-ignore
|
||||
method,
|
||||
path,
|
||||
// @ts-ignore
|
||||
parameters
|
||||
) => {
|
||||
const params = parseQuery<HistoryQueryParams>(path.split("?")[1]);
|
||||
const entities = params.filter_entity_id.split(",");
|
||||
|
||||
const results: HassEntity[][] = [];
|
||||
|
||||
for (const entityId of entities) {
|
||||
const state = hass.states[entityId];
|
||||
|
||||
if (!state) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!state.attributes.unit_of_measurement) {
|
||||
results.push(generateHistory(state, [state.state]));
|
||||
continue;
|
||||
}
|
||||
|
||||
const numberState = Number(state.state);
|
||||
|
||||
if (isNaN(numberState)) {
|
||||
// tslint:disable-next-line
|
||||
console.log(
|
||||
"Ignoring state with unparsable state but with a unit",
|
||||
entityId,
|
||||
state
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const statesToGenerate = 15;
|
||||
let genFunc;
|
||||
|
||||
if (incrementalUnits.includes(state.attributes.unit_of_measurement)) {
|
||||
let initial = Math.floor(
|
||||
numberState * 0.4 + numberState * Math.random() * 0.2
|
||||
);
|
||||
const diff = Math.max(
|
||||
1,
|
||||
Math.floor((numberState - initial) / statesToGenerate)
|
||||
);
|
||||
genFunc = () => {
|
||||
initial += diff;
|
||||
return Math.min(numberState, initial);
|
||||
};
|
||||
} else {
|
||||
const diff = Math.floor(numberState * (numberState > 80 ? 0.05 : 0.5));
|
||||
genFunc = () =>
|
||||
numberState - diff + Math.floor(Math.random() * 2 * diff);
|
||||
}
|
||||
|
||||
results.push(
|
||||
generateHistory(
|
||||
{
|
||||
entity_id: state.entity_id,
|
||||
attributes: state.attributes,
|
||||
},
|
||||
Array.from({ length: statesToGenerate }, genFunc)
|
||||
)
|
||||
);
|
||||
}
|
||||
return results;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
|
||||
export const mockSystemLog = (hass: MockHomeAssistant) => {
|
||||
hass.mockAPI("error/all", () => []);
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
|
||||
export const mockTemplate = (hass: MockHomeAssistant) => {
|
||||
hass.mockAPI("template", () =>
|
||||
Promise.reject({
|
||||
body: { message: "Template dev tool does not work in the demo." },
|
||||
})
|
||||
);
|
||||
};
|
|
@ -11,7 +11,7 @@ export const demoConfig: HassConfig = {
|
|||
temperature: "°C",
|
||||
volume: "L",
|
||||
},
|
||||
components: ["conversation"],
|
||||
components: ["conversation", "notify.html5", "history"],
|
||||
time_zone: "America/Los_Angeles",
|
||||
config_dir: "/config",
|
||||
version: "DEMO",
|
||||
|
|
|
@ -66,7 +66,7 @@ export class Entity {
|
|||
}
|
||||
}
|
||||
|
||||
export class LightEntity extends Entity {
|
||||
class LightEntity extends Entity {
|
||||
public async handleService(domain, service, data) {
|
||||
if (!["homeassistant", this.domain].includes(domain)) {
|
||||
return;
|
||||
|
@ -89,7 +89,7 @@ export class LightEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
export class SwitchEntity extends Entity {
|
||||
class ToggleEntity extends Entity {
|
||||
public async handleService(domain, service, data) {
|
||||
if (!["homeassistant", this.domain].includes(domain)) {
|
||||
return;
|
||||
|
@ -109,7 +109,7 @@ export class SwitchEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
export class LockEntity extends Entity {
|
||||
class LockEntity extends Entity {
|
||||
public async handleService(
|
||||
domain,
|
||||
service,
|
||||
|
@ -128,7 +128,31 @@ export class LockEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
export class CoverEntity extends Entity {
|
||||
class AlarmControlPanelEntity extends Entity {
|
||||
public async handleService(
|
||||
domain,
|
||||
service,
|
||||
// @ts-ignore
|
||||
data
|
||||
) {
|
||||
if (domain !== this.domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
const serviceStateMap = {
|
||||
alarm_arm_night: "armed_night",
|
||||
alarm_arm_home: "armed_home",
|
||||
alarm_arm_away: "armed_away",
|
||||
alarm_disarm: "disarmed",
|
||||
};
|
||||
|
||||
if (serviceStateMap[service]) {
|
||||
this.update(serviceStateMap[service], this.baseAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CoverEntity extends Entity {
|
||||
public async handleService(
|
||||
domain,
|
||||
service,
|
||||
|
@ -147,7 +171,7 @@ export class CoverEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
export class ClimateEntity extends Entity {
|
||||
class ClimateEntity extends Entity {
|
||||
public async handleService(domain, service, data) {
|
||||
if (domain !== this.domain) {
|
||||
return;
|
||||
|
@ -162,7 +186,7 @@ export class ClimateEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
export class GroupEntity extends Entity {
|
||||
class GroupEntity extends Entity {
|
||||
public async handleService(domain, service, data) {
|
||||
if (!["homeassistant", this.domain].includes(domain)) {
|
||||
return;
|
||||
|
@ -180,12 +204,14 @@ export class GroupEntity extends Entity {
|
|||
}
|
||||
|
||||
const TYPES = {
|
||||
alarm_control_panel: AlarmControlPanelEntity,
|
||||
climate: ClimateEntity,
|
||||
cover: CoverEntity,
|
||||
group: GroupEntity,
|
||||
input_boolean: ToggleEntity,
|
||||
light: LightEntity,
|
||||
lock: LockEntity,
|
||||
switch: SwitchEntity,
|
||||
switch: ToggleEntity,
|
||||
};
|
||||
|
||||
export const getEntity = (
|
||||
|
|
|
@ -13,7 +13,8 @@ import { translationMetadata } from "../resources/translations-metadata";
|
|||
const ensureArray = <T>(val: T | T[]): T[] =>
|
||||
Array.isArray(val) ? val : [val];
|
||||
|
||||
type RestCallback = (
|
||||
type MockRestCallback = (
|
||||
hass: MockHomeAssistant,
|
||||
method: string,
|
||||
path: string,
|
||||
parameters: { [key: string]: any } | undefined
|
||||
|
@ -25,7 +26,7 @@ export interface MockHomeAssistant extends HomeAssistant {
|
|||
updateStates(newStates: HassEntities);
|
||||
addEntities(entites: Entity | Entity[], replace?: boolean);
|
||||
mockWS(type: string, callback: (msg: any) => any);
|
||||
mockAPI(path: string | RegExp, callback: RestCallback);
|
||||
mockAPI(path: string | RegExp, callback: MockRestCallback);
|
||||
mockEvent(event);
|
||||
mockTheme(theme: { [key: string]: string } | null);
|
||||
}
|
||||
|
@ -39,7 +40,7 @@ export const provideHass = (
|
|||
const hass = (): MockHomeAssistant => elements[0].hass;
|
||||
|
||||
const wsCommands = {};
|
||||
const restResponses: Array<[string | RegExp, RestCallback]> = [];
|
||||
const restResponses: Array<[string | RegExp, MockRestCallback]> = [];
|
||||
const eventListeners: {
|
||||
[event: string]: Array<(event) => void>;
|
||||
} = {};
|
||||
|
@ -160,7 +161,7 @@ export const provideHass = (
|
|||
);
|
||||
|
||||
return response
|
||||
? response[1](method, path, parameters)
|
||||
? response[1](hass(), method, path, parameters)
|
||||
: Promise.reject(`API Mock for ${path} is not implemented`);
|
||||
},
|
||||
fetchWithAuth: () => Promise.reject("Not implemented"),
|
||||
|
|
|
@ -210,7 +210,9 @@ For loop example:
|
|||
this.rendering = false;
|
||||
}.bind(this),
|
||||
function(error) {
|
||||
this.processed = error.body.message;
|
||||
this.processed =
|
||||
(error && error.body && error.body.message) ||
|
||||
"Unknown error rendering template";
|
||||
this.error = true;
|
||||
this.rendering = false;
|
||||
}.bind(this)
|
||||
|
|
Loading…
Reference in New Issue