mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
networks: Overhaul Wi-Fi network scan page
Fixes: #1725. - Show multiple Wi-Fi devices in separate tables so that users can pick them understanding what they are. Also avoids some confusion related to why APs are duplicated. - Request scanning if the last scan time was long ago. - Show the last scanned time. - Refresh page in 10 seconds if scan has been requested so that the results of scan can be shown without user explicitly refreshing the page. Show spinner when scan has been requested and we are awaiting results. - Refresh page every 60 seconds in other cases. - When an SSID can't be decoded into a string, don't show it. - Don't show hidden networks with no SSID set. - Improve the styling for signal strength. - Show a message when no Wi-Fi devices are present. - Show a message when no Wi-Fi networks are found for a device. Tests: - Test on a machine with Wi-Fi device available. - When page is loaded is for the first time, spinner is shown and refresh happens in 10 seconds. After refresh if the scan has not completed, again, spinner is shown and page is reloaded in 10 seconds. Otherwise, spinner is not shown and page is reloaded in 60 seconds. - Hidden networks are not shown. - On a machine with no Wi-Fi devices, 'No Wi-Fi device detected.' message is shown. - Clicking on a network takes us to new Wi-Fi network connection page with 'connection name', 'network interface' and SSID filled in correctly. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
a32a226492
commit
064f3c6c0c
@ -10,28 +10,52 @@
|
||||
|
||||
<h3>{{ title }}</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="list-group list-group-two-column">
|
||||
{% for access_point in access_points %}
|
||||
<div class="list-group-item">
|
||||
<span class="primary">
|
||||
{% if access_point.ssid %}
|
||||
<a href="{% url 'networks:add_wifi' access_point.ssid access_point.interface_name %}">
|
||||
{{ access_point.ssid }}
|
||||
</a>
|
||||
{% else %}
|
||||
--
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if not device_access_points %}
|
||||
<p>{% trans "No Wi-Fi device detected." %}</p>
|
||||
{% else %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{% for device in device_access_points %}
|
||||
{% if device_access_points|length > 1 %}
|
||||
<h4>
|
||||
{% blocktrans trimmed with interface_name=device.interface_name %}
|
||||
Device: {{ interface_name }}
|
||||
{% endblocktrans %}
|
||||
</h4>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% trans "Last scanned: " %}
|
||||
{% if device.last_scan_time %}
|
||||
{{ device.last_scan_time|timesince }}
|
||||
{% else %}
|
||||
{% trans "never" %}
|
||||
{% endif %}
|
||||
{% if device.scan_requested %}
|
||||
<span class="fa fa-spinner fa-spin"></span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="list-group list-group-two-column">
|
||||
{% for access_point in device.access_points %}
|
||||
<div class="list-group-item">
|
||||
<span class="primary">
|
||||
<a href="{% url 'networks:add_wifi' access_point.ssid_string device.interface_name %}">
|
||||
{{ access_point.ssid_string }}
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<span class="btn btn-primary btn-sm secondary">
|
||||
{{ access_point.strength }}%
|
||||
</span>
|
||||
<span class="badge badge-secondary secondary">
|
||||
{{ access_point.strength }}%
|
||||
</span>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>
|
||||
{% trans "No Wi-Fi networks found." %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -385,11 +385,17 @@ def deactivate(request, uuid):
|
||||
|
||||
def scan(request):
|
||||
"""Show a list of nearby visible Wi-Fi access points."""
|
||||
access_points = network.wifi_scan()
|
||||
return TemplateResponse(request, 'wifi_scan.html', {
|
||||
'title': _('Nearby Wi-Fi Networks'),
|
||||
'access_points': access_points
|
||||
})
|
||||
device_access_points = network.wifi_scan()
|
||||
scanning = any(
|
||||
(device['scan_requested'] for device in device_access_points))
|
||||
# Refresh page in 10s if scanning, 60s otherwise
|
||||
refresh_page_sec = 10 if scanning else 60
|
||||
return TemplateResponse(
|
||||
request, 'wifi_scan.html', {
|
||||
'title': _('Nearby Wi-Fi Networks'),
|
||||
'device_access_points': device_access_points,
|
||||
'refresh_page_sec': refresh_page_sec
|
||||
})
|
||||
|
||||
|
||||
def add(request):
|
||||
|
||||
@ -4,6 +4,7 @@ Helper functions for working with network manager.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import datetime
|
||||
import logging
|
||||
import socket
|
||||
import struct
|
||||
@ -613,27 +614,79 @@ def delete_connection(connection_uuid):
|
||||
return name
|
||||
|
||||
|
||||
def _get_access_point_as_dict(access_point, active_ap_path):
|
||||
"""Return Wi-Fi access point information as a dictionary."""
|
||||
ssid = access_point.get_ssid()
|
||||
if not ssid: # Hidden network
|
||||
return None
|
||||
|
||||
try:
|
||||
ssid_string = ssid.get_data().decode(encoding='utf-8')
|
||||
except UnicodeError:
|
||||
# XXX: Can't deal with binary SSIDs. Don't show SSIDs that are
|
||||
# binary only.
|
||||
return None
|
||||
|
||||
is_active = (active_ap_path == access_point.get_path())
|
||||
return {
|
||||
'ssid': ssid,
|
||||
'ssid_string': ssid_string,
|
||||
'strength': access_point.get_strength(),
|
||||
'is_active': is_active
|
||||
}
|
||||
|
||||
|
||||
def wifi_scan():
|
||||
"""Scan for available access points across all Wi-Fi devices."""
|
||||
access_points = []
|
||||
device_access_points = []
|
||||
for device in get_nm_client().get_devices():
|
||||
if device.get_device_type() != nm.DeviceType.WIFI:
|
||||
continue
|
||||
|
||||
for access_point in device.get_access_points():
|
||||
# Retrieve the bytes in SSID. Don't convert to utf-8 or
|
||||
# escape it in any way as it may contain null bytes. When
|
||||
# this is used in the URL it will be escaped properly and
|
||||
# unescaped when taken as view function's argument.
|
||||
ssid = access_point.get_ssid()
|
||||
ssid_string = ssid.get_data().decode() if ssid else ''
|
||||
access_points.append({
|
||||
'interface_name': device.get_iface(),
|
||||
'ssid': ssid_string,
|
||||
'strength': access_point.get_strength()
|
||||
})
|
||||
if device.get_client() is None:
|
||||
# The device got deleted (see NM:show-wifi-networks.py)
|
||||
return False
|
||||
|
||||
return access_points
|
||||
# Active access point
|
||||
active_ap_path = device.get_active_access_point()
|
||||
|
||||
# Last scan time
|
||||
last_scan = device.get_last_scan()
|
||||
last_scan_time = None
|
||||
scan_requested = False
|
||||
if last_scan == -1:
|
||||
last_scan = None
|
||||
else:
|
||||
boot_time = time.clock_gettime(time.CLOCK_BOOTTIME)
|
||||
last_scan = boot_time - (last_scan / 1000)
|
||||
last_scan_time = datetime.datetime.now() - datetime.timedelta(
|
||||
seconds=last_scan)
|
||||
|
||||
# Request a scan if the last scan was more than 20 seconds ago
|
||||
if (not last_scan) or last_scan > 20:
|
||||
device.request_scan()
|
||||
scan_requested = True
|
||||
|
||||
# Access points
|
||||
access_points = []
|
||||
for access_point in device.get_access_points():
|
||||
ap_dict = _get_access_point_as_dict(access_point, active_ap_path)
|
||||
if ap_dict:
|
||||
access_points.append(ap_dict)
|
||||
|
||||
access_points = sorted(access_points,
|
||||
key=lambda point: -point['strength'])
|
||||
|
||||
device_access_points.append({
|
||||
'interface_name': device.get_iface(),
|
||||
'access_points': access_points,
|
||||
'last_scan': last_scan,
|
||||
'last_scan_time': last_scan_time,
|
||||
'scan_requested': scan_requested
|
||||
})
|
||||
|
||||
return sorted(device_access_points,
|
||||
key=lambda device: device['interface_name'])
|
||||
|
||||
|
||||
def refeed_dns():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user