From 98310465924a54e812124762fd9981e507f22f25 Mon Sep 17 00:00:00 2001 From: Tobias Hopp Date: Fri, 29 Mar 2024 03:45:47 +0100 Subject: [PATCH] fix wifi settings --- scripts/addWifi.sh | 8 ++- scripts/connectToWifi.sh | 83 ++------------------------ src/OSHandler.ts | 126 +++++++++++++++++++++++++++++---------- src/SmartMonopoly.ts | 16 +++-- src/web/WiFi.tsx | 16 +++-- 5 files changed, 128 insertions(+), 121 deletions(-) mode change 100644 => 100755 scripts/addWifi.sh mode change 100644 => 100755 scripts/connectToWifi.sh diff --git a/scripts/addWifi.sh b/scripts/addWifi.sh old mode 100644 new mode 100755 index ee9c33f..a79ab43 --- a/scripts/addWifi.sh +++ b/scripts/addWifi.sh @@ -31,15 +31,21 @@ update_config=1 fi # Validate arguments -if [ -z "$ssid" ] || [ -z "$psk" ]; then +if [ -z "$ssid" ]; then echo "invalid-args" exit 1 fi +key="WPA-PSK" +if [ -z "$psk" ]; then + key="NONE" +fi + echo " network={ ssid=\"$ssid\" psk=\"$psk\" + key_mgmt=\"$key\" } " | sudo tee -a "$file" >/dev/null diff --git a/scripts/connectToWifi.sh b/scripts/connectToWifi.sh old mode 100644 new mode 100755 index 5aa0203..bb5016f --- a/scripts/connectToWifi.sh +++ b/scripts/connectToWifi.sh @@ -3,92 +3,17 @@ iface=$(iw dev | awk '$1=="Interface"{print $2}' | grep '^wlan') file="/etc/wpa_supplicant/wpa_supplicant-monopoly.conf" -ssid="no_args_given" - -# Parse arguments -while getopts ":s:p:" opt; do - case ${opt} in - s ) - ssid="$OPTARG" - ;; - : ) - echo "Invalid option: $OPTARG" 1>&2 - exit 1 - ;; - esac -done -shift $((OPTIND -1)) - - - -# Remove all disabled -sudo sed -i '/disabled=1/d' "$file" - -# Temporary file to store modified content -temp_file=$(mktemp) - -# Use awk to add disabled=1 within each network block -awk ' -BEGIN { RS="\n\n"; FS="\n"; OFS="\n" } -{ - found=0 - for(i=1; i<=NF; i++) { - if ($i ~ /^network=/) { - for(j=i+1; j<=NF && $j !~ /^}/; j++) { - if ($j ~ /^disabled=1/) { - found=1 - break - } - } - if (!found) { - $i = $i "\n disabled=1" - } - } - } - print $0 "\n" -}' "$file" > "$temp_file" - -# Overwrite the original file with the modified content -sudo mv -f "$temp_file" "$file" - - -temp_file=$(mktemp) - -while IFS= read -r line -do - if [[ "$line" == *"$ssid"* ]]; then - echo $line $ssid - remove_line=1 - echo "remove_line=1" - fi - - if [[ "$remove_line" -eq 1 && "$line" == *"disabled=1"* ]]; then - echo "skipped disabled line" - continue - fi - - if [[ "$line" == *"}"* ]]; then - in_block=0 - remove_line=0 - fi - - echo "$line" >> "$temp_file" -done < "$file" - -# Overwrite the original file with the modified content -sudo mv -f "$temp_file" "$file" - -cat $file +sleep 5 +echo "!!ok" exit 0 - sudo ip addr flush dev $iface sudo killall wpa_supplicant sudo truncate -s 0 /tmp/wifi_connection_status.txt sudo wpa_supplicant -B -i $iface -f /tmp/wifi_connection_status.txt -c $file declare -i i=0 -declare -i timeout=5 +declare -i timeout=8 while [ $i -le $timeout ]; do if grep -iq 'CTRL-EVENT-CONNECTED' /tmp/wifi_connection_status.txt; then sudo dhclient wlan0 @@ -100,5 +25,5 @@ while [ $i -le $timeout ]; do (( i++ )) sleep 1 done - +echo "!!ok" exit 0 \ No newline at end of file diff --git a/src/OSHandler.ts b/src/OSHandler.ts index 5d9e78c..ce7e816 100644 --- a/src/OSHandler.ts +++ b/src/OSHandler.ts @@ -3,15 +3,22 @@ import {spawn, exec} from 'node:child_process'; import * as dns from "dns"; import * as process from "process"; import * as path from "path"; +import * as fs from "fs"; const wifiScan = require("node-wifi-scanner"); export default class OSHandler { + static scriptPath = path.resolve(process.cwd(), "scripts"); + + static async enableAllWifis() { + return this.overwriteWifis(await this.getKnownWifis()); + } + static getKnownWifis(): Promise { return new Promise((resolve, reject) => { exec("sudo touch /etc/wpa_supplicant/wpa_supplicant-monopoly.conf && sudo cat /etc/wpa_supplicant/wpa_supplicant-monopoly.conf", (err, stdout) => { - if(err) + if (err) return reject(err); let lines = stdout.split("\n"); @@ -20,25 +27,26 @@ export default class OSHandler { let inBlock = false; let currentNetwork: WiFiNetwork = {ssid: "", psk: "", isSecured: false}; - for(let line of lines) - { - if(line.includes("network={")) + for (let line of lines) { + if (line.includes("network={")) inBlock = true; - if(line.includes("}")) { + if (line.includes("}")) { inBlock = false; - currentNetwork.isSecured = !!currentNetwork.psk; - if(currentNetwork.ssid) - wifis.push(currentNetwork); + //currentNetwork.isSecured = !!currentNetwork.psk; + if (currentNetwork.ssid) + wifis.push({...currentNetwork}); currentNetwork.ssid = ""; currentNetwork.psk = ""; currentNetwork.isSecured = false; } - if(inBlock && line.includes("ssid")) - currentNetwork.ssid = line.substring(line.indexOf('"')+1, line.lastIndexOf('"')); - if(inBlock && line.includes("psk")) - currentNetwork.psk = line.substring(line.indexOf('"')+1, line.lastIndexOf('"')); + if (inBlock && line.includes("ssid")) + currentNetwork.ssid = line.substring(line.indexOf('"') + 1, line.lastIndexOf('"')); + if (inBlock && line.includes("psk")) + currentNetwork.psk = line.substring(line.indexOf('"') + 1, line.lastIndexOf('"')); + if (inBlock && line.includes("key_mgmt")) + currentNetwork.isSecured = line.includes("WPA-PSK"); } resolve(wifis); @@ -46,32 +54,91 @@ export default class OSHandler { }); } - static addWifi(wifi: string, passkey: string | null) { + /** + * Adds a new wifi to the known networks + * @param ssid + * @param passkey + */ + static addWifi(ssid: string, passkey: string) { + return new Promise(async (resolve, reject) => { + try { + let knownWifis = await this.getKnownWifis(); + let found = false; + for (let wifi of knownWifis) { + if (wifi.ssid == wifi.ssid) { + // We know this wifi! - Refresh it! + found = true; + wifi.psk = passkey; + wifi.isSecured = !!passkey; + } + } + if (!found) { + knownWifis.push({ssid: ssid, psk: passkey, isSecured: !!passkey}); + } + await this.overwriteWifis(knownWifis); + return resolve(); + } catch (e) { + return reject(e); + } + }); + } + + /** + * Overwrites the custom wpa_supplicant file + * @param wifis + * @param ssid + */ + static overwriteWifis(wifis: WiFiNetwork[], ssid = "") { return new Promise((resolve, reject) => { - let p = path.resolve(process.cwd(), "/scripts/addWifi.sh"); - exec(p + ` -s "${wifi}" -p "${passkey}"`, (err, stdout) => { - if(err) + let wifi_str = `ctrl_interface=/run/wpa_supplicant \nupdate_config=0\n\n`; + for (let wifi of wifis) { + wifi_str += "network={\n"; + wifi_str += ` ssid="${wifi.ssid}"\n` + wifi_str += ` key_mgmt="${wifi.isSecured ? "WPA-PSK" : "NONE"}"\n` + + if (ssid && ssid != wifi.ssid) + wifi_str += ` disabled=1\n` + if (wifi.psk) + wifi_str += ` psk="${wifi.psk}"\n` + wifi_str += `}\n\n` + } + fs.writeFileSync("/tmp/wpa_supplicant.conf", wifi_str); + exec("sudo mv -f /tmp/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-monopoly.conf", (err, stdout) => { + if (err) return reject(err); - if(stdout == "ok") - resolve(); - else - reject("no-return"); - }) - }); + resolve(); + }); + }) + } - static connectToWifi(ssid: string) - { + /** + * Connects to a specific wifi + * @param ssid + */ + static connectToWifi(ssid: string) { return new Promise((resolve, reject) => { - - let p = path.resolve(process.cwd(), "/scripts/connectToWifi.sh"); - exec(p + ``) + this.getKnownWifis().then((wifis) => { + this.overwriteWifis(wifis, ssid).then(() => { + let p = path.resolve(this.scriptPath, "connectToWifi.sh"); + exec(p, (error, stdout, stderr) => { + if (!error) + return resolve(stdout.includes("!!ok")); + reject(error); + }); + }).catch(reject); + }).catch(reject); }); } - static disableAllWifis() { + static removeWifi(ssid: string) { return new Promise((resolve, reject) => { - + this.getKnownWifis().then(wifis => { + wifis.filter((ele) => { + return ele.ssid != ssid; + }); + this.overwriteWifis(wifis).then(resolve).catch(reject); + }).catch(reject); }); } @@ -113,7 +180,6 @@ export default class OSHandler { return -1; }); - console.log(networks); networks = networks.filter((ele, index) => { // If empty ssid diff --git a/src/SmartMonopoly.ts b/src/SmartMonopoly.ts index b32f546..f458e55 100644 --- a/src/SmartMonopoly.ts +++ b/src/SmartMonopoly.ts @@ -12,7 +12,7 @@ const wifiScan = require("node-wifi-scanner"); export default class SmartMonopoly { static run() { this.setupIPCEvents(); - OSHandler.getKnownWifis().then(console.log); + OSHandler.enableAllWifis().then().catch(console.error); } static setupIPCEvents() { @@ -30,11 +30,15 @@ export default class SmartMonopoly { }); IPCHandler("WIFI_CONNECT", async (e, request, args) => { - let data = request.data as {wifi: string, password: string} - await OSHandler.addWifi(data.wifi, data.password); - - - return {status: false} + let data = request.data as {ssid: string, psk: string} + try { + await OSHandler.addWifi(data.ssid, data.psk); + let status = await OSHandler.connectToWifi(data.ssid); + return {status: status}; + } catch(e) + { + return {status: false} + } }); IPCHandler("WIFI_SCAN", async (e, request, args) => { diff --git a/src/web/WiFi.tsx b/src/web/WiFi.tsx index f67072b..7f63101 100644 --- a/src/web/WiFi.tsx +++ b/src/web/WiFi.tsx @@ -26,7 +26,8 @@ interface WiFiState { selectedSecured: boolean, foundWiFis: WiFiNetwork[], scanning: boolean, - status: status + status: status, + password: string, } type status = "NONE" | "SELECTION_FAILURE" | "CONNECTING" | "PASSWORD_NEEDED" | "FAILURE" | "CONNECTED" | 'SCAN_FAILURE'; @@ -41,6 +42,7 @@ export default class WiFi extends Component<{}, WiFiState> { foundWiFis: [], scanning: false, status: "NONE", + password: "", }; } @@ -100,7 +102,7 @@ export default class WiFi extends Component<{}, WiFiState> { ...prevState, status: "CONNECTING" })); - window.api.request('WIFI_CONNECT', {data: this.state.currentSelection}).then((answer: IPCAnswer) => { + window.api.request('WIFI_CONNECT', {data: {ssid: this.state.currentSelection, psk: this.state.password}}).then((answer: IPCAnswer) => { this.setState((prevState) => ({ ...prevState, status: answer.status ? "CONNECTED" : "FAILURE" @@ -149,9 +151,10 @@ export default class WiFi extends Component<{}, WiFiState> { + severity={this.state.status.includes("FAILURE") ? "error" : (this.state.status == "CONNECTED" ? "success" : "info")}> {this.state.status == "NONE" && "Bitte wählen Sie eins der folgenden Netzwerke aus"} {this.state.status == "CONNECTING" && "Verbinden..." } + {this.state.status == "CONNECTED" && "Verbunden!" } {this.state.status == "SCAN_FAILURE" && "Das Scannen ist fehlgeschlagen. - Möglicherweise fehlen Berechtigungen, um Netzwerke zu scannen, oder es befindet sich kein WLAN-Interface auf diesem Gerät." } {this.state.status == "FAILURE" && "Verbindungsfehler!" } {this.state.status == "SELECTION_FAILURE" && "Bitte zunächst ein Netzwerk auswählen!" } @@ -193,7 +196,10 @@ export default class WiFi extends Component<{}, WiFiState> { - + this.setState(prev => ({ + ...prev, + password: evt.target.value + }))} label="Passwort" disabled={this.state.scanning || !this.state.selectedSecured} variant="outlined" /> @@ -219,7 +225,7 @@ export default class WiFi extends Component<{}, WiFiState> { + color="secondary">Schließen