Merge branch 'master' into dey-4.0/maint
|
|
@ -29,9 +29,13 @@ import socketserver
|
|||
import stat
|
||||
import subprocess
|
||||
|
||||
from digi.apix.bluetooth import BluetoothException, BluetoothDevice, BluetoothProfile
|
||||
from digi.apix.exceptions import DigiAPIXException
|
||||
from digi.apix.network import IPMode, NetworkException, NetStatus, NetworkInterface, NetworkProfile
|
||||
from digi.apix.wifi import SecurityMode, WifiException, WifiInterface, WifiProfile
|
||||
from logging.handlers import SysLogHandler
|
||||
from subprocess import call, TimeoutExpired
|
||||
from threading import Thread, Event
|
||||
from threading import Thread
|
||||
|
||||
|
||||
# Constants.
|
||||
|
|
@ -52,9 +56,15 @@ ZERO_MAC = "00:00:00:00:00:00"
|
|||
ZERO_IP = "0.0.0.0"
|
||||
NOT_AVAILABLE = "N/A"
|
||||
|
||||
ELEMENT_BLUETOOTH = "bluetooth"
|
||||
ELEMENT_ETHERNET = "ethernet"
|
||||
ELEMENT_WIFI = "wifi"
|
||||
|
||||
PREFIX_ETHERNET = "eth"
|
||||
PREFIX_WIFI = "wlan"
|
||||
|
||||
# Variables.
|
||||
log = logging.getLogger(APP_NAME)
|
||||
stop_event = Event()
|
||||
last_cpu_work = 0
|
||||
last_cpu_total = 0
|
||||
led_status = {}
|
||||
|
|
@ -113,7 +123,11 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
mca_versions = get_mca_version()
|
||||
info = {
|
||||
"uboot_version": read_proc_file("/proc/device-tree/digi,uboot,version"),
|
||||
"kernel_version": "%s %s %s %s %s GNU/Linux" % (platform.system(), platform.node(), platform.release(), platform.version(), platform.machine()),
|
||||
"kernel_version": "%s %s %s %s %s GNU/Linux" % (platform.system(),
|
||||
platform.node(),
|
||||
platform.release(),
|
||||
platform.version(),
|
||||
platform.machine()),
|
||||
"dey_version": "DEY-%s-%s" % (get_dey_version(), read_file("/etc/version")),
|
||||
"serial_number": read_proc_file("/proc/device-tree/digi,hwid,sn"),
|
||||
"device_type": read_proc_file("/proc/device-tree/digi,machine,name"),
|
||||
|
|
@ -126,14 +140,57 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
"flash_size": get_storage_size(),
|
||||
"video_resolution": get_video_resolution(),
|
||||
"fw_store_path": get_fw_store_path(),
|
||||
"bluetooth_mac": get_bt_mac("hci0"),
|
||||
"wifi_mac": read_file("/sys/class/net/wlan0/address").strip().upper() if "wlan0" in list_net_ifaces() else ZERO_MAC,
|
||||
"wifi_ip": get_iface_ip("wlan0") if "wlan0" in list_net_ifaces() else ZERO_IP,
|
||||
"ethernet0_mac": read_file("/sys/class/net/eth0/address").strip().upper() if "eth0" in list_net_ifaces() else ZERO_MAC,
|
||||
"ethernet0_ip": get_iface_ip("eth0") if "eth0" in list_net_ifaces() else ZERO_IP,
|
||||
"ethernet1_mac": read_file("/sys/class/net/eth1/address").strip().upper() if "eth1" in list_net_ifaces() else ZERO_MAC,
|
||||
"ethernet1_ip": get_iface_ip("eth1") if "eth1" in list_net_ifaces() else ZERO_IP,
|
||||
"bluetooth_mac": ZERO_MAC,
|
||||
"wifi_mac": ZERO_MAC,
|
||||
"wifi_ip": ZERO_IP,
|
||||
"ethernet0_mac": ZERO_MAC,
|
||||
"ethernet0_ip": ZERO_IP,
|
||||
"ethernet1_mac": ZERO_MAC,
|
||||
"ethernet1_ip": ZERO_IP,
|
||||
}
|
||||
# Fill bluetooth data.
|
||||
try:
|
||||
bt_devices = BluetoothDevice.list_devices()
|
||||
if bt_devices and "hci0" in bt_devices:
|
||||
try:
|
||||
bt_device = BluetoothDevice.get("hci0")
|
||||
info["bluetooth_mac"] = mac_to_human_string(bt_device.mac)
|
||||
except BluetoothException as exc2:
|
||||
log.error("Error reading interface 'hci0' data: %s", str(exc2))
|
||||
except DigiAPIXException as exc:
|
||||
log.error("Error listing bluetooth devices: %s", str(exc))
|
||||
# Fill ethernet interfaces data.
|
||||
try:
|
||||
interfaces = NetworkInterface.list_interfaces()
|
||||
if interfaces and "eth0" in interfaces:
|
||||
try:
|
||||
net_iface = NetworkInterface.get("eth0")
|
||||
info["ethernet0_mac"] = str(net_iface.mac)
|
||||
info["ethernet0_ip"] = str(net_iface.ipv4)
|
||||
except NetworkException as exc2:
|
||||
log.error("Error reading interface 'eth0' data: %s", str(exc2))
|
||||
if interfaces and "eth1" in interfaces:
|
||||
try:
|
||||
net_iface = NetworkInterface.get("eth1")
|
||||
info["ethernet1_mac"] = mac_to_human_string(net_iface.mac)
|
||||
info["ethernet1_ip"] = str(net_iface.ipv4)
|
||||
except NetworkException as exc2:
|
||||
log.error("Error reading interface 'eth1' data: %s", str(exc2))
|
||||
except DigiAPIXException as exc:
|
||||
log.error("Error listing network interfaces: %s", str(exc))
|
||||
|
||||
# Fill WiFi interfaces data.
|
||||
try:
|
||||
interfaces = WifiInterface.list_interfaces()
|
||||
if interfaces and "wlan0" in interfaces:
|
||||
try:
|
||||
net_iface = WifiInterface.get("wlan0")
|
||||
info["wifi_mac"] = mac_to_human_string(net_iface.mac)
|
||||
info["wifi_ip"] = str(net_iface.ipv4)
|
||||
except WifiException as exc2:
|
||||
log.error("Error reading interface 'wlan0' data: %s", str(exc2))
|
||||
except DigiAPIXException as exc:
|
||||
log.error("Error listing network interfaces: %s", str(exc))
|
||||
|
||||
# Send the JSON value.
|
||||
self.wfile.write(json.dumps(info).encode(encoding="utf_8"))
|
||||
|
|
@ -147,7 +204,7 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
mem_total = int(mem_info.get("MemTotal", "-1")) if mem_info else -1
|
||||
mem_free = int(mem_info.get("MemFree", "-1")) if mem_info else -1
|
||||
mem_used = (mem_total - mem_free) if (mem_total > 0 and mem_free > 0) else -1
|
||||
bt_data = get_bt_data("hci0")
|
||||
|
||||
status = {
|
||||
"system_monitor/cpu_load": get_cpu_load(),
|
||||
"system_monitor/cpu_temperature": get_cpu_temp(),
|
||||
|
|
@ -155,18 +212,56 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
"system_monitor/uptime": get_uptime(),
|
||||
"system_monitor/free_memory": mem_free,
|
||||
"system_monitor/used_memory": mem_used,
|
||||
"system_monitor/led_status": get_led_status("USER_LED"),
|
||||
"system_monitor/hci0/state": bt_data.get("state", 0),
|
||||
"system_monitor/hci0/rx_bytes": bt_data.get("rx_bytes", 0),
|
||||
"system_monitor/hci0/tx_bytes": bt_data.get("tx_bytes", 0),
|
||||
"system_monitor/led_status": get_led_status("USER_LED")
|
||||
}
|
||||
|
||||
list_ifaces = list_net_ifaces()
|
||||
for name in list_ifaces:
|
||||
data = get_iface_data(name)
|
||||
status["system_monitor/%s/state" % name] = data["state"]
|
||||
status["system_monitor/%s/rx_bytes" % name] = data["rx_bytes"]
|
||||
status["system_monitor/%s/tx_bytes" % name] = data["tx_bytes"]
|
||||
# Fill bluetooth devices data.
|
||||
try:
|
||||
bt_devices = BluetoothDevice.list_devices() or []
|
||||
for device in bt_devices:
|
||||
try:
|
||||
bt_device = BluetoothDevice.get(device)
|
||||
statistics = bt_device.get_statistics()
|
||||
status[f"system_monitor/{device}/state"] = 1 if \
|
||||
bt_device.is_enabled else 0
|
||||
status[f"system_monitor/{device}/rx_bytes"] = statistics.rx_bytes
|
||||
status[f"system_monitor/{device}/tx_bytes"] = statistics.tx_bytes
|
||||
except NetworkException as exc2:
|
||||
log.error("Error reading bluetooth device '%s' data: %s", device, str(exc2))
|
||||
except DigiAPIXException as exc:
|
||||
log.error("Error listing bluetooth devices: %s", str(exc))
|
||||
|
||||
# Fill ethernet interfaces data.
|
||||
try:
|
||||
interfaces = NetworkInterface.list_interfaces() or []
|
||||
for iface in interfaces:
|
||||
try:
|
||||
net_iface = NetworkInterface.get(iface)
|
||||
statistics = net_iface.get_statistics()
|
||||
status[f"system_monitor/{iface}/state"] = 1 if \
|
||||
net_iface.status == NetStatus.CONNECTED else 0
|
||||
status[f"system_monitor/{iface}/rx_bytes"] = statistics.rx_bytes
|
||||
status[f"system_monitor/{iface}/tx_bytes"] = statistics.tx_bytes
|
||||
except NetworkException as exc2:
|
||||
log.error("Error reading interface '%s' data: %s", iface, str(exc2))
|
||||
except DigiAPIXException as exc:
|
||||
log.error("Error listing network interfaces: %s", str(exc))
|
||||
|
||||
# Fill WiFi interfaces data.
|
||||
try:
|
||||
interfaces = WifiInterface.list_interfaces() or []
|
||||
for iface in interfaces:
|
||||
try:
|
||||
wifi_iface = WifiInterface.get(iface)
|
||||
statistics = wifi_iface.get_statistics()
|
||||
status[f"system_monitor/{iface}/state"] = 1 if \
|
||||
wifi_iface.status == NetStatus.CONNECTED else 0
|
||||
status[f"system_monitor/{iface}/rx_bytes"] = statistics.rx_bytes
|
||||
status[f"system_monitor/{iface}/tx_bytes"] = statistics.tx_bytes
|
||||
except WifiException as exc2:
|
||||
log.error("Error reading interface '%s' data: %s", iface, str(exc2))
|
||||
except DigiAPIXException as exc:
|
||||
log.error("Error listing WiFi interfaces: %s", str(exc))
|
||||
|
||||
# Send the JSON value.
|
||||
self.wfile.write(json.dumps(status).encode(encoding="utf_8"))
|
||||
|
|
@ -196,6 +291,23 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
return
|
||||
|
||||
self.wfile.write("{}".encode(encoding="utf_8"))
|
||||
elif re.search("/ajax/play_music", self.path) is not None:
|
||||
# Set the response headers.
|
||||
self._set_headers(200)
|
||||
|
||||
# Get the JSON data.
|
||||
data = self.rfile.read(int(self.headers["Content-Length"]))
|
||||
play = json.loads(data.decode("utf-8")).get("play", None)
|
||||
music_file = json.loads(data.decode("utf-8")).get("music_file", None)
|
||||
|
||||
log.debug("Play music: %s", play)
|
||||
if music_file:
|
||||
log.debug("Music file: %s", music_file)
|
||||
|
||||
play_music(play, music_file)
|
||||
|
||||
# Send the JSON value.
|
||||
self.wfile.write(json.dumps({"play": play}).encode(encoding="utf_8"))
|
||||
elif re.search("/ajax/set_audio_volume", self.path) is not None:
|
||||
# Set the response headers.
|
||||
self._set_headers(200)
|
||||
|
|
@ -212,7 +324,7 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
self.wfile.write(json.dumps({"error": error}).encode(encoding="utf_8"))
|
||||
return
|
||||
|
||||
vol, error = set_audio_volume(value)
|
||||
error = set_audio_volume(value)
|
||||
|
||||
# Send the JSON value.
|
||||
if error:
|
||||
|
|
@ -221,7 +333,7 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
return
|
||||
|
||||
# Send the JSON value.
|
||||
self.wfile.write(json.dumps({"value": vol}).encode(encoding="utf_8"))
|
||||
self.wfile.write("{}".encode(encoding="utf_8"))
|
||||
elif re.search("/ajax/fs_list_directory", self.path) is not None:
|
||||
# Set the response headers.
|
||||
self._set_headers(200)
|
||||
|
|
@ -462,7 +574,34 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||
progress = 100
|
||||
if fw_process and fw_process.poll() is None:
|
||||
progress = "?"
|
||||
self.wfile.write(json.dumps({"progress": progress, "message": "Updating firmare"}).encode(encoding="utf_8"))
|
||||
self.wfile.write(json.dumps({"progress": progress, "message": "Updating firmware"}).encode(encoding="utf_8"))
|
||||
elif re.search("/ajax/get_config", self.path) is not None:
|
||||
# Set the response headers.
|
||||
self._set_headers(200)
|
||||
# Get the JSON data.
|
||||
data = self.rfile.read(int(self.headers["Content-Length"]))
|
||||
elements = json.loads(data.decode("utf-8")).get("elements", None)
|
||||
# Fill configuration data.
|
||||
config_data = get_elements_configuration(elements)
|
||||
# Send the answer.
|
||||
if "error" in config_data:
|
||||
self.wfile.write(json.dumps(config_data).encode(encoding="utf_8"))
|
||||
else:
|
||||
self.wfile.write(json.dumps(
|
||||
{"data": json.dumps(config_data)}).encode(encoding="utf_8"))
|
||||
elif re.search("/ajax/set_config", self.path) is not None:
|
||||
# Set the response headers.
|
||||
self._set_headers(200)
|
||||
# Get the JSON data.
|
||||
data = self.rfile.read(int(self.headers["Content-Length"]))
|
||||
configuration = json.loads(data.decode("utf-8")).get("configuration", None)
|
||||
# Apply configuration.
|
||||
result = set_configuration(configuration)
|
||||
# Send the answer.
|
||||
if "error" in result:
|
||||
self.wfile.write(json.dumps(result).encode(encoding="utf_8"))
|
||||
else:
|
||||
self.wfile.write(json.dumps({"data": json.dumps(result)}).encode(encoding="utf_8"))
|
||||
else:
|
||||
# Forbidden.
|
||||
self._set_headers(403)
|
||||
|
|
@ -507,7 +646,7 @@ def filter_by_extension(name, filters):
|
|||
if name.endswith(ext):
|
||||
return True
|
||||
|
||||
return False;
|
||||
return False
|
||||
|
||||
|
||||
def get_uptime():
|
||||
|
|
@ -652,7 +791,7 @@ def get_video_resolution():
|
|||
if res == NOT_AVAILABLE:
|
||||
res = read_file("/sys/class/graphics/fb0/modes")
|
||||
if res == NOT_AVAILABLE:
|
||||
return "-"
|
||||
return "No video device found"
|
||||
|
||||
line = res.splitlines()[0]
|
||||
if ":" in line:
|
||||
|
|
@ -737,146 +876,6 @@ def get_mca_version():
|
|||
return NOT_AVAILABLE, NOT_AVAILABLE
|
||||
|
||||
|
||||
def list_net_ifaces():
|
||||
"""
|
||||
Returs a list with the names of the network interfaces.
|
||||
|
||||
Returns:
|
||||
List: List of network inteface names.
|
||||
"""
|
||||
return os.listdir("/sys/class/net")
|
||||
|
||||
|
||||
def get_iface_ip(iface_name):
|
||||
"""
|
||||
Gets the IP address of the provided interface.
|
||||
|
||||
Args:
|
||||
iface_name (String): Name of the network interface to get its IP.
|
||||
|
||||
Returns:
|
||||
String: The IP of the interface.
|
||||
"""
|
||||
res = exec_cmd("ip addr show %s" % iface_name)
|
||||
if res[0] == 0:
|
||||
tmp = res[1].split("inet ")
|
||||
if len(tmp) > 1:
|
||||
return tmp[1].split("/")[0]
|
||||
|
||||
log.error("Error getting IP of interface '%s': %s", iface_name, res[1])
|
||||
|
||||
return ZERO_IP
|
||||
|
||||
|
||||
def get_iface_data(iface_name):
|
||||
"""
|
||||
Gets network interface state and statistics.
|
||||
|
||||
Args:
|
||||
iface_name (String): Name of the interface to get data.
|
||||
|
||||
Returns:
|
||||
Dictionary: The network interface state and statistics.
|
||||
"""
|
||||
data = {
|
||||
"state": 0,
|
||||
"rx_bytes": 0,
|
||||
"tx_bytes": 0
|
||||
}
|
||||
state = read_file("/sys/class/net/%s/operstate" % iface_name)
|
||||
if state != NOT_AVAILABLE:
|
||||
data["state"] = 1 if state.strip() == "up" else 0
|
||||
|
||||
stats = read_file("/proc/net/dev")
|
||||
if stats == NOT_AVAILABLE:
|
||||
return data
|
||||
|
||||
for line in stats.splitlines():
|
||||
if not line.strip().startswith("%s: " % iface_name):
|
||||
continue
|
||||
fields = line.split()
|
||||
data["rx_bytes"] = fields[1]
|
||||
data["tx_bytes"] = fields[9]
|
||||
break
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def is_bt_available():
|
||||
"""
|
||||
Checks if Bluetooth is available on the device.
|
||||
|
||||
Returns:
|
||||
Boolean: True if available, False otherwise.
|
||||
"""
|
||||
return os.path.isdir("/proc/device-tree/bluetooth")
|
||||
|
||||
|
||||
def get_bt_mac(iface_name):
|
||||
"""
|
||||
Gets Bluetooth MAC address.
|
||||
|
||||
Args:
|
||||
iface_name (String): Name of the interface to get the MAC.
|
||||
|
||||
Returns:
|
||||
String: The Bluetooth MAC.
|
||||
"""
|
||||
if not is_bt_available():
|
||||
return ZERO_MAC
|
||||
|
||||
res = exec_cmd("hciconfig %s" % iface_name)
|
||||
if res[0] == 0:
|
||||
return res[1].split("BD Address:")[1].split("ACL")[0].strip()
|
||||
else:
|
||||
log.error("Error getting MAC of Bluetooth interface '%s': %s", iface_name, res[1])
|
||||
return ZERO_MAC
|
||||
|
||||
|
||||
def get_bt_data(iface_name):
|
||||
"""
|
||||
Gets Bluetooth interface state and statistics.
|
||||
|
||||
Args:
|
||||
iface_name (String): Name of the interface to get data.
|
||||
|
||||
Returns:
|
||||
Dictionary: The Bluetooth interface state and statistics.
|
||||
"""
|
||||
data = {
|
||||
"state": 0,
|
||||
"rx_bytes": 0,
|
||||
"tx_bytes": 0
|
||||
}
|
||||
|
||||
if not is_bt_available():
|
||||
return data
|
||||
|
||||
res = exec_cmd("hciconfig %s" % iface_name)
|
||||
if res[0] == 0:
|
||||
info = res[1]
|
||||
else:
|
||||
log.error("Error getting status of Bluetooth interface '%s': %s", iface_name, res[1])
|
||||
return data
|
||||
|
||||
lines = info.splitlines()
|
||||
if not lines:
|
||||
return data
|
||||
|
||||
if len(lines) > 2 and re.fullmatch("(UP) .*", lines[2].strip()):
|
||||
data["state"] = 1
|
||||
|
||||
if len(lines) > 3:
|
||||
m = re.fullmatch("RX bytes:([0-9]+) .*", lines[3].strip())
|
||||
data["rx_bytes"] = m.group(1) if m else 0
|
||||
|
||||
if len(lines) > 4:
|
||||
m = re.fullmatch("TX bytes:([0-9]+) .*", lines[4].strip())
|
||||
data["tx_bytes"] = m.group(1) if m else 0
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_led_status(name):
|
||||
"""
|
||||
Get the LED value.
|
||||
|
|
@ -951,6 +950,19 @@ def get_led_by_alias(alias):
|
|||
return led_loc.split(",")
|
||||
|
||||
|
||||
def play_music(play, music_file):
|
||||
"""
|
||||
Sets the play music value.
|
||||
|
||||
Args:
|
||||
play (Boolean): `True` to play music, `False` to stop it.
|
||||
music_file (String): Path of the music file to play.
|
||||
"""
|
||||
exec_cmd("pkill -KILL -f mpg123")
|
||||
if play:
|
||||
exec_cmd_nowait(f"mpg123 {music_file}")
|
||||
|
||||
|
||||
def set_audio_volume(value):
|
||||
"""
|
||||
Configures the audio volume.
|
||||
|
|
@ -959,27 +971,277 @@ def set_audio_volume(value):
|
|||
value (Integer): Volume to set in percentage.
|
||||
|
||||
Returns:
|
||||
Tuple (Integer, String): Current volume value and error string if fails.
|
||||
String: Error string if fails.
|
||||
"""
|
||||
res = exec_cmd("amixer set Headphone %d%%" % value)
|
||||
res = exec_cmd(f"amixer set 'Speaker' {value}% && amixer set 'Headphone' {value}%")
|
||||
if res[0] != 0:
|
||||
return -1, res[1]
|
||||
return res[1]
|
||||
return None
|
||||
|
||||
tmp = res[1].split("Front Right:")
|
||||
if len(tmp) < 1:
|
||||
return -1, "Unable to get current volume"
|
||||
|
||||
m = re.search("\[(.+?)%\]", tmp[1])
|
||||
if not m:
|
||||
return -1, "Unable to get current volume"
|
||||
def get_elements_configuration(elements):
|
||||
"""
|
||||
Gets the configuration for the given elements.
|
||||
|
||||
if len(m.groups()) < 1:
|
||||
return -1, "Unable to get current volume"
|
||||
Args:
|
||||
elements (List): Elements for which to get the configuration.
|
||||
|
||||
Returns:
|
||||
Dictionary: The elements configuration data.
|
||||
"""
|
||||
data = {}
|
||||
for element in elements:
|
||||
if element == ELEMENT_BLUETOOTH:
|
||||
data[element] = get_bluetooth_element_configuration()
|
||||
elif element in (ELEMENT_ETHERNET, ELEMENT_WIFI):
|
||||
data[element] = get_network_element_configuration(element)
|
||||
else:
|
||||
data["error"] = f"Unknown element '{element}'"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_network_element_configuration(element):
|
||||
"""
|
||||
Gets the configuration for the given network element.
|
||||
|
||||
Args:
|
||||
element (String): Network element for which to get the configuration.
|
||||
|
||||
Returns:
|
||||
Dictionary: The network element configuration data.
|
||||
"""
|
||||
data = {}
|
||||
prefix = PREFIX_ETHERNET
|
||||
if element == ELEMENT_WIFI:
|
||||
prefix = PREFIX_WIFI
|
||||
try:
|
||||
return int(m.group(1)), ""
|
||||
except ValueError:
|
||||
return -1, "Unable to get current volume"
|
||||
ifaces = NetworkInterface.list_interfaces() or []
|
||||
for iface in ifaces:
|
||||
if prefix in iface:
|
||||
data[iface] = get_network_iface_configuration(iface)
|
||||
except DigiAPIXException as exc:
|
||||
data["error"] = f"Error listing network interfaces: '{str(exc)}'"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_network_iface_configuration(interface):
|
||||
"""
|
||||
Returns the network configuration of the given interface.
|
||||
|
||||
Args:
|
||||
interface (String): Network interface to get its configuration.
|
||||
|
||||
Returns:
|
||||
Dictionary: dictionary with the interface configuration.
|
||||
"""
|
||||
data = {}
|
||||
try:
|
||||
net_iface = NetworkInterface.get(interface)
|
||||
data["enable"] = 1 if net_iface.status == NetStatus.CONNECTED else 0
|
||||
data["mac"] = mac_to_human_string(net_iface.mac)
|
||||
data["type"] = 0 if net_iface.ip_mode == IPMode.STATIC else 1
|
||||
data["ip"] = str(net_iface.ipv4)
|
||||
data["netmask"] = str(net_iface.netmask)
|
||||
data["dns1"] = str(net_iface.dns1)
|
||||
data["dns2"] = str(net_iface.dns2)
|
||||
data["gateway"] = str(net_iface.gateway)
|
||||
if PREFIX_WIFI in interface:
|
||||
try:
|
||||
wifi_iface = WifiInterface.get(interface)
|
||||
data["ssid"] = wifi_iface.ssid
|
||||
data["frequency"] = wifi_iface.frequency
|
||||
data["channel"] = wifi_iface.channel
|
||||
data["sec_mode"] = 0 if wifi_iface.sec_mode == SecurityMode.UNKNOWN \
|
||||
else wifi_iface.sec_mode.code
|
||||
except WifiException as exc:
|
||||
raise NetworkException({str(exc)}) from exc
|
||||
except NetworkException as exc2:
|
||||
data["error"] = f"Error reading interface data: {str(exc2)}"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def set_configuration(config_data):
|
||||
"""
|
||||
Applies the given configuration.
|
||||
|
||||
Args:
|
||||
config_data (Dictionary): Configuration to apply.
|
||||
|
||||
Returns:
|
||||
Dictionary: The operation result.
|
||||
"""
|
||||
data = {}
|
||||
for element in config_data:
|
||||
if element == ELEMENT_BLUETOOTH:
|
||||
data[element] = set_bluetooth_element_configuration(config_data[element])
|
||||
elif element in (ELEMENT_ETHERNET, ELEMENT_WIFI):
|
||||
data[element] = set_network_element_configuration(config_data[element])
|
||||
else:
|
||||
data["error"] = f"Unknown element '{element}'"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def set_network_element_configuration(config_data):
|
||||
"""
|
||||
Applies the given network configuration.
|
||||
|
||||
Args:
|
||||
config_data (Dictionary): Network configuration to apply.
|
||||
|
||||
Returns:
|
||||
Dictionary: The operation result.
|
||||
"""
|
||||
data = {}
|
||||
for iface in config_data:
|
||||
data[iface] = set_network_iface_configuration(iface, config_data[iface])
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def set_network_iface_configuration(interface, config_data):
|
||||
"""
|
||||
Applies the given network configuration to the given interface.
|
||||
|
||||
Args:
|
||||
interface (String): Network interface to apply configuration to.
|
||||
config_data (Dictionary): Network configuration to apply.
|
||||
|
||||
Returns:
|
||||
Dictionary: Operation result.
|
||||
"""
|
||||
data = {}
|
||||
profile = NetworkProfile()
|
||||
if PREFIX_WIFI in interface:
|
||||
profile = WifiProfile()
|
||||
profile.connect = config_data.get("enable", None)
|
||||
profile.mode = IPMode.get(config_data["type"]) if "type" in config_data else None
|
||||
profile.ipv4 = config_data.get("ip", None)
|
||||
profile.netmask = config_data.get("netmask", None)
|
||||
profile.gateway = config_data.get("gateway", None)
|
||||
profile.dns1 = config_data.get("dns1", None)
|
||||
profile.dns2 = config_data.get("dns2", None)
|
||||
if PREFIX_WIFI in interface:
|
||||
profile.ssid = config_data.get("ssid", None)
|
||||
profile.sec_mode = (SecurityMode.get(config_data["sec_mode"])
|
||||
if "sec_mode" in config_data else None)
|
||||
profile.psk = config_data.get("psk", None)
|
||||
try:
|
||||
if PREFIX_ETHERNET in interface:
|
||||
net_iface = NetworkInterface.get(interface)
|
||||
elif PREFIX_WIFI in interface:
|
||||
net_iface = WifiInterface.get(interface)
|
||||
else:
|
||||
raise DigiAPIXException(f"Unknown interface '{interface}'")
|
||||
net_iface.configure(profile)
|
||||
data["status"] = 0
|
||||
except DigiAPIXException as exc2:
|
||||
data["status"] = 1
|
||||
data["desc"] = f"Error configuring interface: {str(exc2)}"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_bluetooth_element_configuration():
|
||||
"""
|
||||
Gets the configuration for the bluetooth element.
|
||||
|
||||
Returns:
|
||||
Dictionary: The bluetooth element configuration data.
|
||||
"""
|
||||
data = {}
|
||||
try:
|
||||
bt_devices = BluetoothDevice.list_devices() or []
|
||||
for bt_device in bt_devices:
|
||||
data[bt_device] = get_bluetooth_device_configuration(bt_device)
|
||||
except DigiAPIXException as exc:
|
||||
data["error"] = f"Error listing bluetooth devices: '{str(exc)}'"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_bluetooth_device_configuration(device):
|
||||
"""
|
||||
Returns the configuration of the given bluetooth device.
|
||||
|
||||
Args:
|
||||
device (String): Bluetooth device to get its configuration.
|
||||
|
||||
Returns:
|
||||
Dictionary: dictionary with the device configuration.
|
||||
"""
|
||||
data = {}
|
||||
try:
|
||||
bt_device = BluetoothDevice.get(device)
|
||||
data["device_id"] = bt_device.device_id
|
||||
data["advert_name"] = str(bt_device.advert_name)
|
||||
data["mac"] = mac_to_human_string(bt_device.mac)
|
||||
data["enable"] = 1 if bt_device.is_enabled else 0
|
||||
data["running"] = 1 if bt_device.is_running else 0
|
||||
except BluetoothException as exc:
|
||||
data["error"] = f"Error reading device data: {str(exc)}"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def set_bluetooth_element_configuration(config_data):
|
||||
"""
|
||||
Applies the given bluetooth configuration.
|
||||
|
||||
Args:
|
||||
config_data (Dictionary): Bluetooth configuration to apply.
|
||||
|
||||
Returns:
|
||||
Dictionary: The operation result.
|
||||
"""
|
||||
data = {}
|
||||
for device in config_data:
|
||||
data[device] = set_bluetooth_device_configuration(device, config_data[device])
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def set_bluetooth_device_configuration(device, config_data):
|
||||
"""
|
||||
Applies the given bluetooth configuration to the given device.
|
||||
|
||||
Args:
|
||||
device (String): Bluetooth device to apply configuration to.
|
||||
config_data (Dictionary): Bluetooth configuration to apply.
|
||||
|
||||
Returns:
|
||||
Dictionary: Operation result.
|
||||
"""
|
||||
data = {}
|
||||
try:
|
||||
bt_device = BluetoothDevice.get(device)
|
||||
profile = BluetoothProfile()
|
||||
profile.enable = config_data.get("enable", None)
|
||||
profile.advert_name = config_data.get("advert_name", None)
|
||||
bt_device.configure(profile)
|
||||
data["status"] = 0
|
||||
except DigiAPIXException as exc2:
|
||||
data["status"] = 1
|
||||
data["desc"] = f"Error configuring interface: {str(exc2)}"
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def mac_to_human_string(mac, num_bytes=6):
|
||||
"""
|
||||
Transforms the given MAC address into a human readable string.
|
||||
|
||||
Args:
|
||||
mac (:class:`.MacAddress`): The MAC address to transform.
|
||||
num_bytes (Integer): The number of bytes to use in the MAC Address.
|
||||
|
||||
Return:
|
||||
String: The given MAC as human readable string.
|
||||
"""
|
||||
return ":".join(["%02X" % i for i in mac][8-num_bytes:]).upper()
|
||||
|
||||
|
||||
def read_proc_file(path):
|
||||
|
|
@ -1025,6 +1287,21 @@ def exec_cmd(cmd, timeout=None):
|
|||
return e.returncode, e.stdout
|
||||
|
||||
|
||||
def exec_cmd_nowait(command, *args):
|
||||
"""
|
||||
Executes the provided command without waiting to finish.
|
||||
|
||||
Args:
|
||||
command (String): The command to execute.
|
||||
args (List): The list of arguments.
|
||||
"""
|
||||
arguments = []
|
||||
for arg in args:
|
||||
arguments.extend(arg)
|
||||
subprocess.Popen([command] + arguments, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, text=True)
|
||||
|
||||
|
||||
def read_file(path):
|
||||
"""
|
||||
Reads the provided file path.
|
||||
|
|
@ -1124,8 +1401,6 @@ def signal_handler(signal_number, _frame):
|
|||
_frame: Current stack frame.
|
||||
"""
|
||||
log.debug("Signal received %d", signal_number)
|
||||
if signal_number in (signal.SIGTERM, signal.SIGINT):
|
||||
stop_event.set()
|
||||
|
||||
|
||||
def main():
|
||||
|
|
@ -1161,7 +1436,8 @@ def main():
|
|||
server_thread.deamon = True
|
||||
server_thread.start()
|
||||
|
||||
stop_event.wait()
|
||||
# Wait for termination/interrupt signal.
|
||||
signal.sigwait([signal.SIGTERM, signal.SIGINT])
|
||||
|
||||
server.shutdown()
|
||||
server.server_close()
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ Digi Demo - Dashboard
|
|||
<p id="banner-text">ConnectCore Demo</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="nav-right-container">
|
||||
<div>
|
||||
<img src="./static/images/board.png" class="device-title-img" title="Device">
|
||||
|
|
@ -69,6 +68,14 @@ Digi Demo - Dashboard
|
|||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_network">
|
||||
<a data-pjax href="network.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-network-wired fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Network</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_management">
|
||||
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
|
|
@ -620,6 +627,13 @@ Digi Demo - Dashboard
|
|||
<span>Audio control</span>
|
||||
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('audio', false)"></div>
|
||||
</div>
|
||||
<div class="device-card-content" style="padding-bottom: 0px;">
|
||||
<span class="device-card-content-text" style="margin-right: 15px;">Music:</span>
|
||||
<div id="play_audio_button" class="fas fa-play audio-button" onclick="playMusic(true)">
|
||||
</div>
|
||||
<div id="stop_audio_button" class="fas fa-stop audio-button" onclick="playMusic(false)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="device-card-content">
|
||||
<div>
|
||||
<span class="device-card-content-text">Volume:</span>
|
||||
|
|
@ -740,12 +754,14 @@ Digi Demo - Dashboard
|
|||
|
||||
<!-- Local JS files and functions -->
|
||||
<script type="text/javascript" src="./static/js/sidebar.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp133-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp157-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx6ulsbc.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
|
||||
<script type="text/javascript" src="./static/js/dashboard.js"></script>
|
||||
<script type="text/javascript" src="./static/js/network.js"></script>
|
||||
<script type="text/javascript" src="./static/js/multimedia.js"></script>
|
||||
<script type="text/javascript" src="./static/js/management.js"></script>
|
||||
<script type="text/javascript" src="./static/js/file-system.js"></script>
|
||||
|
|
|
|||
|
|
@ -34,14 +34,13 @@ Digi Demo - Management
|
|||
<p id="banner-text">ConnectCore Demo</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="nav-right-container">
|
||||
|
||||
<div>
|
||||
<img src="./static/images/board.png" class="device-title-img" title="Device">
|
||||
</div>
|
||||
<div id="device-name">DEY DEVICE</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="bg-light" id="body-row">
|
||||
|
|
@ -69,6 +68,14 @@ Digi Demo - Management
|
|||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_network">
|
||||
<a data-pjax href="network.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-network-wired fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Network</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_management">
|
||||
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
|
|
@ -286,12 +293,14 @@ Digi Demo - Management
|
|||
|
||||
<!-- Local JS files and functions -->
|
||||
<script type="text/javascript" src="./static/js/sidebar.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp133-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp157-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx6ulsbc.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
|
||||
<script type="text/javascript" src="./static/js/dashboard.js"></script>
|
||||
<script type="text/javascript" src="./static/js/network.js"></script>
|
||||
<script type="text/javascript" src="./static/js/multimedia.js"></script>
|
||||
<script type="text/javascript" src="./static/js/management.js"></script>
|
||||
<script type="text/javascript" src="./static/js/file-system.js"></script>
|
||||
|
|
|
|||
|
|
@ -34,14 +34,13 @@ Digi Demo - Multimedia
|
|||
<p id="banner-text">ConnectCore Demo</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="nav-right-container">
|
||||
|
||||
<div>
|
||||
<img src="./static/images/board.png" class="device-title-img" title="Device">
|
||||
</div>
|
||||
<div id="device-name">DEY DEVICE</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="bg-light" id="body-row">
|
||||
|
|
@ -69,6 +68,14 @@ Digi Demo - Multimedia
|
|||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_network">
|
||||
<a data-pjax href="network.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-network-wired fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Network</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_management">
|
||||
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
|
|
@ -227,12 +234,14 @@ Digi Demo - Multimedia
|
|||
|
||||
<!-- Local JS files and functions -->
|
||||
<script type="text/javascript" src="./static/js/sidebar.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp133-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp157-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx6ulsbc.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
|
||||
<script type="text/javascript" src="./static/js/dashboard.js"></script>
|
||||
<script type="text/javascript" src="./static/js/network.js"></script>
|
||||
<script type="text/javascript" src="./static/js/multimedia.js"></script>
|
||||
<script type="text/javascript" src="./static/js/management.js"></script>
|
||||
<script type="text/javascript" src="./static/js/file-system.js"></script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,508 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Digi Demo - Network
|
||||
</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="./static/css/stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="./static/css/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
|
||||
<link href="./static/css/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/css/bootstrap-slider.min.css" rel="stylesheet">
|
||||
<link href="./static/css/fontawesome5.15.4/all.min.css" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="./static/css/general.css">
|
||||
<link rel="stylesheet" href="./static/css/toastr.css">
|
||||
|
||||
<!-- JS, Popper.js, and jQuery -->
|
||||
<script src="./static/js/code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
||||
<script src="./static/js/cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
|
||||
<script src="./static/js/stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
|
||||
<script src="./static/js/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
|
||||
<script src="./static/js/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/bootstrap-slider.min.js"></script>
|
||||
<script type="text/javascript" src="./static/js/common.js"></script>
|
||||
<script type="text/javascript" src="./static/js/devices.js"></script>
|
||||
<script type="text/javascript" src="./static/js/jquery.pjax.js"></script>
|
||||
<script type="text/javascript" src="./static/js/jquery.matchHeight-min.js"></script>
|
||||
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||
<div class="nav-container">
|
||||
<a id="banner-link" class="navbar-brand align-middle" href="/">
|
||||
<div class="d-flex align-items-baseline">
|
||||
<img id="banner-logo" class="banner-icon" src="./static/images/Digi_logo_banner.png">
|
||||
<p id="banner-text">ConnectCore Demo</p>
|
||||
</div>
|
||||
</a>
|
||||
<div class="nav-right-container">
|
||||
<div>
|
||||
<img src="./static/images/board.png" class="device-title-img" title="Device">
|
||||
</div>
|
||||
<div id="device-name">DEY DEVICE</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="bg-light" id="body-row">
|
||||
|
||||
<!-- Sidebar https://www.codeply.com/go/3e0RAjccRO/bootstrap-4-collapsing-sidebar-menu# -->
|
||||
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block">
|
||||
<!-- d-* hides the Sidebar in smaller devices. Its items can be kept on the Navbar 'Menu' -->
|
||||
<div id="sidebar-contents">
|
||||
<!-- Bootstrap List Group -->
|
||||
|
||||
<ul id="sections" data-pjax class="list-group">
|
||||
<li id="section_dashboard">
|
||||
<a data-pjax href="index.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-tachometer-alt fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Dashboard</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_multimedia">
|
||||
<a data-pjax href="multimedia.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-film fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Multimedia</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_network">
|
||||
<a data-pjax href="network.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-network-wired fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Network</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="section_management">
|
||||
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span class="digi-menu-icon fas fa-cog fa-fw fa-lg mr-3"></span>
|
||||
<span class="menu-collapsed">Management</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="collapsator" class="list-group">
|
||||
<a href="#top" data-toggle="sidebar-collapse" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<div class="d-flex w-100 justify-content-start align-items-center">
|
||||
<span id="collapse-icon" class="digi-menu-icon fas fa-fw fa-lg mr-3"></span>
|
||||
<span id="collapse-text" class="menu-collapsed">Collapse</span>
|
||||
</div>
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<div id="loading">
|
||||
<img id="loading-image" src="./static/images/loading.gif" alt="Loading..." />
|
||||
</div>
|
||||
<div id="pjax-container">
|
||||
<div class="row justify-content-lg-center">
|
||||
<div class="col-lg-12 col-xl-12">
|
||||
<div id="loading_popup" class="popup popup-loading shadow">
|
||||
<img class="popup-item" src="./static/images/loading.gif" alt="Loading..." />
|
||||
<div id="loading_popup_message" class="popup-text">Loading configuration...</div>
|
||||
</div>
|
||||
<div id="info_popup" class="popup popup-info shadow d-none">
|
||||
<div id="info_popup_title" class="popup-title">Error</div>
|
||||
<div id="info_popup_message" class="popup-text">-</div>
|
||||
</div>
|
||||
<div id="confirm_dialog" class="confirm-dialog d-none">
|
||||
<div class="device-card-header">
|
||||
<span class="fas fa-question-circle fa-lg mr-2"></span>
|
||||
<span id="confirm_dialog_title"></span>
|
||||
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="showPopup(ID_LOADING_WRAPPER, ID_CONFIRM_DIALOG, false)"></div>
|
||||
</div>
|
||||
<div id="confirm_dialog_message" class="confirm-dialog-message"></div>
|
||||
<div class="confirm-dialog-buttons-container">
|
||||
<div id="confirm_dialog_no_button" class="device-card-button confirm-dialog-button">No</div>
|
||||
<div id="confirm_dialog_yes_button" class="device-card-button confirm-dialog-button">Yes</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="loading_wrapper" class="loading-wrapper">
|
||||
<div class="card shadow-sm" style="padding: 0px">
|
||||
<div id="eth0_panel_header" class="interface-header" style="cursor: pointer;" onclick="togglePanelVisibility('eth0')">
|
||||
<span class="fas fa-ethernet fa-lg mr-2"></span>
|
||||
<span id="eth0_title" class="card-title interface-title">Ethernet 0</span>
|
||||
<div id="eth0_toggle_button" class="fas fa-caret-up fa-lg device-card-header-button"></div>
|
||||
</div>
|
||||
<div id="eth0_panel_container" class="interface-panel-container">
|
||||
<div>Configure ethernet parameters.</div>
|
||||
<div class="param-container">
|
||||
<span class="param-label">MAC Address:</span>
|
||||
<span id="eth0_mac" class="param-value"></span>
|
||||
</div>
|
||||
<div class="param-container">
|
||||
<span class="param-label">Connected:</span>
|
||||
<label class="switch-control">
|
||||
<input id="eth0_enable" type="checkbox">
|
||||
<span class="slider-control round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="eth0_ip_mode_param" class="param-container">
|
||||
<span class="param-label">IP mode:</span>
|
||||
<select name="eth0_ip_mode" id="eth0_ip_mode" class="select-control">
|
||||
<option value="static">Static</option>
|
||||
<option value="dhcp" selected="selected">DHCP</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="eth0_ip_addr_param" class="param-container">
|
||||
<span class="param-label">IP address:</span>
|
||||
<input id="eth0_ip_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth0_ip_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth0_subnet_mask_param" class="param-container">
|
||||
<span class="param-label">Subnet mask:</span>
|
||||
<input id="eth0_subnet_mask" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth0_subnet_mask_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth0_default_gateway_param" class="param-container">
|
||||
<span class="param-label">Default gateway:</span>
|
||||
<input id="eth0_default_gateway" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth0_default_gateway_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth0_dns1_addr_param" class="param-container">
|
||||
<span class="param-label">DNS1 address:</span>
|
||||
<input id="eth0_dns1_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth0_dns1_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth0_dns2_addr_param" class="param-container">
|
||||
<span class="param-label">DNS2 address:</span>
|
||||
<input id="eth0_dns2_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth0_dns2_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div class="buttons-container">
|
||||
<div id="eth0_refresh_button" class="device-card-button config-button" onclick="readConfiguration(['ethernet'], 'eth0')">Refresh</div>
|
||||
<div id="eth0_save_button" class="device-card-button config-button config-button-disabled" onclick="saveInterface('ethernet', 'eth0')">Save</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="eth1" class="card shadow-sm" style="padding: 0px">
|
||||
<div id="eth1_panel_header" class="interface-header" style="cursor: pointer;" onclick="togglePanelVisibility('eth1')">
|
||||
<span class="fas fa-ethernet fa-lg mr-2"></span>
|
||||
<span id="eth1_title" class="card-title interface-title">Ethernet 1</span>
|
||||
<div id="eth1_toggle_button" class="fas fa-caret-down fa-lg device-card-header-button"></div>
|
||||
</div>
|
||||
<div id="eth1_panel_container" class="interface-panel-container" style="display: none;">
|
||||
<div>Configure ethernet 1 parameters.</div>
|
||||
<div class="param-container">
|
||||
<span class="param-label">MAC Address:</span>
|
||||
<span id="eth1_mac" class="param-value"></span>
|
||||
</div>
|
||||
<div class="param-container">
|
||||
<span class="param-label">Connected:</span>
|
||||
<label class="switch-control">
|
||||
<input id="eth1_enable" type="checkbox">
|
||||
<span class="slider-control round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="eth1_ip_mode_param" class="param-container">
|
||||
<span class="param-label">IP mode:</span>
|
||||
<select name="eth1_ip_mode" id="eth1_ip_mode" class="select-control">
|
||||
<option value="static">Static</option>
|
||||
<option value="dhcp" selected="selected">DHCP</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="eth1_ip_addr_param" class="param-container">
|
||||
<span class="param-label">IP address:</span>
|
||||
<input id="eth1_ip_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth1_ip_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth1_subnet_mask_param" class="param-container">
|
||||
<span class="param-label">Subnet mask:</span>
|
||||
<input id="eth1_subnet_mask" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth1_subnet_mask_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth1_default_gateway_param" class="param-container">
|
||||
<span class="param-label">Default gateway:</span>
|
||||
<input id="eth1_default_gateway" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth1_default_gateway_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth1_dns1_addr_param" class="param-container">
|
||||
<span class="param-label">DNS1 address:</span>
|
||||
<input id="eth1_dns1_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth1_dns1_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="eth1_dns2_addr_param" class="param-container">
|
||||
<span class="param-label">DNS2 address:</span>
|
||||
<input id="eth1_dns2_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="eth1_dns2_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div class="buttons-container">
|
||||
<div id="eth1_refresh_button" class="device-card-button config-button" onclick="readConfiguration(['ethernet'], 'eth1')">Refresh</div>
|
||||
<div id="eth1_save_button" class="device-card-button config-button config-button-disabled" onclick="saveInterface('ethernet', 'eth1')">Save</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wlan0" class="card shadow-sm" style="padding: 0px;">
|
||||
<div id="wlan0_panel_header" class="interface-header" style="cursor: pointer;" onclick="togglePanelVisibility('wlan0')">
|
||||
<span class="fas fa-wifi fa-lg mr-2"></span>
|
||||
<span id="wlan0_title" class="card-title interface-title">Wi-Fi</span>
|
||||
<div id="wlan0_toggle_button" class="fas fa-caret-down fa-lg device-card-header-button"></div>
|
||||
</div>
|
||||
<div id="wlan0_panel_container" class="interface-panel-container" style="display: none;">
|
||||
<div>Configure wifi parameters.</div>
|
||||
<div class="param-container">
|
||||
<span class="param-label">MAC Address:</span>
|
||||
<span id="wlan0_mac" class="param-value"></span>
|
||||
</div>
|
||||
<div class="param-container">
|
||||
<span class="param-label">Connected:</span>
|
||||
<label class="switch-control">
|
||||
<input id="wlan0_enable" type="checkbox">
|
||||
<span class="slider-control round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="wlan0_ssid_param" class="param-container">
|
||||
<span class="param-label">SSID:</span>
|
||||
<input id="wlan0_ssid" class="input-control input-control-wide" type="text"/>
|
||||
<div id="wlan0_ssid_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="wlan0_enc_type_param" class="param-container">
|
||||
<span class="param-label">Encryption type:</span>
|
||||
<select name="wlan0_enc_type" id="wlan0_enc_type" class="select-control">
|
||||
<option value="0">Open</option>
|
||||
<option value="1">WPA</option>
|
||||
<option value="2">WPA2</option>
|
||||
<option value="3">WPA3</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="wlan0_password_param" class="param-container">
|
||||
<span class="param-label">Password:</span>
|
||||
<input id="wlan0_password" class="input-control input-control-wide" type="password"/>
|
||||
<div id="wlan0_password_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="wlan0_ip_mode_param" class="param-container">
|
||||
<span class="param-label">IP mode:</span>
|
||||
<select name="wlan0_ip_mode" id="wlan0_ip_mode" class="select-control">
|
||||
<option value="static">Static</option>
|
||||
<option value="dhcp" selected="selected">DHCP</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="wlan0_ip_addr_param" class="param-container">
|
||||
<span class="param-label">IP address:</span>
|
||||
<input id="wlan0_ip_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="wlan0_ip_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="wlan0_subnet_mask_param" class="param-container">
|
||||
<span class="param-label">Subnet mask:</span>
|
||||
<input id="wlan0_subnet_mask" class="input-control input-control-wide" type="text"/>
|
||||
<div id="wlan0_subnet_mask_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="wlan0_default_gateway_param" class="param-container">
|
||||
<span class="param-label">Default gateway:</span>
|
||||
<input id="wlan0_default_gateway" class="input-control input-control-wide" type="text"/>
|
||||
<div id="wlan0_default_gateway_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="wlan0_dns1_addr_param" class="param-container">
|
||||
<span class="param-label">DNS1 address:</span>
|
||||
<input id="wlan0_dns1_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="wlan0_dns1_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div id="wlan0_dns2_addr_param" class="param-container">
|
||||
<span class="param-label">DNS2 address:</span>
|
||||
<input id="wlan0_dns2_addr" class="input-control input-control-wide" type="text"/>
|
||||
<div id="wlan0_dns2_addr_error" class="error-label"></div>
|
||||
</div>
|
||||
<div class="buttons-container">
|
||||
<div id="wlan0_refresh_button" class="device-card-button config-button" onclick="readConfiguration(['wifi'], 'wlan0')">Refresh</div>
|
||||
<div id="wlan0_save_button" class="device-card-button config-button config-button-disabled" onclick="saveInterface('wifi', 'wlan0')">Save</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Reset variables.
|
||||
readingNetworkInfo = false;
|
||||
// Register input changed events.
|
||||
$('#eth0_enable').click(function(){
|
||||
updateInterfaceControls("eth0");
|
||||
});
|
||||
$("#eth0_ip_mode").on("change", function(event) {
|
||||
updateInterfaceControls("eth0");
|
||||
});
|
||||
$("#eth0_ip_addr").on("input", function(event) {
|
||||
validateInterface("eth0");
|
||||
});
|
||||
$("#eth0_subnet_mask").on("input", function(event) {
|
||||
validateInterface("eth0");
|
||||
});
|
||||
$("#eth0_default_gateway").on("input", function(event) {
|
||||
validateInterface("eth0");
|
||||
});
|
||||
$("#eth0_dns1_addr").on("input", function(event) {
|
||||
validateInterface("eth0");
|
||||
});
|
||||
$("#eth0_dns2_addr").on("input", function(event) {
|
||||
validateInterface("eth0");
|
||||
});
|
||||
$('#eth1_enable').click(function(){
|
||||
updateInterfaceControls("eth1");
|
||||
});
|
||||
$("#eth1_ip_mode").on("change", function(event) {
|
||||
updateInterfaceControls("eth1");
|
||||
});
|
||||
$("#eth1_ip_addr").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$("#eth1_subnet_mask").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$('#eth1_enable').click(function(){
|
||||
updateInterfaceControls("eth1");
|
||||
});
|
||||
$("#eth1_ip_mode").on("change", function(event) {
|
||||
updateInterfaceControls("eth1");
|
||||
});
|
||||
$("#eth1_ip_addr").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$("#eth1_subnet_mask").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$("#eth1_default_gateway").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$("#eth1_dns1_addr").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$("#eth1_dns2_addr").on("input", function(event) {
|
||||
validateInterface("eth1");
|
||||
});
|
||||
$('#wlan0_enable').click(function(){
|
||||
updateInterfaceControls("wlan0");
|
||||
});
|
||||
$("#wlan0_ssid").on("input", function(event) {
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
$("#wlan0_enc_type").on("change", function(event) {
|
||||
document.getElementById("wlan0_password").value = "";
|
||||
passwordChanged = true;
|
||||
updateInterfaceControls("wlan0");
|
||||
});
|
||||
$("#wlan0_password").on("input", function(event) {
|
||||
passwordChanged = true;
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
$("#wlan0_ip_mode").on("change", function(event) {
|
||||
updateInterfaceControls("wlan0");
|
||||
});
|
||||
$("#wlan0_ip_addr").on("input", function(event) {
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
$("#wlan0_subnet_mask").on("input", function(event) {
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
$("#wlan0_default_gateway").on("input", function(event) {
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
$("#wlan0_dns1_addr").on("input", function(event) {
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
$("#wlan0_dns2_addr").on("input", function(event) {
|
||||
validateInterface("wlan0");
|
||||
});
|
||||
// Gray out page.
|
||||
document.getElementById("loading_wrapper").classList.add("element-grayed");
|
||||
// Update all controls.
|
||||
updateAllControls();
|
||||
// Initialize page.
|
||||
initializeNetworkPage();
|
||||
});
|
||||
</script>
|
||||
|
||||
</div> <!-- pjax-container -->
|
||||
|
||||
</div> <!-- container fluid -->
|
||||
</div> <!--bg light -->
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#banner-link").on({
|
||||
"mouseover" : function() {
|
||||
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner_gray.png");
|
||||
},
|
||||
"mouseout" : function() {
|
||||
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner.png");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Enable the tooltip library.
|
||||
$(function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Local JS files and functions -->
|
||||
<script type="text/javascript" src="./static/js/sidebar.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccmp157-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx6ulsbc.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
|
||||
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
|
||||
<script type="text/javascript" src="./static/js/dashboard.js"></script>
|
||||
<script type="text/javascript" src="./static/js/network.js"></script>
|
||||
<script type="text/javascript" src="./static/js/multimedia.js"></script>
|
||||
<script type="text/javascript" src="./static/js/management.js"></script>
|
||||
<script type="text/javascript" src="./static/js/file-system.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Don't show the loading spinner at the beginning. Initial page
|
||||
// load is full, so not relying on AJAX.
|
||||
$("#loading").hide();
|
||||
|
||||
// Set up PJAX.
|
||||
if ($.support.pjax) {
|
||||
$.pjax.defaults.timeout = 20000;
|
||||
$.pjax.defaults.fragment = "#pjax-container";
|
||||
$(document).pjax("a[data-pjax]", "#pjax-container");
|
||||
|
||||
$(document).on("pjax:beforeSend", function() {
|
||||
// Do not load new content if there are unsaved changes.
|
||||
if ($("#save-schedule").length && !$("#save-schedule").attr("disabled") && !confirm("There are unsaved changes. Do you want to exit?"))
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).on("pjax:send", function(e) {
|
||||
setSelectedSection(e.currentTarget.activeElement);
|
||||
$("#pjax-container").hide();
|
||||
$("#loading").show();
|
||||
});
|
||||
|
||||
$(document).on("pjax:complete", function() {
|
||||
$("#loading").hide();
|
||||
$("#pjax-container").show();
|
||||
});
|
||||
}
|
||||
|
||||
// Append the URL parameters to the section links.
|
||||
var params = new URLSearchParams(window.location.search).toString();
|
||||
if (params) {
|
||||
$("#sections li").each(function(i, n) {
|
||||
n.children[0].href += "?" + params;
|
||||
});
|
||||
}
|
||||
|
||||
// Update available sections.
|
||||
updateAvailableSections();
|
||||
|
||||
// Set the selected section.
|
||||
setSelectedSection();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -373,7 +373,7 @@ body {
|
|||
/* POPUP */
|
||||
.popup {
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: white;
|
||||
padding: 20px 10px;
|
||||
|
|
@ -1058,11 +1058,24 @@ body {
|
|||
|
||||
/* AUDIO */
|
||||
.audio-panel {
|
||||
width: 350px;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
#audio_panel .slider-horizontal {
|
||||
width: 180px;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.audio-button {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.audio-button:hover {
|
||||
cursor: pointer;
|
||||
color: var(--digi-green);
|
||||
}
|
||||
/* END AUDIO */
|
||||
|
||||
|
|
@ -1869,20 +1882,25 @@ body {
|
|||
}
|
||||
/* END MULTIMEDIA VIEWER */
|
||||
|
||||
/* MANAGEMENT */
|
||||
.system-monitor-param-container {
|
||||
/* CONFIG CONTROLS */
|
||||
.param-container {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.system-monitor-param-label {
|
||||
.param-label {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
.system-monitor-input {
|
||||
.param-value {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-control {
|
||||
position: relative;
|
||||
-webkit-transition: none !important;
|
||||
-moz-transition: none !important;
|
||||
|
|
@ -1892,13 +1910,100 @@ body {
|
|||
width: 80px !important;
|
||||
padding: 0px !important;
|
||||
margin: 0px !important;
|
||||
text-align: left !important;
|
||||
padding-left: 5px !important;
|
||||
}
|
||||
|
||||
.system-monitor-input-error {
|
||||
.input-control-wide {
|
||||
width: 180px !important;
|
||||
}
|
||||
|
||||
.input-control-error {
|
||||
background-color: #f3b1b1 !important;
|
||||
}
|
||||
|
||||
.system-monitor-error {
|
||||
.input-control-disabled {
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
pointer-events: none !important;
|
||||
color: #939393 !important;
|
||||
}
|
||||
|
||||
.select-control {
|
||||
position: relative;
|
||||
-webkit-transition: none !important;
|
||||
-moz-transition: none !important;
|
||||
-ms-transition: none !important;
|
||||
-o-transition: none !important;
|
||||
transition: none !important;
|
||||
width: 80px !important;
|
||||
padding: 0px !important;
|
||||
margin: 0px !important;
|
||||
text-align-last: left !important;
|
||||
padding-left: 5px !important;
|
||||
}
|
||||
|
||||
.switch-control {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 48px;
|
||||
height: 22px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.switch-control input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.slider-control {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider-control:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider-control {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus + .slider-control {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked + .slider-control:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
.slider-control.round {
|
||||
border-radius: 11px;
|
||||
}
|
||||
|
||||
.slider-control.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.error-label {
|
||||
color: red;
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
|
|
@ -1906,6 +2011,67 @@ body {
|
|||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.buttons-container {
|
||||
with: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.config-button {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0;
|
||||
margin-top: 15px;
|
||||
width: 100px;
|
||||
float: left;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.config-button-disabled {
|
||||
cursor: default;
|
||||
color: white;
|
||||
background-color: #c3c3c3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type=text], input[type=password], select {
|
||||
background-color: #f6f6f6;
|
||||
border: none;
|
||||
color: #0d0d0d;
|
||||
padding: 12px 30px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
margin: 0px 0px 25px 0px;
|
||||
width: 85%;
|
||||
border: 2px solid #f6f6f6;
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
-ms-transition: all 0.5s ease-in-out;
|
||||
-o-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out;
|
||||
-webkit-border-radius: 5px 5px 5px 5px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
input[type=text]:focus, input[type=password]:focus, select:focus {
|
||||
background-color: #fff;
|
||||
border-bottom: 2px solid var(--digi-green);
|
||||
}
|
||||
|
||||
select {
|
||||
-moz-appearance:none; /* Firefox */
|
||||
-webkit-appearance:none; /* Safari and Chrome */
|
||||
appearance:none;
|
||||
text-align-last: center;
|
||||
background-image: url("../images/combo_arrow_gray.png");
|
||||
background-repeat: no-repeat, repeat;
|
||||
background-position: right .7em top 50%;
|
||||
background-size: .65em auto;
|
||||
}
|
||||
/* END CONFIG CONTROLS */
|
||||
|
||||
/* MANAGEMENT */
|
||||
.system-monitor-help {
|
||||
font-size: 16px;
|
||||
padding-left: 5px;
|
||||
|
|
@ -1927,21 +2093,6 @@ body {
|
|||
outline: none;
|
||||
}
|
||||
|
||||
.system-monitor-save {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0;
|
||||
margin-top: 15px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.system-monitor-save-disabled {
|
||||
cursor: default;
|
||||
color: white;
|
||||
background-color: #c3c3c3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.firmware-file-input {
|
||||
position: relative;
|
||||
margin-top: 15px;
|
||||
|
|
@ -1996,13 +2147,6 @@ body {
|
|||
background-color: #a72a2a;
|
||||
}
|
||||
|
||||
.management-button-disabled {
|
||||
cursor: default;
|
||||
color: #c3c3c3;
|
||||
background-color: #e3e3e3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.update-firmware-progress {
|
||||
position: relative;
|
||||
margin-top: 15px;
|
||||
|
|
@ -2196,3 +2340,20 @@ body {
|
|||
margin-top: 5px;
|
||||
}
|
||||
/* END MANAGEMENT */
|
||||
|
||||
/* NETWORK */
|
||||
.interface-header {
|
||||
padding: 15px 20px 10px 20px;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.interface-panel-container {
|
||||
padding: 0px 20px 15px 20px;
|
||||
}
|
||||
|
||||
.interface-title {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
/* END NETWORK */
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
|
Before Width: | Height: | Size: 564 KiB After Width: | Height: | Size: 564 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
|
@ -110,17 +110,17 @@ class CCIMX6ULSBC extends ConnectCoreDevice {
|
|||
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 21;
|
||||
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 8;
|
||||
|
||||
AUDIO_COMPONENT_VISIBLE = false;
|
||||
AUDIO_COMPONENT_VISIBLE = true;
|
||||
AUDIO_COMPONENT_HAS_PANEL = true;
|
||||
AUDIO_COMPONENT_HAS_ARROW = true;
|
||||
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
|
||||
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 51;
|
||||
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 28;
|
||||
AUDIO_COMPONENT_ARROW_PERCENT = 69;
|
||||
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
|
||||
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 76.5;
|
||||
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 76;
|
||||
AUDIO_COMPONENT_ARROW_PERCENT = 81.5;
|
||||
AUDIO_COMPONENT_AREA_TOP_PERCENT = 74;
|
||||
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 66;
|
||||
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 9.3;
|
||||
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 9.5;
|
||||
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 18.5;
|
||||
|
||||
LED_COMPONENT_VISIBLE = true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright 2022, Digi International Inc.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
class CCMP133 extends ConnectCoreDevice {
|
||||
|
||||
// Public constants.
|
||||
static DEVICE_TYPE = "ccmp133-dvk";
|
||||
static PLATFORM_NAME = "ConnectCore MP133";
|
||||
|
||||
// Variables.
|
||||
BOARD_IMAGE = "ccmp133_board.png";
|
||||
BOARD_IMAGE_SCALE = 82;
|
||||
|
||||
CPU_COMPONENT_VISIBLE = true;
|
||||
CPU_COMPONENT_HAS_PANEL = true;
|
||||
CPU_COMPONENT_HAS_ARROW = true;
|
||||
CPU_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
CPU_COMPONENT_PANEL_ORIENTATION = VALUE_RIGHT;
|
||||
CPU_COMPONENT_PANEL_HORIZONTAL_PERCENT = 68.5;
|
||||
CPU_COMPONENT_PANEL_VERTICAL_PERCENT = 45;
|
||||
CPU_COMPONENT_ARROW_PERCENT = 54.5;
|
||||
CPU_COMPONENT_AREA_TOP_PERCENT = 50;
|
||||
CPU_COMPONENT_AREA_LEFT_PERCENT = 32.9;
|
||||
CPU_COMPONENT_AREA_WIDTH_PERCENT = 10;
|
||||
CPU_COMPONENT_AREA_HEIGHT_PERCENT = 13;
|
||||
|
||||
MEMORY_COMPONENT_VISIBLE = true;
|
||||
MEMORY_COMPONENT_HAS_PANEL = true;
|
||||
MEMORY_COMPONENT_HAS_ARROW = true;
|
||||
MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
|
||||
MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 25;
|
||||
MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 67.5;
|
||||
MEMORY_COMPONENT_ARROW_PERCENT = 37;
|
||||
MEMORY_COMPONENT_AREA_TOP_PERCENT = 34.5;
|
||||
MEMORY_COMPONENT_AREA_LEFT_PERCENT = 31.1;
|
||||
MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 15.4;
|
||||
MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 15.5;
|
||||
|
||||
WIFI_BT_COMPONENT_VISIBLE = true;
|
||||
WIFI_BT_COMPONENT_HAS_PANEL = true;
|
||||
WIFI_BT_COMPONENT_HAS_ARROW = true;
|
||||
WIFI_BT_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
WIFI_BT_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
|
||||
WIFI_BT_COMPONENT_PANEL_HORIZONTAL_PERCENT = 55;
|
||||
WIFI_BT_COMPONENT_PANEL_VERTICAL_PERCENT = 28;
|
||||
WIFI_BT_COMPONENT_ARROW_PERCENT = 43.5;
|
||||
WIFI_BT_COMPONENT_AREA_TOP_PERCENT = 41;
|
||||
WIFI_BT_COMPONENT_AREA_LEFT_PERCENT = 46.7;
|
||||
WIFI_BT_COMPONENT_AREA_WIDTH_PERCENT = 6.8;
|
||||
WIFI_BT_COMPONENT_AREA_HEIGHT_PERCENT = 9;
|
||||
|
||||
ETHERNET0_COMPONENT_VISIBLE = true;
|
||||
ETHERNET0_COMPONENT_HAS_PANEL = true;
|
||||
ETHERNET0_COMPONENT_HAS_ARROW = true;
|
||||
ETHERNET0_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
ETHERNET0_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
|
||||
ETHERNET0_COMPONENT_PANEL_HORIZONTAL_PERCENT = -3;
|
||||
ETHERNET0_COMPONENT_PANEL_VERTICAL_PERCENT = 73;
|
||||
ETHERNET0_COMPONENT_ARROW_PERCENT = 8;
|
||||
ETHERNET0_COMPONENT_AREA_TOP_PERCENT = 29;
|
||||
ETHERNET0_COMPONENT_AREA_LEFT_PERCENT = 3.8;
|
||||
ETHERNET0_COMPONENT_AREA_WIDTH_PERCENT = 12.2;
|
||||
ETHERNET0_COMPONENT_AREA_HEIGHT_PERCENT = 12.5;
|
||||
|
||||
CONSOLE_COMPONENT_VISIBLE = true;
|
||||
CONSOLE_COMPONENT_HAS_PANEL = false;
|
||||
CONSOLE_COMPONENT_HAS_ARROW = false;
|
||||
CONSOLE_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
CONSOLE_COMPONENT_AREA_TOP_PERCENT = 79.9;
|
||||
CONSOLE_COMPONENT_AREA_LEFT_PERCENT = 90.5;
|
||||
CONSOLE_COMPONENT_AREA_WIDTH_PERCENT = 3.3;
|
||||
CONSOLE_COMPONENT_AREA_HEIGHT_PERCENT = 6.2;
|
||||
|
||||
VIDEO_COMPONENT_VISIBLE = true;
|
||||
VIDEO_COMPONENT_HAS_PANEL = true;
|
||||
VIDEO_COMPONENT_HAS_ARROW = true;
|
||||
VIDEO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
VIDEO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
|
||||
VIDEO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 55;
|
||||
VIDEO_COMPONENT_PANEL_VERTICAL_PERCENT = 16;
|
||||
VIDEO_COMPONENT_ARROW_PERCENT = 72.8;
|
||||
VIDEO_COMPONENT_AREA_TOP_PERCENT = 4.8;
|
||||
VIDEO_COMPONENT_AREA_LEFT_PERCENT = 70.2;
|
||||
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 8.6;
|
||||
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 9.1;
|
||||
|
||||
AUDIO_COMPONENT_VISIBLE = true;
|
||||
AUDIO_COMPONENT_HAS_PANEL = true;
|
||||
AUDIO_COMPONENT_HAS_ARROW = true;
|
||||
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
|
||||
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 81;
|
||||
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 37;
|
||||
AUDIO_COMPONENT_ARROW_PERCENT = 87;
|
||||
AUDIO_COMPONENT_AREA_TOP_PERCENT = 28;
|
||||
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 83.5;
|
||||
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 10.2;
|
||||
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 7;
|
||||
|
||||
LED_COMPONENT_VISIBLE = true;
|
||||
LED_COMPONENT_HAS_PANEL = true;
|
||||
LED_COMPONENT_HAS_ARROW = false;
|
||||
LED_COMPONENT_PANEL_ALWAYS_VISIBLE = true;
|
||||
LED_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
|
||||
LED_COMPONENT_PANEL_HORIZONTAL_PERCENT = 69;
|
||||
LED_COMPONENT_PANEL_VERTICAL_PERCENT = 10;
|
||||
LED_COMPONENT_AREA_TOP_PERCENT = 91;
|
||||
LED_COMPONENT_AREA_LEFT_PERCENT = 70.6;
|
||||
LED_COMPONENT_AREA_WIDTH_PERCENT = 1.8;
|
||||
LED_COMPONENT_AREA_HEIGHT_PERCENT = 4;
|
||||
|
||||
FLASH_MEMORY_COMPONENT_VISIBLE = true;
|
||||
FLASH_MEMORY_COMPONENT_HAS_PANEL = true;
|
||||
FLASH_MEMORY_COMPONENT_HAS_ARROW = true;
|
||||
FLASH_MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
FLASH_MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
|
||||
FLASH_MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 27;
|
||||
FLASH_MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 65;
|
||||
FLASH_MEMORY_COMPONENT_ARROW_PERCENT = 46.7;
|
||||
FLASH_MEMORY_COMPONENT_AREA_TOP_PERCENT = 50;
|
||||
FLASH_MEMORY_COMPONENT_AREA_LEFT_PERCENT = 43.5;
|
||||
FLASH_MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 10;
|
||||
FLASH_MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 13;
|
||||
|
||||
|
||||
// Capabilities
|
||||
SUPPORTS_VIDEO_BRIGHTNESS = false;
|
||||
SUPPORTS_DUAL_ETHERNET = false;
|
||||
|
||||
// Constructor.
|
||||
constructor(deviceData) {
|
||||
super(CCMP133.DEVICE_TYPE, CCMP133.PLATFORM_NAME, deviceData);
|
||||
}
|
||||
}
|
||||
|
|
@ -97,18 +97,18 @@ class CCMP157 extends ConnectCoreDevice {
|
|||
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 8.6;
|
||||
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 9.1;
|
||||
|
||||
AUDIO_COMPONENT_VISIBLE = false;
|
||||
AUDIO_COMPONENT_VISIBLE = true;
|
||||
AUDIO_COMPONENT_HAS_PANEL = true;
|
||||
AUDIO_COMPONENT_HAS_ARROW = true;
|
||||
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
|
||||
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
|
||||
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 1;
|
||||
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 19;
|
||||
AUDIO_COMPONENT_ARROW_PERCENT = 16;
|
||||
AUDIO_COMPONENT_AREA_TOP_PERCENT = 7;
|
||||
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 14.5;
|
||||
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 5.4;
|
||||
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 11;
|
||||
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 81;
|
||||
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 37;
|
||||
AUDIO_COMPONENT_ARROW_PERCENT = 87;
|
||||
AUDIO_COMPONENT_AREA_TOP_PERCENT = 28;
|
||||
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 83.5;
|
||||
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 10.2;
|
||||
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 7;
|
||||
|
||||
LED_COMPONENT_VISIBLE = true;
|
||||
LED_COMPONENT_HAS_PANEL = true;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ const ID_CPU_TEMPERATURE = "cpu_temperature";
|
|||
const ID_CPU_UPTIME = "cpu_uptime";
|
||||
const ID_CURRENT_DIR = "current_dir";
|
||||
const ID_DATA = "data";
|
||||
const ID_DESC = "desc";
|
||||
const ID_DEVICE_NAME = "device-name";
|
||||
const ID_DEVICE_TYPE = "device_type";
|
||||
const ID_DEVICES = "devices";
|
||||
|
|
@ -133,18 +134,31 @@ const VALUE_SUCCESSFUL = "successful";
|
|||
const VALUE_TOP = "top";
|
||||
const VALUE_UNKNOWN = "unknown";
|
||||
|
||||
const CLASS_ARROW_DOWN = "fa-caret-down";
|
||||
const CLASS_ARROW_UP = "fa-caret-up";
|
||||
const CLASS_D_NONE = "d-none";
|
||||
const CLASS_DISABLED_DIV = "disabled-div";
|
||||
const CLASS_ELEMENT_GRAYED = "element-grayed";
|
||||
const CLASS_INPUT_DISABLED = "input-control-disabled";
|
||||
const CLASS_INPUT_ERROR = "input-control-error";
|
||||
const CLASS_CONFIG_BUTTON_DISABLED = "config-button-disabled";
|
||||
const CLASS_SELECTED = "selected";
|
||||
const CLASS_VALUE_ANIMATION = "value-animation";
|
||||
const CLASS_VALUE_UPDATED = "value-updated";
|
||||
|
||||
const ERROR_ABORTED = "Operation aborted";
|
||||
const ERROR_BAD_REQUEST = "Bad request";
|
||||
const ERROR_FIELD_EMPTY = "Field cannot be empty";
|
||||
const ERROR_FORBIDDEN = "Could not perform the selected action. Make sure you have the correct access rights.";
|
||||
const ERROR_URL_NOT_FOUND = "Requested URL not found";
|
||||
const ERROR_SERVER_ERROR = "Internal server error";
|
||||
const ERROR_TITLE = "Error";
|
||||
const ERROR_UNKNOWN_ERROR = "Unknown error";
|
||||
const ERROR_UNKNOWN_ERROR = "Unknown error. Make sure that the server is running.";
|
||||
|
||||
const IFACE_BT = "hci0";
|
||||
const IFACE_ETH0 = "eth0";
|
||||
const IFACE_ETH1 = "eth1";
|
||||
const IFACE_WIFI = "wlan0";
|
||||
|
||||
const PREFIX_STREAM = "system_monitor/";
|
||||
const STREAM_CPU_LOAD = PREFIX_STREAM + "cpu_load";
|
||||
|
|
@ -237,8 +251,10 @@ function processAjaxErrorResponse(response) {
|
|||
errorMessage = response.responseJSON[ID_ERROR];
|
||||
// Show the error message (if any).
|
||||
if (errorMessage == null)
|
||||
errorMessage = ERROR_UNKNOWN_ERROR;
|
||||
} else if (response.status == 404)
|
||||
errorMessage = ERROR_BAD_REQUEST;
|
||||
} else if (response.status == 403)
|
||||
errorMessage = ERROR_FORBIDDEN;
|
||||
else if (response.status == 404)
|
||||
errorMessage = ERROR_URL_NOT_FOUND;
|
||||
else if (response.status == 500)
|
||||
errorMessage = ERROR_SERVER_ERROR;
|
||||
|
|
@ -475,6 +491,11 @@ function isDashboardShowing() {
|
|||
return window.location.pathname.indexOf("index") > -1;
|
||||
}
|
||||
|
||||
// Returns whether the network page is showing or not.
|
||||
function isNetworkShowing() {
|
||||
return window.location.pathname.indexOf("network") > -1;
|
||||
}
|
||||
|
||||
// Returns whether the management page is showing or not.
|
||||
function isManagementShowing() {
|
||||
return window.location.pathname.indexOf("management") > -1;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Music by https://www.bensound.com
|
||||
*/
|
||||
|
||||
// Constants.
|
||||
|
|
@ -55,6 +57,7 @@ const ID_MEMORY_PANEL_AREA = "memory_panel_area";
|
|||
const ID_MEMORY_PANEL_ARROW = "memory_panel_arrow";
|
||||
const ID_MEMORY_PANEL_ICON = "memory_panel_icon";
|
||||
const ID_PLATFORM_NAME = "platform_name";
|
||||
const ID_PLAY = "play";
|
||||
const ID_VIDEO_BRIGHTNESS_CONTAINER = "video_brightness_container";
|
||||
const ID_VIDEO_PANEL = "video_panel";
|
||||
const ID_VIDEO_PANEL_AREA = "video_panel_area";
|
||||
|
|
@ -66,36 +69,29 @@ const ID_WIFI_BT_PANEL_AREA = "wifi_bt_panel_area";
|
|||
const ID_WIFI_BT_PANEL_ARROW = "wifi_bt_panel_arrow";
|
||||
const ID_WIFI_BT_PANEL_ICON = "wifi_bt_panel_icon";
|
||||
|
||||
const IFACE_BT = "hci0/";
|
||||
const IFACE_ETHERNET0 = "eth0/";
|
||||
const IFACE_ETHERNET1 = "eth1/";
|
||||
const IFACE_WIFI = "wlan0/";
|
||||
|
||||
const USER_LED = "user_led";
|
||||
|
||||
const STREAM_CPU_FREQUENCY = PREFIX_STREAM + "frequency";
|
||||
const STREAM_CPU_TEMPERATURE = PREFIX_STREAM + "cpu_temperature";
|
||||
const STREAM_CPU_UPTIME = PREFIX_STREAM + "uptime";
|
||||
const STREAM_ETHERNET0_READ_BYTES = PREFIX_STREAM + IFACE_ETHERNET0 + "rx_bytes";
|
||||
const STREAM_ETHERNET0_SENT_BYTES = PREFIX_STREAM + IFACE_ETHERNET0 + "tx_bytes";
|
||||
const STREAM_ETHERNET0_STATE = PREFIX_STREAM + IFACE_ETHERNET0 + "state";
|
||||
const STREAM_ETHERNET1_READ_BYTES = PREFIX_STREAM + IFACE_ETHERNET1 + "rx_bytes";
|
||||
const STREAM_ETHERNET1_SENT_BYTES = PREFIX_STREAM + IFACE_ETHERNET1 + "tx_bytes";
|
||||
const STREAM_ETHERNET1_STATE = PREFIX_STREAM + IFACE_ETHERNET1 + "state";
|
||||
const STREAM_ETHERNET0_READ_BYTES = PREFIX_STREAM + IFACE_ETH0 + "/rx_bytes";
|
||||
const STREAM_ETHERNET0_SENT_BYTES = PREFIX_STREAM + IFACE_ETH0 + "/tx_bytes";
|
||||
const STREAM_ETHERNET0_STATE = PREFIX_STREAM + IFACE_ETH0 + "/state";
|
||||
const STREAM_ETHERNET1_READ_BYTES = PREFIX_STREAM + IFACE_ETH1 + "/rx_bytes";
|
||||
const STREAM_ETHERNET1_SENT_BYTES = PREFIX_STREAM + IFACE_ETH1 + "/tx_bytes";
|
||||
const STREAM_ETHERNET1_STATE = PREFIX_STREAM + IFACE_ETH1 + "/state";
|
||||
const STREAM_LED_STATUS = PREFIX_STREAM + "led_status";
|
||||
const STREAM_MEMORY_USED = PREFIX_STREAM + "used_memory";
|
||||
const STREAM_WIFI_READ_BYTES = PREFIX_STREAM + IFACE_WIFI + "rx_bytes";
|
||||
const STREAM_WIFI_SENT_BYTES = PREFIX_STREAM + IFACE_WIFI + "tx_bytes";
|
||||
const STREAM_WIFI_STATE = PREFIX_STREAM + IFACE_WIFI + "state";
|
||||
const STREAM_BT_READ_BYTES = PREFIX_STREAM + IFACE_BT + "rx_bytes";
|
||||
const STREAM_BT_SENT_BYTES = PREFIX_STREAM + IFACE_BT + "tx_bytes";
|
||||
const STREAM_BT_STATE = PREFIX_STREAM + IFACE_BT + "state";
|
||||
const STREAM_WIFI_READ_BYTES = PREFIX_STREAM + IFACE_WIFI + "/rx_bytes";
|
||||
const STREAM_WIFI_SENT_BYTES = PREFIX_STREAM + IFACE_WIFI + "/tx_bytes";
|
||||
const STREAM_WIFI_STATE = PREFIX_STREAM + IFACE_WIFI + "/state";
|
||||
const STREAM_BT_READ_BYTES = PREFIX_STREAM + IFACE_BT + "/rx_bytes";
|
||||
const STREAM_BT_SENT_BYTES = PREFIX_STREAM + IFACE_BT + "/tx_bytes";
|
||||
const STREAM_BT_STATE = PREFIX_STREAM + IFACE_BT + "/state";
|
||||
|
||||
const PANEL_ARROW_WIDTH_100 = 20;
|
||||
const PANEL_BOARD_WIDTH_100 = 1200;
|
||||
|
||||
const CLASS_ARROW_DOWN = "fa-caret-down";
|
||||
const CLASS_ARROW_UP = "fa-caret-up";
|
||||
const CLASS_LED_PANEL_AREA_ON = "led-panel-area-on";
|
||||
const CLASS_PANEL_AREA_SELECTED = "panel-area-selected";
|
||||
const CLASS_PANEL_AREA_ICON_SELECTED = "panel-area-icon-selected";
|
||||
|
|
@ -103,6 +99,9 @@ const CLASS_PANEL_TOOLTIP = "panel-tooltip";
|
|||
|
||||
const MESSAGE_CHANGING_VIDEO_BRIGHTNESS = "Changing video brightness...";
|
||||
const MESSAGE_CHANGING_AUDIO_VOLUME = "Changing audio volume...";
|
||||
const MESSAGE_MUSIC_PLAYING = "Music playing..."
|
||||
const MESSAGE_MUSIC_STOPPED = "Music stopped."
|
||||
const MESSAGE_PLAY_MUSIC = "Setting play music value..."
|
||||
const MESSAGE_READING_DEVICE_INFO = "Reading device info...";
|
||||
const MESSAGE_READING_DEVICE_STATUS = "Reading device status...";
|
||||
const MESSAGE_TOGGLING_LED_VALUE = "Toggling LED value...";
|
||||
|
|
@ -111,6 +110,8 @@ const ERROR_LED_UNKNOWN = "LED status has not been read yet, please wait.";
|
|||
const ERROR_NOT_SUPPORTED_DEVICE_MESSAGE = "The selected device type is not supported: {0}";
|
||||
const ERROR_NOT_SUPPORTED_DEVICE_TITLE = "Unsupported device";
|
||||
|
||||
const MUSIC_FILE = "/srv/www/static/sounds/inspire.mp3"
|
||||
|
||||
// Variables.
|
||||
var deviceInitialized = false;
|
||||
var device = null;
|
||||
|
|
@ -239,6 +240,7 @@ function processDeviceInfoResponse(response) {
|
|||
// Position components after some time to give time to the image to load.
|
||||
window.setTimeout(function () {
|
||||
positionComponents();
|
||||
adjustImageSize();
|
||||
setInfoPanelsVisible(false);
|
||||
}, 500);
|
||||
// Read device status.
|
||||
|
|
@ -368,6 +370,9 @@ function createDevice(deviceData) {
|
|||
case CCMP157.DEVICE_TYPE:
|
||||
device = new CCMP157(deviceData);
|
||||
break;
|
||||
case CCMP133.DEVICE_TYPE:
|
||||
device = new CCMP133(deviceData);
|
||||
break;
|
||||
}
|
||||
if (device != null) {
|
||||
// Draw the device.
|
||||
|
|
@ -934,6 +939,50 @@ function processSetVideoBrightnessResponse(response) {
|
|||
videoSlider.enable();
|
||||
}
|
||||
|
||||
// Handles what happens when the Play music button is pressed.
|
||||
function playMusic(play) {
|
||||
// Show the loading panel of the device.
|
||||
showLoadingPopup(true, MESSAGE_PLAY_MUSIC);
|
||||
// Send request to play music.
|
||||
$.post(
|
||||
"http://" + getServerAddress() + "/ajax/play_music",
|
||||
JSON.stringify({
|
||||
"play": play,
|
||||
"music_file": MUSIC_FILE
|
||||
}),
|
||||
function(data) {
|
||||
// Process only in the dashboard page.
|
||||
if (!isDashboardShowing())
|
||||
return;
|
||||
// Process answer.
|
||||
processPlayMusicResponse(data);
|
||||
}
|
||||
).fail(function(response) {
|
||||
// Process only in the dashboard page.
|
||||
if (!isDashboardShowing())
|
||||
return;
|
||||
// Process error.
|
||||
processAjaxErrorResponse(response);
|
||||
// Hide the loading panel of the device.
|
||||
showLoadingPopup(false);
|
||||
});
|
||||
}
|
||||
|
||||
// Processes the "play music" request answer.
|
||||
function processPlayMusicResponse(response) {
|
||||
// Check if there was any error in the request.
|
||||
if (!checkErrorResponse(response, false)) {
|
||||
play = response[ID_PLAY];
|
||||
// Show confirmation.
|
||||
if (play)
|
||||
toastr.info(MESSAGE_MUSIC_PLAYING);
|
||||
else
|
||||
toastr.info(MESSAGE_MUSIC_STOPPED);
|
||||
}
|
||||
// Hide the loading panel of the device.
|
||||
showLoadingPopup(false);
|
||||
}
|
||||
|
||||
// Processes an audio volume changed event.
|
||||
function volumeChanged(newValue) {
|
||||
// Show the loading panel of the device.
|
||||
|
|
@ -976,10 +1025,9 @@ function processSetAudioVolumeResponse(response) {
|
|||
audioSlider.setValue(volume);
|
||||
} else {
|
||||
// Save new volume value.
|
||||
volume = response["value"];
|
||||
if (volume == null)
|
||||
volume = audioSlider.getValue();
|
||||
audioSlider.setValue(volume);
|
||||
// Show confirmation.
|
||||
toastr.info("Volume changed to " + volume + "%")
|
||||
}
|
||||
// Hide the loading panel of the device.
|
||||
showLoadingPopup(false);
|
||||
|
|
@ -1049,6 +1097,10 @@ function processSetLEDResponse(response) {
|
|||
if (!checkErrorResponse(response, false)) {
|
||||
// Update the LED status.
|
||||
updateLEDStatus();
|
||||
if (ledStatus)
|
||||
toastr.info("User LED set to ON");
|
||||
else
|
||||
toastr.info("User LED set to OFF");
|
||||
}
|
||||
// Hide the loading panel of the device.
|
||||
showLoadingPopup(false);
|
||||
|
|
|
|||
|
|
@ -325,6 +325,11 @@ class ConnectCoreDevice {
|
|||
return this.#ethernetIP[index];
|
||||
}
|
||||
|
||||
// Returns whether the device supports Wifi or not.
|
||||
hasWifi() {
|
||||
return this.#wifiMAC != null && this.#wifiMAC != "undefined"
|
||||
}
|
||||
|
||||
// Returns the device WiFi MAC address.
|
||||
getWifiMAC() {
|
||||
return this.#wifiMAC;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ const ID_UPDATE_RUNNING = "update_running";
|
|||
const CLASS_FIRMWARE_TAB = "firmware-tab";
|
||||
const CLASS_FIRMWARE_TAB_HEADER = "firmware-tab-header";
|
||||
const CLASS_FIRMWARE_TAB_HEADER_ACTIVE = "firmware-tab-header-active";
|
||||
const CLASS_MANAGEMENT_BUTTON_DISABLED = "management-button-disabled";
|
||||
const CLASS_PROGRESS_BAR_ERROR = "update-firmware-progress-bar-error";
|
||||
const CLASS_PROGRESS_BAR_INFO = "update-firmware-progress-bar-info";
|
||||
const CLASS_PROGRESS_BAR_SUCCESS = "update-firmware-progress-bar-success";
|
||||
|
|
@ -625,10 +624,12 @@ function enableManagementButton(buttonID, enable) {
|
|||
var buttonElement = document.getElementById(buttonID);
|
||||
if (buttonElement != null) {
|
||||
if (enable) {
|
||||
if (buttonElement.classList.contains(CLASS_MANAGEMENT_BUTTON_DISABLED))
|
||||
buttonElement.classList.remove(CLASS_MANAGEMENT_BUTTON_DISABLED);
|
||||
} else
|
||||
buttonElement.classList.add(CLASS_MANAGEMENT_BUTTON_DISABLED);
|
||||
if (buttonElement.classList.contains(CLASS_CONFIG_BUTTON_DISABLED))
|
||||
buttonElement.classList.remove(CLASS_CONFIG_BUTTON_DISABLED);
|
||||
} else {
|
||||
if (!buttonElement.classList.contains(CLASS_CONFIG_BUTTON_DISABLED))
|
||||
buttonElement.classList.add(CLASS_CONFIG_BUTTON_DISABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* Copyright 2022, Digi International Inc.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
// Constants.
|
||||
const ELEMENT_ETHERNET = "ethernet";
|
||||
const ELEMENT_WIFI = "wifi";
|
||||
|
||||
const FIELD_DEFAULT_GATEWAY = "_default_gateway";
|
||||
const FIELD_DNS1_ADDRESS = "_dns1_addr";
|
||||
const FIELD_DNS2_ADDRESS = "_dns2_addr";
|
||||
const FIELD_ENABLE = "_enable";
|
||||
const FIELD_ENCRYPTION_TYPE = "_enc_type";
|
||||
const FIELD_ERROR = "_error";
|
||||
const FIELD_MAC_ADDRESS = "_mac";
|
||||
const FIELD_IP_ADDRESS = "_ip_addr";
|
||||
const FIELD_IP_MODE = "_ip_mode";
|
||||
const FIELD_PARAM = "_param";
|
||||
const FIELD_PASSWORD = "_password";
|
||||
const FIELD_SAVE_BUTTON = "_save_button";
|
||||
const FIELD_SSID = "_ssid";
|
||||
const FIELD_SUBNET_MASK = "_subnet_mask";
|
||||
|
||||
const ID_DNS1 = "dns1";
|
||||
const ID_DNS2 = "dns2";
|
||||
const ID_ENABLE = "enable";
|
||||
const ID_ETH0_TITLE = "eth0_title";
|
||||
const ID_GATEWAY = "gateway";
|
||||
const ID_IP = "ip";
|
||||
const ID_IP_MODE = "type";
|
||||
const ID_INTERFACE = "interface";
|
||||
const ID_MAC = "mac";
|
||||
const ID_NETMASK = "netmask";
|
||||
const ID_PANEL_CONTAINER = "_panel_container";
|
||||
const ID_PASSWORD = "psk";
|
||||
const ID_SECURITY_MODE = "sec_mode";
|
||||
const ID_SSID = "ssid";
|
||||
const ID_TOGGLE_BUTTON = "_toggle_button";
|
||||
|
||||
const IP_MODE_DHCP = "dhcp";
|
||||
const IP_MODE_STATIC = "static";
|
||||
|
||||
const ERROR_IP_VALUE_FORMAT = "Value must follow this format: XXX.XXX.XXX.XXX";
|
||||
const ERROR_PASSWORD_INVALID = "Password must be between 8 and 63 characters long";
|
||||
const ERROR_SSID_INVALID = "SSID value is not valid";
|
||||
const ERROR_UNKNOWN = "Unknown error saving configuration.";
|
||||
|
||||
const MESSAGE_LOADING_CONFIGURATION = "Loading configuration...";
|
||||
const MESSAGE_SAVING_CONFIGURATION = "Saving configuration...";
|
||||
const MESSAGE_CONFIGURATION_SAVED = "Configuration saved successfully!";
|
||||
|
||||
const PREFIX_ETHERNET = "eth";
|
||||
const PREFIX_WIFI = "wlan";
|
||||
|
||||
const REGEX_IP = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$';
|
||||
const REGEX_SSID = '^[^!#;+\\]/"\t][^+\\]/"\t]{0,31}$';
|
||||
const REGEX_PASSWORD = '^[\u0020-\u007e]{8,63}$';
|
||||
|
||||
const ALL_ELEMENTS = "all";
|
||||
|
||||
// Variables.
|
||||
var readingNetworkInfo = false;
|
||||
var passwordChanged = false;
|
||||
|
||||
// Initializes the network page.
|
||||
function initializeNetworkPage() {
|
||||
// Sanity checks.
|
||||
if (!isNetworkShowing())
|
||||
return;
|
||||
// Read network configuration.
|
||||
readElements = [ELEMENT_ETHERNET, ELEMENT_WIFI];
|
||||
readConfiguration(readElements, ALL_ELEMENTS);
|
||||
}
|
||||
|
||||
// Gets the device configuration the given elements.
|
||||
function readConfiguration(readElements, parseElement) {
|
||||
// Execute only in the network page.
|
||||
if (!isNetworkShowing() || readingNetworkInfo)
|
||||
return;
|
||||
// Flag reading variable.
|
||||
readingNetworkInfo = true;
|
||||
// Hide the info popup.
|
||||
showInfoPopup(false);
|
||||
// Show the loading popup.
|
||||
showLoadingPopup(true, MESSAGE_LOADING_CONFIGURATION);
|
||||
// Send request to retrieve configuration.
|
||||
$.post(
|
||||
"http://" + getServerAddress() + "/ajax/get_config",
|
||||
JSON.stringify({
|
||||
"elements": readElements
|
||||
}),
|
||||
function(data) {
|
||||
// Process only in the network page.
|
||||
if (!isNetworkShowing())
|
||||
return;
|
||||
// Process answer.
|
||||
processReadConfigurationResponse(data, parseElement);
|
||||
}
|
||||
).fail(function(response) {
|
||||
// Flag reading variable.
|
||||
readingNetworkInfo = false;
|
||||
// Clear the element being read.
|
||||
elementReading = "";
|
||||
// Process only in the network page.
|
||||
if (!isNetworkShowing())
|
||||
return;
|
||||
// Hide the loading panel.
|
||||
showLoadingPopup(false);
|
||||
// Process error.
|
||||
processAjaxErrorResponse(response);
|
||||
// Update controls.
|
||||
updateAllControls();
|
||||
});
|
||||
}
|
||||
|
||||
// Processes the response of the read configuration request.
|
||||
function processReadConfigurationResponse(response, parseElement) {
|
||||
// Check if there was any error in the request.
|
||||
if (!checkErrorResponse(response, false)) {
|
||||
// Fill network info.
|
||||
fillNetworkInfo(JSON.parse(response[ID_DATA]), parseElement);
|
||||
} else {
|
||||
// Flag reading variable.
|
||||
readingNetworkInfo = false;
|
||||
// Hide the loading panel.
|
||||
showLoadingPopup(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Fills network information.
|
||||
function fillNetworkInfo(response, parseElement) {
|
||||
var numEthernetIfaces = 0;
|
||||
var numWifiIfaces = 0;
|
||||
for (const [element, elementData] of Object.entries(response)) {
|
||||
if (element != ELEMENT_ETHERNET && element != ELEMENT_WIFI)
|
||||
continue;
|
||||
for (const [iface, ifaceData] of Object.entries(elementData)) {
|
||||
if (!iface.startsWith(PREFIX_WIFI) && !iface.startsWith(PREFIX_ETHERNET))
|
||||
continue;
|
||||
if (parseElement != ALL_ELEMENTS && iface != parseElement)
|
||||
continue;
|
||||
var enabled = ifaceData[ID_ENABLE];
|
||||
var ipMode = ifaceData[ID_IP_MODE];
|
||||
if (iface.startsWith(PREFIX_ETHERNET))
|
||||
numEthernetIfaces += 1;
|
||||
else if (iface.startsWith(PREFIX_WIFI))
|
||||
numWifiIfaces += 1;
|
||||
// Fill MAC.
|
||||
document.getElementById(iface + FIELD_MAC_ADDRESS).innerText = ifaceData[ID_MAC];
|
||||
// Set enable state.
|
||||
document.getElementById(iface + FIELD_ENABLE).checked = enabled;
|
||||
// Set IP mode.
|
||||
if (ipMode == 0)
|
||||
document.getElementById(iface + FIELD_IP_MODE).value = IP_MODE_STATIC;
|
||||
else
|
||||
document.getElementById(iface + FIELD_IP_MODE).value = IP_MODE_DHCP;
|
||||
// Fill the rest of the fields.
|
||||
document.getElementById(iface + FIELD_IP_ADDRESS).value = ifaceData[ID_IP];
|
||||
document.getElementById(iface + FIELD_SUBNET_MASK).value = ifaceData[ID_NETMASK];
|
||||
document.getElementById(iface + FIELD_DEFAULT_GATEWAY).value = ifaceData[ID_GATEWAY];
|
||||
document.getElementById(iface + FIELD_DNS1_ADDRESS).value = ifaceData[ID_DNS1];
|
||||
document.getElementById(iface + FIELD_DNS2_ADDRESS).value = ifaceData[ID_DNS2];
|
||||
// Specific Wifi fields.
|
||||
if (iface.startsWith(PREFIX_WIFI)) {
|
||||
document.getElementById(iface + FIELD_SSID).value = ifaceData[ID_SSID];
|
||||
document.getElementById(iface + FIELD_ENCRYPTION_TYPE).selectedIndex = ifaceData[ID_SECURITY_MODE];
|
||||
if (ifaceData[ID_SECURITY_MODE] != 0)
|
||||
document.getElementById(iface + FIELD_PASSWORD).value = "dummy_password";
|
||||
passwordChanged = false;
|
||||
}
|
||||
// Update controls.
|
||||
updateInterfaceControls(iface);
|
||||
}
|
||||
}
|
||||
// Update interfaces visibility.
|
||||
if (parseElement == ALL_ELEMENTS) {
|
||||
if (numEthernetIfaces == 1) {
|
||||
document.getElementById(IFACE_ETH1).style.display = "none";
|
||||
document.getElementById(ID_ETH0_TITLE).innerHTML = "Ethernet";
|
||||
}
|
||||
if (numWifiIfaces == 0)
|
||||
document.getElementById(IFACE_WIFI).style.display = "none";
|
||||
}
|
||||
// Flag reading variable.
|
||||
readingNetworkInfo = false;
|
||||
// Hide the loading panel.
|
||||
showLoadingPopup(false);
|
||||
}
|
||||
|
||||
// Updates all controls of the page.
|
||||
function updateAllControls() {
|
||||
updateInterfaceControls(IFACE_ETH0);
|
||||
updateInterfaceControls(IFACE_ETH1);
|
||||
updateInterfaceControls(IFACE_WIFI);
|
||||
}
|
||||
|
||||
// Updates the given interface controls based on its configuration.
|
||||
function updateInterfaceControls(iface) {
|
||||
// Initialize variables.
|
||||
var ipGroup = document.getElementById(iface + FIELD_IP_ADDRESS + FIELD_PARAM);
|
||||
var ipField = document.getElementById(iface + FIELD_IP_ADDRESS);
|
||||
var subnetGroup = document.getElementById(iface + FIELD_SUBNET_MASK + FIELD_PARAM);
|
||||
var subnetField = document.getElementById(iface + FIELD_SUBNET_MASK);
|
||||
var gatewayGroup = document.getElementById(iface + FIELD_DEFAULT_GATEWAY + FIELD_PARAM);
|
||||
var gatewayField = document.getElementById(iface + FIELD_DEFAULT_GATEWAY);
|
||||
var dns1Group = document.getElementById(iface + FIELD_DNS1_ADDRESS + FIELD_PARAM);
|
||||
var dns1Field = document.getElementById(iface + FIELD_DNS1_ADDRESS);
|
||||
var dns2Group = document.getElementById(iface + FIELD_DNS2_ADDRESS + FIELD_PARAM);
|
||||
var dns2Field = document.getElementById(iface + FIELD_DNS2_ADDRESS);
|
||||
var ipModeGroup = document.getElementById(iface + FIELD_IP_MODE + FIELD_PARAM);
|
||||
var ipModeField = document.getElementById(iface + FIELD_IP_MODE);
|
||||
var enableField = document.getElementById(iface + FIELD_ENABLE);
|
||||
var enabled = enableField.checked;
|
||||
var ipMode = ipModeField.value;
|
||||
var ssidGroup, encryptionTypeGroup, encryptionTypeField, passwordGroup, usePassword;
|
||||
if (iface.startsWith(PREFIX_WIFI)) {
|
||||
ssidGroup = document.getElementById(iface + FIELD_SSID + FIELD_PARAM);
|
||||
encryptionTypeGroup = document.getElementById(iface + FIELD_ENCRYPTION_TYPE + FIELD_PARAM);
|
||||
encryptionTypeField = document.getElementById(iface + FIELD_ENCRYPTION_TYPE);
|
||||
passwordGroup = document.getElementById(iface + FIELD_PASSWORD + FIELD_PARAM);
|
||||
usePassword = encryptionTypeField.value != 0;
|
||||
if (usePassword)
|
||||
passwordGroup.style.display = "block";
|
||||
else
|
||||
passwordGroup.style.display = "none";
|
||||
}
|
||||
// Determine if IP fields can be edited.
|
||||
if (ipMode == IP_MODE_DHCP) {
|
||||
if (!ipField.classList.contains(CLASS_INPUT_DISABLED))
|
||||
ipField.classList.add(CLASS_INPUT_DISABLED);
|
||||
if (!subnetField.classList.contains(CLASS_INPUT_DISABLED))
|
||||
subnetField.classList.add(CLASS_INPUT_DISABLED);
|
||||
if (!gatewayField.classList.contains(CLASS_INPUT_DISABLED))
|
||||
gatewayField.classList.add(CLASS_INPUT_DISABLED);
|
||||
if (!dns1Field.classList.contains(CLASS_INPUT_DISABLED))
|
||||
dns1Field.classList.add(CLASS_INPUT_DISABLED);
|
||||
if (!dns2Field.classList.contains(CLASS_INPUT_DISABLED))
|
||||
dns2Field.classList.add(CLASS_INPUT_DISABLED);
|
||||
} else if (ipMode == IP_MODE_STATIC) {
|
||||
if (ipField.classList.contains(CLASS_INPUT_DISABLED))
|
||||
ipField.classList.remove(CLASS_INPUT_DISABLED);
|
||||
if (subnetField.classList.contains(CLASS_INPUT_DISABLED))
|
||||
subnetField.classList.remove(CLASS_INPUT_DISABLED);
|
||||
if (gatewayField.classList.contains(CLASS_INPUT_DISABLED))
|
||||
gatewayField.classList.remove(CLASS_INPUT_DISABLED);
|
||||
if (dns1Field.classList.contains(CLASS_INPUT_DISABLED))
|
||||
dns1Field.classList.remove(CLASS_INPUT_DISABLED);
|
||||
if (dns2Field.classList.contains(CLASS_INPUT_DISABLED))
|
||||
dns2Field.classList.remove(CLASS_INPUT_DISABLED);
|
||||
}
|
||||
// Validate the network interface.
|
||||
validateInterface(iface);
|
||||
}
|
||||
|
||||
// Validates the given network interface.
|
||||
function validateInterface(iface) {
|
||||
// Initialize vars.
|
||||
var valid = true;
|
||||
var saveButton = document.getElementById(iface + FIELD_SAVE_BUTTON);
|
||||
var enableField = document.getElementById(iface + FIELD_ENABLE);
|
||||
var ipModeField = document.getElementById(iface + FIELD_IP_MODE);
|
||||
var ipField = document.getElementById(iface + FIELD_IP_ADDRESS);
|
||||
var subnetField = document.getElementById(iface + FIELD_SUBNET_MASK);
|
||||
var gatewayField = document.getElementById(iface + FIELD_DEFAULT_GATEWAY);
|
||||
var dns1Field = document.getElementById(iface + FIELD_DNS1_ADDRESS);
|
||||
var dns2Field = document.getElementById(iface + FIELD_DNS2_ADDRESS);
|
||||
var ipMode = ipModeField.value;
|
||||
var forceValid = false;
|
||||
// Validate fields.
|
||||
if (ipMode == IP_MODE_DHCP)
|
||||
forceValid = true;
|
||||
valid &= validateIPField(iface + FIELD_IP_ADDRESS, iface + FIELD_IP_ADDRESS + FIELD_ERROR, forceValid);
|
||||
valid &= validateIPField(iface + FIELD_SUBNET_MASK, iface + FIELD_SUBNET_MASK + FIELD_ERROR, forceValid);
|
||||
valid &= validateIPField(iface + FIELD_DEFAULT_GATEWAY, iface + FIELD_DEFAULT_GATEWAY + FIELD_ERROR, forceValid);
|
||||
valid &= validateIPField(iface + FIELD_DNS1_ADDRESS, iface + FIELD_DNS1_ADDRESS + FIELD_ERROR, forceValid);
|
||||
valid &= validateIPField(iface + FIELD_DNS2_ADDRESS, iface + FIELD_DNS2_ADDRESS + FIELD_ERROR, forceValid);
|
||||
if (iface.startsWith(PREFIX_WIFI)) {
|
||||
valid &= validateField(iface + FIELD_SSID, iface + FIELD_SSID + FIELD_ERROR, REGEX_SSID, ERROR_SSID_INVALID, false);
|
||||
if (parseInt(document.getElementById(iface + FIELD_ENCRYPTION_TYPE).value) != 0)
|
||||
valid &= validateField(iface + FIELD_PASSWORD, iface + FIELD_PASSWORD + FIELD_ERROR, REGEX_PASSWORD, ERROR_PASSWORD_INVALID, false);
|
||||
}
|
||||
// Check errors.
|
||||
if (!valid) {
|
||||
if (!saveButton.classList.contains(CLASS_CONFIG_BUTTON_DISABLED))
|
||||
saveButton.classList.add(CLASS_CONFIG_BUTTON_DISABLED);
|
||||
} else {
|
||||
if (saveButton.classList.contains(CLASS_CONFIG_BUTTON_DISABLED))
|
||||
saveButton.classList.remove(CLASS_CONFIG_BUTTON_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
// Validates the given IP field.
|
||||
function validateIPField(fieldID, errorID, forceValid) {
|
||||
return validateField(fieldID, errorID, REGEX_IP, ERROR_IP_VALUE_FORMAT, forceValid);
|
||||
}
|
||||
|
||||
// Validates the given field.
|
||||
function validateField(fieldID, errorID, regexPattern, errorMessage, forceValid) {
|
||||
// Initialize vars.
|
||||
var field = document.getElementById(fieldID);
|
||||
var fieldError = document.getElementById(errorID);
|
||||
var isValid = true;
|
||||
var error = "";
|
||||
// Sanity checks.
|
||||
if (field == null || fieldError == null)
|
||||
return false;
|
||||
// Check if value is valid.
|
||||
if (!forceValid) {
|
||||
var value = field.value;
|
||||
if (value.length == 0) {
|
||||
isValid = false;
|
||||
error = ERROR_FIELD_EMPTY;
|
||||
} else if (!value.match(regexPattern)) {
|
||||
isValid = false;
|
||||
error = errorMessage;
|
||||
}
|
||||
}
|
||||
// Update controls.
|
||||
if (isValid) {
|
||||
if (field.classList.contains(CLASS_INPUT_ERROR))
|
||||
field.classList.remove(CLASS_INPUT_ERROR);
|
||||
fieldError.innerHTML = " ";
|
||||
fieldError.style.display = "none";
|
||||
} else {
|
||||
if (!field.classList.contains(CLASS_INPUT_ERROR))
|
||||
field.classList.add(CLASS_INPUT_ERROR);
|
||||
fieldError.innerHTML = error;
|
||||
fieldError.style.display = "block";
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// Retrieves the given network interface form data.
|
||||
function getInterfaceData(element, iface) {
|
||||
// Initialize variables.
|
||||
var data = {};
|
||||
var ifaceData = {};
|
||||
var networkData = {};
|
||||
var enable = document.getElementById(iface + FIELD_ENABLE).checked;
|
||||
var ipMode = document.getElementById(iface + FIELD_IP_MODE).value;
|
||||
// Fill network data.
|
||||
networkData[ID_ENABLE] = enable;
|
||||
if (ipMode == IP_MODE_STATIC) {
|
||||
networkData[ID_IP_MODE] = 0;
|
||||
networkData[ID_IP] = document.getElementById(iface + FIELD_IP_ADDRESS).value;
|
||||
networkData[ID_NETMASK] = document.getElementById(iface + FIELD_SUBNET_MASK).value;
|
||||
networkData[ID_GATEWAY] = document.getElementById(iface + FIELD_DEFAULT_GATEWAY).value;
|
||||
networkData[ID_DNS1] = document.getElementById(iface + FIELD_DNS1_ADDRESS).value;
|
||||
networkData[ID_DNS2] = document.getElementById(iface + FIELD_DNS2_ADDRESS).value;
|
||||
} else {
|
||||
networkData[ID_IP_MODE] = 1;
|
||||
}
|
||||
if (iface.startsWith(PREFIX_WIFI)) {
|
||||
networkData[ID_SSID] = document.getElementById(iface + FIELD_SSID).value;
|
||||
networkData[ID_SECURITY_MODE] = parseInt(document.getElementById(iface + FIELD_ENCRYPTION_TYPE).value);
|
||||
if (networkData[ID_SECURITY_MODE] != 0 && passwordChanged)
|
||||
networkData[ID_PASSWORD] = document.getElementById(iface + FIELD_PASSWORD).value;
|
||||
}
|
||||
ifaceData[iface] = networkData;
|
||||
data[element] = ifaceData;
|
||||
return data;
|
||||
}
|
||||
|
||||
// Saves the network settings for the given interface.
|
||||
function saveInterface(element, iface) {
|
||||
// Execute only in the network page.
|
||||
if (!isNetworkShowing())
|
||||
return;
|
||||
// Hide the info popup.
|
||||
showInfoPopup(false);
|
||||
// Show the loading popup.
|
||||
showLoadingPopup(true, MESSAGE_SAVING_CONFIGURATION);
|
||||
// Send request to set new configuration.
|
||||
$.post(
|
||||
"http://" + getServerAddress() + "/ajax/set_config",
|
||||
JSON.stringify({
|
||||
"configuration": getInterfaceData(element, iface)
|
||||
}),
|
||||
function(data) {
|
||||
// Process only in the network page.
|
||||
if (!isNetworkShowing())
|
||||
return;
|
||||
// Process answer.
|
||||
processSaveInterfaceResponse(data, element, iface);
|
||||
}
|
||||
).fail(function(response) {
|
||||
// Process only in the network page.
|
||||
if (!isNetworkShowing())
|
||||
return;
|
||||
// Hide the loading panel.
|
||||
showLoadingPopup(false);
|
||||
// Process error.
|
||||
processAjaxErrorResponse(response);
|
||||
});
|
||||
}
|
||||
|
||||
// Processes the save network request response.
|
||||
function processSaveInterfaceResponse(response, element, iface) {
|
||||
// Check for error in the response.
|
||||
if (!checkErrorResponse(response, false)) {
|
||||
var statusFound = false;
|
||||
// Check status in the response.
|
||||
if (response[ID_DATA] != null) {
|
||||
data = JSON.parse(response[ID_DATA]);
|
||||
for (const [elementEntry, elementData] of Object.entries(data)) {
|
||||
if (elementEntry != element)
|
||||
continue;
|
||||
for (const [ifaceEntry, ifaceData] of Object.entries(elementData)) {
|
||||
if (ifaceEntry != iface)
|
||||
continue;
|
||||
if (ifaceData[ID_STATUS] != null) {
|
||||
statusFound = true;
|
||||
if (ifaceData[ID_STATUS] != 0)
|
||||
toastr.error(ifaceData[ID_DESC]);
|
||||
else
|
||||
toastr.success(MESSAGE_CONFIGURATION_SAVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!statusFound)
|
||||
toastr.error(ERROR_UNKNOWN);
|
||||
}
|
||||
// Hide the loading panel.
|
||||
showLoadingPopup(false);
|
||||
}
|
||||
|
||||
// Toggles the visibility of the given interface panel.
|
||||
function togglePanelVisibility(interface) {
|
||||
// Initialize variables.
|
||||
var panelButton = document.getElementById(interface + ID_TOGGLE_BUTTON);
|
||||
// Sanity checks.
|
||||
if (panelButton == null)
|
||||
return;
|
||||
// Check visibility.
|
||||
if (panelButton.classList.contains(CLASS_ARROW_UP)) {
|
||||
$("#" + interface + ID_PANEL_CONTAINER).slideUp("fast", function() {
|
||||
panelButton.classList.remove(CLASS_ARROW_UP);
|
||||
panelButton.classList.add(CLASS_ARROW_DOWN);
|
||||
});
|
||||
} else {
|
||||
$("#" + interface + ID_PANEL_CONTAINER).slideDown("fast", function() {
|
||||
panelButton.classList.remove(CLASS_ARROW_DOWN);
|
||||
panelButton.classList.add(CLASS_ARROW_UP);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -93,5 +93,10 @@ function setSelectedSection(element=null) {
|
|||
}
|
||||
});
|
||||
}
|
||||
if (isDashboardShowing()) {
|
||||
window.setTimeout(function () {
|
||||
adjustImageSize();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||