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:
235
Docs/plans/PHASE_0_INFRASTRUCTURE.md
Normal file
235
Docs/plans/PHASE_0_INFRASTRUCTURE.md
Normal 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
|
||||
Reference in New Issue
Block a user