Initial commit: COPILOT D6 Flutter keyboard controller

Flutter web app replacing legacy WPF CCTV surveillance keyboard controller.
Includes wall overview, section view with monitor grid, camera input,
PTZ control, alarm/lock/sequence BLoCs, and legacy-matching UI styling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
klas
2026-02-12 14:57:38 +01:00
commit 40143734fc
125 changed files with 65073 additions and 0 deletions

View File

@@ -0,0 +1,235 @@
# Phase 0: Infrastructure Implementation Plan
**Status:** In Progress
**Duration:** Week 1-2
**Goal:** Finalize bridges, add event subscriptions, test direct commands, document configurations
---
## Current State Assessment
### Bridge Readiness
| Bridge | Port | Status | PLC Events | ViewerConnectLive | PTZ | Playback |
|--------|------|--------|------------|-------------------|-----|----------|
| GeViScope | 7720 | ✅ Ready | ✅ | ✅ | ✅ | ✅ |
| G-Core | 7721 | ✅ Ready | ✅ | ✅ | ✅ | ✅ |
| GeViServer | 7710 | ⚠️ Minimal | ⚠️ Events only | ❌ | ❌ | ❌ |
**Decision:** GeViServer Bridge remains minimal per design ("Minimal GeViSoft usage").
---
## Phase 0 Tasks
### Task 1: Event Notification Forwarding ✅ COMPLETED
**Priority:** HIGH
**Effort:** 4-6 hours
**Status:** Done (2026-02-03)
The bridges have PLC subscriptions but notifications are only logged. For the new architecture, events must be forwarded to the Flutter app.
**Sub-tasks:**
1. [x] Add WebSocket endpoint to GeViScope Bridge for event streaming (`ws://localhost:7720/ws/events`)
2. [x] Add WebSocket endpoint to G-Core Bridge for event streaming (`ws://localhost:7721/ws/events`)
3. [x] Define event message format (JSON)
4. [x] Forward these events:
- `ViewerConnected(Viewer, Channel, PlayMode)`
- `ViewerCleared(Viewer)`
- `ViewerSelectionChanged(Viewer, Channel, PlayMode)`
- `EventStarted(EventID, TypeID, ForeignKey)`
- `EventStopped(EventID, TypeID)`
- `VCAlarmQueueNotification(Viewer, Notification, AlarmID, TypeID)`
- `DigitalInput(Contact, State)`
- `ConnectionLost` (bonus)
**Event Message Format:**
```json
{
"timestamp": "2026-02-03T10:30:00.123Z",
"server": "GeViScope-01",
"action": "ViewerConnected",
"params": {
"Viewer": 5,
"Channel": 101,
"PlayMode": 11
}
}
```
---
### Task 2: Alarm Query Endpoints ✅ COMPLETED (Event-Based)
**Priority:** HIGH
**Effort:** 3-4 hours
**Status:** Done (2026-02-03)
Add alarm query capability to bridges (critical for "never miss alarms" requirement).
**Finding:** GeViScope/G-Core SDKs don't have direct alarm query APIs like GeViSoft. They use event-based tracking.
**Implementation:**
- [x] Research GeViScope SDK - uses EventStarted/EventStopped notifications (no query API)
- [x] Research G-Core SDK - uses EventStarted/EventStopped notifications (no query API)
- [x] Implement `GET /alarms/active` - returns alarms tracked from events
- [x] Implement `GET /alarms` - returns all tracked alarms (active + stopped)
- [x] Track alarm state from EventStarted/EventStopped notifications
**Important:** For complete alarm state on startup (before any events received), the Flutter app should query GeViServer bridge which has `GeViSQ_GetFirstAlarm/GetNextAlarm` methods.
---
### Task 3: Monitor State Query ✅ COMPLETED (Event-Based)
**Priority:** MEDIUM
**Effort:** 2-3 hours
**Status:** Done (2026-02-03)
Add ability to query current monitor state on startup.
**Finding:** GeViScope/G-Core SDKs use ViewerConnected/ViewerCleared events for state changes. GetFirstVideoOutput is GeViSoft SDK only.
**Implementation:**
- [x] Research GeViScope SDK - uses ViewerConnected/ViewerCleared/ViewerSelectionChanged events
- [x] Research G-Core SDK - same event-based approach
- [x] Implement `GET /monitors` - returns all monitored states tracked from events
- [x] Implement `GET /monitors/{viewerId}` - returns specific monitor state
- [x] Track monitor state from ViewerConnected/ViewerCleared events
**Important:** For complete monitor state on startup (before any events received), the Flutter app should either:
1. Trigger a ViewerConnectLive to each known monitor (will fire ViewerConnected event)
2. Query GeViServer bridge if GeViSoft integration is acceptable
---
### Task 4: Server Configuration Documentation ✅ COMPLETED
**Priority:** MEDIUM
**Effort:** 2-3 hours
**Status:** Done (2026-02-03)
Document server configurations for deployment.
**Sub-tasks:**
1. [x] Create `servers.json` template with all server definitions
2. [x] Document camera ID ranges per server
3. [x] Document monitor ID mappings
4. [x] Create `crossswitch-rules.json` template
5. [x] Create `keyboards.json` template
**Files Created:**
- `C:\DEV\COPILOT_D6\config\servers.json.template`
- `C:\DEV\COPILOT_D6\config\crossswitch-rules.json.template`
- `C:\DEV\COPILOT_D6\config\keyboards.json.template`
---
### Task 5: Bridge Health Checks ✅ COMPLETED
**Priority:** MEDIUM
**Effort:** 1-2 hours
**Status:** Done (2026-02-03)
Enhance health check endpoints for production monitoring.
**Sub-tasks:**
1. [x] Add detailed status to `/status` endpoint:
- `is_connected` (bool)
- `address` (server address)
- `connection_duration_sec`
- `event_count` (since connection)
- `websocket_clients` (connected WS clients)
- `plc_active` (bool)
2. [x] Add `/health` endpoint for load balancer probes
3. [ ] Add connection auto-reconnect logic (deferred to Phase 1)
---
### Task 6: Integration Testing ⬜ IN PROGRESS
**Priority:** HIGH
**Effort:** 4-6 hours
Test bridges against actual servers.
**Sub-tasks:**
1. [ ] Test GeViScope Bridge against real GeViScope server
- [ ] Connection/disconnection
- [ ] ViewerConnectLive
- [ ] PTZ control
- [ ] Event reception via WebSocket
2. [ ] Test G-Core Bridge against real G-Core server
- [ ] Same tests as above
3. [x] Create test scripts (HTTP files)
- `C:\DEV\COPILOT_D6\tests\test-geviscope.http`
- `C:\DEV\COPILOT_D6\tests\test-gcore.http`
4. [ ] Document any SDK issues found
---
### Task 7: Logging Standardization ⬜
**Priority:** LOW
**Effort:** 2 hours
Standardize logging format for Kibana integration.
**Sub-tasks:**
1. [ ] Configure Serilog with JSON formatter
2. [ ] Add structured logging fields:
- keyboard_id
- server_id
- command
- duration_ms
- success
3. [ ] Configure log rotation
4. [ ] Test log output format
---
## File Structure After Phase 0
```
C:\DEV\COPILOT_D6\
├── docs\
│ ├── NEW_SYSTEM_DESIGN_SUMMARY.md
│ ├── IMPLEMENTATION_QUICK_REFERENCE.md
│ └── plans\
│ └── PHASE_0_INFRASTRUCTURE.md
├── config\
│ ├── servers.json.template ✅ Created
│ ├── crossswitch-rules.json.template ✅ Created
│ └── keyboards.json.template ✅ Created
└── tests\
├── test-geviscope.http ✅ Created
└── test-gcore.http ✅ Created
Bridges (existing, enhanced):
├── C:\DEV\COPILOT\geviscope-bridge\ ✅ WebSocket added
└── C:\DEV\COPILOT\gcore-bridge\ ✅ WebSocket added
```
---
## Success Criteria
- [x] Events are streamed via WebSocket from both bridges
- [x] Alarm state can be queried on demand (event-based tracking + `/alarms/active` endpoint)
- [x] Monitor state can be queried on demand (event-based tracking + `/monitors` endpoint)
- [x] Configuration templates are documented
- [ ] All bridge endpoints tested against real servers
- [ ] Logging format matches ELK requirements (Task 7 - pending, low priority)
---
## Dependencies
- Access to GeViScope server for testing
- Access to G-Core server for testing
- GeViScope SDK documentation (chunk files available)
- G-Core SDK documentation (chunk files available)
---
## Next Phase
After Phase 0, proceed to **Phase 1: Flutter Keyboard Core**
- Keyboard layout UI
- Direct command execution
- Server routing logic
- State notification subscription