An open API service indexing awesome lists of open source software.

https://github.com/typingincolor/home-control

A modern React web application for controlling your smart home.
https://github.com/typingincolor/home-control

hue-api hue-bridge hue-lights javascript nodejs react

Last synced: 3 months ago
JSON representation

A modern React web application for controlling your smart home.

Awesome Lists containing this project

README

          

# Home Control

[![CI](https://github.com/typingincolor/home-control/actions/workflows/ci.yml/badge.svg)](https://github.com/typingincolor/home-control/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/typingincolor/home-control/graph/badge.svg)](https://codecov.io/gh/typingincolor/home-control)
[![Release](https://img.shields.io/github/v/release/typingincolor/home-control)](https://github.com/typingincolor/home-control/releases/latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org/)
[![Last Commit](https://img.shields.io/github/last-commit/typingincolor/home-control)](https://github.com/typingincolor/home-control/commits/main)

A modern React web application for smart home control. Integrates **Philips Hue** (lights, scenes, rooms, zones via local Bridge API) and **UK Hive** (heating, hot water via cloud API). Features a responsive interface with visual controls, real-time updates, and a **backend-heavy architecture** where the backend handles business logic and exposes a REST API with WebSocket support.

![Dashboard Screenshot](docs/dashboard-screenshot.png)

## Features

### Core Functionality

- **True Color Display**: Light buttons show actual bulb colors with mathematical color space conversion (xy/mirek → RGB)
- **Information Dashboard**: At-a-glance summary showing total lights on, room count, and scene count
- **Brightness Indicators**: Live brightness percentage displayed on each light and room average
- **Room Status Badges**: See "{X} of {Y} lights on" for each room at a glance
- **Zone Support**: Control Hue zones (light groups spanning multiple rooms) with compact bar UI
- **Motion Zone Detection**: Always-visible inline bar showing MotionAware zones with real-time status indicators
- **Automation Triggers**: Manually trigger Hue smart scenes (automations) from a dedicated tab
- **Room Organization**: Lights automatically grouped by room with modern card layout
- **Scene Management**: Select and activate scenes for each room and zone
- **Master Controls**: Turn all lights in a room or zone on/off with one button

### Modern Architecture

- **WebSocket Real-Time Updates**: Instant state synchronization across all connected devices
- **Session-Based Authentication**: Secure token-based sessions with automatic refresh
- **Backend Business Logic**: Colors, shadows, and statistics pre-computed on server
- **Simplified API**: Frontend makes 1-2 calls instead of 4-6 (67-83% reduction)
- **Responsive Design**: Device-specific layouts (iPad: 4×2, iPhone: 2×4, Raspberry Pi 7": 4×2)
- **Centralized UI Text**: UI_TEXT constants for consistency and easy maintenance

### Authentication & Discovery

- **Bridge Discovery**: Automatically find your Hue Bridge or enter IP manually
- **Link Button Authentication**: Simple guided flow with visual feedback
- **Persistent Sessions**: Sessions saved in browser localStorage with auto-recovery
- **Session Auto-Refresh**: Tokens refresh automatically before expiration
- **Multi-Client Support**: Second client connects instantly using server-stored credentials (no re-pairing needed)
- **Demo Mode**: Try the app without a Hue Bridge using `?demo=true` URL parameter

### Technical Features

- **CORS Solution**: Backend handles CORS and self-signed HTTPS certificates
- **Multi-Machine Support**: Access from any device on your network
- **Centralized Configuration**: All settings managed through config.yaml
- **Modern API v2**: Uses the latest Philips Hue API for future-proof functionality
- **Comprehensive Testing**: 748 unit tests (261 frontend + 487 backend) with 179 E2E tests
- **Rate Limiting**: API protection with per-IP rate limits (100 req/min for API, 10 req/min for discovery)

## Prerequisites

- **Philips Hue Bridge** (v2 recommended) with lights configured
- **Node.js** (v16 or higher)
- Server machine on the **same local network** as your bridge
- Modern web browser (Chrome, Firefox, Safari, Edge)

## Quick Start

### 1. Install Dependencies

```bash
npm install
```

### 2. Development Mode

Run both frontend and backend servers with hot reload:

```bash
npm run dev
```

This starts:

- **Frontend** on http://localhost:5173 (React dev server with hot reload)
- **Backend** on http://localhost:3001 (API proxy server)

Open your browser to http://localhost:5173

### 3. Production Deployment

Build and start the production server:

```bash
npm run deploy
```

Or step by step:

```bash
npm run build # Build frontend
npm run build:backend # Copy frontend to backend
npm run start # Start production server
```

The server runs on http://0.0.0.0:3001 and serves both the API and frontend.

### 4. Access from Other Devices

Once the server is running, access it from any device on your network:

```
http://192.168.68.86:3001
```

Replace `192.168.68.86` with your server's local IP address.

To find your server's IP:

```bash
ifconfig | grep "inet " | grep -v 127.0.0.1
```

### 5. Initial Setup

1. **Discover or Enter Bridge IP**: Use auto-discovery or manually enter your bridge's IP address
2. **Press Link Button**: Press the physical button on top of your Hue Bridge
3. **Authenticate**: Click "I Pressed the Button" within 30 seconds
4. **Session Created**: A session token is automatically created and saved
5. **Control Your Lights**: View and control all your lights organized by room with real-time WebSocket updates

### 6. Demo Mode (No Bridge Required)

Try the app without a Hue Bridge:

```
http://localhost:5173/?demo=true # Development
http://192.168.1.100:3001/?demo=true # Production (use your server IP)
```

**Demo mode features:**

- 2 rooms with 6 lights (Living Room, Bedroom)
- 4 scenes (Bright, Relax, Energize, Nightlight)
- 2 zones (Downstairs, Upstairs)
- 2 motion zones with simulated detection
- 4 automations (smart scenes) to trigger
- Mock weather data (London)
- Full interactivity: toggle lights, change brightness, activate scenes
- State persists in memory (resets on server restart)

**How it works:**

- Frontend detects `?demo=true` and sends `X-Demo-Mode: true` header
- Backend returns mock data instead of connecting to a real bridge
- WebSocket receives mock updates every 15 seconds
- All API endpoints work identically to real mode

## Architecture

### Monorepo Structure

The app is organized as a monorepo with separate frontend and backend workspaces:

```
philips-hue-connector/
├── config.yaml # Centralized configuration
├── package.json # Root workspace manager
├── frontend/ # React frontend workspace
│ ├── package.json
│ ├── vite.config.js # Vite config (reads config.yaml)
│ ├── vitest.config.js # Test configuration
│ ├── stryker.conf.json # Mutation testing config
│ ├── TESTING.md # Testing documentation
│ ├── index.html
│ ├── dist/ # Build output (gitignored)
│ └── src/
│ ├── main.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── components/
│ │ ├── BridgeDiscovery.jsx
│ │ ├── Authentication.jsx
│ │ ├── MotionZones.jsx
│ │ └── LightControl/
│ │ ├── index.jsx # Main container
│ │ ├── TopToolbar.jsx # Header bar
│ │ ├── BottomNav.jsx # Room tabs
│ │ ├── MainPanel.jsx # Content container
│ │ ├── RoomContent.jsx # Room display
│ │ ├── LightTile.jsx # Light button with fill
│ │ ├── ZonesView.jsx # Zones list
│ │ ├── SceneDrawer.jsx # Slide-out drawer for scenes
│ │ ├── SceneSelector.jsx # Scene icons
│ │ ├── SettingsPage.jsx # Settings page
│ │ ├── WeatherDisplay.jsx # Toolbar weather
│ │ └── DashboardSummary.jsx
│ ├── utils/ # Utility functions
│ │ └── validation.js # IP validation (frontend-only)
│ ├── constants/ # Centralized constants
│ │ ├── uiText.js # UI_TEXT - All user-facing text
│ │ ├── polling.js
│ │ ├── storage.js
│ │ ├── colors.js
│ │ ├── validation.js
│ │ └── messages.js
│ ├── services/
│ │ ├── hueApi.js # v1 API client (calls backend endpoints)
│ │ └── weatherApi.js # Weather API integration
│ ├── hooks/ # Custom React hooks
│ │ ├── useHueBridge.js
│ │ ├── useSession.js
│ │ ├── useSettings.js
│ │ ├── useWeather.js
│ │ └── useWebSocket.js
│ └── test/
│ └── setup.js # Test environment setup
└── backend/ # Express backend workspace
├── package.json
├── server.js # Express server (v1 API + WebSocket + static files)
├── middleware/ # Express middleware
│ ├── auth.js # Session & demo mode authentication
│ └── demoMode.js # X-Demo-Mode header detection
├── routes/v1/ # v1 API routes
│ ├── auth.js # Authentication endpoints
│ ├── dashboard.js # Dashboard data endpoint
│ ├── lights.js # Light control endpoints
│ ├── rooms.js # Room control endpoints
│ ├── zones.js # Zone control endpoints
│ ├── scenes.js # Scene activation endpoint
│ ├── settings.js # Settings API endpoints
│ └── weather.js # Weather API endpoint
├── services/ # Business logic layer
│ ├── hueClient.js # Real Hue Bridge API client
│ ├── mockHueClient.js # Mock client for demo mode
│ ├── mockData.js # Demo mode mock data
│ ├── hueClientFactory.js # Returns real or mock client
│ ├── dashboardService.js # Dashboard data aggregation
│ ├── roomService.js # Room hierarchy & statistics
│ ├── zoneService.js # Zone hierarchy & statistics
│ ├── motionService.js # Motion sensor parsing
│ ├── statsService.js # Dashboard statistics
│ ├── sessionManager.js # Session token management
│ ├── settingsService.js # Per-session settings storage
│ ├── weatherService.js # Weather API with caching
│ └── websocketService.js # WebSocket server & state updates
├── utils/ # Utility functions
│ ├── colorConversion.js # Color space conversion
│ ├── stateConversion.js # State format conversion
│ ├── validation.js # Input validation
│ └── errors.js # Custom error classes
├── constants/ # Backend constants
│ ├── timings.js # Intervals and timeouts
│ └── errorMessages.js # Error message constants
├── scripts/
│ └── copy-frontend.js # Build script
├── test/ # Backend tests
│ ├── services/ # Service layer tests
│ ├── middleware/ # Middleware tests
│ └── routes/ # API route tests
└── public/ # Served frontend (gitignored)
```

### Configuration File

All hostnames, IPs, and ports are centralized in `config.yaml`:

```yaml
server:
port: 3001
host: '0.0.0.0'
corsEnabled: true

hue:
discoveryEndpoint: 'https://discovery.meethue.com/'

development:
frontendPort: 5173
backendPort: 3001
```

**Benefits:**

- Single source of truth for configuration
- Easy to modify without code changes
- Backend exposes `/api/config` endpoint for frontend access
- Can be overridden by environment variables

### How It Works

**Backend-Heavy Architecture:**
The backend is the brains of the operation:

- **Business Logic**: Processes Hue API responses, builds room hierarchies, calculates statistics
- **Color Computation**: Converts xy/mirek to RGB, applies warm dim blending, generates shadows
- **Data Aggregation**: Combines 4-6 Hue API calls into single unified responses
- **WebSocket Server**: Pushes real-time updates to all connected clients
- **Session Management**: Handles authentication tokens with auto-refresh

The frontend is a thin presentation layer:

- **Simple Rendering**: Displays pre-computed data from backend
- **User Events**: Sends interactions to backend via v1 API
- **WebSocket Client**: Receives real-time updates without polling

**Development Mode:**

- Frontend: Vite dev server on port 5173 with hot reload
- Backend: Express server on port 3001 with v1 REST API + WebSocket
- Vite proxies `/api/*` requests to backend automatically

**Production Mode:**

- Backend serves both API and frontend on single port (3001)
- Frontend uses relative URLs (same origin = no CORS issues)
- Access from any machine using server's IP address

**Performance Benefits:**

- Frontend API calls: **4-6 → 1-2** (67-83% reduction)
- Network latency: **Multiple round trips → Single round trip**
- Frontend complexity: **Reduced by ~1,300 lines** (business logic moved to backend)
- Updates: **30-second polling → Instant WebSocket push**

**CORS Solution:**
The Philips Hue Bridge doesn't send CORS headers and uses self-signed HTTPS certificates. The backend server:

- Communicates with Hue Bridge on behalf of frontend
- Adds proper CORS headers for browser access
- Accepts the bridge's self-signed SSL certificate
- Listens on all network interfaces (0.0.0.0)

**No browser extensions or workarounds needed!**

### Technology Stack

**Frontend:**

- **React 18** - UI framework with hooks
- **Vite 6** - Fast build tool and dev server
- **WebSocket** - Real-time bidirectional communication
- **localStorage** - Session persistence
- **CSS Grid & Flexbox** - Responsive card layout
- **CSS Custom Properties** - Dynamic sizing with clamp()
- **PropTypes** - Runtime type validation

**Backend:**

- **Express 5** - REST API server + WebSocket server + static file serving
- **ws** - WebSocket library for real-time updates
- **Axios** - HTTP client with HTTPS agent support for Hue Bridge
- **Philips Hue API v2** - Modern local bridge communication

**Testing:**

- **Vitest 4** - Fast, Vite-native test runner
- **Testing Library** - React component testing
- **MSW (Mock Service Worker)** - Network-level API mocking for integration tests
- **Stryker Mutator** - Mutation testing for test validation

**Development:**

- **npm workspaces** - Monorepo management
- **ESLint** - Code quality
- **Prettier** - Code formatting

## Available Scripts

### Root Scripts (run from project root)

#### `npm run dev`

Starts both frontend and backend in development mode with hot reload

#### `npm run build`

Builds the frontend for production (output: `frontend/dist/`)

#### `npm run build:backend`

Copies frontend build to backend/public/ directory

#### `npm run start`

Starts the production server (backend serves API + frontend)

#### `npm run deploy`

Full deployment: builds frontend, copies to backend, starts server

### Workspace Scripts

#### `npm run dev:frontend`

Starts only the frontend dev server

#### `npm run dev:backend`

Starts only the backend server

### Testing Scripts

#### `npm run test`

Runs all unit tests in watch mode (interactive)

#### `npm run test:ui`

Opens Vitest UI for interactive test exploration

#### `npm run test:run`

Runs all tests once (useful for CI/CD)

#### `npm run test:coverage`

Generates code coverage report

#### `npm run test:mutation`

Runs mutation testing with Stryker (validates test quality)

## Testing

The project includes comprehensive testing infrastructure with **748 unit tests** (261 frontend + 487 backend), **179 E2E tests**, and mutation testing to ensure code quality.

### Test Coverage

**Frontend Tests (261 tests):**

- **Unit tests**: Utilities, hooks, and components
- **Integration tests**: 10 end-to-end flow tests with MSW
- **Vitest 4.0** - Fast, Vite-native test runner
- **Testing Library** - React component testing with user-centric approach
- **MSW** - Network-level API mocking for integration tests

**Backend Tests (486 tests):**

- **Service layer tests**: Color conversion, room hierarchy, motion sensors, statistics, WebSocket service
- **Route tests**: API endpoint validation
- **Session management tests**: Token handling and refresh logic
- **Zone service tests**: Zone hierarchy and statistics
- **Multi-client integration tests**: 10 tests for credential sharing flow
- **Auth middleware tests**: Demo mode and credential extraction
- **Demo mode tests**: MockHueClient, mock data, demo middleware, hueClientFactory
- **Settings & Weather tests**: Settings service, weather service, API routes

**Test Quality:**

- **73.25% mutation score** - excellent test effectiveness
- **Stryker Mutator** - Mutation testing to validate test quality

### Test Organization

**Frontend Tests:**

```
frontend/src/
├── utils/
│ └── validation.test.js # 8 tests - IP validation
├── hooks/
│ ├── useSession.test.js # 23 tests - Session management
│ ├── useSettings.test.js # 10 tests - Settings API
│ ├── useWeather.test.jsx # 10 tests - Weather API
│ └── useWebSocket.test.js # 28 tests - WebSocket connection
├── components/
│ ├── MotionZones.test.jsx # 9 tests - Motion zone compact bar
│ └── LightControl/
│ ├── DashboardSummary.test.jsx # 5 tests - Summary statistics
│ ├── SceneSelector.test.jsx # 8 tests - Scene icon buttons
│ ├── SettingsPage.test.jsx # 32 tests - Settings page
│ ├── WeatherDisplay.test.jsx # 11 tests - Weather display
│ ├── index.test.jsx # 18 tests - Main control component
│ └── index.zones.test.jsx # 9 tests - Zone integration tests
├── services/
│ └── hueApi.test.js # 22 tests - API client methods
└── integration.test.jsx # 10 tests - Full app flow tests
```

**Backend Tests:**

```
backend/test/
├── services/
│ ├── colorService.test.js # 14 tests - Color conversions
│ ├── roomService.test.js # 23 tests - Room hierarchy
│ ├── motionService.test.js # 13 tests - Motion sensor parsing
│ ├── statsService.test.js # 10 tests - Dashboard statistics
│ └── sessionManager.test.js # 12 tests - Session management
├── middleware/
│ └── auth.test.js # 13 tests - Credential extraction/storage
├── integration/
│ └── multiClient.test.js # 10 tests - Multi-client credential sharing
└── routes/
└── (various route tests) # API endpoints
```

### Running Tests

**Watch mode** (auto-runs on file changes):

```bash
npm run test
```

**Interactive UI** (visual test explorer):

```bash
npm run test:ui
```

**Coverage report** (see what's tested):

```bash
npm run test:coverage
# Report opens at frontend/coverage/index.html
```

**Mutation testing** (validate test effectiveness):

```bash
npm run test:mutation
# Report opens at frontend/reports/mutation/index.html
```

### What Is Mutation Testing?

Mutation testing validates that your tests actually catch bugs by:

1. **Introducing bugs** (mutants) into your code automatically
2. **Running your tests** against the mutated code
3. **Checking if tests fail** - if they do, the mutant is "killed" ✅
4. **Reporting survived mutants** - bugs your tests didn't catch ⚠️

A **73.25% mutation score** means our tests successfully detect 73% of introduced bugs - considered excellent for code with complex mathematical operations.

### Test Quality Highlights

- ✅ **Mathematical precision**: Color conversion tests verify RGB outputs within valid ranges
- ✅ **Edge case coverage**: Tests include 0% brightness, missing data, boundary values
- ✅ **Integration testing**: Room hierarchy tests validate device→light mapping
- ✅ **User interaction**: Component tests use userEvent for realistic interactions
- ✅ **Timer testing**: Polling tests use fake timers for controlled time advancement
- ✅ **Mock isolation**: Hooks tested in isolation with mocked dependencies

For detailed testing documentation, see [frontend/TESTING.md](frontend/TESTING.md).

## CI/CD

GitHub Actions workflows automate testing, building, and releasing.

### Continuous Integration

On every push to `main` and pull request:

| Job | Description |
| ------------------ | ------------------------------- |
| **Lint & Format** | ESLint + Prettier checks |
| **Frontend Tests** | Vitest unit tests with coverage |
| **Backend Tests** | Vitest unit tests with coverage |
| **E2E Tests** | Playwright browser tests |
| **Build** | Production build verification |

Tests run in parallel for speed. Build artifacts are uploaded for debugging.

### Releases

To create a release:

```bash
# Create and push a version tag
npm version patch # or minor, major
git push --tags
```

This triggers:

1. Full test suite runs
2. Production build is created
3. Release archive (`home-control-v*.tar.gz`) is published to GitHub Releases

### Raspberry Pi Deployment

For deploying to a Raspberry Pi on your local network:

```bash
# On your Pi - one-time setup
curl -O https://raw.githubusercontent.com/YOUR_USER/home-control/main/scripts/deploy-pi.sh
chmod +x deploy-pi.sh

# Set your repo (required)
export GITHUB_REPO="your-username/home-control"

# Deploy latest release
./deploy-pi.sh

# Or deploy specific version
./deploy-pi.sh v1.2.0
```

The script:

- Downloads the release archive from GitHub
- Backs up existing installation
- Installs new version with dependencies
- Preserves your `config.yaml`
- Restarts the systemd service (if configured)

## UI Features

### Information Density

- **Dashboard Summary**: Overall statistics showing lights on, room count, and available scenes
- **Room Status Badges**: Each room shows "{X} of {Y} on" count
- **Brightness Bars**: Visual indicators showing average room brightness with percentage labels
- **Per-Light Brightness**: Individual brightness percentages overlaid on each button

### Color-Accurate Display

- **RGB Color Lights**: Display actual colors using xy color space conversion (CIE 1931 → sRGB)
- **White Ambiance Lights**: Show warm/cool white based on color temperature (mirek → RGB)
- **Basic On/Off Lights**: Fallback to emerald green gradient
- **Dynamic Shadows**: Button shadows match the light's actual color
- **Universal Hover**: Brightness filter darkens any color on hover

### Motion Zone Detection

- **Real-time Status**: Green dot (🟢) = no motion, Red dot (🔴) = motion detected
- **MotionAware Integration**: Works with Philips Hue lights that have built-in motion detection
- **WebSocket Updates**: Instant push notifications when motion state changes
- **Room Association**: Motion zones linked to their respective rooms

### Responsive Layout

- **Mobile Optimized**: Reduced padding on iPhone 14+ for maximum usable space (94% vs 87% screen width)
- **iPad Enhanced**: Larger buttons (60-82px) and text labels for comfortable touch targets
- **Uniform Cards**: CSS Grid ensures consistent card sizing across all rows
- **Smart Grid**: Maximum 4 rooms per row on large screens, 5 lights per row when space allows
- **Text Protection**: Overflow handling prevents cut-off names for rooms, lights, and scenes

### Visual Design

- **Modern Color Palette**: Tailwind-inspired colors (emerald green, blue accents, neutral grays)
- **Layered Shadows**: Soft, depth-creating shadows on cards and buttons
- **Smooth Transitions**: Cubic-bezier easing for professional animations
- **Visual Hierarchy**: Clear section separation with badges, bars, and spacing
- **Loading States**: Animated indicators during operations
- **Hover Effects**: Cards lift and buttons darken on interaction

## Finding Your Bridge IP

If auto-discovery doesn't work, find your bridge IP:

### Method 1: Philips Hue App

1. Open the Philips Hue app
2. Go to **Settings** → **My Hue System** → **Bridge**
3. Note the IP address

### Method 2: Router Admin Panel

1. Log into your router's admin interface
2. Look for connected devices or DHCP clients
3. Find "Philips Hue Bridge"

### Method 3: Discovery Website

Visit: https://discovery.meethue.com/

## API Reference

The backend exposes a **simplified v1 REST API** that aggregates Hue API v2 data and pre-computes UI-ready responses.

### Backend v1 API Endpoints

**Authentication:**

- `POST /api/v1/auth/pair` - Create new Hue Bridge user (requires link button)

```json
Request: { "bridgeIp": "192.168.1.100", "appName": "hue_control_app" }
Response: { "username": "hue-username-abc123" }
```

- `POST /api/v1/auth/session` - Create session token

```json
Request: { "bridgeIp": "192.168.1.100", "username": "hue-username" }
Response: { "sessionToken": "hue_sess_xyz789", "expiresIn": 86400, "bridgeIp": "..." }
```

- `POST /api/v1/auth/connect` - Connect using server-stored credentials (multi-client support)

```json
Request: { "bridgeIp": "192.168.1.100" }
Response: { "sessionToken": "hue_sess_xyz789", "expiresIn": 86400, "bridgeIp": "..." }
Error 404: { "error": "No stored credentials", "requiresPairing": true }
```

- `GET /api/v1/auth/bridge-status` - Check if bridge has stored credentials

```
Query: ?bridgeIp=192.168.1.100
Response: { "bridgeIp": "192.168.1.100", "hasCredentials": true }
```

- `POST /api/v1/auth/refresh` - Refresh session token

```
Header: Authorization: Bearer {sessionToken}
Response: { "sessionToken": "hue_sess_new123", "expiresIn": 86400 }
```

- `DELETE /api/v1/auth/session` - Revoke session token
```
Header: Authorization: Bearer {sessionToken}
Response: { "success": true }
```

**Data Endpoints:**

- `GET /api/v1/dashboard` - Get complete dashboard (lights, rooms, zones, scenes, statistics)

```
Header: Authorization: Bearer {sessionToken}
Response: {
"summary": { "totalLights": 12, "lightsOn": 5, "roomCount": 4, "sceneCount": 8 },
"rooms": [
{
"id": "room-uuid",
"name": "Living Room",
"stats": { "lightsOnCount": 2, "totalLights": 4, "averageBrightness": 75.5 },
"lights": [ /* pre-computed with color and shadow */ ],
"scenes": [ /* filtered by room */ ]
}
],
"zones": [
{
"id": "zone-uuid",
"name": "Downstairs",
"stats": { "lightsOnCount": 2, "totalLights": 3, "averageBrightness": 85 },
"lights": [ /* lights in zone */ ],
"scenes": [ /* zone scenes */ ]
}
],
"motionZones": [ /* motion detection zones */ ]
}
```

- `GET /api/v1/motion-zones` - Get MotionAware zones with current status
```
Header: Authorization: Bearer {sessionToken}
Response: { "zones": [ { "id": "...", "name": "...", "motionDetected": false } ] }
```

**Control Endpoints:**

- `PUT /api/v1/lights/{lightId}` - Update light state

```
Header: Authorization: Bearer {sessionToken}
Body: { "on": true, "brightness": 80 }
Response: { "light": { /* updated light with pre-computed color */ } }
```

- `PUT /api/v1/rooms/{roomId}/lights` - Update all lights in room

```
Header: Authorization: Bearer {sessionToken}
Body: { "on": true, "brightness": 100 }
Response: { "updatedLights": [ /* all updated lights */ ] }
```

- `PUT /api/v1/zones/{zoneId}/lights` - Update all lights in zone

```
Header: Authorization: Bearer {sessionToken}
Body: { "on": true }
Response: { "updatedLights": [ /* all updated lights */ ] }
```

- `POST /api/v1/scenes/{sceneId}/activate` - Activate scene
```
Header: Authorization: Bearer {sessionToken}
Response: { "affectedLights": [ /* lights affected by scene */ ] }
```

**Settings Endpoints:**

- `GET /api/v1/settings` - Get current settings

```
Header: Authorization: Bearer {sessionToken}
Response: { "location": { "lat": 51.5, "lon": -0.1, "name": "London" }, "units": "celsius" }
```

- `PUT /api/v1/settings` - Update all settings

```
Header: Authorization: Bearer {sessionToken}
Body: { "location": { "lat": 51.5, "lon": -0.1, "name": "London" }, "units": "fahrenheit" }
Response: { "location": {...}, "units": "fahrenheit" }
```

- `PUT /api/v1/settings/location` - Update location only

```
Header: Authorization: Bearer {sessionToken}
Body: { "lat": 51.5, "lon": -0.1, "name": "London" }
Response: { "location": {...}, "units": "celsius" }
```

- `DELETE /api/v1/settings/location` - Clear location
```
Header: Authorization: Bearer {sessionToken}
Response: { "location": null, "units": "celsius" }
```

**Weather Endpoints:**

- `GET /api/v1/weather` - Get weather for stored location
```
Header: Authorization: Bearer {sessionToken}
Response: {
"current": { "temperature": 15, "condition": "Partly cloudy", "humidity": 65, "windSpeed": 12 },
"forecast": [ { "date": "2024-01-15", "high": 18, "low": 10, "condition": "Sunny" }, ... ]
}
Error 404: { "error": "No location set" }
```

**WebSocket:**

- `WS /api/v1/ws` - WebSocket connection for real-time updates

```
// Session authentication
Connect → Send: { "type": "auth", "sessionToken": "hue_sess_..." }

// Demo mode authentication (no credentials needed)
Connect → Send: { "type": "auth", "demoMode": true }

// Responses
Receive: { "type": "initial_state", "data": { /* dashboard */ } }
Receive: { "type": "state_update", "changes": [ /* light/room/zone changes */ ] }
```

**Demo Mode Header:**

All endpoints support demo mode via the `X-Demo-Mode: true` header:

```
GET /api/v1/dashboard
Header: X-Demo-Mode: true
Response: { /* mock dashboard data */ }
```

When demo mode is enabled:

- No bridge connection or credentials required
- Returns mock data (2 rooms, 6 lights, 4 scenes, 2 zones)
- State changes persist in memory
- WebSocket pushes mock updates every 15 seconds

**Utility Endpoints:**

- `GET /api/config` - Get safe configuration values
- `GET /api/discovery` - Discover bridges on network
- `GET /api/health` - Health check endpoint

### Official Documentation

- [Philips Hue Developer Portal](https://developers.meethue.com/)
- [CLIP API v2 Documentation](https://developers.meethue.com/develop/hue-api-v2/)
- [Getting Started Guide](https://developers.meethue.com/develop/get-started-2/)

## Deployment Guide

### Single Server Deployment (Recommended)

1. **Build the application:**

```bash
npm run build
npm run build:backend
```

2. **Start the server:**

```bash
npm run start
```

3. **Access from any device:**
```
http://:3001
```

### Configuration

Edit `config.yaml` to customize:

- Server port (default: 3001)
- Server host (default: 0.0.0.0 for all interfaces)
- Development ports
- Hue discovery endpoint

Environment variables override config.yaml:

```bash
PORT=8080 npm run start
```

### Network Requirements

- **Backend server** must be on the same local network as the Hue Bridge
- **Client devices** can be on any network that can reach the server
- **Firewall**: Ensure port 3001 (or your configured port) is accessible

## Troubleshooting

### "Could not discover bridges"

- Ensure your device is on the same network as your Hue Bridge
- Try entering the IP address manually
- Check that your bridge is powered on and connected to your network

### "Could not connect to proxy server"

- Make sure the backend server is running
- Check that nothing else is using the configured port
- Verify http://localhost:3001/api/health returns "ok"

### "Link button not pressed" or Authentication Failed

- Press the physical button on the bridge
- You have 30 seconds to click "I Pressed the Button"
- Try again if you missed the window
- If WebSocket connection fails, the app will automatically retry

### Connection times out

- Verify the bridge IP address is correct
- Ensure server and bridge are on the same network
- Check firewall settings
- Try restarting the bridge

### No lights showing up

- Ensure lights are paired with your bridge in the Hue app
- Check that lights are powered on
- Verify your credentials are correct
- Check that WebSocket connection is established (look for "Connected" status)

### No motion zones showing

- MotionAware requires compatible Hue lights with built-in motion detection
- Zones must be configured in the Philips Hue app first
- Motion zones auto-hide if none are configured

### WebSocket not connecting or "Disconnected" status

- Check that the backend server is running
- Verify http://localhost:3001/api/health returns "ok"
- The app will automatically retry connection up to 5 times
- If session expires, you'll be logged out automatically
- Try refreshing the page to re-establish connection

## Security Notes

- **Session tokens** are stored in browser localStorage and expire after 24 hours
- **Bridge credentials** are stored server-side only (not in browser)
- Session tokens act as API keys - keep them secure
- Clear browser data to remove saved credentials
- **Auto-refresh**: Sessions are automatically refreshed before expiration
- The app communicates only with your local bridge and backend
- The backend accepts self-signed certificates (required for Hue Bridge)
- No data is sent to external servers except Hue discovery (discovery.meethue.com)
- CORS is open by default (configure in config.yaml if needed)
- WebSocket connections are authenticated with session tokens

## Build Info

Build numbers are derived from git commit count: `git rev-list --count HEAD`

Current build: **158** (commit `945e536`)

## Contributing

This project demonstrates modern React patterns, backend-heavy architecture, WebSocket real-time updates, session-based authentication, Hue API v2 integration, comprehensive testing with integration tests, and responsive design. Feel free to fork and modify for your needs.

## License

MIT

## Acknowledgments

- Built with React, Vite, Express, and WebSocket (ws)
- Backend-heavy architecture with v1 REST API
- Uses the Philips Hue Local API v2 (CLIP API)
- Responsive design with CSS Grid and Flexbox
- MotionAware integration for built-in motion detection
- Integration testing with MSW (Mock Service Worker)
- Mutation testing with Stryker Mutator

## Support

For issues related to:

- **This app**: Check the troubleshooting section above
- **Philips Hue Bridge**: Visit [Philips Hue Support](https://www.philips-hue.com/support)
- **Hue API**: Check the [Philips Hue Developer Portal](https://developers.meethue.com/)

---

**Built with ❤️ for the smart home community**