diff --git a/ks_includes/wifi.py b/ks_includes/wifi.py index 350f01c4..d0e467fb 100644 --- a/ks_includes/wifi.py +++ b/ks_includes/wifi.py @@ -38,6 +38,7 @@ class WifiManager(Thread): self.read_wpa_supplicant() def run(self): + logger.debug("Setting up wifi event loop") self.loop = asyncio.new_event_loop() loop = self.loop asyncio.set_event_loop(loop) @@ -60,8 +61,11 @@ class WifiManager(Thread): async def _poll(self): while True: - await self.scan() - await asyncio.sleep(RESCAN_INTERVAL) + try: + await self.scan() + await asyncio.sleep(RESCAN_INTERVAL) + except: + logger.exception("Poll wifi error") def get_current_wifi(self, interface="wlan0"): p = subprocess.Popen(["iwconfig",interface], stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -156,18 +160,19 @@ class WifiManager(Thread): for network in networks: self.networks_in_supplicant.append(network) - async def scan(self, interface='wlan0'): - p = subprocess.Popen(["sudo","iwlist",interface,"scan"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - aps = self.parse(p.stdout.read().decode('utf-8')) - cur_info = self.get_current_wifi() + async def scan(self, interface='wlan0'): + logger.debug("Scanning %s" % interface) + p = subprocess.Popen(["sudo","iwlist",interface,"scan"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + aps = self.parse(p.stdout.read().decode('utf-8')) + cur_info = self.get_current_wifi() - self.networks = {} - for ap in aps: - self.networks[ap['essid']] = ap - if cur_info is not None and cur_info[0] == ap['essid'] and cur_info[1] == ap['mac']: - self.networks[ap['essid']]['connected'] = True - for net in self.networks_in_supplicant: - if ap['essid'] == net['ssid'] and "psk" in net: - ap['psk'] = net['psk'] - break + self.networks = {} + for ap in aps: + self.networks[ap['essid']] = ap + if cur_info is not None and cur_info[0] == ap['essid'] and cur_info[1] == ap['mac']: + self.networks[ap['essid']]['connected'] = True + for net in self.networks_in_supplicant: + if ap['essid'] == net['ssid'] and "psk" in net: + ap['psk'] = net['psk'] + break diff --git a/panels/network.py b/panels/network.py index e0dff469..e01c166f 100644 --- a/panels/network.py +++ b/panels/network.py @@ -1,9 +1,10 @@ import gi import logging import os +import re gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib +from gi.repository import Gtk, Gdk, GLib, Pango from ks_includes.screen_panel import ScreenPanel @@ -13,6 +14,10 @@ def create_panel(*args): return NetworkPanel(*args) class NetworkPanel(ScreenPanel): + networks = {} + network_list = [] + interface = "wlan0" + def initialize(self, menu): _ = self.lang.gettext grid = self._gtk.HomogeneousGrid() @@ -25,12 +30,142 @@ class NetworkPanel(ScreenPanel): stream = os.popen('hostname -I') ip = stream.read() + self.labels['networks'] = {} + + self.labels['interface'] = Gtk.Label() + self.labels['interface'].set_text(" %s: %s" % (_("Interface"), self.interface)) + self.labels['disconnect'] = self._gtk.Button(_("Disconnect"), "color2") - self.labels['networkinfo'] = Gtk.Label( - _("Network Info") + "\n\n%s%s" % (hostname, ip) - ) - self.labels['networkinfo'].get_style_context().add_class('temperature_entry') - grid.attach(self.labels['networkinfo'], 1, 0, 1, 1) + sbox = Gtk.Box() + sbox.set_hexpand(True) + sbox.set_vexpand(False) + sbox.add(self.labels['interface']) + #sbox.add(self.labels['disconnect']) - self.content.add(grid) + + scroll = Gtk.ScrolledWindow() + scroll.set_property("overlay-scrolling", False) + scroll.set_vexpand(True) + + box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) + box.set_vexpand(True) + box.pack_start(sbox, False, False, 0) + box.pack_start(scroll, True, True, 0) + + self.labels['networklist'] = Gtk.Grid() + self.files = {} + + GLib.idle_add(self.load_networks) + + scroll.add(self.labels['networklist']) + + #self.labels['networkinfo'] = Gtk.Label( + # _("Network Info") + "\n\n%s%s" % (hostname, ip) + #) + #self.labels['networkinfo'].get_style_context().add_class('temperature_entry') + #grid.attach(self.labels['networkinfo'], 1, 0, 1, 1) + + self.content.add(box) + + def load_networks(self): + networks = self._screen.wifi.get_networks() + for net in networks: + self.add_network(net, False) + + self.content.show_all() + + def add_network(self, essid, show=True): + _ = self.lang.gettext + + netinfo = self._screen.wifi.get_network_info(essid) + if netinfo == None: + return + + # For now, only add connected network + if "connected" not in netinfo: + return + + frame = Gtk.Frame() + frame.set_property("shadow-type",Gtk.ShadowType.NONE) + frame.get_style_context().add_class("frame-item") + + + name = Gtk.Label() + name.set_markup("%s" % (essid)) + name.set_hexpand(True) + name.set_halign(Gtk.Align.START) + name.set_line_wrap(True) + name.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) + + stream = os.popen('ip add show dev %s' % self.interface) + content = stream.read() + ipv4_re = re.compile(r'inet ([0-9\.]+)/[0-9]+', re.MULTILINE) + ipv6_re = re.compile(r'inet6 ([a-fA-F0-9:\.]+)/[0-9+]', re.MULTILINE) + match = ipv4_re.search(content) + ipv4 = "" + if match: + ipv4 = "%s: %s " % (_("IPv4"), match.group(1)) + match = ipv6_re.search(content) + ipv6 = "" + if match: + ipv6 = "%s: %s " % (_("IPv6"), match.group(1)) + + + stream = os.popen('hostname -f') + hostname = stream.read().strip() + + connected = "" + if "connected" in netinfo: + connected = "%s\n%s: %s\n%s%s\n" % (_("Connected"),_("Hostname"),hostname, ipv4, ipv6) + elif "psk" in netinfo: + connected = "Password saved." + freq = "2.4 GHz" if netinfo['frequency'][0:1] == "2" else "5 Ghz" + info = Gtk.Label() + info.set_markup("%s%s %s %s %s %s%s" % ( connected, + "" if netinfo['encryption'] == "off" else netinfo['encryption'].upper(), + freq, _("Channel"), netinfo['channel'], netinfo['signal_level_dBm'], _("dBm") + )) + info.set_halign(Gtk.Align.START) + #info.set_markup(self.get_file_info_str(essid)) + labels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + labels.add(name) + labels.add(info) + labels.set_vexpand(True) + labels.set_valign(Gtk.Align.CENTER) + labels.set_halign(Gtk.Align.START) + + actions = self._gtk.ButtonImage("print",None,"color3") + #actions.connect("clicked", self.confirm_print, essid) + actions.set_hexpand(False) + actions.set_halign(Gtk.Align.END) + + network = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5) + network.set_hexpand(True) + network.set_vexpand(False) + + network.add(labels) + if not "connected" in netinfo: + network.add(actions) + + self.networks[essid] = frame + frame.add(network) + + reverse = False + nets = sorted(self.networks, reverse=reverse) + pos = nets.index(essid) + if "connected" in netinfo: + pos = 0 + elif self._screen.wifi.is_connected(): + pos += 1 + + self.labels['networks'][essid] = { + "info": info, + "name": name, + "row": network + } + + self.labels['networklist'].insert_row(pos) + self.labels['networklist'].attach(self.networks[essid], 0, pos, 1, 1) + if show == True: + self.labels['networklist'].show_all() diff --git a/screen.py b/screen.py index c2d2e398..0222a39f 100644 --- a/screen.py +++ b/screen.py @@ -28,6 +28,7 @@ from ks_includes.KlippyRest import KlippyRest from ks_includes.files import KlippyFiles from ks_includes.KlippyGtk import KlippyGtk from ks_includes.printer import Printer +from ks_includes.wifi import WifiManager from ks_includes.config import KlipperScreenConfig @@ -109,6 +110,9 @@ class KlipperScreen(Gtk.Window): self.lang = gettext.translation('KlipperScreen', localedir='ks_includes/locales', fallback=True) self._config = KlipperScreenConfig(configfile, self.lang, self) + self.wifi = WifiManager() + self.wifi.start() + logger.debug("OS Language: %s" % os.getenv('LANG')) self.lang_ltr = True @@ -131,8 +135,6 @@ class KlipperScreen(Gtk.Window): self.gtk = KlippyGtk(self.width, self.height) self.init_style() - #self._load_panels() - self.printer_initializing(_("Initializing")) # Disable DPMS