Skip to content

Commit

Permalink
Merge pull request #457 from tiiuae/field_test_updates
Browse files Browse the repository at this point in the history
Field Test Logger update to get halow support working
  • Loading branch information
joenpera authored May 15, 2024
2 parents 1c38941 + 0f2ee1b commit 12fd751
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
6 changes: 6 additions & 0 deletions common/tools/field_test_logger/field_test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def timestamp() -> str:
ftl.register_logger_function("rssi [MAC,dBm;MAC,dBm ...]", wifi_stats.get_rssi)
ftl.register_logger_function("txpower [dBm]", wifi_stats.get_txpower)
ftl.register_logger_function("noise [dBm]", wifi_stats.get_noise)
ftl.register_logger_function("Halow SNR", wifi_stats.get_snr)
ftl.register_logger_function("RX MCS [MAC,MCS;MAC,MCS ...]", wifi_stats.get_rx_mcs)
ftl.register_logger_function("TX MCS [MAC,MCS;MAC,MCS ...]", wifi_stats.get_tx_mcs)
ftl.register_logger_function("RX throughput [Bits/s]", wifi_stats.get_rx_throughput)
Expand Down Expand Up @@ -179,6 +180,11 @@ def timestamp() -> str:
ftl.register_logger_function("DCin (XT30) voltage [mV]", info.get_dc_voltage)
ftl.register_logger_function("DCin (XT30) current [mA]", info.get_dc_current)

# radio wait loop:
while not wifi_stats.is_up(INTERFACE_ARG) or not wifi_stats.is_mesh(INTERFACE_ARG):
print(f"{INTERFACE_ARG} is not UP or not in mesh-point mode. Waiting...")
time.sleep(2)

ftl.create_csv(f"{wifi_stats.get_mac_addr()}{UNIQUE_ARG}")

while True:
Expand Down
107 changes: 75 additions & 32 deletions common/tools/field_test_logger/wifi_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def __init__(self, interval, interface, batman_interface):
self.__country = ""
self.__txpower = ""
self.__noise = ""
self.__snr = "NaN" # halow specific
self.__rx_throughput = 0
self.__tx_throughput = 0
self.__stations = {}
Expand All @@ -23,6 +24,14 @@ def __init__(self, interval, interface, batman_interface):

# ----------------------------------------

def __run_command(self, cmd):
try:
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
return proc.communicate()[0].decode().rstrip()
except FileNotFoundError:
print(f"Error running command: {cmd}")
return ""

def get_mac_addr(self):
try:
with open(f"/sys/class/net/{self.__interface}/address", 'r') as f:
Expand Down Expand Up @@ -54,6 +63,9 @@ def get_rssi(self):

return out

def get_snr(self):
return self.__snr

def get_rx_mcs(self):
out = ""
for i in self.__stations.keys():
Expand Down Expand Up @@ -92,8 +104,7 @@ def get_tx_throughput(self):

def __update_channel_and_twpower(self):
iw_cmd = ['iw', 'dev']
iw_proc = subprocess.Popen(iw_cmd, stdout=subprocess.PIPE)
out = iw_proc.communicate()[0].decode().rstrip()
out = self.__run_command(iw_cmd)

lines = out.split("\n")

Expand Down Expand Up @@ -132,9 +143,7 @@ def __update_channel_and_twpower(self):

def __update_mcs_and_rssi(self):
iw_cmd = ['iw', 'dev', f"{self.__interface}", 'station', 'dump']
iw_proc = subprocess.Popen(iw_cmd, stdout=subprocess.PIPE)
out = iw_proc.communicate()[0].decode().rstrip()

out = self.__run_command(iw_cmd)
lines = out.split("\n")

station_mac = "NaN"
Expand All @@ -157,54 +166,69 @@ def __update_mcs_and_rssi(self):
rssi = rssi[:rssi.index("]")+1]
else:
# halow station dump does not contain [].
# signal: -63 dBm
rssi = rssi[:rssi.index("dBm")-4]
# rssi: "-63 dBm" --> drop the last 4 characters
rssi = rssi[:-4]

if "tx bitrate:" in line:
if "MCS" in line:
tx_mcs = line[line.index("MCS")+4:line.index("MCS") + 6]
else:
if (halow_stations is None):
elif self.__interface.startswith("halow"):
if halow_stations is None:
halow_stations = self.get_halow_stations()
try:
tx_mcs = halow_stations.get(station_mac)[0]
except IndexError:
except (IndexError, TypeError):
pass
elif "rx bitrate:" in line:
if "MCS" in line:
rx_mcs = line[line.index("MCS")+4:line.index("MCS") + 6]
else:
if (halow_stations is None):
elif self.__interface.startswith("halow"):
if halow_stations is None:
halow_stations = self.get_halow_stations()
try:
rx_mcs = halow_stations.get(station_mac)[1]
except IndexError:
except (IndexError, TypeError):
pass
self.__stations[station_mac] = [rssi, tx_mcs, rx_mcs]

