// HOMECORE-UI contract-conformant mock layer — ADR-131 §7.1. // // "Where a service is not yet stable, the panel is still built against // its defined contract (with a contract-conformant mock standing in for // the live endpoint only until that endpoint lands)." // // Shapes mirror the schemas described in ADR-131 §4 + the calibration // RoomState contract (docs/integration/calibration-appliance-integration.md) // + the SEED HTTPS API. Live endpoints replace these the moment they // exist; nothing here is presented to the operator as real (the UI shows // a DEMO badge whenever the mock layer is serving a panel — see api.js). const now = () => new Date().toISOString(); const ago = (s) => new Date(Date.now() - s * 1000).toISOString(); function jitter(base, amp) { return +(base + (Math.sin(Date.now() / 3000 + base) * amp)).toFixed(2); } function spark(base, amp, n = 24) { return Array.from({ length: n }, (_, i) => +(base + Math.sin(i / 2) * amp + (i % 3) * amp * 0.2).toFixed(2)); } // Factory for a bedroom SEED node — keeps the three bedrooms consistent // while varying the values that matter for the analysis views. function bedroomSeed(o) { return { device_id: o.device_id, firmware: '0.7.3', online: true, conn: o.conn || 'wifi', epoch: o.epoch, vector_count: o.vector_count, vector_dim: 8, knn_latency_ms: o.knn_latency_ms, last_ingest: ago(2), witness_valid: true, witness_len: o.witness_len, witness_last_verify: ago(1800), zone: o.zone, storage_used: o.vector_count, storage_budget: 100000, sensors: { bme280: { temp_c: o.temp_c, humidity_pct: o.humidity_pct, pressure_hpa: 1013.0 }, pir: { motion: o.motion, last_trigger: ago(o.motion ? 5 : 640) }, reed: { open: false, last_change: ago(30000) }, ads1115: [{ label: 'ch0', v: 0.11 }, { label: 'ch1', v: 0.0 }, { label: 'ch2', v: 0.0 }, { label: 'ch3', v: 0.0 }], vibration: { active: false, last_trigger: null }, }, reflex: [ { name: 'fragility_alarm', threshold: 0.3, target: 'relay actuator', last_fired: o.fired ? ago(420) : null, fired_recently: !!o.fired }, { name: 'drift_cutoff', threshold: 1.0, target: 'ingest gate', last_fired: null, fired_recently: false }, { name: 'hd_anomaly_indicator', threshold: 200, target: 'PWM brightness', last_fired: null, fired_recently: false }, ], cognition: { fragility: o.fragility, coherence_phases: o.phases, knn_rebuild_s: 10 }, ingest: { batch: 64, flush_ms: 1000, bridge: 'direct', esp32: [{ node_id: o.node, packet: '0xC5110003', rate_hz: 1.0 }] }, esp32_nodes: 1, frame_rate_hz: 100, }; } // ── v0 Appliance health (§4.1) ────────────────────────────────────── export function applianceHealth() { return { cpu_pct: jitter(34, 6), ram_pct: jitter(58, 4), hailo_load_pct: jitter(41, 12), hailo_temp_c: jitter(52, 3), uptime_s: 824510, services: [ { name: 'ruview-mcp-brain', port: 9876, status: 'running' }, { name: 'cognitum-rvf-agent', port: 9004, status: 'running' }, { name: 'ruvector-hailo-worker', port: 50051, status: 'running' }, ], event_rate: spark(120, 40), channel_capacity: 4096, channel_lag: 0, }; } // ── SEED fleet (§4.1 / §4.2) ──────────────────────────────────────── const SEEDS = [ { device_id: 'seed-livingroom-a1', firmware: '0.7.3', online: true, conn: 'wifi', epoch: 184, vector_count: 71280, vector_dim: 8, knn_latency_ms: 2.1, last_ingest: ago(3), witness_valid: true, witness_len: 184210, witness_last_verify: ago(900), zone: 'Living Room', storage_used: 71280, storage_budget: 100000, sensors: { bme280: { temp_c: 21.6, humidity_pct: 44, pressure_hpa: 1013.2 }, pir: { motion: true, last_trigger: ago(8) }, reed: { open: false, last_change: ago(7200) }, ads1115: [{ label: 'soil', v: 0.42 }, { label: 'light', v: 0.71 }, { label: 'aux2', v: 0.03 }, { label: 'aux3', v: 0.0 }], vibration: { active: false, last_trigger: ago(40000) }, }, reflex: [ { name: 'fragility_alarm', threshold: 0.3, target: 'relay actuator', last_fired: ago(300), fired_recently: true }, { name: 'drift_cutoff', threshold: 1.0, target: 'ingest gate', last_fired: null, fired_recently: false }, { name: 'hd_anomaly_indicator', threshold: 200, target: 'PWM brightness', last_fired: ago(12000), fired_recently: false }, ], cognition: { fragility: 0.42, coherence_phases: [{ t: ago(3600), label: 'empty' }, { t: ago(1800), label: 'occupied' }, { t: ago(300), label: 'regime-change' }], knn_rebuild_s: 10 }, ingest: { batch: 64, flush_ms: 1000, bridge: 'host-laptop hop', esp32: [{ node_id: 'esp32-lr-01', packet: '0xC5110003', rate_hz: 1.0 }, { node_id: 'esp32-lr-02', packet: '0xC5110002', rate_hz: 0.9 }] }, esp32_nodes: 2, frame_rate_hz: 98, }, bedroomSeed({ device_id: 'seed-bedroom-1', zone: 'Bedroom 1 (primary)', epoch: 183, vector_count: 38110, knn_latency_ms: 1.7, witness_len: 91022, temp_c: 20.1, humidity_pct: 47, motion: false, fragility: 0.12, phases: [{ t: ago(7200), label: 'empty' }, { t: ago(3600), label: 'sleep' }], node: 'esp32-br1-01', conn: 'usb', }), bedroomSeed({ device_id: 'seed-bedroom-2', zone: 'Bedroom 2 (guest)', epoch: 181, vector_count: 29440, knn_latency_ms: 1.9, witness_len: 70210, temp_c: 19.4, humidity_pct: 50, motion: true, fragility: 0.21, phases: [{ t: ago(5400), label: 'empty' }, { t: ago(900), label: 'occupied' }], node: 'esp32-br2-01', conn: 'wifi', }), bedroomSeed({ device_id: 'seed-bedroom-3', zone: 'Bedroom 3 (kids)', epoch: 179, vector_count: 24105, knn_latency_ms: 2.0, witness_len: 60880, temp_c: 21.0, humidity_pct: 45, motion: false, fragility: 0.34, phases: [{ t: ago(9000), label: 'empty' }, { t: ago(4200), label: 'sleep' }, { t: ago(600), label: 'restless' }], node: 'esp32-br3-01', conn: 'wifi', fired: true, }), { device_id: 'seed-hallway-c3', firmware: '0.6.9', online: false, conn: 'wifi', epoch: 170, vector_count: 12044, vector_dim: 8, knn_latency_ms: null, last_ingest: ago(5400), witness_valid: true, witness_len: 40110, witness_last_verify: ago(86400), zone: 'Hallway', storage_used: 12044, storage_budget: 100000, sensors: null, reflex: [], cognition: { fragility: null, coherence_phases: [], knn_rebuild_s: 10 }, ingest: { batch: 64, flush_ms: 1000, bridge: 'direct', esp32: [] }, esp32_nodes: 0, frame_rate_hz: 0, warnings: ['stale firmware version (0.6.9 < 0.7.3)', 'offline > 1h'], }, ]; export function seeds() { return SEEDS.map((s) => ({ ...s })); } export function seed(id) { return SEEDS.find((s) => s.device_id === id) || null; } // ── ESP32 node warnings (§4.1) ────────────────────────────────────── export function esp32Warnings() { return [ { node_id: 'esp32-lr-02', seed: 'seed-livingroom-a1', issue: 'presence_score normalisation anomaly' }, { node_id: 'esp32-hw-01', seed: 'seed-hallway-c3', issue: 'stale firmware version' }, ]; } // ── COG runtime (§4.6) ────────────────────────────────────────────── const COGS = [ { id: 'cog-ha-matter', version: '1.4.2', arch: 'arm', status: 'running', pid: 4120, sha256_verified: true, signature_verified: true }, { id: 'cog-pose-estimation', version: '2.1.0', arch: 'hailo10', status: 'running', pid: 4188, sha256_verified: true, signature_verified: true, hef: ['rf_foundation_encoder.hef', 'pose_head.hef'], throughput_fps: 41 }, { id: 'cog-person-count', version: '0.9.4', arch: 'arm', status: 'running', pid: 4205, sha256_verified: true, signature_verified: true }, { id: 'cog-calibration', version: '1.0.1', arch: 'arm', status: 'running', pid: 4250, sha256_verified: true, signature_verified: true }, { id: 'cog-anomaly-watch', version: '0.3.0', arch: 'arm', status: 'failed', pid: null, sha256_verified: true, signature_verified: true, error: 'panic: bank not found' }, { id: 'cog-legacy-bridge', version: '0.1.2', arch: 'arm', status: 'stopped', pid: null, sha256_verified: false, signature_verified: false }, ]; export function cogs() { return COGS.map((c) => ({ ...c })); } export function cogUpdates() { return [{ id: 'cog-pose-estimation', from: '2.1.0', to: '2.2.0', new_entities: ['sensor.lr_pose_confidence'], config_changes: ['add: max_persons'] }]; } export function appRegistry() { return [ { id: 'cog-fall-detect', title: 'Fall Detection', desc: 'Multistatic fall detection specialist', category: 'safety', arch: 'arm', featured: true, new_entities: ['binary_sensor.{room}_fall'] }, { id: 'cog-sleep-stage', title: 'Sleep Staging', desc: 'REM/deep/light from breathing + restlessness', category: 'health', arch: 'hailo10', new_entities: ['sensor.{room}_sleep_stage'] }, { id: 'cog-gesture', title: 'Gesture Control', desc: 'DTW gesture classifier → service calls', category: 'control', arch: 'arm', new_entities: ['event.{room}_gesture'] }, ]; } // ── RoomState / sensing (§4.5) — calibration contract ─────────────── export function roomStates() { return [ { room_id: 'living_room', stale: false, vetoed: false, seeds: ['seed-livingroom-a1'], presence: { value: 'occupied', confidence: 0.93 }, posture: { value: 'sitting', confidence: 0.81 }, breathing_bpm: { value: jitter(15, 1.5), confidence: 0.77 }, heart_bpm: { value: jitter(72, 3), confidence: 0.64 }, restlessness: { value: 0.22, confidence: 0.7 }, anomaly: { value: 0.18, confidence: 0.8, threshold: 0.8 }, }, { // Bedroom 1 — primary; healthy sleeping vitals. room_id: 'bedroom_1', stale: false, vetoed: false, seeds: ['seed-bedroom-1'], presence: { value: 'occupied', confidence: 0.91 }, posture: { value: 'lying', confidence: 0.9 }, breathing_bpm: { value: jitter(12, 1), confidence: 0.85 }, heart_bpm: { value: jitter(58, 2), confidence: 0.72 }, restlessness: { value: 0.08, confidence: 0.8 }, anomaly: { value: 0.12, confidence: 0.84, threshold: 0.8 }, }, { // Bedroom 2 — guest; STALE bank (recalibrate demo). room_id: 'bedroom_2', stale: true, vetoed: false, seeds: ['seed-bedroom-2'], presence: { value: 'occupied', confidence: 0.86 }, posture: { value: 'sitting', confidence: 0.7 }, breathing_bpm: { value: jitter(16, 1.5), confidence: 0.66 }, heart_bpm: { value: jitter(74, 3), confidence: 0.58 }, restlessness: { value: 0.31, confidence: 0.62 }, anomaly: { value: 0.4, confidence: 0.6, threshold: 0.8 }, }, { // Bedroom 3 — kids; heartbeat specialist not yet trained. room_id: 'bedroom_3', stale: false, vetoed: false, seeds: ['seed-bedroom-3'], presence: { value: 'occupied', confidence: 0.79 }, posture: { value: 'lying', confidence: 0.74 }, breathing_bpm: { value: jitter(18, 2), confidence: 0.69 }, heart_bpm: null, // null = not trained (§6 invariant 3) restlessness: { value: 0.46, confidence: 0.6 }, anomaly: { value: 0.22, confidence: 0.7, threshold: 0.8 }, }, { room_id: 'kitchen', stale: false, vetoed: true, seeds: ['seed-livingroom-a1', 'seed-hallway-c3'], presence: { value: 'occupied', confidence: 0.6 }, posture: { value: null, confidence: null }, // suppressed by veto — withheld, NOT zero (§4.5) breathing_bpm: { value: null, confidence: null }, heart_bpm: { value: null, confidence: null }, restlessness: { value: 0.4, confidence: 0.5 }, anomaly: { value: 0.91, confidence: 0.88, threshold: 0.8 }, }, { room_id: 'office', stale: false, vetoed: false, seeds: ['seed-bedroom-1'], presence: { value: 'absent', confidence: 0.95 }, posture: null, // null = not trained (§6 invariant 3) breathing_bpm: null, heart_bpm: null, restlessness: { value: 0.0, confidence: 0.9 }, anomaly: { value: 0.05, confidence: 0.9, threshold: 0.8 }, }, ]; } // ── Fleet map / federation (§4.3) ─────────────────────────────────── export function federation() { return { coordinator: 'seed-livingroom-a1', round: 47, k_healthy: 4, delta_status: 'exchanging', invariant: 'model deltas only — never raw CSI', krum: { f: 1, multi: true }, cadence_min: 30, mesh_links: [ { a: 'seed-livingroom-a1', b: 'seed-bedroom-1', health: 'green' }, { a: 'seed-bedroom-1', b: 'seed-bedroom-2', health: 'green' }, { a: 'seed-bedroom-2', b: 'seed-bedroom-3', health: 'amber' }, { a: 'seed-bedroom-1', b: 'seed-hallway-c3', health: 'red' }, ], fused_events: [{ kind: 'fall', seeds: ['seed-livingroom-a1', 'seed-hallway-c3'], n: 2 }, { kind: 'occupant-track', seeds: ['seed-bedroom-1', 'seed-bedroom-2', 'seed-livingroom-a1'], n: 3 }], }; } // ── Witness / audit (§4.9) ────────────────────────────────────────── export function witnessLog(page = 0, size = 12) { const total = 240; const items = Array.from({ length: size }, (_, i) => { const n = page * size + i; const seedTier = n % 2 === 0; return { entity_id: seedTier ? `rvf.store.write.${184210 - n}` : ['sensor.living_room_presence', 'binary_sensor.front_door', 'sensor.bedroom_breathing_rate'][n % 3], old_state: seedTier ? null : ['false', 'off', '14.5'][n % 3], new_state: seedTier ? `sha256:${(0x9a3f + n).toString(16)}…` : ['true', 'on', '15.1'][n % 3], ts: ago(n * 37), tier: seedTier ? 'seed-sha256' : 'homecore-ed25519', seed: ['seed-livingroom-a1', 'seed-bedroom-1', 'seed-bedroom-2', 'seed-bedroom-3'][n % 4], key_fp: ['a1b2c3d4', 'e5f6a7b8', 'c9d0e1f2', 'b3a4c5d6'][n % 4], }; }); return { items, page, size, total }; } export function privacyModes() { return [ { seed: 'seed-livingroom-a1', mode: 'full-publish' }, { seed: 'seed-bedroom-1', mode: 'audit-only' }, { seed: 'seed-bedroom-2', mode: 'audit-only' }, { seed: 'seed-bedroom-3', mode: 'audit-only' }, { seed: 'seed-hallway-c3', mode: 'audit-only' }, ]; } // ── Events / automations (§4.8) ───────────────────────────────────── export function recentEvents(n = 40) { const variants = ['StateChanged', 'EntityRegistered', 'ConfigReloaded']; const ents = ['sensor.living_room_presence', 'binary_sensor.front_door', 'light.kitchen_ceiling', 'sensor.bedroom_breathing_rate']; return Array.from({ length: n }, (_, i) => ({ type: variants[i % 3], entity_id: ents[i % ents.length], old_state: ['off', 'false', '14.5'][i % 3], new_state: ['on', 'true', '15.1'][i % 3], ts: ago(i * 11), user_id: i % 4 === 0 ? 'operator' : null, context: { id: 'ctx-' + (1000 + i), parent_id: i % 3 === 0 ? 'ctx-' + (999 + i) : null, grandparent_id: i % 6 === 0 ? 'ctx-' + (998 + i) : null }, source: ['seed-livingroom-a1', 'cog-ha-matter'][i % 2], })); } // ── Settings (§4.10) ──────────────────────────────────────────────── export function settings() { return { mqtt: { broker: 'mqtt://cognitum-v0:1883', user: 'homecore', mdns: '_ruview-ha._tcp', connected: true }, tokens: [ { name: 'ios-companion', last_used: ago(120), created: ago(8000000) }, { name: 'node-red', last_used: ago(60000), created: ago(20000000) }, ], ha_disco_entities: 21, esp32: [ { node_id: 'esp32-lr-01', ip: '192.168.1.31', port: 5566, firmware: '1.2.0', room: 'living_room', seed: 'seed-livingroom-a1' }, { node_id: 'esp32-br1-01', ip: '192.168.1.32', port: 5566, firmware: '1.2.0', room: 'bedroom_1', seed: 'seed-bedroom-1' }, { node_id: 'esp32-br2-01', ip: '192.168.1.33', port: 5566, firmware: '1.2.0', room: 'bedroom_2', seed: 'seed-bedroom-2' }, { node_id: 'esp32-br3-01', ip: '192.168.1.34', port: 5566, firmware: '1.2.0', room: 'bedroom_3', seed: 'seed-bedroom-3' }, ], }; }