Skip to content

Commit

Permalink
Show correct speed if log_interval != 1000
Browse files Browse the repository at this point in the history
  • Loading branch information
svpcom committed Sep 29, 2024
1 parent c330dda commit 397faaf
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 36 deletions.
53 changes: 32 additions & 21 deletions wfb_ng/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ def format_ant(ant_id):
class AntennaStat(Int32StringReceiver):
MAX_LENGTH = 1024 * 1024
is_cluster = False
log_interval = settings.common.log_interval
temp_overheat_warning = settings.common.temp_overheat_warning

def stringReceived(self, string):
attrs = msgpack.unpackb(string, strict_map_key=False, use_list=False)
Expand All @@ -150,7 +152,10 @@ def stringReceived(self, string):
elif attrs['type'] == 'tx':
self.draw_tx(attrs)
elif attrs['type'] == 'cli_title':
self.is_cluster = attrs['is_cluster']
# Fallbacks added for compatibility with old server versions
self.is_cluster = attrs.get('is_cluster', False)
self.log_interval = attrs.get('log_interval', settings.common.log_interval)
self.temp_overheat_warning = attrs.get('temp_overheat_warning', settings.common.temp_overheat_warning)
set_window_title(attrs['cli_title'])

def draw_rx(self, attrs):
Expand All @@ -167,12 +172,15 @@ def draw_rx(self, attrs):
window.erase()
addstr_markup(window, 0, 0, ' {pkt/s pkt}')

msg_l = (('{recv} %4d$ (%d)' % tuple(p['all']), 0),
('{udp} %4d$ (%d)' % tuple(p['out']), 0),
('fec_r %4d$ (%d)' % tuple(p['fec_rec']), curses.A_REVERSE if p['fec_rec'][0] else 0),
('lost %4d$ (%d)' % tuple(p['lost']), curses.A_REVERSE if p['lost'][0] else 0),
('d_err %4d$ (%d)' % tuple(p['dec_err']), curses.A_REVERSE if p['dec_err'][0] else 0),
('bad %4d$ (%d)' % tuple(p['bad']), curses.A_REVERSE if p['bad'][0] else 0))
def _norm(l):
return (1000 * l[0] // self.log_interval, l[1])

msg_l = (('{recv} %4d$ (%d)' % _norm(p['all']), 0),
('{udp} %4d$ (%d)' % _norm(p['out']), 0),
('fec_r %4d$ (%d)' % _norm(p['fec_rec']), curses.A_REVERSE if p['fec_rec'][0] else 0),
('lost %4d$ (%d)' % _norm(p['lost']), curses.A_REVERSE if p['lost'][0] else 0),
('d_err %4d$ (%d)' % _norm(p['dec_err']), curses.A_REVERSE if p['dec_err'][0] else 0),
('bad %4d$ (%d)' % _norm(p['bad']), curses.A_REVERSE if p['bad'][0] else 0))

ymax = window.getmaxyx()[0]
for y, (msg, attr) in enumerate(msg_l, 1):
Expand All @@ -181,8 +189,8 @@ def draw_rx(self, attrs):


flow_str = '{Flow:} %s -> %s ' % \
(human_rate(p['all_bytes'][0]),
human_rate(p['out_bytes'][0]))
(human_rate(1000 * p['all_bytes'][0] / self.log_interval),
human_rate(1000 * p['out_bytes'][0] / self.log_interval))

if session_d:
flow_str += '{FEC:} %(fec_k)d/%(fec_n)d' % (session_d)
Expand All @@ -205,7 +213,7 @@ def draw_rx(self, attrs):
addstr_markup(window, y, 20, '%04d %3d %2d %s%s%s %4d %3d < {%3d} < %3d %3d < {%3d} < %3d' % \
(freq, mcs_index, bandwith,
'{' if active_tx else '', format_ant(ant_id), '}' if active_tx else '',
pkt_s,
1000 * pkt_s // self.log_interval,
rssi_min, rssi_avg, rssi_max,
snr_min, snr_avg, snr_max), 0 if active_tx else curses.A_DIM)
else:
Expand All @@ -226,11 +234,14 @@ def draw_tx(self, attrs):
window.erase()
addstr_noerr(window, 0, 0, ' pkt/s pkt', curses.A_BOLD)

msg_l = (('{sent} %4d$ (%d)' % tuple(p['injected']), 0),
('{udp} %4d$ (%d)' % tuple(p['incoming']), 0),
('fec_t %4d$ (%d)' % tuple(p['fec_timeouts']), 0),
('drop %4d$ (%d)' % tuple(p['dropped']), curses.A_REVERSE if p['dropped'][0] else 0),
('trunc %4d$ (%d)' % tuple(p['truncated']), curses.A_REVERSE if p['truncated'][0] else 0))
def _norm(l):
return (1000 * l[0] // self.log_interval, l[1])

msg_l = (('{sent} %4d$ (%d)' % _norm(p['injected']), 0),
('{udp} %4d$ (%d)' % _norm(p['incoming']), 0),
('fec_t %4d$ (%d)' % _norm(p['fec_timeouts']), 0),
('drop %4d$ (%d)' % _norm(p['dropped']), curses.A_REVERSE if p['dropped'][0] else 0),
('trunc %4d$ (%d)' % _norm(p['truncated']), curses.A_REVERSE if p['truncated'][0] else 0))

ymax = window.getmaxyx()[0]
for y, (msg, attr) in enumerate(msg_l, 1):
Expand All @@ -239,8 +250,8 @@ def draw_tx(self, attrs):

addstr_markup(window, 0, 20,
'{Flow:} %s -> %s' % \
(human_rate(p['incoming_bytes'][0]),
human_rate(p['injected_bytes'][0])))
(human_rate(1000 * p['incoming_bytes'][0] / self.log_interval),
human_rate(1000 * p['injected_bytes'][0] / self.log_interval)))

if latency_d:
if self.is_cluster:
Expand All @@ -252,21 +263,21 @@ def draw_tx(self, attrs):

addstr_markup(window, 2, 20, '{%s[ANT]%s pkt/s} {\u00b0C} {Injection} [us]' % (lpad, rpad))
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,)
if self.temp_overheat_warning is not None and temp >= self.temp_overheat_warning:
temp = '^%d$' % (temp,)
else:
temp = str(temp)
else:
temp = ' (--)'

