diff --git a/index.html b/index.html index ee7d984..23333ab 100644 --- a/index.html +++ b/index.html @@ -354,6 +354,52 @@ +
+ +
+ Configure Wi-Fi (optional) +
+ +
+ +
+
SSID
+ +
+
+
PSK
+ +

{{ errors['psk'] }}

+
+
+
Channel
+ +
+
+
IP
+ +

{{ errors['ip'] }}

+
+
+
Netmask
+ +

{{ errors['netmask'] }}

+
+
+ + + +
+ +
+ +
@@ -942,6 +988,14 @@ ], }, + // Wi-Fi + wifiChannel: "", // means "don't change" + wifiSSID: "Reticulum_WiFi", + wifiPSK: "password", + wifiIP: "", + wifiNetmask: "", + + errors: {}, }; }, mounted() { @@ -1849,6 +1903,83 @@ reader.readAsBinaryString(blob); }); }, + // mode = 0: disable Wi-Fi + // mode = 1: enable Wi-Fi in station mode + // mode = 2: enable Wi-Fi in AP mode + async configureWifi(mode) { + // Check for validation errors + for (const key in this.errors) { + if (this.errors[key]!=="") { + return + } + } + + // ask for rnode + const rnode = await this.askForRNode(); + if(!rnode){ + return; + } + + // check if device has been provisioned + const rom = await rnode.getRomAsObject(); + const details = rom.parse(); + if(!details || !details.is_provisioned){ + alert("Eeprom is not provisioned. You must do this first!"); + await rnode.close(); + return; + } + + // todo check if firmware hashes match, as config will not save if device has invalid target hash, because radio must be able to init + + // configure + console.log("configuring Wi-Fi"); + if (this.wifiChannel !== "") { + await rnode.setChannel(this.wifiChannel); + } + await rnode.setSSID(this.wifiSSID); + await rnode.setPSK(this.wifiPSK); + await rnode.setIP(this.wifiIP); + await rnode.setNetmask(this.wifiNetmask); + await rnode.setWifiMode(mode); + console.log("configuring Wi-Fi: done"); + + // save config + console.log("saving config"); + await Utils.sleepMillis(500); + await rnode.saveConfig(); + console.log("saving config: done"); + + await rnode.close(); + alert("Wi-Fi has been " + (mode === 0 ? "disabled!" : "enabled!")); + }, + async disableWifi() { + await this.configureWifi(0); + }, + async enableWifiStation() { + await this.configureWifi(1); + }, + async enableWifiAP() { + await this.configureWifi(2); + }, + validateIP(value, name) { + // Regex for validating an IPv4 address (0.0.0.0 to 255.255.255.255) + const ipv4Pattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + + if (value === '') { + this.errors[name] = ''; + } else if (ipv4Pattern.test(value)) { + this.errors[name] = ''; + } else { + this.errors[name] = 'Invalid IPv4 address format'; + } + }, + validatePSK(value, name) { + if (value.length < 8) { + this.errors[name] = 'PSK length should be between 8 and 33'; + } else { + this.errors[name] = ''; + } + } }, computed: { recommendedFirmwareFilename() { diff --git a/js/rnode.js b/js/rnode.js index 120ca40..7c11bf1 100644 --- a/js/rnode.js +++ b/js/rnode.js @@ -63,6 +63,13 @@ class RNode { CMD_STAT_RSSI = 0x23; CMD_STAT_SNR = 0x24; + CMD_WIFI_MODE = 0x6A + CMD_WIFI_SSID = 0x6B + CMD_WIFI_PSK = 0x6C + CMD_WIFI_CHN = 0x6E + CMD_WIFI_IP = 0x84 + CMD_WIFI_NM = 0x85 + CMD_BOARD = 0x47; CMD_PLATFORM = 0x48; CMD_MCU = 0x49; @@ -766,6 +773,61 @@ class RNode { ]); } + async setChannel(channel) { + await this.sendKissCommand([ + this.CMD_WIFI_CHN, + channel + ]); + } + + async setSSID(ssid) { + // empty ssid is valid, and means "delete" + const encoder = new TextEncoder(); + let data = encoder.encode(ssid); + + await this.sendKissCommand([ + this.CMD_WIFI_SSID, + ...data, + 0x00 + ]); + } + + async setPSK(psk) { + // empty psk is valid, and means "delete" + const encoder = new TextEncoder(); + let data = encoder.encode(psk); + + await this.sendKissCommand([ + this.CMD_WIFI_PSK, + ...data, + 0x00 + ]); + } + + async setIP(ip) { + let data = ipStrToBytes(ip); + + await this.sendKissCommand([ + this.CMD_WIFI_IP, + ...data, + ]); + } + + async setNetmask(netmask) { + let data = ipStrToBytes(netmask); + + await this.sendKissCommand([ + this.CMD_WIFI_NM, + ...data, + ]); + } + + async setWifiMode(mode) { + await this.sendKissCommand([ + this.CMD_WIFI_MODE, + mode + ]); + } } class ROM { @@ -1018,3 +1080,17 @@ class ROM { } } + +// ipStrToBytes converts IPv4 address in string format to array of bytes +function ipStrToBytes(ip) { + if (ip.length === 0) { + // means "delete" + ip = "0.0.0.0" + } + let octets = ip.split(".") + let data = [] + for (const octet of octets) { + data.push(+octet) + } + return data; +}