|
| 1 | + |
| 2 | +# Local Development |
| 3 | + |
| 4 | +This guide will help you set up and run the Virtual Device Server locally for development. |
| 5 | + |
| 6 | +## Prerequisites |
| 7 | + |
| 8 | +Make sure you have the following installed: |
| 9 | +- [Docker](https://docs.docker.com/get-docker/) and Docker Compose |
| 10 | +- [Rust](https://rustup.rs/) toolchain (for the backend) |
| 11 | +- [Node.js](https://nodejs.org/) (v16 or later, for the frontend) |
| 12 | +- [Git](https://git-scm.com/) (to clone the repository) |
| 13 | + |
| 14 | +### Step 1: Clone and Setup |
| 15 | + |
| 16 | +```bash |
| 17 | +# Clone the repository |
| 18 | +git clone <repository-url> |
| 19 | +cd virtual-device-server |
| 20 | + |
| 21 | +# Verify the structure |
| 22 | +ls -la |
| 23 | +# Should show: dummy-device-app/, web-portal/, k8s/, README.md |
| 24 | +``` |
| 25 | + |
| 26 | +### Step 2: Start PostgreSQL Database |
| 27 | + |
| 28 | +```bash |
| 29 | +# Start PostgreSQL in Docker |
| 30 | +docker run -d --name postgres-dev \ |
| 31 | + -e POSTGRES_DB=device_db \ |
| 32 | + -e POSTGRES_USER=postgres \ |
| 33 | + -e POSTGRES_PASSWORD=password \ |
| 34 | + -p 5432:5432 \ |
| 35 | + postgres:15-alpine |
| 36 | + |
| 37 | +# Verify the database is running |
| 38 | +docker ps | grep postgres-dev |
| 39 | + |
| 40 | +# Optional: Check database logs |
| 41 | +docker logs postgres-dev |
| 42 | +``` |
| 43 | + |
| 44 | +**Alternative: Use Docker Compose (recommended)** |
| 45 | + |
| 46 | +Create a `docker-compose.yml` file in the root directory: |
| 47 | + |
| 48 | +```yaml |
| 49 | +version: '3.8' |
| 50 | +services: |
| 51 | + postgres: |
| 52 | + image: postgres:15-alpine |
| 53 | + container_name: postgres-dev |
| 54 | + environment: |
| 55 | + POSTGRES_DB: device_db |
| 56 | + POSTGRES_USER: postgres |
| 57 | + POSTGRES_PASSWORD: password |
| 58 | + ports: |
| 59 | + - "5432:5432" |
| 60 | + volumes: |
| 61 | + - postgres_data:/var/lib/postgresql/data |
| 62 | + healthcheck: |
| 63 | + test: ["CMD-SHELL", "pg_isready -U postgres"] |
| 64 | + interval: 10s |
| 65 | + timeout: 5s |
| 66 | + retries: 5 |
| 67 | + |
| 68 | +volumes: |
| 69 | + postgres_data: |
| 70 | +``` |
| 71 | +
|
| 72 | +Then run: |
| 73 | +```bash |
| 74 | +docker-compose up -d postgres |
| 75 | +``` |
| 76 | + |
| 77 | +### Step 3: Run the Rust Backend |
| 78 | + |
| 79 | +```bash |
| 80 | +# Navigate to the backend directory |
| 81 | +cd dummy-device-app |
| 82 | + |
| 83 | +# Install Rust dependencies (if not already done) |
| 84 | +cargo check |
| 85 | + |
| 86 | +# Set environment variables |
| 87 | +export DATABASE_URL="postgres://postgres:password@localhost:5432/device_db" |
| 88 | +export RUST_LOG=info |
| 89 | + |
| 90 | +# Run the application |
| 91 | +cargo run |
| 92 | +``` |
| 93 | + |
| 94 | +You should see output like: |
| 95 | +``` |
| 96 | +2024-01-15T10:30:00.000Z INFO Initializing dummy device server |
| 97 | +2024-01-15T10:30:00.100Z INFO Successfully connected to database |
| 98 | +2024-01-15T10:30:00.200Z INFO Database migrations completed successfully |
| 99 | +2024-01-15T10:30:00.300Z INFO No devices found, initializing default devices |
| 100 | +2024-01-15T10:30:00.400Z INFO Successfully initialized 4 default devices |
| 101 | +2024-01-15T10:30:00.500Z INFO Starting server on 0.0.0.0:3000 |
| 102 | +``` |
| 103 | + |
| 104 | +**Troubleshooting Backend:** |
| 105 | +- If you get database connection errors, ensure PostgreSQL is running: `docker ps | grep postgres` |
| 106 | +- If migrations fail, check the database logs: `docker logs postgres-dev` |
| 107 | +- For more detailed logs, set `RUST_LOG=debug` |
| 108 | + |
| 109 | +### Step 4: Run the React Frontend |
| 110 | + |
| 111 | +Open a new terminal window and navigate to the frontend directory: |
| 112 | + |
| 113 | +```bash |
| 114 | +# Navigate to the frontend directory |
| 115 | +cd web-portal |
| 116 | + |
| 117 | +# Install Node.js dependencies |
| 118 | +npm install |
| 119 | + |
| 120 | +# Start the development server |
| 121 | +npm start |
| 122 | +``` |
| 123 | + |
| 124 | +You should see output like: |
| 125 | +``` |
| 126 | +Compiled successfully! |
| 127 | +
|
| 128 | +You can now view web-portal in the browser. |
| 129 | +
|
| 130 | + Local: http://localhost:3001 |
| 131 | + On Your Network: http://192.168.1.100:3001 |
| 132 | +
|
| 133 | +Note that the development build is not optimized. |
| 134 | +To create a production build, use npm run build. |
| 135 | +``` |
| 136 | + |
| 137 | +**Note:** The frontend runs on port 3001 to avoid conflicts with the backend (port 3000). |
| 138 | + |
| 139 | +### Step 5: Access the Application |
| 140 | + |
| 141 | +Once both services are running: |
| 142 | + |
| 143 | +- **Web UI**: http://localhost:3001 |
| 144 | +- **Backend API**: http://localhost:3000 |
| 145 | +- **Health Check**: http://localhost:3000/health |
| 146 | +- **API Documentation**: See the API Endpoints section below |
| 147 | + |
| 148 | +### Step 6: Test the Setup |
| 149 | + |
| 150 | +1. **Test the Health Check:** |
| 151 | +```bash |
| 152 | +curl http://localhost:3000/health |
| 153 | +# Should return: {"success":true,"data":"OK","error":null} |
| 154 | +``` |
| 155 | + |
| 156 | +2. **Test the API:** |
| 157 | +```bash |
| 158 | +# List all devices |
| 159 | +curl http://localhost:3000/devices |
| 160 | + |
| 161 | +# Create a new device |
| 162 | +curl -X POST http://localhost:3000/devices \ |
| 163 | + -H "Content-Type: application/json" \ |
| 164 | + -d '{"name": "Test Light", "device_type": "LightBulb"}' |
| 165 | +``` |
| 166 | + |
| 167 | +3. **Test the Web UI:** |
| 168 | +- Open http://localhost:3001 in your browser |
| 169 | +- You should see the device management interface |
| 170 | +- Try creating, viewing, and updating devices |
| 171 | + |
| 172 | +#### Development Workflow |
| 173 | + |
| 174 | +1. **Backend Development:** |
| 175 | +```bash |
| 176 | +cd dummy-device-app |
| 177 | +# Make changes to src/main.rs |
| 178 | +cargo run # Automatically recompiles and restarts |
| 179 | +``` |
| 180 | + |
| 181 | +2. **Frontend Development:** |
| 182 | +```bash |
| 183 | +cd web-portal |
| 184 | +# Make changes to src/App.js |
| 185 | +# The development server automatically reloads |
| 186 | +``` |
| 187 | + |
| 188 | +3. **Database Changes:** |
| 189 | +```bash |
| 190 | +cd dummy-device-app |
| 191 | +# Create a new migration |
| 192 | +sqlx migrate add <migration_name> |
| 193 | +# Edit the generated migration file |
| 194 | +cargo run # Applies the migration |
| 195 | +``` |
| 196 | + |
| 197 | +#### Stopping the Services |
| 198 | + |
| 199 | +```bash |
| 200 | +# Stop the backend (Ctrl+C in the terminal) |
| 201 | +# Stop the frontend (Ctrl+C in the terminal) |
| 202 | + |
| 203 | +# Stop PostgreSQL |
| 204 | +docker stop postgres-dev |
| 205 | +docker rm postgres-dev |
| 206 | + |
| 207 | +# Or if using Docker Compose |
| 208 | +docker-compose down |
| 209 | +``` |
| 210 | + |
| 211 | +#### Environment Variables |
| 212 | + |
| 213 | +Create a `.env` file in the `dummy-device-app` directory for easier development: |
| 214 | + |
| 215 | +```bash |
| 216 | +# dummy-device-app/.env |
| 217 | +DATABASE_URL=postgres://postgres:password@localhost:5432/device_db |
| 218 | +RUST_LOG=info |
| 219 | +PORT=3000 |
| 220 | +``` |
| 221 | + |
| 222 | +Then you can run the backend with: |
| 223 | +```bash |
| 224 | +cd dummy-device-app |
| 225 | +cargo run |
| 226 | +``` |
| 227 | + |
| 228 | +#### Logging |
| 229 | + |
| 230 | +The backend includes comprehensive logging. To see different log levels: |
| 231 | + |
| 232 | +```bash |
| 233 | +# Info level (default) |
| 234 | +RUST_LOG=info cargo run |
| 235 | + |
| 236 | +# Debug level (more verbose) |
| 237 | +RUST_LOG=debug cargo run |
| 238 | + |
| 239 | +# Error only |
| 240 | +RUST_LOG=error cargo run |
| 241 | +``` |
| 242 | + |
| 243 | +See `dummy-device-app/LOGGING.md` for detailed logging documentation. |
| 244 | + |
| 245 | +### Adding New Device Types |
| 246 | + |
| 247 | +1. Update the `DeviceType` enum in `dummy-device-app/src/main.rs` |
| 248 | +2. Add the new type to the database migration |
| 249 | +3. Update the default state logic in the `create_device` function |
| 250 | +4. Add the device icon and control logic in `web-portal/src/App.js` |
| 251 | + |
| 252 | +### Testing |
| 253 | + |
| 254 | +```bash |
| 255 | +# Test the Rust backend |
| 256 | +cd dummy-device-app |
| 257 | +cargo test |
| 258 | + |
| 259 | +# Test the React frontend |
| 260 | +cd web-portal |
| 261 | +npm test |
| 262 | +``` |
| 263 | + |
| 264 | +## API Endpoints |
| 265 | + |
| 266 | +### Health Check |
| 267 | +- `GET /health` - Service health status |
| 268 | + |
| 269 | +### Devices |
| 270 | +- `GET /devices` - List all devices |
| 271 | +- `POST /devices` - Create a new device |
| 272 | +- `GET /devices/{id}` - Get device details |
| 273 | +- `PUT /devices/{id}/state` - Update device state |
| 274 | + |
| 275 | +### Example API Usage |
| 276 | + |
| 277 | +```bash |
| 278 | +# List all devices |
| 279 | +curl http://localhost:3000/devices |
| 280 | + |
| 281 | +# Create a new light bulb |
| 282 | +curl -X POST http://localhost:3000/devices \ |
| 283 | + -H "Content-Type: application/json" \ |
| 284 | + -d '{"name": "Living Room Light", "device_type": "LightBulb"}' |
| 285 | + |
| 286 | +# Update device state |
| 287 | +curl -X PUT http://localhost:3000/devices/{device-id}/state \ |
| 288 | + -H "Content-Type: application/json" \ |
| 289 | + -d '{"state": {"on": true}}' |
| 290 | +``` |
| 291 | + |
| 292 | +## Features |
| 293 | + |
| 294 | +- **Real-time Device Management**: View and control device states through a modern web interface |
| 295 | +- **Persistent Storage**: All device states are stored in PostgreSQL |
| 296 | +- **Scalable Architecture**: Microservices architecture with separate pods for each component |
| 297 | +- **Health Monitoring**: Built-in health checks for all services |
| 298 | +- **RESTful API**: Clean, documented API for device management |
| 299 | +- **Responsive UI**: Modern React interface with Tailwind CSS |
| 300 | + |
0 commit comments