code wiki / (root) / nx_iot_smartconfig.nx

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}