def get_halow_stations(self):
cli_app_cmd = ['cli_app', 'show', 'sta', '0', 'all']
cli_app_proc = subprocess.Popen(cli_app_cmd, stdout=subprocess.PIPE)
out = cli_app_proc.communicate()[0].decode().rstrip()
def get_halow_stations(self) -> dict:
cli_app_cmd = ['/usr/local/bin/cli_app', 'show', 'sta', '0', 'all']
out = self.__run_command(cli_app_cmd)
lines = out.split("\n")
data_begins = False
halow_stations = {}
for line in lines:
if (data_begins):
if data_begins:
# 0 84:25:3f:9c:0a:e9 2 ASSOC 3.00MBit/s(MCS 7) 0.30MBit/s(MCS 0)
cols = line.split()
if (cols.count == 8):
if len(cols) == 8:
halow_stations[cols[1]] = [cols[5][:-1], cols[7][:-1]]
if "=======" in line:
data_begins = True
if "Duplicate" in line:
break
return halow_stations

def __update_snr(self):
if self.__interface.startswith("halow"):
cmd = ["/usr/local/bin/cli_app", "show", "signal"]
out = self.__run_command(cmd)
mac_snr = {}
for line in out.splitlines():
splitted = line.split()
if "MAC addr" in line and len(splitted) > 3:
mac = splitted[3]
if "snr" in line and len(splitted) > 8:
mac_snr[mac] = splitted[9]

self.__snr = ';'.join([f"{k},{v}" for k, v in mac_snr.items()])
else:
self.__snr = "NaN"


def __update_noise(self):
iw_cmd = ['iw', 'dev', f"{self.__interface}", 'survey', 'dump']
iw_proc = subprocess.Popen(iw_cmd, stdout=subprocess.PIPE)
out = iw_proc.communicate()[0].decode().rstrip()
out = self.__run_command(iw_cmd)

lines = out.split("\n")
found_in_use = False
Expand All @@ -223,8 +247,7 @@ def __update_noise(self):

def __update_country_code(self):
iw_cmd = ['iw', 'reg', 'get']
iw_proc = subprocess.Popen(iw_cmd, stdout=subprocess.PIPE)
out = iw_proc.communicate()[0].decode().rstrip()
out = self.__run_command(iw_cmd)

lines = out.split("\n")

Expand Down Expand Up @@ -273,11 +296,7 @@ def __update_throughputs(self):

def __update_batman_neighbors(self):
batctl_cmd = ['batctl', 'meshif', self.__batman_interface, 'n']

batctl_proc = subprocess.Popen(batctl_cmd,
stdout=subprocess.PIPE)

out = batctl_proc.communicate()[0].decode().rstrip()
out = self.__run_command(batctl_cmd)

routing_algo = None
lines = out.split('\n')
Expand Down Expand Up @@ -309,11 +328,8 @@ def __update_batman_neighbors(self):

def __update_batman_originators(self):
batctl_cmd = ['batctl', 'meshif', self.__batman_interface, 'o', '-n', '-H']
out = self.__run_command(batctl_cmd)

batctl_proc = subprocess.Popen(batctl_cmd,
stdout=subprocess.PIPE)

out = batctl_proc.communicate()[0].decode().rstrip()
# Remove parentheses and square brackets
out = re.sub('[()\\[\\]]', '', out)

Expand All @@ -330,6 +346,32 @@ def __update_batman_originators(self):

# ----------------------------------------

@staticmethod
def is_up(interface):
cmd = ['ip', 'link', 'show', 'dev', interface]
try:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, text=True)
# Check if the interface state is not "DOWN"
if 'state UP' in output:
return True
return False
except subprocess.CalledProcessError as e:
print(f"Error running command: {e}")
return False

@staticmethod
def is_mesh(interface):
cmd = ['iw', 'dev', interface, 'info']
try:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, text=True)
# Check if the interface type is "mesh point"
if 'type mesh point' in output:
return True
return False
except subprocess.CalledProcessError as e:
print(f"Error running command: {e}")
return False

def update(self):
"""
Update variables with latest info
Expand All @@ -338,6 +380,7 @@ def update(self):
self.__update_noise()
self.__update_country_code()
self.__update_mcs_and_rssi()
self.__update_snr()
self.__update_throughputs()
self.__update_batman_neighbors()
self.__update_batman_originators()

0 comments on commit 12fd751

Please sign in to comment.