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>
236 lines
7.3 KiB
Markdown
236 lines
7.3 KiB
Markdown
# 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
|