Tau.Acuvim/docs/acuvim-spec-09.md
Renier Forster 84a0668c54 Initial commit: Tau Acuvim IoT monitoring system
Complete IoT monitoring platform for Acuvim II power meters via ESP32.

Firmware (Phases 1-7):
- ESP32-WROVER-B (TTGO T-Call v1.4) with RS485 Modbus RTU
- WiFi STA+AP concurrent mode with GSM/GPRS failover
- Transport abstraction layer with 4 priority modes
- MQTT protocol with 20 commands, LWT, QoS, exponential backoff
- SD card offline buffering with JSONL rotation and non-blocking drain
- OTA firmware updates with dual partition rollback protection
- Watchdog timer, crash loop detection, Acuvim health monitoring
- Captive portal provisioning with AP mode

Console backend (Phase 8):
- .NET 10 minimal API with PostgreSQL + EF Core
- JWT authentication, SignalR real-time updates
- MQTTnet 5.x bridge service with health monitoring
- Device, telemetry, firmware, alert, group management
- Rate limiting, security headers, Swagger/OpenAPI

Frontend (Phase 9):
- React 18 + TypeScript + Vite with Ant Design 5
- ECharts telemetry visualization, TanStack Query
- SignalR live updates, device management UI
- Dashboard, fleet management, firmware deployment

Testing & Production (Phase 10):
- 28 firmware unit tests (Modbus, JSON, config, version)
- 23 xUnit backend tests (device, telemetry, command, alert)
- Docker Compose with nginx, TLS MQTT, PostgreSQL
- Production deployment, commissioning, and troubleshooting docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-16 19:05:32 +02:00

