nx_iot_smartconfig.nx source
↩ module page · 101 lines · 4522 B
1// nx_iot_smartconfig.nx -- SOVEREIGN ESP-Touch v1 (SmartConfig / EZ-mode) ENCODER. (R1b)
2//
3// Operator 2026-06-23: a superior sovereign Nishi IoT onboarder, hardware-rung-up. Tuya/ESP devices
4// pair via EZ mode = SmartConfig: the sender (on the home 2.4GHz Wi-Fi) BROADCASTS the SSID+password
5// encoded in UDP packet LENGTHS; the device in pairing mode SNIFFS + decodes. This organ produces that
6// length sequence -- a byte-exact port of Espressif's EsptouchGenerator/DatumCode/DataCode/GuideCode/
7// CRC8 (sovereignly fetched to knowledge/fetched/sc_java_*.raw; cited, not guessed). The broadcaster
8// (send one UDP packet of each length to a multicast group on the 2.4GHz) is the thin live shim --
9// runs on the GL.iNet router, which is already the 2.4GHz AP. NO app, NO Windows, NO SoftAP join.
10//
11// Spec: guide U8s = [515,514,513,512]; EXTRA_HEAD_LEN=5; EXTRA_LEN=40; CRC8 = Dallas/Maxim (reflected
12// poly 0x8C, init 0). Data layout (each datum byte carries its own index so order is free; we emit
13// contiguous index 0..totalLen+5, equivalent to the Java insertions):
14// 0:totalLen 1:pwdLen 2:ssidCRC 3:bssidCRC 4:totalXOR 5..8:ip 9..:pwd ..:ssid totalLen..:bssid
15// totalLen = 9 + pwdLen + ssidLen. Each datum byte (value@index) -> 3 U8 lengths:
16// [ (crcHi<<4|dataHi)+40 , 296+index , (crcLo<<4|dataLo)+40 ]
17// where dataHi/Lo = value nibbles, crc = CRC8(value,index), crcHi/Lo = crc nibbles.
18//
19// Pure caller-buffer (no syscalls) -> portable + gate-provable. NEVER-BRICK #26: emits Wi-Fi creds
20// (reversible) only; no firmware. license_tier: ORIGINAL
21
22// CRC8 Dallas/Maxim: one-byte update (reflected poly 0x8C)
23func nx_sc_crc8_upd(crc: i64, byte: i64) -> i64 {
24 var c: i64 = (crc ^ (byte & 0xff)) & 0xff
25 var k: i64 = 0
26 while k < 8 {
27 if (c & 1) == 1 { c = ((c >> 1) ^ 0x8C) & 0xff } else { c = (c >> 1) & 0xff }
28 k = k + 1
29 }
30 return c & 0xff
31}
32func nx_sc_crc8(buf: *u8, n: i64) -> i64 {
33 var crc: i64 = 0
34 var i: i64 = 0
35 while i < n { crc = nx_sc_crc8_upd(crc, buf[i] as i64); i = i + 1 }
36 return crc
37}
38
39// Emit the 3 U8 packet-lengths for one datum byte (value @ index) into out[off..]; return off+3.
40func nx_sc_emit_dc(out: *i64, off: i64, value: i64, index: i64) -> i64 {
41 let dataHi: i64 = (value >> 4) & 0xf
42 let dataLo: i64 = value & 0xf
43 var crc: i64 = nx_sc_crc8_upd(0, value)
44 crc = nx_sc_crc8_upd(crc, index)
45 let crcHi: i64 = (crc >> 4) & 0xf
46 let crcLo: i64 = crc & 0xf
47 out[off] = ((crcHi << 4) | dataHi) + 40
48 out[off + 1] = 296 + index
49 out[off + 2] = ((crcLo << 4) | dataLo) + 40
50 return off + 3
51}
52
53// Build the full ESP-Touch U8 length sequence (guide + datum) into out (caller *i64, cap entries).
54// bssid = 6 bytes, ip = 4 bytes. Returns the U8 count, or -1 on overflow.
55func nx_sc_encode(ssid: *u8, ssid_n: i64, bssid: *u8, pwd: *u8, pwd_n: i64,
56 ip: *u8, out: *i64, cap: i64) -> i64 {
57 if cap < 4 { return 0 - 1 }
58 out[0] = 515
59 out[1] = 514
60 out[2] = 513
61 out[3] = 512
62 var o: i64 = 4
63
64 let ssidCrc: i64 = nx_sc_crc8(ssid, ssid_n)
65 let bssidCrc: i64 = nx_sc_crc8(bssid, 6)
66 let totalLen: i64 = 9 + pwd_n + ssid_n
67
68 // totalXor = XOR(totalLen, pwdLen, ssidCrc, bssidCrc, ip[0..3], pwd[], ssid[]) (NOT bssid/xor)
69 var tx: i64 = 0
70 tx = tx ^ (totalLen & 0xff)
71 tx = tx ^ (pwd_n & 0xff)
72 tx = tx ^ ssidCrc
73 tx = tx ^ bssidCrc
74 var i: i64 = 0
75 while i < 4 { tx = tx ^ ((ip[i] as i64) & 0xff); i = i + 1 }
76 i = 0
77 while i < pwd_n { tx = tx ^ ((pwd[i] as i64) & 0xff); i = i + 1 }
78 i = 0
79 while i < ssid_n { tx = tx ^ ((ssid[i] as i64) & 0xff); i = i + 1 }
80 tx = tx & 0xff
81
82 // datum: contiguous index 0..totalLen+5 (each carries its index; order is free for the decoder)
83 let last: i64 = totalLen + 5
84 var idx: i64 = 0
85 while idx <= last {
86 if (o + 3) > cap { return 0 - 1 }
87 var v: i64 = 0
88 if idx == 0 { v = totalLen & 0xff }
89 if idx == 1 { v = pwd_n & 0xff }
90 if idx == 2 { v = ssidCrc }
91 if idx == 3 { v = bssidCrc }
92 if idx == 4 { v = tx }
93 if idx >= 5 { if idx <= 8 { v = (ip[idx - 5] as i64) & 0xff } }
94 if idx >= 9 { if idx < (9 + pwd_n) { v = (pwd[idx - 9] as i64) & 0xff } }
95 if idx >= (9 + pwd_n) { if idx < totalLen { v = (ssid[idx - 9 - pwd_n] as i64) & 0xff } }
96 if idx >= totalLen { v = (bssid[idx - totalLen] as i64) & 0xff }
97 o = nx_sc_emit_dc(out, o, v, idx)
98 idx = idx + 1
99 }
100 return o
101}