-
-
-
-
- Save/Update
-
-
-
- Apply Encryption File from Base Station
-
-
-
-
diff --git a/ui/general/spirilink.js b/ui/general/spirilink.js
index 96ff835..c4b1ee0 100644
--- a/ui/general/spirilink.js
+++ b/ui/general/spirilink.js
@@ -23,114 +23,143 @@ const mavlinkSysId = document.getElementById("mavlinkSysId");
const mavlinkCompId = document.getElementById("mavlinkCompId");
const mavlinkTcpPort = document.getElementById("mavlinkTcpPort");
+const output = document.getElementById("output");
+
+const wifiChannels = [
+ // 2.4 GHz Channels
+ ["1", "1 (2.412 GHz)"], ["2", "2 (2.417 GHz)"], ["3", "3 (2.422 GHz)"],
+ ["4", "4 (2.427 GHz)"], ["5", "5 (2.432 GHz)"], ["6", "6 (2.437 GHz)"],
+ ["7", "7 (2.442 GHz)"], ["8", "8 (2.447 GHz)"], ["9", "9 (2.452 GHz)"],
+ ["10", "10 (2.457 GHz)"], ["11", "11 (2.462 GHz)"], ["12", "12 (2.467 GHz)"],
+ ["13", "13 (2.472 GHz)"], ["14", "14 (2.484 GHz, Japan only)"],
+ // 5 GHz Channels
+ ["36", "36 (5.180 GHz)"], ["40", "40 (5.200 GHz)"], ["44", "44 (5.220 GHz)"],
+ ["48", "48 (5.240 GHz)"], ["52", "52 (5.260 GHz)"], ["56", "56 (5.280 GHz)"],
+ ["60", "60 (5.300 GHz)"], ["64", "64 (5.320 GHz)"], ["100", "100 (5.500 GHz)"],
+ ["104", "104 (5.520 GHz)"], ["108", "108 (5.540 GHz)"], ["112", "112 (5.560 GHz)"],
+ ["116", "116 (5.580 GHz)"], ["120", "120 (5.600 GHz)"], ["124", "124 (5.620 GHz)"],
+ ["128", "128 (5.640 GHz)"], ["132", "132 (5.660 GHz)"], ["136", "136 (5.680 GHz)"],
+ ["140", "140 (5.700 GHz)"], ["149", "149 (5.745 GHz)"], ["153", "153 (5.765 GHz)"],
+ ["157", "157 (5.785 GHz)"], ["161", "161 (5.805 GHz)"], ["165", "165 (5.825 GHz)"]
+]
+
+const wifiRegions = [
+ ["BO", "BO (Max TX)"],
+ ["US", "US (United States)"],
+ ["EU", "EU (Europe)"],
+ ["JP", "JP (Japan)"],
+ ["AU", "AU (Australia, Max TX)"],
+ ["CA", "CA (Canada)"],
+ ["CN", "CN (China)"],
+ ["IN", "IN (India)"],
+ ["ZA", "ZA (South Africa)"],
+ ["KR", "KR (South Korea)"]
+]
+
+const connectionTypes = [
+ ["listen", "Listen"],
+ ["connect", "Connect"]
+]
+
// Load initial settings
-document.onload = InitPage();
+document.onload = initPage();
// Save file button
-document.getElementById("save").addEventListener("click", SaveSettings);
+document.getElementById("save").addEventListener("click", saveSettings);
// Apply encryption file button
-document.getElementById("applyEncryptionFile").addEventListener("click", ApplyEncryptionFile);
+document.getElementById("applyEncryptionFile").addEventListener("click", applyEncryptionFile);
// Function to initialize the page
-function InitPage() {
- cockpit.script(scriptLocation + "cockpitScript.sh -v")
+function initPage() {
file_location.innerHTML = confLocation;
+ const inputs = document.querySelectorAll("input, select, textarea");
+ inputs.forEach(input => {
+ input.addEventListener("focus", clearResult);
+ });
+
cockpit.file(confLocation)
- .read()
- .then((content) => {
- console.log("Configuration file content:", content);
- SuccessReadFile(content);
- })
- .catch(error => {
- console.error("Failed to read configuration file:", error);
- FailureReadFile(error);
- });
+ .read().then((content) => successReadFile(content))
+ .catch(error => failureReadFile(error));
}
// Load configuration values from the configuration file
-function SuccessReadFile(content) {
+function successReadFile(content) {
try {
// WiFi Configuration
- wifiChannel.value = getValueByKey(content, "common", "wifi_channel");
- console.log("wifi_channel:", wifiChannel.value);
-
// Remove surrounding quotes from wifi_region value if present
- wifiRegion.value = getValueByKey(content, "common", "wifi_region").replace(/^['"]|['"]$/g, "");
- console.log("wifi_region:", wifiRegion.value);
-
- // Handle "None" value for wifi_txpower
+ const currentWifiChannel = getValueByKey(content, "common", "wifi_channel");
+ const currentWifiRegion = getValueByKey(content, "common", "wifi_region").replace(/^['"]|['"]$/g, "");
const txPowerValue = getValueByKey(content, "common", "wifi_txpower");
- wifiTxPower.value = txPowerValue === "None" ? "" : txPowerValue;
- console.log("wifi_txpower:", wifiTxPower.value);
-
- tempInterval.value = getValueByKey(content, "common", "temp_measurement_interval");
- console.log("temp_measurement_interval:", tempInterval.value);
-
- tempWarning.value = getValueByKey(content, "common", "temp_overheat_warning");
- console.log("temp_overheat_warning:", tempWarning.value);
- // Drone MAVLink Configuration
- droneMavlinkFwmark.value = getValueByKey(content, "drone_mavlink", "fwmark");
- console.log("drone_mavlink_fwmark:", droneMavlinkFwmark.value);
+ addDropDown(wifiChannel, wifiChannels, currentWifiChannel);
+ addDropDown(wifiRegion, wifiRegions, currentWifiRegion);
+ wifiTxPower.value = txPowerValue === "None" ? "" : txPowerValue; // None should result in an empty string
- const droneMavlinkPeer = getValueByKey(content, "drone_mavlink", "peer");
- console.log("drone_mavlink_peer:", droneMavlinkPeer);
- if (droneMavlinkPeer) {
- parsePeer(droneMavlinkPeer, droneMavlinkType, droneMavlinkIP, droneMavlinkPort);
- }
+ // Temperature Configuration
+ tempInterval.value = getValueByKey(content, "common", "temp_measurement_interval");
+ tempWarning.value = getValueByKey(content, "common", "temp_overheat_warning");
// Drone Video Configuration
droneVideoFwmark.value = getValueByKey(content, "drone_video", "fwmark");
- console.log("drone_video_fwmark:", droneVideoFwmark.value);
-
const droneVideoPeer = getValueByKey(content, "drone_video", "peer");
- console.log("drone_video_peer:", droneVideoPeer);
if (droneVideoPeer) {
- parsePeer(droneVideoPeer, droneVideoType, droneVideoIP, droneVideoPort);
+ const peer = parsePeer(droneVideoPeer);
+ addDropDown(droneVideoType, connectionTypes, droneVideoType.value);
+ droneVideoIP.value = peer.ip;
+ droneVideoPort.value = peer.port;
}
- // MAVLink Configuration
- injectRssi.checked = getValueByKey(content, "mavlink", "inject_rssi") === "True";
- console.log("inject_rssi:", injectRssi.checked);
-
- mavlinkSysId.value = getValueByKey(content, "mavlink", "mavlink_sys_id");
- console.log("mavlink_sys_id:", mavlinkSysId.value);
-
- mavlinkCompId.value = getValueByKey(content, "mavlink", "mavlink_comp_id");
- console.log("mavlink_comp_id:", mavlinkCompId.value);
+ // Drone MAVLink Configuration
+ droneMavlinkFwmark.value = getValueByKey(content, "drone_mavlink", "fwmark");
+ const droneMavlinkPeer = getValueByKey(content, "drone_mavlink", "peer");
+ if (droneMavlinkPeer) {
+ const peer = parsePeer(droneMavlinkPeer);
+ addDropDown(droneMavlinkType, connectionTypes, peer.type);
+ droneMavlinkIP.value = peer.ip;
+ droneMavlinkPort.value = peer.port;
+ }
+ // MAVLink Settings
+ injectRssi.checked = getValueByKey(content, "mavlink", "inject_rssi") === "True";
+ mavlinkSysId.value = getValueByKey(content, "mavlink", "mavlink_sys_id");
+ mavlinkCompId.value = getValueByKey(content, "mavlink", "mavlink_comp_id");
const tcpPortValue = getValueByKey(content, "mavlink", "mavlink_tcp_port");
mavlinkTcpPort.value = tcpPortValue === "None" ? "" : tcpPortValue;
- console.log("mavlink_tcp_port:", mavlinkTcpPort.value);
+
} catch (e) {
- console.error("Error parsing configuration file:", e);
- FailureReadFile(e);
+ failureReadFile(e);
}
}
+function failureReadFile(error) {
+ // Display error message
+ console.log("Error : " + error.message);
+ displayFail(error.message)
+}
+
// Save configuration values to the configuration file
-function SaveSettings() {
+function saveSettings() {
try {
cockpit.file(confLocation)
.read()
.then((content) => {
- // WiFi Configuration
+ // WiFi & Temperature Configuration
content = setValueByKey(content, "[common]", "wifi_channel", wifiChannel.value);
content = setValueByKey(content, "[common]", "wifi_region", wifiRegion.value);
content = setValueByKey(content, "[common]", "wifi_txpower", wifiTxPower.value === "" ? "None" : wifiTxPower.value);
content = setValueByKey(content, "[common]", "temp_measurement_interval", tempInterval.value);
content = setValueByKey(content, "[common]", "temp_overheat_warning", tempWarning.value);
+
+ // Drone Video Configuration
+ const droneVideoPeer = `${droneVideoType.value}://${droneVideoIP.value}:${droneVideoPort.value}`;
+ content = setValueByKey(content, "[drone_video]", "fwmark", droneVideoFwmark.value);
+ content = setValueByKey(content, "[drone_video]", "peer", droneVideoPeer);
// Drone MAVLink Configuration
const droneMavlinkPeer = `${droneMavlinkType.value}://${droneMavlinkIP.value}:${droneMavlinkPort.value}`;
content = setValueByKey(content, "[drone_mavlink]", "fwmark", droneMavlinkFwmark.value);
content = setValueByKey(content, "[drone_mavlink]", "peer", droneMavlinkPeer);
- // Drone Video Configuration
- const droneVideoPeer = `${droneVideoType.value}://${droneVideoIP.value}:${droneVideoPort.value}`;
- content = setValueByKey(content, "[drone_video]", "fwmark", droneVideoFwmark.value);
- content = setValueByKey(content, "[drone_video]", "peer", droneVideoPeer);
-
// MAVLink Configuration
content = setValueByKey(content, "[mavlink]", "inject_rssi", injectRssi.checked ? "True" : "False");
content = setValueByKey(content, "[mavlink]", "mavlink_sys_id", mavlinkSysId.value);
@@ -139,27 +168,24 @@ function SaveSettings() {
cockpit.file(confLocation, { superuser: "try" }).replace(content)
.then(() => {
- console.log("Configuration saved successfully.");
- RestartWifibroadcastService();
- Success();
+ restartWifibroadcastService();
+ displaySuccess("Configuration saved successfully.");
})
.catch((error) => {
- console.error("Failed to save configuration:", error);
- Fail(error);
+ displayFail("Failed to save configuration: " + error.message);
});
})
.catch(error => {
- console.error("Failed to read configuration file:", error);
- FailureReadFile(error);
+ displayFail("Failed to save configuration: " + error.message);
});
} catch (e) {
console.error("Error during save operation:", e);
- FailureReadFile(e);
+ failureReadFile(e);
}
}
// Apply encryption file from base station
-function ApplyEncryptionFile() {
+function applyEncryptionFile() {
const command = `
/usr/bin/sshpass -p 'spirifriend' scp -o StrictHostKeyChecking=no spiri@spiri-base.local:/home/spiri/drone.key /tmp/drone.key &&
/usr/bin/sudo /bin/mv /tmp/drone.key ${encryptionFileLocation} &&
@@ -168,56 +194,82 @@ function ApplyEncryptionFile() {
cockpit.spawn(["bash", "-c", command], { superuser: "require" })
.then(() => {
- console.log("Encryption key applied and wifibroadcast service restarted.");
- Success();
+ displaySuccess("Encryption key applied and wifibroadcast service restarted.");
})
.catch((error) => {
console.error("Failed to apply encryption key or restart service:", error);
- Fail(error);
+ displayFail("Failed to apply encryption key or restart service: " + error);
});
}
-
// Restart wifibroadcast service
-function RestartWifibroadcastService() {
+function restartWifibroadcastService() {
cockpit.spawn(["systemctl", "restart", "wifibroadcast@drone"], { superuser: "require" })
.then(() => {
- console.log("wifibroadcast@drone service restarted.");
+ displaySuccess("wifibroadcast@drone service restarted.");
})
.catch((error) => {
console.error("Failed to restart wifibroadcast@drone service:", error);
+ displayFail("Failed to restart wifibroadcast@drone service: " + error);
});
}
-// Success handler
-function Success() {
+// Display Success result
+function displaySuccess(msg) {
result.style.color = "green";
- result.innerHTML = "Success, settings saved.";
- setTimeout(() => result.innerHTML = "", 5000);
+ if (result.innerHTML === "")
+ result.innerHTML = msg;
+ else
+ result.innerHTML += "
" + msg;
+
+ // setTimeout(() => result.innerHTML = "", 5000);
}
-// Failure handler
-function Fail(error) {
+// Display failure message
+function displayFail(error) {
result.style.color = "red";
- result.innerHTML = error.message;
+ result.innerHTML = "Error : " + error;
+}
+
+// Clear the result message
+function clearResult() {
+ result.innerHTML = "";
+}
+
+function addDropDown(box, pairs, defaultValue) {
+ try {
+ for(let i = 0; i < pairs.length; i++){
+ if (pairs[i].length == 0 || pairs[i][0] === "" || pairs[i][1] === "") continue;
+ const option = document.createElement("option");
+ option.value = pairs[i][0];
+ option.text = pairs[i][1];
+ box.add(option);
+ if (defaultValue === option.value) {
+ console.log("found")
+ box.value = option.value;
+ }
+ }
+ }
+ catch(e) {
+ displayFail(e)
+ }
}
// Parse Peer configuration (type, IP, port)
-function parsePeer(peer, typeElement, ipElement, portElement) {
- if (!peer) {
- console.warn("Peer value is empty or undefined.");
- return; // Skip if peer is empty
- }
+function parsePeer(peerString) {
+ const peer = { type: "", ip: "", port: "" };
+
+ if (!peerString) return peer;
const regex = /(listen|connect):\/\/([\d.]+):(\d+)/;
- const match = peer.match(regex);
+ const match = peerString.match(regex);
if (match) {
- typeElement.value = match[1];
- ipElement.value = match[2];
- portElement.value = match[3];
- } else {
- console.error("Failed to parse peer:", peer);
+ peer.type = match[1];
+ peer.ip = match[2];
+ peer.port = match[3];
}
+
+ return peer;
}
// Get value by key from configuration content
@@ -225,11 +277,9 @@ function getValueByKey(content, section, key) {
const sectionRegex = new RegExp(`\\[${section}\\][\\s\\S]*?^${key}\\s*=\\s*(.*)`, "m");
const match = content.match(sectionRegex);
if (match) {
- let value = match[1].trim();
- console.log(`Found key [${key}] in section [${section}]:`, value);
+ const value = match[1].trim();
return value;
} else {
- console.warn(`Key [${key}] not found in section [${section}]`);
return "";
}
}