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']
latency_d = attrs['latency']
tx_id = attrs['id']
rf_temperature = attrs['rf_temperature']
window = self.factory.windows.get(tx_id)
if window is None:
@ -218,12 +219,23 @@ class AntennaStat(Int32StringReceiver):
human_rate(p['injected_bytes'][0])))
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):
k = int(k) # json doesn't support int keys
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:
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:
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}
wifi_region = 'BO' # Set CRDA region
wifi_txpower = None # Some cards don't support tx power settings
#wifi_txpower = 58 # Doesn't affect 8812au drivers, use module parameter instead
wifi_txpower = None # Leave None to use default power settings from driver.
# 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:

View File

@ -27,7 +27,7 @@ import hashlib
from itertools import groupby
from twisted.python import log, failure
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.protocols.basic import LineReceiver, Int32StringReceiver
from twisted.internet.serialport import SerialPort
@ -83,6 +83,7 @@ class StatsAndSelectorFactory(Factory):
"""
def __init__(self, profile, wlans, link_domain):
self.wlans = tuple(wlans)
self.ant_sel_cb_list = []
self.rssi_cb_l = []
@ -96,6 +97,46 @@ class StatsAndSelectorFactory(Factory):
# CLI title
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):
self.ant_sel_cb_list.append(ant_sel_cb)
ant_sel_cb(self.tx_sel)
@ -208,7 +249,10 @@ class StatsAndSelectorFactory(Factory):
# Send stats to CLI 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)
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:
# Domain wide antenna selector
profile_cfg = getattr(settings, profile)
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')
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:
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))
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):