{% /* * Part of AREDN® -- Used for creating Amateur Radio Emergency Data Networks * Copyright (C) 2024 Tim Wilkinson * See Contributors file for additional contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Additional Terms: * * Additional use restrictions exist on the AREDN® trademark and logo. * See AREDNLicense.txt for more info. * * Attributions to the AREDN® Project must be retained in the source code. * If importing this code into a new or existing project attribution * to the AREDN® project must be added to the source code. * * You must not misrepresent the origin of the material contained within. * * Modified versions must be modified to attribute to the original source * and be marked in reasonable ways as differentiate it from the original * version */ %} {% if (request.env.REQUEST_METHOD === "PUT") { configuration.prepareChanges(); if ("radio0_mode" in request.args || "radio1_mode" in request.args) { const wlan = radios.getConfiguration(); let radio0_mode = "radio0_mode" in request.args ? int(request.args.radio0_mode) : wlan[0].mode; let radio1_mode = "radio1_mode" in request.args ? int(request.args.radio1_mode) : wlan[1]?.mode; if (radio0_mode === radio1_mode) { if ("radio0_mode" in request.args) { radio1_mode = radios.RADIO_OFF; } else { radio0_mode = radios.RADIO_OFF; } } configuration.setSetting("wifi_enable", "0"); configuration.setSetting("wifi2_enable", "0"); configuration.setSetting("wifi3_enable", "0"); switch (radio0_mode) { case radios.RADIO_MESH: configuration.setSetting("wifi_enable", "1"); if (configuration.setSetting("wifi_intf", "wlan0")) { configuration.setSetting("wifi_channel", wlan[0].def.channel); } break; case radios.RADIO_LAN: configuration.setSetting("wifi2_enable", "1"); if (configuration.setSetting("wifi2_hwmode", wlan[0].def.band === "5GHz" ? "11a" : "11g")) { configuration.setSetting("wifi2_channel", wlan[0].def.channel); } if (configuration.getSettingAsString("wifi2_key", "") === "") { configuration.setSetting("wifi2_key", hexenc("AREDN")); } break; case radios.RADIO_WAN: configuration.setSetting("wifi3_enable", "1"); configuration.setSetting("wifi3_hwmode", wlan[0].def.band === "5GHz" ? "11a" : "11g"); break; case radios.RADIO_OFF: default: break; } switch (radio1_mode) { case radios.RADIO_MESH: configuration.setSetting("wifi_enable", "1"); if (configuration.setSetting("wifi_intf", "wlan1")) { configuration.setSetting("wifi_channel", wlan[1].def.channel); } break; case radios.RADIO_LAN: configuration.setSetting("wifi2_enable", "1"); if (configuration.setSetting("wifi2_hwmode", wlan[1].def.band === "5GHz" ? "11a" : "11g")) { configuration.setSetting("wifi2_channel", wlan[1].def.channel); } if (configuration.getSettingAsString("wifi2_key", "") === "") { configuration.setSetting("wifi2_key", hexenc("AREDN")); } break; case radios.RADIO_WAN: configuration.setSetting("wifi3_enable", "1"); configuration.setSetting("wifi3_hwmode", wlan[1].def.band === "5GHz" ? "11a" : "11g"); break; case radios.RADIO_OFF: default: break; } } if ("radio_channel" in request.args) { configuration.setSetting("wifi_channel", request.args.radio_channel); } if ("radio0_bandwidth" in request.args || "radio1_bandwidth" in request.args) { configuration.setSetting("wifi_chanbw", request.args.radio0_bandwidth || request.args.radio1_bandwidth); } if ("radio_txpower" in request.args) { configuration.setSetting("wifi_txpower", request.args.radio_txpower); } if ("radio0_ssid" in request.args || "radio1_ssid" in request.args) { configuration.setSetting("wifi_ssid", request.args.radio0_ssid || request.args.radio1_ssid); } if ("radio_minsnr" in request.args) { uciMesh.set("aredn", "@lqm[0]", "min_snr", request.args.radio_minsnr); } if ("radio_maxdistance" in request.args) { uciMesh.set("aredn", "@lqm[0]", "max_distance", units.distance2meters(request.args.radio_maxdistance)); } if ("radio_minquality" in request.args) { uciMesh.set("aredn", "@lqm[0]", "min_quality", request.args.radio_minquality); } if ("radio_lan_ssid" in request.args) { configuration.setSetting("wifi2_ssid", hexenc(request.args.radio_lan_ssid)); } if ("radio_lan_channel" in request.args) { configuration.setSetting("wifi2_channel", request.args.radio_lan_channel); } if ("radio_lan_encryption" in request.args) { const encrypt = [ "psk", "psk2", "none" ]; configuration.setSetting("wifi2_encryption", encrypt[int(request.args.radio_lan_encryption)]); } if ("radio_lan_password" in request.args) { configuration.setSetting("wifi2_key", hexenc(request.args.radio_lan_password)); } if ("radio_wan_ssid" in request.args) { configuration.setSetting("wifi3_ssid", hexenc(request.args.radio_wan_ssid)); } if ("radio_wan_password" in request.args) { configuration.setSetting("wifi3_key", hexenc(request.args.radio_wan_password)); } if ("radio_antenna" in request.args) { uciMesh.set("aredn", "@location[0]", "antenna", request.args.radio_antenna); } if ("radio_azimuth" in request.args) { uciMesh.set("aredn", "@location[0]", "azimuth", request.args.radio_azimuth); } if ("radio_height" in request.args) { uciMesh.set("aredn", "@location[0]", "height", request.args.radio_height); } if ("radio_elevation" in request.args) { uciMesh.set("aredn", "@location[0]", "elevation", request.args.radio_elevation); } if ("radio_lqm_enable" in request.args) { uciMesh.set("aredn", "@lqm[0]", "enable", request.args.radio_lqm_enable === "on" ? 1 : 0); } if ("radio_mindistance" in request.args) { uciMesh.set("aredn", "@lqm[0]", "min_distance", request.args.radio_mindistance); } if ("radio_rts_threshold" in request.args) { uciMesh.set("aredn", "@lqm[0]", "rts_threshold", request.args.radio_rts_threshold); } if ("radio_mtu" in request.args) { uciMesh.set("aredn", "@lqm[0]", "mtu", request.args.radio_mtu); } if ("radio_margin_snr" in request.args) { uciMesh.set("aredn", "@lqm[0]", "margin_snr", request.args.radio_margin_snr); } if ("radio_margin_quality" in request.args) { uciMesh.set("aredn", "@lqm[0]", "margin_quality", request.args.radio_margin_quality); } if ("radio_ping_penalty" in request.args) { uciMesh.set("aredn", "@lqm[0]", "ping_penalty", request.args.radio_ping_penalty); } if ("radio_min_routes" in request.args) { uciMesh.set("aredn", "@lqm[0]", "min_routes", request.args.radio_min_routes); } uciMesh.commit("aredn"); configuration.saveSettings(); print(_R("changes")); return; } if (request.env.REQUEST_METHOD === "DELETE") { configuration.revertModalChanges(); print(_R("changes")); return; } %} {% const wlan = radios.getConfiguration(); %}
{{_R("dialog-header", "Radios & Antennas")}}
{% const hasradios = length(wlan) > 0; if (hasradios) { for (let w = 0; w < length(wlan); w++) { const prefix = `radio${w}_`; if (w !== 0) { print("
"); } %}
1 ? "style='font-weight:bold'" : ""}}>Radio {{wlan[w].def.band}}
Radio purpose
{{_H("Select the purpose of the radio. Each radio can be assigned to a specific purpose, but devices with multiple radios cannot have the same purpose for multiple radios (except off).")}}
1 ? "style='padding-left:10px'" : ""}}>
Channel
Channel and frequency of this connection
{{_H("Select the central channel/frequency for the radio.")}}
Channel Width
Channel bandwidth
{{_H("Select the bandwidth of the radio. Be aware that larger bandwidth settings will consume more channels. Avoid overlapping channels as this will impact performance.")}}
Transmit Power
Transmit power
{{_H("Select the transmission power for the radio. Ideally use only enough power to maintain the link at the capacity required.")}}
SSID
AREDN mesh identifier
-{{wlan[w].modes[1].bandwidth}}-v3
Minimum SNR
Acceptable SNR for connection (dB)
{{_H("Low SNR results in higher latency, lower bandwidth and high retranmissions. Setting a minimum SNR allows links with these characteristics to be ignored.")}}
Maximum Distance
Maximum distance allowed to other nodes in {{units.distanceUnit()}}
{{_H("Distance beyond which neighbor node connections will be ignored. Longer distances to nodes can result in poor performance. This will effect all neighbors, not just the distant ones, so it often makes sense to keep this distance to a minimum.")}}
Minimum Quality
Minimum connection quaility percentage
{{_H("The node management system maintains an estimate of how well each neighbor link performs. This link quality is used to determine which links to use. Lowering the minimum quality can impact performance, but may also be necessary under specific circumstances.")}}
1 ? "style='padding-left:10px'" : ""}}> {{_H("In LAN Hotpot mode, the WiFi acts as a wireless hotspot. Any device connecting will appear as a LAN device attached to the node.")}}
SSID
Hotspot SSID
Channel
Hotspot channel
Encryption
Encryption algorithm
Password
Hotspot password
1 ? "style='padding-left:10px'" : ""}}> {{_H("In WAN Client mode, the WiFi connection is used to connect to another wireless network. This network is expected to provide access to the Internet.")}}
SSID
WAN client
Password
Client password

