Skip to content

Commit

Permalink
Improve Tracksight setup (#1297)
Browse files Browse the repository at this point in the history
### Changelist 
<!-- Give a list of the changes covered in this PR. This will help both
you and the reviewer keep this PR within scope. -->

Improve Tracksight setup process, and also document it in
`software/tracksight/README.md`.
  • Loading branch information
gtaharaedmonds authored Jun 5, 2024
1 parent 91b1606 commit f112eb0
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 20 deletions.
16 changes: 12 additions & 4 deletions software/tracksight/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ Check out our [Next.js deployment documentation](https://nextjs.org/docs/deploym

### Running Locally

To start the local stack, navigate to `software/tracksight` and run `./run_local.sh`. This is used for viewing log files, such as from the onboard SD card.
To start the local stack, navigate to `software/tracksight` and run `./run_log.sh`. This is used for viewing log files, such as from the onboard SD card.

This starts the frontend, backend, and InfluxDB database. These are all available at [http://localhost:3000](http://localhost:3000), [http://localhost:5000](http://localhost:5000), and [http://localhost:8086](http://localhost:8086), respectively.

The data source for running locally is from CSV data files. These are essentially a time-series list of the signals sent on the CAN bus, with
their timestamps, names, values, and units. In these CSV files, the required columns are "time" (timestamp that the signal was sent), "signal" (signal name), "value", and "unit" (physical unit that the value is in, leave blank if not applicable).

To specify a data file to read, pass it as the first positional argument to `run_local.sh`. You can upload multiple by providing a comma-seperated list instead. This will upload all of the data in your provided files to the local InfluxDB database. IMPORTANT: Your log file must be in the `software/tracksight/backend/data` directory. If it is not, it will not be uploaded. Provide the path relative to this folder. (Yes I know this is pretty silly, but comp is in 7 days)
To specify a data file to read, pass it with the `--file` or `-f` flag to `run_log.sh`. You can upload multiple by providing a comma-seperated list instead. This will upload all of the data in your provided files to the local InfluxDB database. IMPORTANT: Your log file must be in the `software/tracksight/backend/data` directory. If it is not, it will not be uploaded. Provide the path relative to this folder. (Yes I know this is pretty silly, but comp is in 7 days)

Note that if you stop the compose stack, and restart it again, your data will remain since the data is stored on a Docker volume which isn't wiped if the compose stack is brought down. This is useful if you want to upload more data files, and keep your old ones. To clear the local database, pass the `-c` or `--clean` flag to `run_local.sh`.
Note that if you stop the compose stack, and restart it again, your data will remain since the data is stored on a Docker volume which isn't wiped if the compose stack is brought down. This is useful if you want to upload more data files, and keep your old ones. To clear the local database, pass the `-c` or `--clean` flag to `run_log.sh`.

Example:

Expand All @@ -67,4 +67,12 @@ Example:

### Running Wireless Telemetry

TODO
To start everything manually, do the following steps:

1. Start Docker.
2. Start the frontend and InfluxDB database with docker. Navigate to `Consolidated-Firmware/software/tracksight` and run `docker compose -f docker/wireless.yml up --build`.
3. Start the backend. Navigate to `Consolidated-Firmware/software/tracksight/backend/app` and run `python3 telemetry.py --debug --mode wireless --serial-port /dev/ttyUSB0`. This will start the backend which (currently) uploads some tester signal values in signal_util.py. Note that you need to do step 1 before this, as well as pass through the radio receiver serial port (usually `/dev/ttyUSB0` on Linux, change if running on another OS).

To start everything automatically, navigate to `software/tracksight` and run `./run_wireless.sh`. Pass the serial port to this script using the `--serial-port` or `-p` flag. Note that this method is easier, but less flexibile than starting everything manually. With the backend running in its own terminal, its easier to start/stop it without re-starting the frontend/database Docker compose stack.

Note that if you stop the compose stack, and restart it again, your data will remain since the data is stored on a Docker volume which isn't wiped if the compose stack is brought down. To clear the local database, pass the `-c` or `--clean` flag to `run_wireless.sh`.
2 changes: 1 addition & 1 deletion software/tracksight/backend/app/signal_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def read_messages(cls):
# TODO: Lara: Upload actual signals instead!

# packet_size = int.from_bytes(cls.ser.read(1), byteorder="little")
# logger.debug(f"Received data: {packet_size}")
# logger.info(f"Received data: {packet_size}")
# if packet_size in VALID_PACKET_SIZES:
# continue

Expand Down
16 changes: 8 additions & 8 deletions software/tracksight/backend/app/telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"-m",
type=str,
required=True,
help="Mode to run telemetry in, either 'wireless' or 'local'.",
help="Mode to run telemetry in, either 'wireless' or 'log'.",
)
parser.add_argument(
"--serial-port",
Expand All @@ -66,16 +66,16 @@
args = parser.parse_args()

if args.debug:
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(filename=log_path, level=logging.DEBUG)
logging.basicConfig(filename=log_path, level=logging.INFO)

if args.mode == "wireless" and args.serial_port is None:
raise RuntimeError(
"If running telemetry in wireless mode, you must specify the radio serial port!"
)
elif args.mode != "wireless" and args.mode != "local":
raise RuntimeError("Mode must be either 'wireless' or 'local'")
elif args.mode != "wireless" and args.mode != "log":
raise RuntimeError("Mode must be either 'wireless' or 'log'")

# Configs for Influx DB instance.
required_env_vars = {
Expand Down Expand Up @@ -115,7 +115,7 @@
wireless_thread.start()

# Initialize the Socket.IO app with the main app.
app.run(debug=False)
app.run(debug=False, host="0.0.0.0")
except KeyboardInterrupt:
logger.info("Exiting")

Expand All @@ -124,7 +124,7 @@

logger.info("Thread stopped")

elif args.mode == "local":
elif args.mode == "log":
try:
if args.data_file is not None and args.data_file.strip() != "":
# Read log files and upload to the influx database.
Expand All @@ -138,7 +138,7 @@

# Initialize the Socket.IO app with the main app.
logger.info("Starting Flask app.")
app.run(app, debug=False)
app.run(debug=False, host="0.0.0.0")

except KeyboardInterrupt:
logger.info("Exiting")
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: tracksight-local
name: tracksight-log
services:
influx:
extends:
Expand All @@ -14,9 +14,10 @@ services:
"python3",
"app/telemetry.py",
"--mode",
"local",
"log",
"--data-file",
"${DATA_FILE}"
"${DATA_FILE}",
"--debug"
]
volumes:
- ../backend/logs:/backend/logs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
show_help() {
cat << EOF
Usage: ${0##*/} [-h|--help] [-c|--clean] -f|--file FILE
Run telemetry locally, sourcing data from a CSV log file.
Run telemetry in log mode, sourcing data from a CSV log file.
-h|--help Display this help and exit
-c|--clean Clear all existing data in the local Influx database
Expand Down Expand Up @@ -52,7 +52,7 @@ script_dir="$(dirname "$(readlink -f "$0")")"
# Handle the clean command.
if [ "$clean" -eq 1 ]; then
echo "Cleaning database."
docker compose -f "$script_dir/docker/local.yml" down -v
docker compose -f "$script_dir/docker/log.yml" down -v
fi

# Check if the file path is provided
Expand All @@ -61,5 +61,5 @@ if [ -z "$file" ]; then
fi

# Pass the file argument to the Python script.
echo "Starting telemetry locally."
env DATA_FILE="$file" docker compose -f "$script_dir/docker/local.yml" up --build
echo "Starting telemetry in log mode."
env DATA_FILE="$file" docker compose -f "$script_dir/docker/log.yml" up --build
94 changes: 94 additions & 0 deletions software/tracksight/run_wireless.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/bin/bash

show_help() {
cat << EOF
Usage: ${0##*/} [-h|--help] [-c|--clean] -p|--serial-port PORT
Run telemetry in wireless mode
-h|--help Display this help and exit
-c|--clean Clear all existing data in the local Influx database
-p|--serial-port PORT The serial port of the radio receiver
EOF
}

# Initialize our own variables.
clean=0
port=""

# Process flags and arguments.
while :; do
if [ -z "$1" ]; then
break # Exit the loop if no more arguments are present
fi

case "$1" in
-h|--help)
show_help # Display a help message
exit 0
;;
-c|--clean)
clean=1 # Set a flag to run a clean command later
shift
;;
-p|--serial-port)
if [ -n "$2" ]; then
port="$2" # Assign the next parameter as the port
shift 2
else
echo "Error: --port requires a port argument." >&2
exit 1
fi
;;
*)
echo "Error: Unknown option: $1" >&2
show_help # Display a help message
exit 1
;;
esac
done

script_dir="$(dirname "$(readlink -f "$0")")"

# Handle the clean command.
if [ "$clean" -eq 1 ]; then
echo "Cleaning database."
docker compose -f "$script_dir/docker/wireless.yml" down -v
fi

# Check if the port path is provided
if [ -z "$port" ]; then
echo "Error: No port specified. Use -p or --serial-port to specify the radio receiver's serial port."
exit 1
fi

echo "Starting telemetry in wireless mode."

# Pass the port argument to the Python script.
docker compose -f "$script_dir/docker/wireless.yml" up --build &

# Wait until pinging the database succeeds until we start the
influxdb_url="http://localhost:8086"
timeout=20

start_time=$(date +%s) # Record start time
while true; do
# Ping the host with a timeout of 1 second and check if it's successful
if curl --connect-timeout 1 --silent --head $influxdb_url > /dev/null 2>&1; then
echo "Database started successfully."
break
else
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))

# Check if the total elapsed time is greater than 20s.
if [ $elapsed_time -ge $timeout ]; then
echo "Timeout reached without a successful connection."
exit 1
fi

sleep 1
fi
done

echo "Starting backend server."
python3 "$script_dir/backend/app/telemetry.py" --mode wireless --serial-port $port --debug

0 comments on commit f112eb0

Please sign in to comment.