fixed apn and improved javascripts
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
<script src="/js/band-locking/fetch-bands.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
@@ -140,7 +141,7 @@
|
||||
<div class="column-margin">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell">
|
||||
<div class="cell is-col-span-2 is-col-span-1-mobile">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">4G LTE Band Locking</div>
|
||||
@@ -175,7 +176,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<!-- <div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">5G-NR SA Band Locking</div>
|
||||
@@ -183,7 +184,6 @@
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-5-cols has-3-cols-mobile">
|
||||
<div class="grid" id="sa_bands">
|
||||
<!-- SA bands will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -208,7 +208,7 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
@@ -335,7 +335,7 @@
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
<!-- <script>
|
||||
// Function to fetch current active bands and display them in the footer
|
||||
async function fetchCurrentBands() {
|
||||
try {
|
||||
@@ -385,13 +385,13 @@
|
||||
|
||||
const lteBandsMatch = data.output.match(/"lte_band",([0-9:]+)/);
|
||||
const nsaBandsMatch = data.output.match(/"nsa_nr5g_band",([0-9:]+)/);
|
||||
const saBandsMatch = data.output.match(/"nr5g_band",([0-9:]+)/);
|
||||
// const saBandsMatch = data.output.match(/"nr5g_band",([0-9:]+)/);
|
||||
const saDcBandsMatch = data.output.match(
|
||||
/"nrdc_nr5g_band",([0-9:]+)/
|
||||
);
|
||||
|
||||
if (lteBandsMatch) populateBands(lteBandsMatch[1], "#lte_bands");
|
||||
if (saBandsMatch) populateBands(saBandsMatch[1], "#sa_bands");
|
||||
// if (saBandsMatch) populateBands(saBandsMatch[1], "#sa_bands");
|
||||
if (nsaBandsMatch) populateBands(nsaBandsMatch[1], "#nsa_bands");
|
||||
if (saDcBandsMatch) populateBands(saDcBandsMatch[1], "#sanrdc_bands");
|
||||
|
||||
@@ -429,9 +429,9 @@
|
||||
const activeNsaBands = data.output
|
||||
.match(/"nsa_nr5g_band",([0-9:]+)/)[1]
|
||||
.split(":");
|
||||
const activeSaBands = data.output
|
||||
.match(/"nr5g_band",([0-9:]+)/)[1]
|
||||
.split(":");
|
||||
// const activeSaBands = data.output
|
||||
// .match(/"nr5g_band",([0-9:]+)/)[1]
|
||||
// .split(":");
|
||||
// get the the second to the last line of the output and use it for active sa-dc bands
|
||||
const activeSaDcBandsLine = data.output
|
||||
.split("\n")[6]
|
||||
@@ -441,7 +441,7 @@
|
||||
// // Mark checkboxes as checked for active bands
|
||||
markActiveBands(activeLteBands, "#lte_bands");
|
||||
markActiveBands(activeNsaBands, "#nsa_bands");
|
||||
markActiveBands(activeSaBands, "#sa_bands");
|
||||
// markActiveBands(activeSaBands, "#sa_bands");
|
||||
markActiveBands(activeSaDcBandsLine, "#sanrdc_bands");
|
||||
|
||||
// Fetch current active bands and display them in the footer
|
||||
@@ -505,12 +505,12 @@
|
||||
uncheckAll("#nsa_bands");
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("uncheckSa")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
uncheckAll("#sa_bands");
|
||||
});
|
||||
// document
|
||||
// .getElementById("uncheckSa")
|
||||
// .addEventListener("click", function (event) {
|
||||
// event.preventDefault();
|
||||
// uncheckAll("#sa_bands");
|
||||
// });
|
||||
|
||||
document
|
||||
.getElementById("uncheckSaDc")
|
||||
@@ -675,6 +675,6 @@
|
||||
|
||||
// Initial call to fetch supported bands on page load
|
||||
window.onload = fetchSupportedBands;
|
||||
</script>
|
||||
</script> -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -29,7 +29,7 @@ escape_json() {
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in "AT+QUIMSLOT?" "AT+CNUM" "AT+COPS?" "AT+CIMI" "AT+ICCID" "AT+CGSN" "AT+CPIN?" "AT+CGCONTRDP" "AT+CREG?" "AT+CFUN?" "AT+QENG=\"servingcell\"" "AT+QTEMP" "AT+CGCONTRDP" "AT+QCAINFO" "AT+QRSRP" 'AT+QMAP="WWAN"'; do
|
||||
for COMMAND in "AT+QUIMSLOT?" "AT+CNUM" "AT+COPS?" "AT+CIMI" "AT+ICCID" "AT+CGSN" "AT+CPIN?" "AT+CGCONTRDP=1" "AT+CREG?" "AT+CFUN?" "AT+QENG=\"servingcell\"" "AT+QTEMP" "AT+CGCONTRDP" "AT+QCAINFO" "AT+QRSRP" 'AT+QMAP="WWAN"'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
|
||||
@@ -1,461 +1,299 @@
|
||||
async function fetchCurrentSettings() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/advanced_settings.sh");
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
// api.js - API related functions
|
||||
const api = {
|
||||
async fetch(endpoint, options = {}) {
|
||||
try {
|
||||
const response = await fetch(endpoint, options);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`API Error (${endpoint}):`, error);
|
||||
return null;
|
||||
}
|
||||
const data = await response.json();
|
||||
},
|
||||
|
||||
async fetchCurrentSettings() {
|
||||
const data = await this.fetch("/cgi-bin/advanced_settings.sh");
|
||||
console.log("Current settings:", data);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching current settings:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async function fetchConnectedDevices() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/fetch_macs.sh");
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log("Connected devices:", data);
|
||||
async fetchConnectedDevices() {
|
||||
const data = await this.fetch("/cgi-bin/fetch_macs.sh");
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching connected devices:", error);
|
||||
return null;
|
||||
},
|
||||
|
||||
async sendATCommand(command) {
|
||||
return await this.fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command)
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function populateConnectedDevices(devices) {
|
||||
const selectElement = document.getElementById("connected-devices");
|
||||
if (!selectElement) {
|
||||
console.error("Connected devices select element not found");
|
||||
return;
|
||||
}
|
||||
// uiManager.js - UI related functions
|
||||
const uiManager = {
|
||||
elements: {
|
||||
ipPassthrough: () => document.getElementById("ip-passthrough-mode"),
|
||||
dnsProxy: () => document.getElementById("dns-proxy-mode"),
|
||||
usbModem: () => document.getElementById("usb-modem-protocol"),
|
||||
connectedDevices: () => document.getElementById("connected-devices"),
|
||||
loadingContent: () => document.getElementById("loading-content"),
|
||||
modalButtons: () => document.getElementById("modal-buttons"),
|
||||
countdown: () => document.getElementById("countdown"),
|
||||
rebootModal: () => document.getElementById("reboot-modal"),
|
||||
advancedSettingsIcons: () => document.querySelectorAll(".advanced-settings i")
|
||||
},
|
||||
|
||||
// Clear existing options except the first one
|
||||
while (selectElement.options.length > 1) {
|
||||
selectElement.remove(1);
|
||||
}
|
||||
showLoadingSpinners() {
|
||||
this.elements.advancedSettingsIcons().forEach(icon => {
|
||||
icon.classList.add("fa-spinner", "fa-spin");
|
||||
});
|
||||
},
|
||||
|
||||
// Add new options
|
||||
devices.forEach((device) => {
|
||||
const option = document.createElement("option");
|
||||
option.value = device.mac;
|
||||
option.textContent = `${device.hostname} - ${device.mac}`;
|
||||
selectElement.appendChild(option);
|
||||
});
|
||||
}
|
||||
hideLoadingSpinners() {
|
||||
this.elements.advancedSettingsIcons().forEach(icon => {
|
||||
icon.classList.remove("fa-spinner", "fa-spin");
|
||||
});
|
||||
},
|
||||
|
||||
function updatePassthroughModeState(isEnabled) {
|
||||
const ipPassthroughSelect = document.getElementById("ip-passthrough-mode");
|
||||
if (!ipPassthroughSelect) return;
|
||||
updatePassthroughModeState(isEnabled) {
|
||||
const select = this.elements.ipPassthrough();
|
||||
if (!select) return;
|
||||
|
||||
if (isEnabled) {
|
||||
ipPassthroughSelect.removeAttribute("disabled");
|
||||
ipPassthroughSelect.classList.remove("is-warning");
|
||||
const helpText = ipPassthroughSelect.parentElement.querySelector(".help");
|
||||
if (helpText) {
|
||||
helpText.textContent = "Select a passthrough mode to apply.";
|
||||
helpText.classList.remove("is-warning");
|
||||
helpText.classList.add("is-info");
|
||||
}
|
||||
} else {
|
||||
ipPassthroughSelect.setAttribute("disabled", "disabled");
|
||||
ipPassthroughSelect.classList.add("is-warning");
|
||||
ipPassthroughSelect.value = "Select IP Passthrough Mode";
|
||||
const helpText = ipPassthroughSelect.parentElement.querySelector(".help");
|
||||
if (helpText) {
|
||||
helpText.textContent = "Please select a device first.";
|
||||
helpText.classList.remove("is-info");
|
||||
helpText.classList.add("is-warning");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateUIElements(data) {
|
||||
// Get all required DOM elements
|
||||
const elements = {
|
||||
ipPassthrough: document.getElementById("ip-passthrough-mode"),
|
||||
dnsProxy: document.getElementById("dns-proxy-mode"),
|
||||
usbModem: document.getElementById("usb-modem-protocol"),
|
||||
};
|
||||
|
||||
// Check if all elements exist
|
||||
const missingElements = Object.entries(elements)
|
||||
.filter(([key, element]) => !element)
|
||||
.map(([key]) => key);
|
||||
|
||||
if (missingElements.length > 0) {
|
||||
console.error("Missing DOM elements:", missingElements);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Initially disable IP Passthrough mode
|
||||
updatePassthroughModeState(false);
|
||||
|
||||
// Passthrough Mode (will be disabled until device is selected)
|
||||
const mpdnRuleLine = data[0].response.split("\n")[1];
|
||||
if (mpdnRuleLine) {
|
||||
const mpdnRule = mpdnRuleLine.split(":")[1].trim();
|
||||
switch (mpdnRule) {
|
||||
case '"MPDN_rule",0,0,0,0,0':
|
||||
elements.ipPassthrough.value = "Disabled";
|
||||
break;
|
||||
case '"MPDN_rule",0,1,0,1,1':
|
||||
elements.ipPassthrough.value = "ETH Only";
|
||||
break;
|
||||
case '"MPDN_rule",0,1,0,3,1':
|
||||
elements.ipPassthrough.value = "USB Only";
|
||||
break;
|
||||
default:
|
||||
elements.ipPassthrough.value = "Select IP Passthrough Mode";
|
||||
break;
|
||||
const helpText = select.parentElement.querySelector(".help");
|
||||
|
||||
if (isEnabled) {
|
||||
select.removeAttribute("disabled");
|
||||
select.classList.remove("is-warning");
|
||||
if (helpText) {
|
||||
helpText.textContent = "Select a passthrough mode to apply.";
|
||||
helpText.classList.remove("is-warning");
|
||||
helpText.classList.add("is-info");
|
||||
}
|
||||
} else {
|
||||
select.setAttribute("disabled", "disabled");
|
||||
select.classList.add("is-warning");
|
||||
select.value = "Select IP Passthrough Mode";
|
||||
if (helpText) {
|
||||
helpText.textContent = "Please select a device first.";
|
||||
helpText.classList.remove("is-info");
|
||||
helpText.classList.add("is-warning");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// DNS Proxy
|
||||
const dnsProxyLine = data[1].response
|
||||
.split("\n")[1]
|
||||
.split(":")[1]
|
||||
.split(",")[1]
|
||||
.trim();
|
||||
if (dnsProxyLine) {
|
||||
elements.dnsProxy.value =
|
||||
dnsProxyLine === '"disable"' ? "Disabled" : "Enabled";
|
||||
} else {
|
||||
elements.dnsProxy.value = "Select Onboard DNS Proxy";
|
||||
populateConnectedDevices(devices) {
|
||||
const select = this.elements.connectedDevices();
|
||||
if (!select) {
|
||||
console.error("Connected devices select element not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// USB Modem Protocol
|
||||
const usbModemProtocolLine = data[2].response
|
||||
.split("\n")[1]
|
||||
.split(":")[1]
|
||||
.split(",")[1]
|
||||
.trim();
|
||||
switch (usbModemProtocolLine) {
|
||||
case "0":
|
||||
elements.usbModem.value = "RMNET";
|
||||
break;
|
||||
case "1":
|
||||
elements.usbModem.value = "ECM (Recommended)";
|
||||
break;
|
||||
case "2":
|
||||
elements.usbModem.value = "MBIM";
|
||||
break;
|
||||
case "3":
|
||||
elements.usbModem.value = "RNDIS";
|
||||
break;
|
||||
default:
|
||||
elements.usbModem.value = "Select USB Modem Protocol";
|
||||
break;
|
||||
// Clear existing options except the first one
|
||||
while (select.options.length > 1) {
|
||||
select.remove(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error updating UI elements:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to send an AT command based on the DNS proxy mode
|
||||
async function sendDnsProxyCommand(command) {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
// Add new options
|
||||
devices.forEach(device => {
|
||||
const option = document.createElement("option");
|
||||
option.value = device.mac;
|
||||
option.textContent = `${device.hostname} - ${device.mac}`;
|
||||
select.appendChild(option);
|
||||
});
|
||||
},
|
||||
|
||||
const data = await response.json();
|
||||
console.log("DNS Proxy AT command executed:", data.output);
|
||||
} catch (error) {
|
||||
console.error("Error sending DNS Proxy AT command:", error);
|
||||
showModal() {
|
||||
const modal = this.elements.rebootModal();
|
||||
if (modal) {
|
||||
modal.classList.add("is-active");
|
||||
}
|
||||
},
|
||||
|
||||
showLoadingContent() {
|
||||
this.elements.loadingContent().style.display = "flex";
|
||||
this.elements.modalButtons().style.display = "none";
|
||||
this.showModal();
|
||||
},
|
||||
|
||||
startCountdown(duration) {
|
||||
const countdownElement = this.elements.countdown();
|
||||
let countdown = duration;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
countdown--;
|
||||
countdownElement.textContent = countdown;
|
||||
|
||||
if (countdown <= 0) {
|
||||
clearInterval(interval);
|
||||
location.reload();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Function to handle DNS Proxy changes
|
||||
function handleDnsProxyChange() {
|
||||
const dnsProxySelect = document.getElementById("dns-proxy-mode");
|
||||
const currentDnsProxyMode = dnsProxySelect.getAttribute("data-current-mode"); // Store current mode as a data attribute
|
||||
// settingsManager.js - Settings management
|
||||
const settingsManager = {
|
||||
async updateSettings(data) {
|
||||
const elements = {
|
||||
ipPassthrough: uiManager.elements.ipPassthrough(),
|
||||
dnsProxy: uiManager.elements.dnsProxy(),
|
||||
usbModem: uiManager.elements.usbModem()
|
||||
};
|
||||
|
||||
dnsProxySelect.addEventListener("change", function (e) {
|
||||
// Validate required elements
|
||||
const missingElements = Object.entries(elements)
|
||||
.filter(([, element]) => !element)
|
||||
.map(([key]) => key);
|
||||
|
||||
if (missingElements.length > 0) {
|
||||
console.error("Missing DOM elements:", missingElements);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
uiManager.updatePassthroughModeState(false);
|
||||
|
||||
// Update IP Passthrough Mode
|
||||
const mpdnRuleLine = data[0].response.split("\n")[1];
|
||||
if (mpdnRuleLine) {
|
||||
const mpdnRule = mpdnRuleLine.split(":")[1].trim();
|
||||
elements.ipPassthrough.value = this.getPassthroughModeValue(mpdnRule);
|
||||
}
|
||||
|
||||
// Update DNS Proxy
|
||||
const dnsProxyLine = data[1].response.split("\n")[1].split(":")[1].split(",")[1].trim();
|
||||
elements.dnsProxy.value = dnsProxyLine === '"disable"' ? "Disabled" : "Enabled";
|
||||
|
||||
// Update USB Modem Protocol
|
||||
const usbModemProtocolLine = data[2].response.split("\n")[1].split(":")[1].split(",")[1].trim();
|
||||
elements.usbModem.value = this.getUsbModemProtocolValue(usbModemProtocolLine);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error updating settings:", error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
getPassthroughModeValue(mpdnRule) {
|
||||
const modes = {
|
||||
'"MPDN_rule",0,0,0,0,0': "Disabled",
|
||||
'"MPDN_rule",0,1,0,1,1': "ETH Only",
|
||||
'"MPDN_rule",0,1,0,3,1': "USB Only"
|
||||
};
|
||||
return modes[mpdnRule] || "Select IP Passthrough Mode";
|
||||
},
|
||||
|
||||
getUsbModemProtocolValue(protocol) {
|
||||
const protocols = {
|
||||
"0": "RMNET",
|
||||
"1": "ECM (Recommended)",
|
||||
"2": "MBIM",
|
||||
"3": "RNDIS"
|
||||
};
|
||||
return protocols[protocol] || "Select USB Modem Protocol";
|
||||
}
|
||||
};
|
||||
|
||||
// eventHandlers.js - Event handling
|
||||
const eventHandlers = {
|
||||
async handleDnsProxyChange(e) {
|
||||
const selectedMode = e.target.value;
|
||||
const currentMode = e.target.getAttribute("data-current-mode");
|
||||
|
||||
// Send AT command only if the selected mode differs from the current one
|
||||
if (selectedMode !== currentDnsProxyMode) {
|
||||
if (selectedMode === "Enabled") {
|
||||
sendDnsProxyCommand('AT+QMAP="DHCPV4DNS","enable"');
|
||||
} else if (selectedMode === "Disabled") {
|
||||
sendDnsProxyCommand('AT+QMAP="DHCPV4DNS","disable"');
|
||||
}
|
||||
} else {
|
||||
console.log("No changes made to DNS Proxy mode");
|
||||
if (selectedMode !== currentMode) {
|
||||
const command = selectedMode === "Enabled"
|
||||
? 'AT+QMAP="DHCPV4DNS","enable"'
|
||||
: 'AT+QMAP="DHCPV4DNS","disable"';
|
||||
await api.sendATCommand(command);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Function to send an AT command based on the IP Passthrough mode
|
||||
async function sendIpPassthroughCommand(command) {
|
||||
if (command) {
|
||||
showLoadingContent(); // Show loading content and hide the buttons
|
||||
startCountdown(80); // Start the countdown for 5 seconds
|
||||
}
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log("IP Passthrough AT command executed:", data.output);
|
||||
} catch (error) {
|
||||
console.error("Error sending IP Passthrough AT command:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle IP Passthrough mode changes
|
||||
function handleIpPassthroughChange() {
|
||||
// track if the device is selected by listening to the connected devices dropdown change event
|
||||
const connectedDevicesSelect = document.getElementById("connected-devices");
|
||||
if (connectedDevicesSelect) {
|
||||
connectedDevicesSelect.addEventListener("change", function (e) {
|
||||
const selectedMAC = e.target.value;
|
||||
const selectedHostname = e.target.options[e.target.selectedIndex].text;
|
||||
console.log("Selected device:", {
|
||||
mac: selectedMAC,
|
||||
hostname: selectedHostname,
|
||||
});
|
||||
|
||||
// Enable/disable IP Passthrough mode based on selection
|
||||
const isDeviceSelected = selectedMAC !== "Select Device MAC";
|
||||
if (isDeviceSelected) {
|
||||
updatePassthroughModeState(true);
|
||||
} else {
|
||||
updatePassthroughModeState(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const ipPassthroughSelect = document.getElementById("ip-passthrough-mode");
|
||||
const currentIpPassthroughMode =
|
||||
ipPassthroughSelect.getAttribute("data-current-mode"); // Store current mode as a data attribute
|
||||
|
||||
ipPassthroughSelect.addEventListener("change", function (e) {
|
||||
async handleIpPassthroughChange(e) {
|
||||
const selectedMode = e.target.value;
|
||||
const selectedDeviceMAC =
|
||||
document.getElementById("connected-devices").value;
|
||||
const currentMode = e.target.getAttribute("data-current-mode");
|
||||
const selectedDeviceMAC = uiManager.elements.connectedDevices().value;
|
||||
|
||||
// Send AT command only if the selected mode differs from the current one
|
||||
if (selectedMode !== currentIpPassthroughMode) {
|
||||
let command;
|
||||
switch (selectedMode) {
|
||||
case "Disabled":
|
||||
command = 'AT+QMPDN="MPDN_rule",0;+CFUN=1,1';
|
||||
break;
|
||||
case "ETH Only":
|
||||
command = `AT+QMPDN="MPDN_rule",0,1,0,1,1,"${selectedDeviceMAC}"`;
|
||||
break;
|
||||
case "USB Only":
|
||||
command = `AT+QMPDN="MPDN_rule",0,1,0,3,1,"${selectedDeviceMAC}"`;
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid IP Passthrough mode:", selectedMode);
|
||||
return;
|
||||
if (selectedMode !== currentMode) {
|
||||
const commands = {
|
||||
"Disabled": 'AT+QMPDN="MPDN_rule",0;+CFUN=1,1',
|
||||
"ETH Only": `AT+QMPDN="MPDN_rule",0,1,0,1,1,"${selectedDeviceMAC}"`,
|
||||
"USB Only": `AT+QMPDN="MPDN_rule",0,1,0,3,1,"${selectedDeviceMAC}"`
|
||||
};
|
||||
|
||||
const command = commands[selectedMode];
|
||||
if (command) {
|
||||
uiManager.showLoadingContent();
|
||||
uiManager.startCountdown(80);
|
||||
await api.sendATCommand(command);
|
||||
}
|
||||
|
||||
sendIpPassthroughCommand(command);
|
||||
} else {
|
||||
console.log("No changes made to IP Passthrough mode");
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Function to send an AT command based on the USB Modem Protocol
|
||||
async function sendUsbModemProtocolCommand(command) {
|
||||
try {
|
||||
if (command) {
|
||||
showLoadingContent(); // Show loading content and hide the buttons
|
||||
startCountdown(80); // Start the countdown for 5 seconds
|
||||
}
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log("USB Modem Protocol AT command executed:", data.output);
|
||||
} catch (error) {
|
||||
console.error("Error sending USB Modem Protocol AT command:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle USB Modem Protocol changes
|
||||
function handleUsbModemProtocolChange() {
|
||||
const usbModemSelect = document.getElementById("usb-modem-protocol");
|
||||
const currentUsbModemProtocol = usbModemSelect.getAttribute(
|
||||
"data-current-protocol"
|
||||
); // Store current protocol as a data attribute
|
||||
|
||||
usbModemSelect.addEventListener("change", function (e) {
|
||||
async handleUsbModemProtocolChange(e) {
|
||||
const selectedProtocol = e.target.value;
|
||||
const currentProtocol = e.target.getAttribute("data-current-protocol");
|
||||
|
||||
// Send AT command only if the selected protocol differs from the current one
|
||||
if (selectedProtocol !== currentUsbModemProtocol) {
|
||||
let command;
|
||||
switch (selectedProtocol) {
|
||||
case "RMNET":
|
||||
command = 'AT+QCFG="usbnet",0;+CFUN=1,1';
|
||||
break;
|
||||
case "ECM (Recommended)":
|
||||
command = 'AT+QCFG="usbnet",1;+CFUN=1,1';
|
||||
break;
|
||||
case "MBIM":
|
||||
command = 'AT+QCFG="usbnet",2;+CFUN=1,1';
|
||||
break;
|
||||
case "RNDIS":
|
||||
command = 'AT+QCFG="usbnet",3;+CFUN=1,1';
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid USB Modem Protocol:", selectedProtocol);
|
||||
return;
|
||||
if (selectedProtocol !== currentProtocol) {
|
||||
const commands = {
|
||||
"RMNET": 'AT+QCFG="usbnet",0;+CFUN=1,1',
|
||||
"ECM (Recommended)": 'AT+QCFG="usbnet",1;+CFUN=1,1',
|
||||
"MBIM": 'AT+QCFG="usbnet",2;+CFUN=1,1',
|
||||
"RNDIS": 'AT+QCFG="usbnet",3;+CFUN=1,1'
|
||||
};
|
||||
|
||||
const command = commands[selectedProtocol];
|
||||
if (command) {
|
||||
uiManager.showLoadingContent();
|
||||
uiManager.startCountdown(80);
|
||||
await api.sendATCommand(command);
|
||||
}
|
||||
|
||||
sendUsbModemProtocolCommand(command);
|
||||
} else {
|
||||
console.log("No changes made to USB Modem Protocol");
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Function to show the modal
|
||||
function showModal() {
|
||||
const modal = document.getElementById("reboot-modal");
|
||||
if (modal) {
|
||||
modal.classList.add("is-active"); // Bulma modals require "is-active" to be shown
|
||||
handleDeviceSelection(e) {
|
||||
const selectedMAC = e.target.value;
|
||||
const selectedHostname = e.target.options[e.target.selectedIndex].text;
|
||||
console.log("Selected device:", { mac: selectedMAC, hostname: selectedHostname });
|
||||
|
||||
const isDeviceSelected = selectedMAC !== "Select Device MAC";
|
||||
uiManager.updatePassthroughModeState(isDeviceSelected);
|
||||
}
|
||||
};
|
||||
|
||||
// main.js - Application initialization
|
||||
async function init() {
|
||||
uiManager.showLoadingSpinners();
|
||||
|
||||
try {
|
||||
const [settings, devices] = await Promise.all([
|
||||
api.fetchCurrentSettings(),
|
||||
api.fetchConnectedDevices()
|
||||
]);
|
||||
|
||||
if (settings) {
|
||||
const updateSuccess = await settingsManager.updateSettings(settings);
|
||||
if (updateSuccess) {
|
||||
uiManager.hideLoadingSpinners();
|
||||
|
||||
// Set up event listeners
|
||||
uiManager.elements.dnsProxy().addEventListener("change", eventHandlers.handleDnsProxyChange);
|
||||
uiManager.elements.ipPassthrough().addEventListener("change", eventHandlers.handleIpPassthroughChange);
|
||||
uiManager.elements.usbModem().addEventListener("change", eventHandlers.handleUsbModemProtocolChange);
|
||||
uiManager.elements.connectedDevices().addEventListener("change", eventHandlers.handleDeviceSelection);
|
||||
}
|
||||
}
|
||||
|
||||
if (devices) {
|
||||
uiManager.populateConnectedDevices(devices);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Initialization error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to show loading content and show the modal
|
||||
function showLoadingContent() {
|
||||
document.getElementById("loading-content").style.display = "flex"; // Show the loading section
|
||||
document.getElementById("modal-buttons").style.display = "none"; // Hide the buttons
|
||||
|
||||
// Activate the modal
|
||||
showModal();
|
||||
}
|
||||
|
||||
// Function to start the countdown
|
||||
function startCountdown(duration) {
|
||||
let countdownElement = document.getElementById("countdown");
|
||||
let countdown = duration;
|
||||
let interval = setInterval(function () {
|
||||
countdown--;
|
||||
countdownElement.textContent = countdown;
|
||||
|
||||
if (countdown <= 0) {
|
||||
clearInterval(interval);
|
||||
// Add any additional logic after countdown reaches 0 (like reloading or closing the modal)
|
||||
location.reload(); // Reload the page
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Function for initializing the page
|
||||
function init() {
|
||||
// Replace all i elements under the class advanced-settings with a spinner icon initially
|
||||
const advancedSettingsIcons = document.querySelectorAll(
|
||||
".advanced-settings i"
|
||||
);
|
||||
advancedSettingsIcons.forEach((icon) => {
|
||||
icon.classList.add("fa-spinner", "fa-spin");
|
||||
});
|
||||
|
||||
Promise.all([fetchCurrentSettings(), fetchConnectedDevices()])
|
||||
.then(([settings, devices]) => {
|
||||
if (settings) {
|
||||
const updateSuccess = updateUIElements(settings);
|
||||
if (!updateSuccess) {
|
||||
console.error("Failed to update UI elements");
|
||||
} else {
|
||||
// Revert the spinner icons back to their original state
|
||||
advancedSettingsIcons.forEach((icon) => {
|
||||
icon.classList.remove("fa-spinner", "fa-spin");
|
||||
});
|
||||
|
||||
handleDnsProxyChange(); // Add event listener for DNS Proxy changes
|
||||
handleUsbModemProtocolChange(); // Add event listener for USB Modem Protocol changes
|
||||
handleIpPassthroughChange(); // Add event listener for IP Passthrough changes
|
||||
}
|
||||
} else {
|
||||
console.error("Failed to fetch current settings");
|
||||
}
|
||||
|
||||
if (devices) {
|
||||
populateConnectedDevices(devices);
|
||||
} else {
|
||||
console.error("Failed to fetch connected devices");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error during initialization:", error);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize event listeners when DOM is ready
|
||||
// document.addEventListener("DOMContentLoaded", () => {
|
||||
// // Initialize the page
|
||||
// init();
|
||||
|
||||
// // Add event listener for usb modem protocol changes
|
||||
// handleUsbModemProtocolChange();
|
||||
|
||||
// // Add event listener for connected devices dropdown
|
||||
// const connectedDevicesSelect = document.getElementById("connected-devices");
|
||||
// if (connectedDevicesSelect) {
|
||||
// connectedDevicesSelect.addEventListener("change", function (e) {
|
||||
// const selectedMAC = e.target.value;
|
||||
// const selectedHostname = e.target.options[e.target.selectedIndex].text;
|
||||
// console.log("Selected device:", {
|
||||
// mac: selectedMAC,
|
||||
// hostname: selectedHostname,
|
||||
// });
|
||||
|
||||
// // Enable/disable IP Passthrough mode based on selection
|
||||
// const isDeviceSelected = selectedMAC !== "Select Device MAC";
|
||||
// updatePassthroughModeState(isDeviceSelected);
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Add event listener for IP Passthrough mode changes
|
||||
// const ipPassthroughSelect = document.getElementById("ip-passthrough-mode");
|
||||
// if (ipPassthroughSelect) {
|
||||
// ipPassthroughSelect.addEventListener("change", function (e) {
|
||||
// const selectedMode = e.target.value;
|
||||
// const connectedDevicesSelect =
|
||||
// document.getElementById("connected-devices");
|
||||
// const selectedMAC = connectedDevicesSelect
|
||||
// ? connectedDevicesSelect.value
|
||||
// : null;
|
||||
|
||||
// if (selectedMAC && selectedMAC !== "Select Device MAC") {
|
||||
// console.log("Applying IP Passthrough mode:", {
|
||||
// mode: selectedMode,
|
||||
// deviceMAC: selectedMAC,
|
||||
// });
|
||||
// // Here you can add the API call to apply the passthrough mode
|
||||
// } else {
|
||||
// console.error("No device selected for IP Passthrough mode");
|
||||
// e.target.value = "Select IP Passthrough Mode";
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// Initialize event listeners when DOM is ready
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Initialize the page
|
||||
init();
|
||||
});
|
||||
// Initialize when DOM is ready
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
214
www/js/band-locking/fetch-bands.js
Normal file
214
www/js/band-locking/fetch-bands.js
Normal file
@@ -0,0 +1,214 @@
|
||||
// api.js - API related functions
|
||||
const api = {
|
||||
async sendCommand(command) {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: `command=${encodeURIComponent(command)}`,
|
||||
});
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error("API Error:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// bandManager.js - Band management functionality
|
||||
const bandManager = {
|
||||
async fetchCurrentBands() {
|
||||
try {
|
||||
const data = await api.sendCommand("AT+QCAINFO");
|
||||
const lteBands = data.output.match(/LTE BAND ([0-9]+)/g) || [];
|
||||
const nrBands = data.output.match(/NR5G BAND ([0-9]+)/g) || [];
|
||||
|
||||
const currentBandsElement = document.getElementById("currentBands");
|
||||
if (!currentBandsElement) return;
|
||||
|
||||
if (lteBands.length === 0 && nrBands.length === 0) {
|
||||
currentBandsElement.textContent = "No active bands found";
|
||||
} else if (lteBands.length === 0) {
|
||||
currentBandsElement.textContent = nrBands.join(", ");
|
||||
} else if (nrBands.length === 0) {
|
||||
currentBandsElement.textContent = lteBands.join(", ");
|
||||
} else {
|
||||
currentBandsElement.textContent = [...lteBands, ...nrBands].join(", ");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching current bands:", error);
|
||||
}
|
||||
},
|
||||
|
||||
async fetchSupportedBands() {
|
||||
try {
|
||||
const data = await api.sendCommand('AT+QNWPREFCFG="policy_band"');
|
||||
|
||||
const matches = {
|
||||
lte: data.output.match(/"lte_band",([0-9:]+)/),
|
||||
nsa: data.output.match(/"nsa_nr5g_band",([0-9:]+)/),
|
||||
saDc: data.output.match(/"nrdc_nr5g_band",([0-9:]+)/)
|
||||
};
|
||||
|
||||
if (matches.lte) this.populateBands(matches.lte[1], "#lte_bands");
|
||||
if (matches.nsa) this.populateBands(matches.nsa[1], "#nsa_bands");
|
||||
if (matches.saDc) this.populateBands(matches.saDc[1], "#sanrdc_bands");
|
||||
|
||||
await this.fetchActiveBands();
|
||||
} catch (error) {
|
||||
console.error("Error fetching supported bands:", error);
|
||||
}
|
||||
},
|
||||
|
||||
async fetchActiveBands() {
|
||||
try {
|
||||
const command = 'AT+QNWPREFCFG="lte_band";+QNWPREFCFG="nsa_nr5g_band";+QNWPREFCFG="nr5g_band";+QNWPREFCFG="nrdc_nr5g_band"';
|
||||
const data = await api.sendCommand(command);
|
||||
|
||||
const output = data.output.split("\n").slice(1).join("\n").replace("OK", "");
|
||||
|
||||
const matches = {
|
||||
lte: output.match(/"lte_band",([0-9:]+)/),
|
||||
nsa: output.match(/"nsa_nr5g_band",([0-9:]+)/),
|
||||
saDc: output.split("\n")[6]?.match(/"nr5g_band",([0-9:]+)/)
|
||||
};
|
||||
|
||||
if (matches.lte) this.markActiveBands(matches.lte[1].split(":"), "#lte_bands");
|
||||
if (matches.nsa) this.markActiveBands(matches.nsa[1].split(":"), "#nsa_bands");
|
||||
if (matches.saDc) this.markActiveBands(matches.saDc[1].split(":"), "#sanrdc_bands");
|
||||
|
||||
await this.fetchCurrentBands();
|
||||
} catch (error) {
|
||||
console.error("Error fetching active bands:", error);
|
||||
}
|
||||
},
|
||||
|
||||
populateBands(bandsString, targetId) {
|
||||
const container = document.querySelector(targetId);
|
||||
if (!container) return;
|
||||
|
||||
const html = bandsString.split(":").map(band => `
|
||||
<div class="cell">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" value="${band}" /> B${band}
|
||||
</label>
|
||||
</div>
|
||||
`).join("");
|
||||
|
||||
container.innerHTML = html;
|
||||
},
|
||||
|
||||
markActiveBands(activeBands, targetId) {
|
||||
document.querySelectorAll(`${targetId} input[type="checkbox"]`).forEach(checkbox => {
|
||||
if (activeBands.includes(checkbox.value)) {
|
||||
checkbox.setAttribute("checked", "checked");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
uncheckAll(targetId) {
|
||||
document.querySelectorAll(`${targetId} input[type="checkbox"]`).forEach(checkbox => {
|
||||
checkbox.removeAttribute("checked");
|
||||
checkbox.checked = false;
|
||||
});
|
||||
},
|
||||
|
||||
async lockBands(targetId, commandType) {
|
||||
const checkboxes = document.querySelectorAll(`${targetId} input[type="checkbox"]:checked`);
|
||||
const checkedBands = Array.from(checkboxes)
|
||||
.map(cb => cb.value)
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
if (checkedBands.length === 0) {
|
||||
alert("Please select at least one band to lock.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const command = `AT+QNWPREFCFG="${commandType}",${checkedBands.join(":")}`;
|
||||
await api.sendCommand(command);
|
||||
alert(`Successfully locked ${commandType.split("_")[0].toUpperCase()} bands`);
|
||||
await this.fetchActiveBands();
|
||||
} catch (error) {
|
||||
alert(`Failed to lock bands: ${error.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
async resetBands(targetId, bandType) {
|
||||
const checkboxes = document.querySelectorAll(`${targetId} input[type="checkbox"]`);
|
||||
const selectedBands = [];
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.setAttribute("checked", "checked");
|
||||
checkbox.checked = true;
|
||||
selectedBands.push(checkbox.value);
|
||||
});
|
||||
|
||||
try {
|
||||
const command = `AT+QNWPREFCFG="${bandType}",${selectedBands.join(":")}`;
|
||||
await api.sendCommand(command);
|
||||
await this.fetchActiveBands();
|
||||
} catch (error) {
|
||||
console.error(`Error resetting ${bandType}:`, error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// eventHandlers.js - Event handling setup
|
||||
function setupEventListeners() {
|
||||
const handlers = {
|
||||
uncheck: {
|
||||
"uncheckLte": "#lte_bands",
|
||||
"uncheckNsa": "#nsa_bands",
|
||||
"uncheckSaDc": "#sanrdc_bands"
|
||||
},
|
||||
lock: {
|
||||
"lockLte": ["#lte_bands", "lte_band"],
|
||||
"lockNsa": ["#nsa_bands", "nsa_nr5g_band"],
|
||||
"lockSaDc": ["#sanrdc_bands", "nrdc_nr5g_band"]
|
||||
},
|
||||
reset: {
|
||||
"resetLte": ["#lte_bands", "lte_band"],
|
||||
"resetNsa": ["#nsa_bands", "nsa_nr5g_band"],
|
||||
"resetSaDc": ["#sanrdc_bands", "nrdc_nr5g_band"]
|
||||
}
|
||||
};
|
||||
|
||||
// Setup uncheck handlers
|
||||
Object.entries(handlers.uncheck).forEach(([id, targetId]) => {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
bandManager.uncheckAll(targetId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Setup lock handlers
|
||||
Object.entries(handlers.lock).forEach(([id, [targetId, commandType]]) => {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.addEventListener("click", () => bandManager.lockBands(targetId, commandType));
|
||||
}
|
||||
});
|
||||
|
||||
// Setup reset handlers
|
||||
Object.entries(handlers.reset).forEach(([id, [targetId, bandType]]) => {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
bandManager.resetBands(targetId, bandType);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// main.js - Application initialization
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setupEventListeners();
|
||||
bandManager.fetchSupportedBands();
|
||||
});
|
||||
Reference in New Issue
Block a user