nx_electrical_test.nx source
↩ module page · 99 lines · 4391 B
1// nx_electrical_test.nx -- gate for the electrical-health kernel (#5).
2//
3// Proves the safety verdicts (ground-fault / overload / voltage sag+swell /
4// high-load), sovereign energy metering (10A x 120V x 1h = 1200 Wh), and the
5// liar-kill: load_permille tracks current (NOMINAL @ 500 vs OVERLOAD @ 1100 at
6// identical voltage).
7//
8// expect_exit: 0
9//
10// license_tier: ORIGINAL
11
12import "nx_syscalls_x86_64.nx"
13import "nx_electrical.nx"
14
15func main() -> i64 {
16 if nx_elec_verdict_is_valid(NX_ELEC_GROUND_FAULT) != 1 { return 1 }
17 if nx_elec_verdict_is_valid(NX_ELEC_N) != 0 { return 2 }
18 if nx_elec_verdict_is_valid(-1) != 0 { return 3 }
19
20 let cur: *i64 = sys_mmap(128) as *i64
21 let volt: *i64 = sys_mmap(128) as *i64
22 let out: *ElecEff = sys_mmap(128) as *ElecEff
23 let spec: *ElecSpec = sys_mmap(64) as *ElecSpec
24 spec.breaker_rating_ca = 2000 // 20A breaker
25 spec.high_load_permille = 800 // warn at 80% (16A)
26 spec.nominal_voltage_cv = 12000 // 120V
27 spec.voltage_band_permille = 50 // +/-5% -> 114..126V
28 spec.ground_fault_ma = 5 // GFCI 5mA
29 spec.idle_current_ca = 50 // 0.5A
30
31 // ===== NOMINAL + energy metering ================================
32 cur[0]=1000; cur[1]=1000; cur[2]=1000; cur[3]=1000
33 volt[0]=12000; volt[1]=12000; volt[2]=12000; volt[3]=12000
34 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
35 if out.verdict != NX_ELEC_NOMINAL { return 10 }
36 if out.load_permille != 500 { return 11 }
37 if out.mean_power_w != 1200 { return 12 }
38 if out.energy_wh != 1200 { return 13 } // 10A x 120V x 1h
39
40 // ===== HIGH_LOAD: 85% of rating ================================
41 cur[0]=1700; cur[1]=1700; cur[2]=1700; cur[3]=1700
42 volt[0]=12000; volt[1]=12000; volt[2]=12000; volt[3]=12000
43 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
44 if out.verdict != NX_ELEC_HIGH_LOAD { return 20 }
45
46 // ===== OVERLOAD: 110% of rating -> fire/trip ===================
47 cur[0]=2200; cur[1]=2200; cur[2]=2200; cur[3]=2200
48 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
49 if out.verdict != NX_ELEC_OVERLOAD { return 30 }
50
51 // ===== VOLTAGE_SAG: brownout (110V < 114V) =====================
52 cur[0]=1000; cur[1]=1000; cur[2]=1000; cur[3]=1000
53 volt[0]=11000; volt[1]=11000; volt[2]=11000; volt[3]=11000
54 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
55 if out.verdict != NX_ELEC_VOLTAGE_SAG { return 40 }
56
57 // ===== VOLTAGE_SWELL: overvoltage (130V > 126V) ================
58 volt[0]=13000; volt[1]=13000; volt[2]=13000; volt[3]=13000
59 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
60 if out.verdict != NX_ELEC_VOLTAGE_SWELL { return 50 }
61
62 // ===== GROUND_FAULT: leakage 8mA > 5mA (safety, checked first) ==
63 volt[0]=12000; volt[1]=12000; volt[2]=12000; volt[3]=12000
64 nx_elec_analyze(cur, volt, 4, 3600, 8, spec, out)
65 if out.verdict != NX_ELEC_GROUND_FAULT { return 60 }
66
67 // ===== IDLE: no load ============================================
68 cur[0]=20; cur[1]=20; cur[2]=20; cur[3]=20
69 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
70 if out.verdict != NX_ELEC_IDLE { return 70 }
71
72 // ===== INSUFFICIENT_DATA: empty window =========================
73 nx_elec_analyze(cur, volt, 0, 3600, 0, spec, out)
74 if out.verdict != NX_ELEC_INSUFFICIENT_DATA { return 80 }
75
76 // ===== BAD_ARG: negative leakage ===============================
77 cur[0]=1000; cur[1]=1000; cur[2]=1000; cur[3]=1000
78 nx_elec_analyze(cur, volt, 4, 3600, 0 - 1, spec, out)
79 if out.verdict != NX_ELEC_BAD_ARG { return 90 }
80
81 // ===== LIAR-KILL: load tracks current ==========================
82 cur[0]=1000; cur[1]=1000; cur[2]=1000; cur[3]=1000
83 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
84 if out.verdict != NX_ELEC_NOMINAL { return 92 }
85 let nom_load: i64 = out.load_permille
86 let nom_verdict: i64 = out.verdict
87 cur[0]=2200; cur[1]=2200; cur[2]=2200; cur[3]=2200
88 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
89 if out.verdict != NX_ELEC_OVERLOAD { return 93 }
90 if out.load_permille == nom_load { return 94 }
91 if out.verdict == nom_verdict { return 95 }
92
93 // ===== BAD_ARG: invalid rating =================================
94 spec.breaker_rating_ca = 0
95 nx_elec_analyze(cur, volt, 4, 3600, 0, spec, out)
96 if out.verdict != NX_ELEC_BAD_ARG { return 96 }
97
98 return 0
99}