Render Page 2: Network Scanner - real host data from database.
(self, image, draw)
| 1150 | now = time.time() |
| 1151 | if not st['scanning'] and (now - st['ts']) > 180: |
| 1152 | st['scanning'] = True |
| 1153 | |
| 1154 | def _worker(): |
| 1155 | try: |
| 1156 | import network_diagnostics as nd |
| 1157 | d = nd.do_dhcp_guardian(quick=True) # rogue-server only, fast-ish |
| 1158 | except Exception as e: |
| 1159 | logger.debug(f"netdiag dhcp fetch error: {e}") |
| 1160 | d = None |
| 1161 | if d: |
| 1162 | st['data'] = d |
| 1163 | st['ts'] = time.time() |
| 1164 | st['scanning'] = False |
| 1165 | |
| 1166 | threading.Thread(target=_worker, daemon=True).start() |
| 1167 | return st |
| 1168 | |
| 1169 | def _fetch_wifi_link(self): |
| 1170 | """Current wireless association for the net-diag WIFI page. Fast and |
| 1171 | passive: reads `iw dev <iface> link` (no scan). Returns a dict with |
| 1172 | ssid=None when the radio isn't associated.""" |
| 1173 | iface = getattr(self, '_wifi_iface', None) or 'wlan0' |
| 1174 | info = {'iface': iface, 'ssid': None, 'signal': None, 'quality': None, |
| 1175 | 'freq': None, 'band': None, 'channel': None, 'rate': None, |
| 1176 | 'bssid': None} |
| 1177 | try: |
| 1178 | r = subprocess.run(['iw', 'dev', iface, 'link'], |
| 1179 | capture_output=True, text=True, timeout=3) |
| 1180 | except Exception as e: |
| 1181 | logger.debug(f"wifi link fetch error: {e}") |
| 1182 | return info |
| 1183 | out = r.stdout or '' |
| 1184 | if r.returncode != 0 or 'Not connected' in out or not out.strip(): |
| 1185 | return info |
| 1186 | m = re.search(r'Connected to ([0-9a-fA-F:]{17})', out) |
| 1187 | if m: |
| 1188 | info['bssid'] = m.group(1) |
| 1189 | m = re.search(r'SSID:\s*(.+)', out) |
| 1190 | if m: |
| 1191 | info['ssid'] = m.group(1).strip() |
| 1192 | m = re.search(r'freq:\s*(\d+)', out) |
| 1193 | if m: |
| 1194 | info['freq'] = int(m.group(1)) |
| 1195 | try: |
| 1196 | import wifi_analyzer as wa |
| 1197 | info['band'], info['channel'] = wa.freq_to_channel(info['freq']) |
| 1198 | except Exception: |
| 1199 | pass |
| 1200 | m = re.search(r'signal:\s*(-?\d+)', out) |
| 1201 | if m: |
| 1202 | info['signal'] = int(m.group(1)) |
| 1203 | info['quality'] = self._dbm_to_quality(info['signal']) |
| 1204 | m = re.search(r'tx bitrate:\s*([\d.]+)\s*MBit/s', out) |
| 1205 | if m: |
| 1206 | info['rate'] = float(m.group(1)) |
no test coverage detected