Initial commit: Electron + React touchscreen kiosk dashboard for Home Assistant

This commit is contained in:
root
2026-02-25 23:01:20 -06:00
commit 97a7912eae
84 changed files with 12059 additions and 0 deletions

149
src/config/entities.ts Normal file
View File

@@ -0,0 +1,149 @@
/**
* Home Assistant Entity Configuration
*
* Configure your actual HA entity IDs here.
* These are placeholder values - update them to match your Home Assistant setup.
*/
export interface ThermostatConfig {
entityId: string;
name: string;
location: string;
}
export interface LightConfig {
entityId: string;
name: string;
room: string;
}
export interface LockConfig {
entityId: string;
name: string;
location: string;
}
export interface CameraConfig {
name: string;
displayName: string;
go2rtcStream: string;
frigateCamera?: string;
}
export interface PersonConfig {
entityId: string;
name: string;
avatarUrl?: string;
}
export interface EntitiesConfig {
thermostats: ThermostatConfig[];
lights: LightConfig[];
locks: LockConfig[];
alarm: string;
packageSensor: string;
todoList: string;
cameras: CameraConfig[];
personDetectionEntities: string[];
people: PersonConfig[];
}
// Default configuration - customize these for your setup
export const entitiesConfig: EntitiesConfig = {
// Thermostats (Nest with heat_cool mode)
thermostats: [
{
entityId: 'climate.upstairs_thermostat',
name: 'Upstairs',
location: 'upstairs',
},
{
entityId: 'climate.downstairs_thermostat',
name: 'Downstairs',
location: 'downstairs',
},
],
// Lights - grouped by room
lights: [
// Living Room
{ entityId: 'light.living_room_main', name: 'Main Light', room: 'Living Room' },
{ entityId: 'light.living_room_lamp', name: 'Lamp', room: 'Living Room' },
// Kitchen
{ entityId: 'light.kitchen_main', name: 'Main Light', room: 'Kitchen' },
{ entityId: 'light.kitchen_under_cabinet', name: 'Under Cabinet', room: 'Kitchen' },
// Bedroom
{ entityId: 'light.bedroom_main', name: 'Main Light', room: 'Bedroom' },
{ entityId: 'light.bedroom_lamp', name: 'Lamp', room: 'Bedroom' },
// Bathroom
{ entityId: 'light.bathroom_main', name: 'Main Light', room: 'Bathroom' },
// Hallway
{ entityId: 'light.hallway', name: 'Hallway', room: 'Hallway' },
// Outdoor
{ entityId: 'light.porch_light', name: 'Porch', room: 'Outdoor' },
{ entityId: 'light.garage_light', name: 'Garage', room: 'Outdoor' },
],
// Door Locks
locks: [
{ entityId: 'lock.front_door', name: 'Front Door', location: 'front' },
{ entityId: 'lock.back_door', name: 'Back Door', location: 'back' },
{ entityId: 'lock.garage_door', name: 'Garage Door', location: 'garage' },
],
// Alarmo alarm control panel
alarm: 'alarm_control_panel.alarmo',
// Package detection binary sensor
packageSensor: 'binary_sensor.package_detected',
// HA built-in to-do list
todoList: 'todo.shopping_list',
// Cameras - configured to use go2rtc streams
cameras: [
{ name: 'FPE', displayName: 'Front Porch Entry', go2rtcStream: 'FPE', frigateCamera: 'FPE' },
{ name: 'Porch_Downstairs', displayName: 'Porch Downstairs', go2rtcStream: 'Porch_Downstairs', frigateCamera: 'Porch_Downstairs' },
{ name: 'Front_Porch', displayName: 'Front Porch', go2rtcStream: 'Front_Porch', frigateCamera: 'Front_Porch' },
{ name: 'Driveway_door', displayName: 'Driveway Door', go2rtcStream: 'Driveway_door', frigateCamera: 'Driveway_door' },
{ name: 'Street_side', displayName: 'Street Side', go2rtcStream: 'Street_side', frigateCamera: 'Street_side' },
{ name: 'Backyard', displayName: 'Backyard', go2rtcStream: 'Backyard', frigateCamera: 'Backyard' },
{ name: 'House_side', displayName: 'House Side', go2rtcStream: 'House_side', frigateCamera: 'House_side' },
{ name: 'Driveway', displayName: 'Driveway', go2rtcStream: 'Driveway', frigateCamera: 'Driveway' },
{ name: 'WyzePanV3', displayName: 'Wyze Pan V3', go2rtcStream: 'WyzePanV3', frigateCamera: 'WyzePanV3' },
],
// Frigate person detection entities - triggers full-screen alert
personDetectionEntities: [
'binary_sensor.fpe_person_occupancy',
'binary_sensor.porch_downstairs_person_occupancy',
],
// People tracking - device_tracker or person entities
// Set avatarUrl to a URL of an image, or leave empty to show initials
people: [
{
entityId: 'person.user1',
name: 'User 1',
},
{
entityId: 'person.user2',
name: 'User 2',
},
],
};
// Helper functions
export function getLightsByRoom(lights: LightConfig[]): Record<string, LightConfig[]> {
return lights.reduce((acc, light) => {
if (!acc[light.room]) {
acc[light.room] = [];
}
acc[light.room].push(light);
return acc;
}, {} as Record<string, LightConfig[]>);
}
export function getCameraByName(cameras: CameraConfig[], name: string): CameraConfig | undefined {
return cameras.find((c) => c.name === name);
}

30
src/config/environment.ts Normal file
View File

@@ -0,0 +1,30 @@
/**
* Environment configuration
* Values are loaded from .env file via Vite
*/
export const env = {
// Home Assistant
haUrl: import.meta.env.VITE_HA_URL || 'http://192.168.1.50:8123',
haWsUrl: import.meta.env.VITE_HA_WS_URL || 'ws://192.168.1.50:8123/api/websocket',
// Frigate & go2rtc
// Use empty string to proxy through same origin (nginx), or set explicit URL
frigateUrl: import.meta.env.VITE_FRIGATE_URL || 'http://192.168.1.241:5000',
go2rtcUrl: import.meta.env.VITE_GO2RTC_URL || 'http://192.168.1.241:1985',
go2rtcRtsp: import.meta.env.VITE_GO2RTC_RTSP || 'rtsp://192.168.1.241:8600',
// Google Calendar
googleClientId: import.meta.env.VITE_GOOGLE_CLIENT_ID || '',
// Screen management
screenIdleTimeout: parseInt(import.meta.env.VITE_SCREEN_IDLE_TIMEOUT || '300000', 10),
// Presence detection
presenceEnabled: import.meta.env.VITE_PRESENCE_DETECTION_ENABLED === 'true',
presenceConfidenceThreshold: parseFloat(import.meta.env.VITE_PRESENCE_CONFIDENCE_THRESHOLD || '0.6'),
// Frigate streaming
frigateStreamEnabled: import.meta.env.VITE_FRIGATE_STREAM_ENABLED === 'true',
frigateRtspOutput: import.meta.env.VITE_FRIGATE_RTSP_OUTPUT || 'rtsp://192.168.1.241:8554/command_center',
} as const;