Refactored everything, creating separate functions and iperf folders & making Communication & Relay classes

This commit is contained in:
M madrigal 2025-10-16 13:53:22 -04:00
parent 406a92b66f
commit ba0ef22559
12 changed files with 472 additions and 430 deletions

View File

@ -4,9 +4,7 @@ import subprocess
import threading
import time
import serial
from at_commands import (
from functions.at_commands import (
get_modem_cops,
get_modem_cpol,
get_modem_creg,
@ -17,117 +15,120 @@ from at_commands import (
get_modem_rsrp,
get_modem_rsrq,
get_modem_sinr,
set_configs,
)
from helper_functions import (
calculate_distance,
normalize,
parse_lat_lon,
save_data_to_json,
from functions.helper_functions import save_data_to_json
from functions.location import get_current_location, set_base_location
from functions.sierra_commands import get_modem_nr_info, get_modem_status
from iperf.iperf_functions import collect_iperf
class Communication:
def __init__(self):
self.running = False
self.base_location = None
set_modem = (
input(
"Do you want limit the modem to NR5G without roaming? (Not recommended if PLMN is not 001) (y/n )"
)
from sierra_commands import get_modem_nr_info, get_modem_status
.strip()
.lower()
)
while set_modem not in ("y", "yes", "n", "no"):
set_modem = input("Your response must be y or n ").strip().lower()
if set_modem in ("y", "yes"):
print("Setting configs...")
set_configs()
# Globals
running = False # To control start/stop
base_location = None # The basestation location
self.ip_address = (
input("Enter the ip address (Default is 10.45.0.1): ").strip().lower()
or "10.45.0.1"
)
self.folder_name = (
input("Enter the log folder name (Default is oct_range_test): ")
.strip()
.lower()
or "oct_range_test"
)
self.interval = int(
input(
"Enter the time interval (s) in between pings/modem data collection (Default is 5): "
)
.strip()
.lower()
or 5
)
self.iperf_duration = int(
input("Enter the iperf test duration (s) (Default is 5): ").strip().lower()
or 5
)
foldername = f"data/{self.folder_name}"
self.filename = foldername + "/test_" + str(int(time.time())) + ".json"
os.makedirs(foldername, exist_ok=True)
def read_gps_data(
port: str = "/dev/ttyACM0", baudrate: int = 9600, timeout: int = 5
) -> dict:
"""
Reads GPS data from a u-blox 7 GPS/GLONASS device and returns it as a dictionary.
def set_location(self):
self.base_location = set_base_location()
save_data_to_json(data=self.base_location, filename=self.filename)
Args:
port (str): The serial port the GPS device is connected to. Default is '/dev/ttyACM0'.
baudrate (int): Baud rate for serial communication. Default is 9600.
timeout (int): Timeout in seconds for the serial port. Default is 5 seconds.
def run_iperf(self):
collect_iperf(
filename=self.filename,
is_client=True,
server_ip=self.ip_address,
duration=self.iperf_duration,
timeout=(self.iperf_duration + 5),
base_location=self.base_location,
)
Returns:
dict: A dictionary containing parsed GPS data.
"""
gps_data = {}
attempts = 0
# Collect and send data continuously from Quectel
def collect_data(self):
while self.running:
data = {}
data = get_current_location(dictionary=data)
data = get_modem_cops(dictionary=data)
data = get_modem_creg(dictionary=data)
data = get_modem_csq(dictionary=data)
data = get_modem_rsrp(dictionary=data)
data = get_modem_rsrq(dictionary=data)
data = get_modem_sinr(dictionary=data)
data = get_modem_cpol(dictionary=data)
data = get_modem_qnwcfg(dictionary=data)
data = get_modem_qnwinfo(dictionary=data)
data = get_modem_qspn(dictionary=data)
data = ping_basestation(dictionary=data, address=self.ip_address)
data["timestamp"] = time.time()
try:
with serial.Serial(port, baudrate=baudrate, timeout=timeout) as ser:
while True:
# Read a line from the GPS device
line = ser.readline().decode("ascii", errors="ignore").strip()
# Send to server
print(f"\nDistance: {data.get('distance')}")
print(f"Service: {data.get('network information')}")
print(f"Ping Time: {data.get(f'{self.ip_address}_ping_time')}")
print(
f"RSRP: {data.get('RSRP PRX')} {data.get('RSRP DRX')} "
f"{data.get('RSRP RX2')} {data.get('RSRP RX3')}"
)
# Filter for GGA or RMC sentences for relevant data
if line.startswith("$GPGGA"): # Global Positioning System Fix Data
parts = line.split(",")
gps_data["utc_time"] = parts[1]
gps_data["latitude"] = parse_lat_lon(parts[2], parts[3])
gps_data["longitude"] = parse_lat_lon(parts[4], parts[5])
gps_data["altitude"] = float(parts[9]) if parts[9] else None
save_data_to_json(data=data, filename=self.filename)
time.sleep(self.interval)
# Count number of times GPGGA has been queried
attempts = attempts + 1
# Collect and send data continuously from Sierra
def collect_sierra_data(self):
while self.running:
data = {}
data = get_current_location(dictionary=data)
data = get_modem_nr_info(dictionary=data)
data = get_modem_status(dictionary=data)
data = ping_basestation(dictionary=data, address=self.ip_address)
data["timestamp"] = time.time()
# Stop after collecting sufficient data
if (
gps_data.get("utc_time")
and gps_data.get("latitude")
and gps_data.get("longitude")
):
break
elif attempts >= 3:
gps_data = {}
break
except serial.SerialException:
pass
except Exception as e:
print(f"Error: {e}")
# Send to server
print(f"\nDistance: {data.get('distance')}")
print(f"Ping Time: {data.get('ping_time')}")
print(f"RSRP: {data.get('RSRP')}")
return gps_data
def set_base_location():
global base_location
base_location = {}
try:
gps_data = read_gps_data()
base_location["latitude"] = gps_data["latitude"]
base_location["longitude"] = gps_data["longitude"]
if gps_data.get("altitude"):
base_location["altitude"] = gps_data["altitude"]
print("Base location found")
except KeyError:
print("Base location could not be found")
except Exception as e:
print(f"Error finding location: {e}")
return base_location
def get_current_location(dictionary={}):
global base_location
try:
gps_data = read_gps_data()
dictionary["latitude"] = gps_data["latitude"]
dictionary["longitude"] = gps_data["longitude"]
if gps_data.get("altitude"):
dictionary["altitude"] = gps_data["altitude"]
if base_location and "latitude" in base_location:
dictionary["baseLatitude"] = base_location["latitude"]
dictionary["baseLongitude"] = base_location["longitude"]
if base_location.get("altitude"):
dictionary["baseAltitude"] = base_location["altitude"]
dictionary["distance"] = calculate_distance(base_location, gps_data)
except KeyError:
print("Location could not be found")
dictionary["distance"] = "Unknown"
except Exception as e:
print(f"Error finding location: {e}")
dictionary["distance"] = "Error"
return dictionary
save_data_to_json(data=data, filename=self.filename)
time.sleep(self.interval)
# Ping base station
@ -152,165 +153,8 @@ def ping_basestation(address="10.45.0.1", name="10.45.0.1", dictionary={}) -> di
return dictionary
# Run iperf test
def collect_iperf(
filename,
server_ip="10.45.0.1",
duration=10,
is_client=True,
stations="",
):
if is_client:
commands = [
["iperf3", "-c", server_ip, "-t", str(duration)],
["iperf3", "-c", server_ip, "-t", str(duration), "-R"],
]
else:
commands = [["iperf3", "-s"]]
for command in commands:
try:
try:
location = read_gps_data()
if base_location:
start_distance = calculate_distance(base_location, location)
else:
start_distance = None
except:
print("Could not collect location")
start_distance = None
# Run the command
result = subprocess.run(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)
output = result.stdout
# Check for errors
if result.returncode != 0:
print(f"Error running iperf3: {result.stderr}")
return result.stderr
matches = re.findall(
r"\[\s*\d+\]\s+\d+\.\d+\-\d+\.\d+\s+sec\s+[\d.]+\s+\w+Bytes\s+([\d.]+)\s+(Kbits/sec|Mbits/sec)",
output,
)
if len(matches) >= 1:
# Normalize the last entries
last_value, last_unit = matches[-1]
sender_bitrate = normalize(float(last_value), last_unit)
# Try to differentiate sender vs receiver
receiver_match = re.search(r"receiver", output, re.IGNORECASE)
sender_match = re.search(r"sender", output, re.IGNORECASE)
if receiver_match and sender_match and len(matches) >= 2:
recv_value, recv_unit = matches[-1]
send_value, send_unit = matches[-2]
receiver_bitrate = normalize(float(recv_value), recv_unit)
sender_bitrate = normalize(float(send_value), send_unit)
else:
receiver_bitrate = sender_bitrate
else:
bitrates = re.findall(r"(\d+\.\d+) Mbits/sec", output)
sender_bitrate = float(bitrates[-2])
receiver_bitrate = float(bitrates[-1])
if "-R" in command:
test_type = "downlink"
else:
test_type = "uplink"
data = {
"iperf_full": output,
"sender_bitrate": sender_bitrate,
"receiver_bitrate": receiver_bitrate,
"start_distance": start_distance,
"location": location,
"type": test_type,
"stations": stations,
}
print(f"\n{server_ip} {test_type} IPERF complete")
print(f"IPERF sender bitrate: {sender_bitrate}")
print(f"IPERF receiver bitrate: {receiver_bitrate}")
save_data_to_json(data=data, filename=filename)
time.sleep(0.25)
except Exception as e:
print(f"iPerf Error: {e}")
# Collect and send data continuously
def collect_data(filename, address):
global base_location
global running
while running:
data = {}
data = get_current_location(dictionary=data)
data = get_modem_cops(dictionary=data)
data = get_modem_creg(dictionary=data)
data = get_modem_csq(dictionary=data)
data = get_modem_rsrp(dictionary=data)
data = get_modem_rsrq(dictionary=data)
data = get_modem_sinr(dictionary=data)
data = get_modem_cpol(dictionary=data)
data = get_modem_qnwcfg(dictionary=data)
data = get_modem_qnwinfo(dictionary=data)
data = get_modem_qspn(dictionary=data)
data = ping_basestation(dictionary=data, address=address)
data["timestamp"] = time.time()
# Send to server
print(f"\nDistance: {data.get('distance')}")
print(f"Service: {data.get('network information')}")
print(f"Ping Time: {data.get(f'{address}_ping_time')}")
print(
f"RSRP: {data.get('RSRP PRX')} {data.get('RSRP DRX')} {data.get('RSRP RX2')} {data.get('RSRP RX3')}"
)
save_data_to_json(data=data, filename=filename)
time.sleep(5)
# Collect and send data continuously
def collect_sierra_data(filename):
global base_location
global running
while running:
data = {}
data = get_current_location(dictionary=data)
data = get_modem_nr_info(dictionary=data)
data = get_modem_status(dictionary=data)
data = ping_basestation(dictionary=data)
data["timestamp"] = time.time()
# Send to server
print(f"\nDistance: {data.get('distance')}")
print(f"Ping Time: {data.get('ping_time')}")
print(f"RSRP: {data.get('RSRP')}")
save_data_to_json(data=data, filename=filename)
time.sleep(5)
# Main function
def main():
global running
address = "10.46.0.1"
foldername = "data/office_test_sept_19"
os.makedirs(foldername, exist_ok=True)
filename = foldername + "/test_" + str(int(time.time())) + ".json"
# print("Setting configs...")
# set_configs()
if __name__ == "__main__":
modem = Communication()
print(
"Type 'l' to set basestation location, 'b' to begin, "
@ -318,24 +162,19 @@ def main():
)
while True:
command = input("> ").strip().lower()
if command == "b" and not running:
if command == "b" and not modem.running:
print("Starting data collection...")
running = True
threading.Thread(target=collect_data, args=(filename, address)).start()
modem.running = True
threading.Thread(target=modem.collect_data).start()
elif command == "l":
base_location_data = set_base_location()
save_data_to_json(data=base_location_data, filename=filename)
modem.set_location()
elif command == "i":
threading.Thread(target=collect_iperf, args=(filename, address)).start()
elif command == "s" and running:
threading.Thread(target=modem.run_iperf).start()
elif command == "s" and modem.running:
print("Stopping data collection...")
running = False
modem.running = False
elif command == "x":
running = False
modem.running = False
break
elif command not in ["l", "b", "s", "i", "x"]:
print("Invalid command. Type 'l', 'b', 's', 'i', or 'x'.")
if __name__ == "__main__":
main()

View File

@ -1,6 +1,6 @@
import serial
from helper_functions import comma_split, extract_numbers
from functions.helper_functions import comma_split, extract_numbers
# For more info on the commands:
# https://files.waveshare.com/upload/8/8a/Quectel_RG520N%26RG52xF%26RG530F%26RM520N%26RM530N_Series_AT_Commands_Manual_V1.0.0_Preliminary_20220812.pdf

97
functions/location.py Normal file
View File

@ -0,0 +1,97 @@
import serial
from functions.helper_functions import calculate_distance, parse_lat_lon
def read_gps_data(
port: str = "/dev/ttyACM0", baudrate: int = 9600, timeout: int = 5
) -> dict:
"""
Reads GPS data from a u-blox 7 GPS/GLONASS device and returns it as a dictionary.
Args:
port (str): The serial port the GPS device is connected to. Default is '/dev/ttyACM0'.
baudrate (int): Baud rate for serial communication. Default is 9600.
timeout (int): Timeout in seconds for the serial port. Default is 5 seconds.
Returns:
dict: A dictionary containing parsed GPS data.
"""
gps_data = {}
attempts = 0
try:
with serial.Serial(port, baudrate=baudrate, timeout=timeout) as ser:
while True:
# Read a line from the GPS device
line = ser.readline().decode("ascii", errors="ignore").strip()
# Filter for GGA or RMC sentences for relevant data
if line.startswith("$GPGGA"): # Global Positioning System Fix Data
parts = line.split(",")
gps_data["utc_time"] = parts[1]
gps_data["latitude"] = parse_lat_lon(parts[2], parts[3])
gps_data["longitude"] = parse_lat_lon(parts[4], parts[5])
gps_data["altitude"] = float(parts[9]) if parts[9] else None
# Count number of times GPGGA has been queried
attempts = attempts + 1
# Stop after collecting sufficient data
if (
gps_data.get("utc_time")
and gps_data.get("latitude")
and gps_data.get("longitude")
):
break
elif attempts >= 3:
gps_data = {}
break
except serial.SerialException:
pass
except Exception as e:
print(f"Error: {e}")
return gps_data
def set_base_location(base_location={}):
try:
gps_data = read_gps_data()
base_location["latitude"] = gps_data["latitude"]
base_location["longitude"] = gps_data["longitude"]
if gps_data.get("altitude"):
base_location["altitude"] = gps_data["altitude"]
print("Base location found")
except KeyError:
print("Base location could not be found")
except Exception as e:
print(f"Error finding location: {e}")
return base_location
def get_current_location(dictionary={}, base_location={}):
try:
gps_data = read_gps_data()
dictionary["latitude"] = gps_data["latitude"]
dictionary["longitude"] = gps_data["longitude"]
if gps_data.get("altitude"):
dictionary["altitude"] = gps_data["altitude"]
if base_location and "latitude" in base_location:
dictionary["baseLatitude"] = base_location["latitude"]
dictionary["baseLongitude"] = base_location["longitude"]
if base_location.get("altitude"):
dictionary["baseAltitude"] = base_location["altitude"]
dictionary["distance"] = calculate_distance(base_location, gps_data)
except KeyError:
print("Location could not be found")
dictionary["distance"] = "Unknown"
except Exception as e:
print(f"Error finding location: {e}")
dictionary["distance"] = "Error"
return dictionary

View File

@ -1,6 +1,6 @@
import serial
from helper_functions import extract_numbers
from functions.helper_functions import extract_numbers
# Fetch operational status

0
iperf/__init__.py Normal file
View File

View File

@ -1,7 +1,7 @@
import re
import socket
from helper_functions import normalize, save_data_to_json
from functions.helper_functions import normalize, save_data_to_json
RELAY_IP = "10.45.0.1" # gNodeB IP of relay
PORT = 5005

126
iperf/iperf_functions.py Normal file
View File

@ -0,0 +1,126 @@
import re
import subprocess
import time
from functions.helper_functions import calculate_distance, normalize, save_data_to_json
from functions.location import read_gps_data
def get_location(base_location):
try:
location = read_gps_data()
if base_location:
start_distance = calculate_distance(base_location, location)
else:
start_distance = None
except Exception as e:
print(f"Could not collect location: {e}")
start_distance = None
return location, start_distance
def parse_iperf_output(output):
if output == "":
return None, None
matches = re.findall(
r"\[\s*\d+\]\s+\d+\.\d+\-\d+\.\d+\s+sec\s+[\d.]+\s+\w+Bytes\s+([\d.]+)\s+(Kbits/sec|Mbits/sec)",
output,
)
if len(matches) >= 1:
# Normalize the last entries
last_value, last_unit = matches[-1]
sender_bitrate = normalize(float(last_value), last_unit)
# Try to differentiate sender vs receiver
receiver_match = re.search(r"receiver", output, re.IGNORECASE)
sender_match = re.search(r"sender", output, re.IGNORECASE)
if receiver_match and sender_match and len(matches) >= 2:
recv_value, recv_unit = matches[-1]
send_value, send_unit = matches[-2]
receiver_bitrate = normalize(float(recv_value), recv_unit)
sender_bitrate = normalize(float(send_value), send_unit)
else:
receiver_bitrate = sender_bitrate
else:
bitrates = re.findall(r"(\d+\.\d+) Mbits/sec", output)
sender_bitrate = float(bitrates[-2])
receiver_bitrate = float(bitrates[-1])
return sender_bitrate, receiver_bitrate
# Run iperf test
def collect_iperf(
filename,
is_client=True,
server_ip="10.45.0.1",
stations="",
duration=10,
timeout=20,
base_location=None,
):
if is_client:
commands = [
["iperf3", "-c", server_ip, "-t", str(duration)],
["iperf3", "-c", server_ip, "-t", str(duration), "-R"],
]
else:
commands = [["iperf3", "-s"]]
for command in commands:
try:
location, start_distance = get_location(base_location=base_location)
# Run iperf with timeout protection
try:
result = subprocess.run(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
timeout=timeout,
)
output = result.stdout
# Check for errors
if result.returncode != 0:
print(f"Error running iperf3: {result.stderr}")
output = ""
except subprocess.TimeoutExpired:
print(f"iPerf test timed out after {timeout} seconds.")
output = ""
sender_bitrate, receiver_bitrate = parse_iperf_output(output)
if "-R" in command:
test_type = "downlink"
else:
test_type = "uplink"
data = {
"iperf_full": output,
"sender_bitrate": sender_bitrate,
"receiver_bitrate": receiver_bitrate,
"start_distance": start_distance,
"location": location,
"type": test_type,
"stations": stations,
}
if output == "":
data["error"] = f"Test exceeded timeout of {timeout}s"
else:
print(f"\n{server_ip} {test_type} IPERF complete")
print(f"IPERF sender bitrate: {sender_bitrate}")
print(f"IPERF receiver bitrate: {receiver_bitrate}")
save_data_to_json(data=data, filename=filename)
time.sleep(0.25)
except Exception as e:
print(f"iPerf Error: {e}")

View File

@ -1,7 +1,7 @@
import json
import re
from helper_functions import calculate_distance
from functions.helper_functions import calculate_distance
def get_data_lists(data, entry_type, default_diconnect):

234
relay.py
View File

@ -2,7 +2,8 @@ import os
import threading
import time
from at_commands import (
from communication import ping_basestation
from functions.at_commands import (
get_modem_cops,
get_modem_cpol,
get_modem_creg,
@ -15,106 +16,16 @@ from at_commands import (
get_modem_sinr,
set_configs,
)
from communication import (
collect_iperf,
get_current_location,
ping_basestation,
set_base_location,
)
from helper_functions import save_data_to_json
# Globals
running = False # To control start/stop
from functions.helper_functions import save_data_to_json
from functions.location import get_current_location, set_base_location
from iperf.iperf_functions import collect_iperf
def calculate_ping(
dictionary: dict, base_address: str, relay_address: str, name: str
) -> dict:
try:
base_ping = float(dictionary[f"{base_address}_ping_time"])
relay_ping = float(dictionary[f"{relay_address}_ping_time"])
calculated_ping = base_ping - relay_ping
dictionary[f"{name}_c_ping_time"] = calculated_ping
except Exception as e:
dictionary[f"{name}_c_ping error"] = f"{e}"
class Relay:
def __init__(self):
self.running = False
self.base_location = None
return dictionary
def relay_iperf(
filename: str, base_address: str, relay_address: str, duration: str
) -> None:
try:
collect_iperf(
filename=filename, server_ip=base_address, duration=duration, stations="eg"
)
except Exception as e:
print(f"iPerf error: {e}")
data = {
"iperf_full": f"Error: {e}",
"stations": "eg",
}
save_data_to_json(data=data, filename=filename)
try:
collect_iperf(
filename=filename, server_ip=relay_address, duration=duration, stations="er"
)
except Exception as e:
print(f"iPerf error: {e}")
data = {
"iperf_full": f"Error: {e}",
"stations": "er",
}
save_data_to_json(data=data, filename=filename)
# Collect and send data continuously
def collect_data(
filename: str, base_address: str, relay_address: str, interval: int
) -> None:
global running
while running:
data = {}
data = get_current_location(dictionary=data)
data = get_modem_cops(dictionary=data)
data = get_modem_creg(dictionary=data)
data = get_modem_csq(dictionary=data)
data = get_modem_rsrp(dictionary=data)
data = get_modem_rsrq(dictionary=data)
data = get_modem_sinr(dictionary=data)
data = get_modem_cpol(dictionary=data)
data = get_modem_qnwcfg(dictionary=data)
data = get_modem_qnwinfo(dictionary=data)
data = get_modem_qspn(dictionary=data)
data = ping_basestation(
dictionary=data, name="eg", address=base_address
) # edge to ground
data = ping_basestation(
dictionary=data, name="er", address=relay_address
) # edge to relay
data = calculate_ping(
dictionary=data,
base_address="eg",
relay_address="er",
name="rg",
) # relay to ground
data["timestamp"] = time.time()
# Send to server
print(f"\nPing Time: {data.get('ping_time')}")
print(
f"RSRP: PRX: {data.get('RSRP PRX')} DRX: {data.get('RSRP DRX')} \
RX2: {data.get('RSRP RX2')} RX3: {data.get('RSRP RX3')}"
)
print(f"Service: {data.get('network information')}")
save_data_to_json(data=data, filename=filename)
time.sleep(interval)
def set_parameters():
set_modem = (
input(
"Do you want limit the modem to NR5G without roaming? (Not recommended if PLMN is not 001) (y/n )"
@ -128,25 +39,25 @@ def set_parameters():
print("Setting configs...")
set_configs()
base_address = (
self.base_address = (
input("Enter the base station (ground) ip address (Default is 10.46.0.1): ")
.strip()
.lower()
or "10.46.0.1"
)
relay_address = (
self.relay_address = (
input("Enter the relay station ip address (Default is 10.45.0.1): ")
.strip()
.lower()
or "10.45.0.1"
)
folder_name = (
self.folder_name = (
input("Enter the log folder name (Default is boat_relay_oct_9): ")
.strip()
.lower()
or "boat_relay_oct_9"
)
interval = int(
self.interval = int(
input(
"Enter the time interval (s) in between pings/modem data collection (Default is 5): "
)
@ -154,21 +65,97 @@ def set_parameters():
.lower()
or 5
)
iperf_duration = int(
input("Enter the iperf test duration (s) (Default is 5): ").strip().lower() or 5
self.iperf_duration = int(
input("Enter the iperf test duration (s) (Default is 5): ").strip().lower()
or 5
)
return base_address, relay_address, folder_name, interval, iperf_duration
foldername = f"data/{self.folder_name}"
self.filename = foldername + "/test_" + str(int(time.time())) + ".json"
os.makedirs(foldername, exist_ok=True)
def set_location(self):
self.base_location = set_base_location()
save_data_to_json(data=self.base_location, filename=self.filename)
def calculate_ping(
self, dictionary: dict, base_address: str, relay_address: str, name: str
) -> dict:
try:
base_ping = float(dictionary[f"{base_address}_ping_time"])
relay_ping = float(dictionary[f"{relay_address}_ping_time"])
calculated_ping = base_ping - relay_ping
dictionary[f"{name}_c_ping_time"] = calculated_ping
except Exception as e:
dictionary[f"{name}_c_ping error"] = f"{e}"
return dictionary
# Run iPerf test from End to Ground, then End to Relay
def relay_iperf(self) -> None:
collect_iperf(
filename=self.filename,
is_client=True,
server_ip=self.base_address,
stations="eg",
duration=self.iperf_duration,
timeout=(self.iperf_duration + 5),
base_location=self.base_location,
)
collect_iperf(
filename=self.filename,
is_client=True,
server_ip=self.relay_address,
stations="er",
duration=self.iperf_duration,
timeout=(self.iperf_duration + 5),
base_location=self.base_location,
)
# Collect and send data continuously
def collect_data(self) -> None:
while self.running:
data = {}
data = get_current_location(dictionary=data)
data = get_modem_cops(dictionary=data)
data = get_modem_creg(dictionary=data)
data = get_modem_csq(dictionary=data)
data = get_modem_rsrp(dictionary=data)
data = get_modem_rsrq(dictionary=data)
data = get_modem_sinr(dictionary=data)
data = get_modem_cpol(dictionary=data)
data = get_modem_qnwcfg(dictionary=data)
data = get_modem_qnwinfo(dictionary=data)
data = get_modem_qspn(dictionary=data)
data = ping_basestation(
dictionary=data, name="eg", address=self.base_address
) # edge to ground
data = ping_basestation(
dictionary=data, name="er", address=self.relay_address
) # edge to relay
data = self.calculate_ping(
dictionary=data,
base_address="eg",
relay_address="er",
name="rg",
) # relay to ground
data["timestamp"] = time.time()
# Send to server
print(f"\nPing Time: {data.get('ping_time')}")
print(
f"RSRP: PRX: {data.get('RSRP PRX')} DRX: {data.get('RSRP DRX')} "
f"RX2: {data.get('RSRP RX2')} RX3: {data.get('RSRP RX3')}"
)
print(f"Service: {data.get('network information')}")
save_data_to_json(data=data, filename=self.filename)
time.sleep(self.interval)
if __name__ == "__main__":
base_address, relay_address, folder_name, interval, iperf_duration = (
set_parameters()
)
foldername = f"data/{folder_name}"
filename = foldername + "/test_" + str(int(time.time())) + ".json"
os.makedirs(foldername, exist_ok=True)
relay = Relay()
print(
"Type 'l' to set basestation location, 'b' to begin, "
@ -176,26 +163,19 @@ if __name__ == "__main__":
)
while True:
command = input("> ").strip().lower()
if command == "b" and not running:
if command == "b" and not relay.running:
print("Starting data collection...")
running = True
threading.Thread(
target=collect_data,
args=(filename, base_address, relay_address, interval),
).start()
relay.running = True
threading.Thread(target=relay.collect_data).start()
elif command == "l":
base_location_data = set_base_location()
save_data_to_json(data=base_location_data, filename=filename)
relay.set_location()
elif command == "i":
threading.Thread(
target=relay_iperf,
args=(filename, base_address, relay_address, iperf_duration),
).start()
elif command == "s" and running:
threading.Thread(target=relay.relay_iperf).start()
elif command == "s" and relay.running:
print("Stopping data collection...")
running = False
relay.running = False
elif command == "x":
running = False
relay.running = False
break
elif command not in ["l", "b", "s", "i", "x"]:
print("Invalid command. Type 'l', 'b', 's', 'i', or 'x'.")