1 ? "style='padding-left:10px'" : ""}}>
Antenna
Antenna
{% if (length(wlan[w].ants) === 1) { %} {{wlan[w].ants[0].description}} {% } else { %} {% } %}
{% if (length(wlan[w].ants) !== 1) { %} {{_H("Select the external antenna attached to the primary radio.")}} {% } %} {% if (w === 0) { %} {% if (!(length(wlan[w].ants) === 1 && wlan[w].ants[0].beamwidth === 360)) { %}
Azimuth
Antenna azimuth in degrees
{{_H("The azimuth, or heading, of the primary radio antenna measured in degrees from north.")}} {% } %}
Height
Antenna height in meters
{{_H("The height of the antenna above ground level in meters.")}}
Elevation
Antenna elevation in degrees
{{_H("Elevation of the antenna, measured in degress, above or below the horizontal.")}} {% } %}
{% } } else { %}
No Radios
Minimum Quality
Minimum connection quaility percentage
{% } %} {{_R("dialog-advanced")}}
{% if (includeAdvanced) { %}
LQM enable
Enable Link Quality Management
{{_R("hideable-switch-g", { name: "radio_lqm_enable", value: uciMesh.get("aredn", "@lqm[0]", "enable") !== "0" })}}
{{_H("Link Quality Management (LQM) is an automatic management system which monitors the efficiency of each neighbor link and optimizes their use for best performance. When disabled, it still gathers data on each link, but this information is not used to effect operation.")}}
{% if (hasradios) { %}
Minimum Distance
Minimum distance to other nodes in {{units.distanceUnit()}}
{{_H("Exclude nodes which are too close to this node.")}}
RTS Threshold
RTS Threshold in bytes before using RTS/CTS when hidden nodes are detected
{{_H("When hidden nodes are detected, the RTS/CTS protocol is automatically enabled to improve performance. By default this is used for all packets being sent, but this can be optimized to only packets over a specific size (between 1 and 2347 bytes). Setting the value to 2347 disables the protocol.")}}
Max Packet Size
Maximum packet size in bytes sent over WiFi
{{_H("By default, WiFi uses the same packet size (1500 bytes) as Ethernet. However, in some noisy environment performance can be improved by reducing the packet size. A value must be between 256 and 1500.")}}
SNR Margin
SNR Margin in dB above Min SNR a signal must reach to be re-activated
{{_H("The SNR margin avoids a link switching quickly between blocked and unblocked when the SNR is the same as the minimum SNR. Once a link falls below the minimum SNR, it must move above minimum SNR + SNR margin to become active again.")}} {% } %}
Quality Margin
Quality Margin percentage increase before neighbor can be re-activated
Ping Penalty
Ping Penalty quality percentage to add when neighbor cannot be pinged
Minimum Routes
Minimum number of routes on a link required to disable blocking
{% } %}
{{_R("dialog-footer")}} {{_R("password-ctrl")}}