Show RF path temperature for 8812eu

This commit is contained in:
Vasily Evseenko 2024-05-28 23:24:20 +03:00
parent 035d0ca6aa
commit 7180ffb3f7
3 changed files with 80 additions and 8 deletions

View File

@ -193,6 +193,7 @@ class AntennaStat(Int32StringReceiver):
p = attrs['packets'] p = attrs['packets']
latency_d = attrs['latency'] latency_d = attrs['latency']
tx_id = attrs['id'] tx_id = attrs['id']
rf_temperature = attrs['rf_temperature']
window = self.factory.windows.get(tx_id) window = self.factory.windows.get(tx_id)
if window is None: if window is None:
@ -218,12 +219,23 @@ class AntennaStat(Int32StringReceiver):
human_rate(p['injected_bytes'][0]))) human_rate(p['injected_bytes'][0])))
if latency_d: if latency_d:
addstr_markup(window, 2, 20, '{[ANT] pkt/s} {Injection} [us]') addstr_markup(window, 2, 20, '{[ANT] pkt/s} {\u00b0C} {Injection} [us]')
for y, (k, v) in enumerate(sorted(latency_d.items()), 3): for y, (k, v) in enumerate(sorted(latency_d.items()), 3):
k = int(k) # json doesn't support int keys k = int(k) # json doesn't support int keys
injected, dropped, lat_min, lat_avg, lat_max = v injected, dropped, lat_min, lat_avg, lat_max = v
# Show max temperature from all RF paths
temp = max((_v for _k, _v in rf_temperature.items() if (_k >> 8) == (k >> 8)), default=None)
if temp is not None:
if temp >= settings.common.temp_overheat_warning:
temp = '{%d}' % (temp,)
else:
temp = str(temp)
else:
temp = ' (--)'
if y < ymax: if y < ymax:
addstr_markup(window, y, 21, '{%02x}(XX) %4d %4d < {%4d} < %4d' % (k >> 8, injected, lat_min, lat_avg, lat_max)) addstr_markup(window, y, 21, '{%02x}(XX) %4d %3s %4d < {%4d} < %4d' % (k >> 8, injected, temp, lat_min, lat_avg, lat_max))
else: else:
addstr_noerr(window, 2, 20, '[No data]', curses.A_REVERSE) addstr_noerr(window, 2, 20, '[No data]', curses.A_REVERSE)

View File

@ -27,8 +27,12 @@ wifi_channel = 165 # radio channel @5825 MHz, range: 5815-5835 MHz, width
# {'wlan0': 161, 'wlan1': 165} # {'wlan0': 161, 'wlan1': 165}
wifi_region = 'BO' # Set CRDA region wifi_region = 'BO' # Set CRDA region
wifi_txpower = None # Some cards don't support tx power settings wifi_txpower = None # Leave None to use default power settings from driver.
#wifi_txpower = 58 # Doesn't affect 8812au drivers, use module parameter instead # For 8812au set to -dBm * 100. I.e for 30dBm set to -3000
# For 8812eu set to dBm * 100. I.e for 30dBm set to 3000
temp_measurement_interval = 10 # [s] (8812eu only) Internal RF path temp measurement.
temp_overheat_warning = 60 # [*C] (8812eu only) Overheat warning threshold.
## Stream allocation scheme: ## Stream allocation scheme:

View File