522 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 9: Console Application Frontend
## Objective
Build the web-based frontend dashboard for the console application. The frontend provides device fleet management, real-time telemetry visualization, remote configuration, OTA firmware deployment, and alert management. It connects to the backend API (Phase 8) and uses SignalR for real-time updates.
## Prerequisites
- Phase 8 complete (backend API running)
- Node.js 18+ (for frontend build tooling)
- Design system chosen
## Deliverables
1. React SPA with responsive dashboard
2. Device fleet overview with status indicators
3. Individual device detail page (telemetry, config, health)
4. Real-time telemetry charts
5. Remote configuration interface
6. Firmware management and deployment UI
7. Alert management dashboard
8. User authentication flow
---
## 9.1 Technology Stack
| Component | Technology | Justification |
|-----------|-----------|---------------|
| Framework | React 18 | Component-based, large ecosystem |
| Language | TypeScript | Type safety, better DX |
| Build | Vite | Fast HMR, modern bundling |
| Routing | React Router v6 | Standard React routing |
| State | TanStack Query (React Query) | Server state caching, auto-refresh |
| UI Library | Ant Design 5 | Complete component set, tables, forms, charts |
| Charts | Apache ECharts (via echarts-for-react) | High-performance, rich chart types |
| Real-time | @microsoft/signalr | SignalR client for live updates |
| HTTP | Axios | HTTP client with interceptors |
| Forms | Ant Design Form | Built-in validation |
| Icons | Ant Design Icons | Consistent with UI library |
## 9.2 Project Structure
```
console/
├── frontend/
│ ├── package.json
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── index.html
│ ├── public/
│ │ └── favicon.ico
│ └── src/
│ ├── main.tsx
│ ├── App.tsx
│ ├── api/
│ │ ├── client.ts # Axios instance with auth interceptor
│ │ ├── devices.ts # Device API calls
│ │ ├── telemetry.ts # Telemetry API calls
│ │ ├── firmware.ts # Firmware API calls
│ │ ├── alerts.ts # Alert API calls
│ │ ├── auth.ts # Auth API calls
│ │ └── commands.ts # Command API calls
│ ├── hooks/
│ │ ├── useDevices.ts
│ │ ├── useTelemetry.ts
│ │ ├── useSignalR.ts
│ │ └── useAuth.ts
│ ├── pages/
│ │ ├── LoginPage.tsx
│ │ ├── DashboardPage.tsx
│ │ ├── DeviceListPage.tsx
│ │ ├── DeviceDetailPage.tsx
│ │ ├── FirmwarePage.tsx
│ │ ├── AlertsPage.tsx
│ │ ├── GroupsPage.tsx
│ │ └── SettingsPage.tsx
│ ├── components/
│ │ ├── layout/
│ │ │ ├── AppLayout.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ └── Header.tsx
│ │ ├── devices/
│ │ │ ├── DeviceTable.tsx
│ │ │ ├── DeviceCard.tsx
│ │ │ ├── DeviceStatusBadge.tsx
│ │ │ ├── DeviceConfigForm.tsx
│ │ │ ├── WifiScanModal.tsx
│ │ │ └── CommandModal.tsx
│ │ ├── telemetry/
│ │ │ ├── TelemetryChart.tsx
│ │ │ ├── LiveReadings.tsx
│ │ │ ├── PowerGauge.tsx
│ │ │ └── EnergyCounter.tsx
│ │ ├── firmware/
│ │ │ ├── FirmwareUpload.tsx
│ │ │ ├── FirmwareTable.tsx
│ │ │ └── DeployModal.tsx
│ │ ├── alerts/
│ │ │ ├── AlertTable.tsx
│ │ │ └── AlertBadge.tsx
│ │ └── dashboard/
│ │ ├── FleetSummary.tsx
│ │ ├── DeviceMap.tsx
│ │ └── RecentAlerts.tsx
│ ├── types/
│ │ ├── device.ts
│ │ ├── telemetry.ts
│ │ ├── firmware.ts
│ │ └── alert.ts
│ └── utils/
│ ├── formatters.ts
│ └── constants.ts
```
## 9.3 Page Layouts
### Dashboard (Home)
Fleet-level overview — the first thing operators see.
```
┌─────────────────────────────────────────────────────────────┐
│ ☰ Tau Acuvim Console admin ▼ [Logout] │
├──────┬──────────────────────────────────────────────────────┤
│ │ │
│ Nav │ Fleet Overview │
│ │ ┌──────────┬──────────┬──────────┬──────────┐ │
│ 📊 │ │ Total │ Online │ Degraded │ Offline │ │
│Dash │ │ 24 │ 21 │ 1 │ 2 │ │
│ │ └──────────┴──────────┴──────────┴──────────┘ │
│ 📱 │ │
│Devs │ ┌────────────────────┬──────────────────────┐ │
│ │ │ Recent Alerts │ Fleet Power │ │
│ 📦 │ │ ⚠ Overvoltage │ ┌─────────────────┐ │ │
│FW │ │ ACV-001 2m ago │ │ Line chart │ │ │
│ │ │ ⚠ Modbus error │ │ (total kW over │ │ │
│ 🔔 │ │ ACV-015 5m ago │ │ last 24h) │ │ │
│Alert │ │ ● Device offline │ └─────────────────┘ │ │
│ │ │ ACV-008 1h ago │ │ │
│ ⚙ │ └────────────────────┴──────────────────────┘ │
│Sets │ │
│ │ Device Status Grid │
│ │ ┌──────┬──────┬──────┬──────┬──────┬──────┐ │
│ │ │●001 │●002 │●003 │●004 │●005 │●006 │ │
│ │ │230V │231V │229V │232V │ OFF │230V │ │
│ │ │10kW │12kW │9kW │11kW │ -- │8kW │ │
│ │ └──────┴──────┴──────┴──────┴──────┴──────┘ │
│ │ │
└──────┴──────────────────────────────────────────────────────┘
```
### Device List
```
┌──────────────────────────────────────────────────────────────┐
│ Devices [+ Add Group] [⚡ Deploy] │
├──────────────────────────────────────────────────────────────┤
│ Filter: [All ▼] [Online ▼] [Group ▼] Search: [________] │
├──────────────────────────────────────────────────────────────┤
│ Status │ Device ID │ Name │ FW │ Conn │ P │
│────────┼─────────────────┼───────────────┼───────┼──────┼────│
│ ● │ ACV-AABBCCDDEEFF│ Building A │ 1.0.0 │ WiFi │10kW│
│ ● │ ACV-112233445566│ Building B │ 1.0.0 │ GSM │12kW│
│ ◐ │ ACV-FFEEDDCCBBAA│ Warehouse │ 0.9.0 │ WiFi │ 9kW│
│ ○ │ ACV-998877665544│ Solar Farm │ 1.0.0 │ -- │ -- │
├──────────────────────────────────────────────────────────────┤
│ Showing 1-20 of 24 devices < 1 2 > │
└──────────────────────────────────────────────────────────────┘
Status indicators: ● Online ◐ Degraded ○ Offline
```
### Device Detail
```
┌──────────────────────────────────────────────────────────────┐
│ ← Devices / ACV-AABBCCDDEEFF - Building A │
├──────────────────────────────────────────────────────────────┤
│ [Overview] [Telemetry] [Config] [Alerts] [Commands] [OTA] │
├──────────────────────────────────────────────────────────────┤
│ │
│ ── Overview Tab ── │
│ │
│ Device Info │ Connection │
│ ID: ACV-AABBCCDDEEFF │ Type: WiFi │
│ Name: Building A │ SSID: MyNetwork │
│ Hardware: TTGO T-Call v1.4 │ RSSI: -45 dBm │
│ Firmware: v1.0.0 │ IP: 192.168.1.100 │
│ Uptime: 3d 2h 15m │ MQTT: Connected │
│ Boot count: 12 │ GSM: Available (standby) │
│ Last heartbeat: 30s ago │ SD: 4GB (0.1% used) │
│ │ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Live Readings ● LIVE │ │
│ │ │ │
│ │ Phase Voltages Phase Currents │ │
│ │ Va: 230.1 V Ia: 15.2 A │ │
│ │ Vb: 231.4 V Ib: 14.8 A │ │
│ │ Vc: 229.8 V Ic: 15.5 A │ │
│ │ │ │
│ │ Power Energy │ │
│ │ Active: 10.5 kW Import: 12,345.6 kWh │ │
│ │ Reactive: 2.1 kVAR Export: 0.0 kWh │ │
│ │ Apparent: 10.7 kVA PF: 0.98 │ │
│ │ Freq: 50.01 Hz │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ [Restart] [WiFi Scan] [Send Command] │
└──────────────────────────────────────────────────────────────┘
```
### Device Detail - Telemetry Tab
```
┌──────────────────────────────────────────────────────────────┐
│ [Overview] [Telemetry] [Config] [Alerts] [Commands] [OTA] │
├──────────────────────────────────────────────────────────────┤
│ │
│ Time Range: [Last 24h ▼] [Custom Range] [Export CSV] │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Phase Voltages (V) │ │
│ │ 240 ┤ │ │
│ │ 235 ┤ ╭─╮ │ │
│ │ 230 ┤───╯ ╰──────────────────────────────────── │ │
│ │ 225 ┤ │ │
│ │ 220 ┤ │ │
│ │ └──┬────┬────┬────┬────┬────┬────┬────┬────┬── │ │
│ │ 00 03 06 09 12 15 18 21 24 │ │
│ │ ── Va ── Vb ── Vc │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Active Power (kW) │ │
│ │ 15 ┤ ╭───╮ │ │
│ │ 10 ┤────╮ ╯ ╰───────╮ │ │
│ │ 5 ┤ ╰──╯ ╰────── │ │
│ │ 0 ┤ │ │
│ │ └──┬────┬────┬────┬────┬────┬────┬────┬────┬── │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Power Factor & Frequency │ │
│ │ ... similar chart ... │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
### Device Detail - Config Tab
```
┌──────────────────────────────────────────────────────────────┐
│ [Overview] [Telemetry] [Config] [Alerts] [Commands] [OTA] │
├──────────────────────────────────────────────────────────────┤
│ │
│ WiFi Configuration │ MQTT Configuration │
│ SSID: [MyNetwork____] │ Broker: [broker.example.com] │
│ Password: [**********] │ Port: [1883] │
│ Enabled: [✓] │ Username: [device1] │
│ [Scan Networks] [Save] │ Password: [**********] │
│ │ Topic: [acuvim] │
│ GSM Configuration │ TLS: [ ] │
│ APN: [internet] │ [Test] [Save] │
│ Enabled: [✓] │ │
│ Priority: [WiFi first ▼] │ Sleep Configuration │
│ [Save] │ Enabled: [ ] │
│ │ Sleep: [15] min │
│ Modbus Configuration │ Wake: [300] sec │
│ Slave Address: [1] │ [Save] │
│ Baud Rate: [9600 ▼] │ │
│ Poll Interval: [5] sec │ Console URL │
│ [Save] │ [https://console.example.com] │
│ │ [Save] │
│ │
│ ⚠ Changes are pushed to the device immediately via MQTT. │
│ The device will apply settings and reconnect as needed. │
└──────────────────────────────────────────────────────────────┘
```
### Firmware Management Page
```
┌──────────────────────────────────────────────────────────────┐
│ Firmware Management [Upload New] │
├──────────────────────────────────────────────────────────────┤
│ │
│ Version │ Size │ Date │ Devices │ Status │ Action │
│─────────┼────────┼──────────────┼─────────┼────────┼─────────│
│ v1.2.0 │ 1.2 MB │ May 16, 2026 │ 0 / 24 │ Active │ [Deploy]│
│ v1.1.0 │ 1.1 MB │ May 10, 2026 │ 3 / 24 │ Active │ [Deploy]│
│ v1.0.0 │ 1.0 MB │ May 01, 2026 │ 21 / 24 │ Active │ [Deploy]│
│ v0.9.0 │ 0.9 MB │ Apr 15, 2026 │ 0 / 24 │ Archived│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ Deploy v1.2.0 to: │
│ ( ) All devices (24) │
│ ( ) Group: [Building A ▼] (8 devices) │
│ (●) Select devices: │
│ [✓] ACV-001 - Building A (v1.0.0) │
│ [✓] ACV-002 - Building B (v1.0.0) │
│ [ ] ACV-003 - Warehouse (v0.9.0) │
│ │
│ Release Notes: │
│ Added THD monitoring improvements │
│ │
│ [Deploy to 2 devices] │
└──────────────────────────────────────────────────────────────┘
```
### Alerts Page
```
┌──────────────────────────────────────────────────────────────┐
│ Alerts Unresolved: 5 [Mark All Read] │
├──────────────────────────────────────────────────────────────┤
│ Filter: [All ▼] [Warning ▼] [Active ▼] Search: [________] │
├──────────────────────────────────────────────────────────────┤
│ Sev │ Device │ Alert │ Value │ Time │ Ack │
│─────┼───────────┼────────────────┼─────────┼─────────┼───────│
│ ⚠ │ ACV-001 │ Overvoltage │ 265.3V │ 2m ago │ [ ] │
│ ⚠ │ ACV-015 │ Modbus errors │ 12% │ 5m ago │ [ ] │
│ ● │ ACV-008 │ Device offline │ -- │ 1h ago │ [ ] │
│ ACV-003 │ Low PF │ 0.82 │ 2h ago │ [✓] │
│ ⚠ │ ACV-001 │ Undervoltage │ 198V │ 3h ago │ [✓] │
├──────────────────────────────────────────────────────────────┤
│ Showing 1-20 of 45 alerts < 1 2 3 > │
└──────────────────────────────────────────────────────────────┘
Severity: ● Critical ⚠ Warning Info
```
## 9.4 SignalR Integration
### Real-Time Hook
```typescript
// useSignalR.ts
function useSignalR() {
const connection = new HubConnectionBuilder()
.withUrl("/hubs/devices", { accessTokenFactory: () => getToken() })
.withAutomaticReconnect()
.build();
useEffect(() => {
connection.start();
connection.on("DeviceStatusChanged", (deviceId, status) => {
queryClient.invalidateQueries(["devices"]);
});
connection.on("TelemetryReceived", (deviceId, data) => {
queryClient.setQueryData(["telemetry", deviceId, "latest"], data);
});
connection.on("AlertCreated", (deviceId, alert) => {
queryClient.invalidateQueries(["alerts"]);
notification.warning({ message: alert.message });
});
return () => connection.stop();
}, []);
}
```
### Live Data Updates
- Device status badges update in real-time (no page refresh)
- Telemetry readings update live on device detail page
- New alerts appear as toast notifications
- Dashboard counters update automatically
## 9.5 Authentication Flow
### Login Page
```
┌──────────────────────────────────────┐
│ │
│ Tau Acuvim Console │
│ │
│ Email: [________________] │
│ Password: [________________] │
│ │
│ [Login] │
│ │
│ Forgot password? │
│ │
└──────────────────────────────────────┘
```
### Auth Implementation
```typescript
// Protected route wrapper
function ProtectedRoute({ children }) {
const { isAuthenticated } = useAuth();
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
return children;
}
```
- JWT token stored in memory (not localStorage) for security
- Refresh token in httpOnly cookie
- Axios interceptor adds `Authorization` header automatically
- On 401 response: redirect to login
## 9.6 Responsive Design
- **Desktop (>1200px):** Full sidebar + content layout
- **Tablet (768-1200px):** Collapsible sidebar, adjusted grid
- **Mobile (<768px):** Bottom navigation, stacked cards, simplified tables
Ant Design's grid system handles responsive breakpoints. Charts resize automatically using ECharts' responsive mode.
## 9.7 Build and Deploy
### Development
```bash
cd console/frontend
npm install
npm run dev # Vite dev server with HMR (port 5173)
```
### Production Build
```bash
npm run build # Output to dist/
```
### Integration with Backend
- In development: Vite proxy forwards `/api` and `/hubs` to the .NET backend
- In production: the .NET backend serves the built frontend files from `wwwroot/`
- `vite.config.ts` configures the proxy for development
```typescript
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api': 'http://localhost:5000',
'/hubs': {
target: 'http://localhost:5000',
ws: true
}
}
}
});
```
### Docker Integration
Add to the Phase 8 Dockerfile:
```dockerfile
# Build frontend
FROM node:18 AS frontend
WORKDIR /app/frontend
COPY console/frontend/package*.json ./
RUN npm ci
COPY console/frontend/ ./
RUN npm run build
# Build backend
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS backend
# ... build steps ...
# Runtime
FROM mcr.microsoft.com/dotnet/aspnet:8.0
# ... copy backend build ...
COPY --from=frontend /app/frontend/dist ./wwwroot/
```
## 9.8 Testing & Validation
| Test | Method | Pass Criteria |
|------|--------|---------------|
| Login | Enter valid credentials | Redirected to dashboard |
| Dashboard loads | Navigate to / | Summary cards, alerts, grid visible |
| Device list | Navigate to /devices | All devices listed with status |
| Device detail | Click a device | Overview tab shows live data |
| Telemetry charts | Select Telemetry tab | Charts render with historical data |
| Time range | Change to Last 7 days | Charts update with correct range |
| Config push | Edit WiFi settings, save | Config sent to device via MQTT |
| WiFi scan | Click Scan Networks | Networks returned and displayed |
| Firmware upload | Upload a .bin file | File uploaded, appears in list |
| Firmware deploy | Deploy to selected devices | OTA commands sent |
| Alert display | Trigger alert from device | Alert appears in list and as toast |
| Alert acknowledge | Click acknowledge | Alert marked as acknowledged |
| Real-time update | Watch dashboard while device publishes | Values update without refresh |
| Responsive | Resize browser to mobile | Layout adapts correctly |
| Auth protection | Access /devices without login | Redirected to /login |
| CSV export | Export telemetry | Valid CSV downloaded |
| Send command | Send restart command | Device restarts, response received |
## 9.9 Phase 9 Completion Criteria
- [ ] React frontend builds and serves
- [ ] Login/logout flow with JWT authentication
- [ ] Dashboard shows fleet summary, alerts, device grid
- [ ] Device list with filtering, search, pagination
- [ ] Device detail with tabs: Overview, Telemetry, Config, Alerts, Commands, OTA
- [ ] Live telemetry readings update via SignalR
- [ ] Historical telemetry charts with time range selection
- [ ] Remote configuration push (WiFi, MQTT, GSM, sleep, Modbus)
- [ ] WiFi scan triggered from console and results displayed
- [ ] Firmware upload and deployment UI
- [ ] Alert management (list, filter, acknowledge)
- [ ] Responsive design (desktop, tablet, mobile)
- [ ] Integrated into .NET backend for production deployment
---
**Previous Phase:** [Phase 8 — Console Application Backend](acuvim-spec-08.md)
**Next Phase:** [Phase 10 — Integration Testing & Production Hardening](acuvim-spec-10.md)