if y < ymax:
addstr_markup(window, y, 20, '{%s} %4d %3s %4d < {%4d} < %4d' % (format_ant(k), injected, temp, lat_min, lat_avg, lat_max))
addstr_markup(window, y, 20, '{%s} %4d %3s %4d < {%4d} < %4d' % \
(format_ant(k), 1000 * injected // self.log_interval, temp, lat_min, lat_avg, lat_max))
else:
addstr_noerr(window, 2, 20, '[No data]', curses.A_REVERSE)

Expand Down
35 changes: 20 additions & 15 deletions wfb_ng/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,16 @@ class StatisticsProtocol(Int32StringReceiver):
MAX_LENGTH = 1024 * 1024

def connectionMade(self):
# Push all config values for CLI into session
# to allow CLI run without config file
# (for example for access from remote host)

self.sendString(msgpack.packb(dict(type='cli_title',
cli_title=self.factory.cli_title or "",
is_cluster=self.factory.is_cluster)))
is_cluster=self.factory.is_cluster,
log_interval=settings.common.log_interval,
temp_overheat_warning=settings.common.temp_overheat_warning)))

self.factory.ui_sessions.append(self)

def stringReceived(self, string):
Expand Down Expand Up @@ -346,17 +353,16 @@ def lineReceived(self, line):
if len(cols) != 3:
raise BadTelemetry()

p_all, b_all, p_dec_err, p_dec_ok, p_fec_rec, p_lost, p_bad, p_outgoing, b_outgoing = list(int(i) for i in cols[2].split(':'))
k_tuple = ('all', 'all_bytes', 'dec_err', 'dec_ok', 'fec_rec', 'lost', 'bad', 'out', 'out_bytes')
counters = tuple(int(i) for i in cols[2].split(':'))
assert len(counters) == len(k_tuple)

if not self.count_all:
self.count_all = (p_all, b_all, p_dec_ok, p_fec_rec, p_lost, p_dec_err, p_bad, p_outgoing, b_outgoing)
self.count_all = counters
else:
self.count_all = tuple((a + b) for a, b in zip((p_all, b_all, p_dec_ok, p_fec_rec, p_lost, p_dec_err, p_bad, p_outgoing, b_outgoing),
self.count_all))
self.count_all = tuple((a + b) for a, b in zip(counters, self.count_all))

stats = dict(zip(('all', 'all_bytes', 'dec_ok', 'fec_rec', 'lost', 'dec_err', 'bad', 'out', 'out_bytes'),
zip((p_all, b_all, p_dec_ok, p_fec_rec, p_lost, p_dec_err, p_bad, p_outgoing, b_outgoing),
self.count_all)))
stats = dict(zip(k_tuple, zip(counters, self.count_all)))

# Send stats to aggregators
if self.ant_stat_cb is not None:
Expand Down Expand Up @@ -437,17 +443,16 @@ def lineReceived(self, line):
if len(cols) != 3:
raise BadTelemetry()

p_fec_timeouts, p_incoming, b_incoming, p_injected, b_injected, p_dropped, p_truncated = list(int(i) for i in cols[2].split(':'))
k_tuple = ('fec_timeouts', 'incoming', 'incoming_bytes', 'injected', 'injected_bytes', 'dropped', 'truncated')
counters = tuple(int(i) for i in cols[2].split(':'))
assert len(counters) == len(k_tuple)

if not self.count_all:
self.count_all = (p_fec_timeouts, p_incoming, b_incoming, p_injected, b_injected, p_dropped, p_truncated)
self.count_all = counters
else:
self.count_all = tuple((a + b) for a, b in zip((p_fec_timeouts, p_incoming, b_incoming, p_injected, b_injected, p_dropped, p_truncated),
self.count_all))
self.count_all = tuple((a + b) for a, b in zip(counters, self.count_all))

stats = dict(zip(('fec_timeouts', 'incoming', 'incoming_bytes', 'injected', 'injected_bytes', 'dropped', 'truncated'),
zip((p_fec_timeouts, p_incoming, b_incoming, p_injected, b_injected, p_dropped, p_truncated),
self.count_all)))
stats = dict(zip(k_tuple, zip(counters, self.count_all)))

# Send stats to aggregators
if self.ant_stat_cb is not None:
Expand Down

0 comments on commit 397faaf

Please sign in to comment.