@ -27,7 +27,7 @@ import hashlib
from itertools import groupby from itertools import groupby
from twisted.python import log, failure from twisted.python import log, failure
from twisted.python.logfile import LogFile from twisted.python.logfile import LogFile
from twisted.internet import reactor, defer, main as ti_main from twisted.internet import reactor, defer, main as ti_main, threads, task
from twisted.internet.protocol import ProcessProtocol, Protocol, Factory from twisted.internet.protocol import ProcessProtocol, Protocol, Factory
from twisted.protocols.basic import LineReceiver, Int32StringReceiver from twisted.protocols.basic import LineReceiver, Int32StringReceiver
from twisted.internet.serialport import SerialPort from twisted.internet.serialport import SerialPort
@ -83,6 +83,7 @@ class StatsAndSelectorFactory(Factory):
""" """
def __init__(self, profile, wlans, link_domain): def __init__(self, profile, wlans, link_domain):
self.wlans = tuple(wlans)
self.ant_sel_cb_list = [] self.ant_sel_cb_list = []
self.rssi_cb_l = [] self.rssi_cb_l = []
@ -96,6 +97,46 @@ class StatsAndSelectorFactory(Factory):
# CLI title # CLI title
self.cli_title = 'WFB-ng_%s @%s %s [%s]' % (settings.common.version, profile, ', '.join(wlans), link_domain) self.cli_title = 'WFB-ng_%s @%s %s [%s]' % (settings.common.version, profile, ', '.join(wlans), link_domain)
# RF module temperature by rf_path
self.rf_temperature = {}
self.lc = task.LoopingCall(self.read_temperature)
self.lc.start(settings.common.temp_measurement_interval, now=True)
def _cleanup(self):
self.lc.stop()
def read_temperature(self):
def _read_temperature():
res = {}
for idx, wlan in enumerate(self.wlans):
fname = '/proc/net/rtl88x2eu/%s/thermal_state' % (wlan,)
try:
with open(fname) as fd:
for line in fd:
line = line.strip()
if not line:
continue
d = {}
for f in line.split(','):
k, v = f.split(':', 1)
d[k.strip()] = int(v.strip())
ant_id = (idx << 8) + d['rf_path']
res[ant_id] = d['temperature']
except FileNotFoundError:
pass
except Exception as v:
reactor.callFromThread(log.err, v, 'Unable to parse %s:' % (fname,))
return res
def _got_temp(temp_d):
self.rf_temperature = temp_d
return threads.deferToThread(_read_temperature).addCallback(_got_temp)
def add_ant_sel_cb(self, ant_sel_cb): def add_ant_sel_cb(self, ant_sel_cb):
self.ant_sel_cb_list.append(ant_sel_cb) self.ant_sel_cb_list.append(ant_sel_cb)
ant_sel_cb(self.tx_sel) ant_sel_cb(self.tx_sel)
@ -208,7 +249,10 @@ class StatsAndSelectorFactory(Factory):
# Send stats to CLI sessions # Send stats to CLI sessions
for s in self.ui_sessions: for s in self.ui_sessions:
s.send_stats(dict(type='tx', id=tx_id, packets=packet_stats, latency=ant_latency)) s.send_stats(dict(type='tx', id=tx_id,
packets=packet_stats,
latency=ant_latency,
rf_temperature=self.rf_temperature))
@ -506,21 +550,33 @@ def init(profiles, wlans):
yield init_wlans(max_bw, wlans) yield init_wlans(max_bw, wlans)
dl = [] dl = []
sockets = []
ant_sel_l = []
def _cleanup(x):
for s in sockets:
s.stopListening()
for f in ant_sel_l:
f._cleanup()
return x
for profile, service_list in services: for profile, service_list in services:
# Domain wide antenna selector # Domain wide antenna selector
profile_cfg = getattr(settings, profile) profile_cfg = getattr(settings, profile)
ant_sel_f = StatsAndSelectorFactory(profile, wlans, profile_cfg.link_domain) ant_sel_f = StatsAndSelectorFactory(profile, wlans, profile_cfg.link_domain)
ant_sel_l.append(ant_sel_f)
link_id = int.from_bytes(hashlib.sha1(profile_cfg.link_domain.encode('utf-8')).digest()[:3], 'big') link_id = int.from_bytes(hashlib.sha1(profile_cfg.link_domain.encode('utf-8')).digest()[:3], 'big')
if profile_cfg.stats_port: if profile_cfg.stats_port:
reactor.listenTCP(profile_cfg.stats_port, ant_sel_f) sockets.append(reactor.listenTCP(profile_cfg.stats_port, ant_sel_f))
for service_name, service_type, srv_cfg in service_list: for service_name, service_type, srv_cfg in service_list:
log.msg('Starting %s/%s@%s on %s' % (profile, service_name, profile_cfg.link_domain, ', '.join(wlans))) log.msg('Starting %s/%s@%s on %s' % (profile, service_name, profile_cfg.link_domain, ', '.join(wlans)))
dl.append(defer.maybeDeferred(type_map[service_type], service_name, srv_cfg, wlans, link_id, ant_sel_f)) dl.append(defer.maybeDeferred(type_map[service_type], service_name, srv_cfg, wlans, link_id, ant_sel_f))
yield defer.gatherResults(dl, consumeErrors=True).addErrback(lambda f: f.trap(defer.FirstError) and f.value.subFailure) yield defer.gatherResults(dl, consumeErrors=True).addBoth(_cleanup).addErrback(lambda f: f.trap(defer.FirstError) and f.value.subFailure)
def init_udp_direct_tx(service_name, cfg, wlans, link_id, ant_sel_f): def init_udp_direct_tx(service_name, cfg, wlans, link_id, ant_sel_f):