119 lines
5.3 KiB
Bash
119 lines
5.3 KiB
Bash
#!/usr/bin/env bash
|
|
# probe_eng.sh — read-only EngineAI PM01 discovery.
|
|
#
|
|
# bash tools/probe_eng.sh <ip> [user]
|
|
# bash tools/probe_eng.sh 10.210.136.150 ubuntu
|
|
#
|
|
# Prints what the robot ACTUALLY exposes, each line labelled with the .env
|
|
# variable it feeds. Installs nothing, writes nothing, publishes to no topic —
|
|
# safe to run against a live robot.
|
|
#
|
|
# Auth: uses an ssh key if FLEET_SSH_KEY is set, otherwise sshpass with
|
|
# FLEET_SSH_PASS (default "ubuntu"). Set FLEET_SSH_PASS in the environment
|
|
# rather than editing this file.
|
|
set -uo pipefail
|
|
|
|
IP="${1:-}"
|
|
USER_="${2:-ubuntu}"
|
|
if [ -z "$IP" ]; then
|
|
echo "usage: bash tools/probe_eng.sh <ip> [user]" >&2
|
|
exit 2
|
|
fi
|
|
|
|
SSH_OPTS="-o StrictHostKeyChecking=accept-new -o ConnectTimeout=8 -o BatchMode=no"
|
|
if [ -n "${FLEET_SSH_KEY:-}" ]; then
|
|
RUN() { ssh $SSH_OPTS -i "$FLEET_SSH_KEY" "$USER_@$IP" "$@"; }
|
|
elif command -v sshpass >/dev/null 2>&1; then
|
|
RUN() { sshpass -p "${FLEET_SSH_PASS:-ubuntu}" ssh $SSH_OPTS "$USER_@$IP" "$@"; }
|
|
else
|
|
RUN() { ssh $SSH_OPTS "$USER_@$IP" "$@"; }
|
|
fi
|
|
|
|
hdr() { printf '\n\033[1m== %s\033[0m\n' "$1"; }
|
|
|
|
# The robot's own environment file is the source of truth for ROS_DOMAIN_ID,
|
|
# RMW_IMPLEMENTATION and CYCLONEDDS_URI. Sourcing it (rather than guessing 0)
|
|
# is the difference between seeing 44 topics and seeing 2.
|
|
ROSENV='set +u
|
|
. /opt/ros/humble/setup.bash >/dev/null 2>&1
|
|
. /app/applications/install/bringup/ros_env.sh >/dev/null 2>&1'
|
|
|
|
hdr "host (-> SOFTWARE_*, MAC_INTERFACE, STORAGE_PATH)"
|
|
RUN "hostname; uname -srm; grep PRETTY_NAME /etc/os-release
|
|
echo -n 'board : '; tr -d '\0' < /proc/device-tree/model 2>/dev/null; echo
|
|
echo -n 'board_serial: '; tr -d '\0' < /proc/device-tree/serial-number 2>/dev/null; echo
|
|
echo -n 'l4t : '; head -1 /etc/nv_tegra_release 2>/dev/null
|
|
echo -n 'product : '; cat /app/applications/install/bringup/product.env 2>/dev/null
|
|
echo '--- NICs (MAC_INTERFACE = the one carrying the LAN address) ---'
|
|
ip -o -4 addr show | awk '{printf \" %-10s %-18s mac=\", \$2, \$4}
|
|
{\"cat /sys/class/net/\" \$2 \"/address\" | getline m; print m}'
|
|
echo '--- disk (STORAGE_PATH) ---'; df -h / | tail -1"
|
|
|
|
hdr "ROS env (-> ROS_DOMAIN_ID; the unit must source ros_env.sh)"
|
|
RUN "cat /app/applications/install/bringup/ros_env.sh 2>/dev/null
|
|
echo '--- CycloneDDS interface pinning ---'
|
|
cat /app/applications/install/bringup/cyclonedds.xml 2>/dev/null"
|
|
|
|
hdr "ROS topics (-> ENG_TOPIC_* / ENG_TYPE_*)"
|
|
RUN "$ROSENV; timeout 30 ros2 topic list -t 2>/dev/null"
|
|
|
|
hdr "message definitions (-> ENG_FIELD_*)"
|
|
RUN "for m in PowerInfo JointState MotorDebug MotionState; do
|
|
echo \"--- \$m ---\"
|
|
find /app/applications/install/interface_protocol -name \"\$m.msg\" \
|
|
-exec cat {} \; 2>/dev/null
|
|
echo
|
|
done"
|
|
|
|
hdr "live samples (-> verify ENG_SOC_SCALE / ENG_CURRENT_SIGN / units)"
|
|
RUN "$ROSENV
|
|
echo '--- /hardware/power_info (battery: percentage, voltage, current) ---'
|
|
timeout 12 ros2 topic echo --once /hardware/power_info 2>/dev/null
|
|
echo '--- /motion/motion_state (control.mode + switchable_modes) ---'
|
|
timeout 12 ros2 topic echo --once /motion/motion_state 2>/dev/null
|
|
echo '--- /hardware/motor_debug (motor_temp; first lines only) ---'
|
|
timeout 12 ros2 topic echo --once /hardware/motor_debug 2>/dev/null | head -12"
|
|
|
|
hdr "publish rates (-> ENG_JOINT_MIN_PERIOD / ENG_MOTOR_MIN_PERIOD)"
|
|
RUN "$ROSENV
|
|
for t in /hardware/power_info /hardware/joint_state /hardware/motor_debug /motion/motion_state; do
|
|
printf ' %-28s ' \"\$t\"
|
|
timeout 8 ros2 topic hz \$t 2>/dev/null | grep -m1 average || echo 'NO DATA'
|
|
done"
|
|
|
|
hdr "CHARGE DIRECTION (-> ENG_CURRENT_SIGN) ~45s"
|
|
echo " If percentage FALLS while current is POSITIVE, positive = discharge"
|
|
echo " and ENG_CURRENT_SIGN must be -1 (otherwise the robot reports 'charging'"
|
|
echo " forever while its battery drains)."
|
|
RUN "$ROSENV
|
|
for i in 1 2 3; do
|
|
printf ' %s ' \"\$(date +%H:%M:%S)\"
|
|
timeout 8 ros2 topic echo --once /hardware/power_info 2>/dev/null \
|
|
| tr '\n' ' ' | sed 's/---//'
|
|
echo
|
|
[ \$i -lt 3 ] && sleep 18
|
|
done"
|
|
|
|
hdr "position sources (-> ENG_POSITION_SOURCE / ENG_TOPIC_ODOM)"
|
|
RUN "$ROSENV
|
|
echo -n ' odometry topics: '
|
|
timeout 20 ros2 topic list 2>/dev/null | grep -iE 'odom|/tf$|amcl|pose' || echo 'NONE (position reports null)'
|
|
echo -n ' sanad nav status: '
|
|
curl -s -m5 http://127.0.0.1:8014/api/nav/status 2>/dev/null | head -c 220; echo"
|
|
|
|
hdr "dashboards / remote (-> REMOTE_PORTS, SSH_USER)"
|
|
RUN "echo '--- listening ports ---'; ss -tlnp 2>/dev/null | awk 'NR>1{print \" \" \$4}' | sort -u
|
|
for p in 8014 8001 9002 9003 9004 8765; do
|
|
printf ' %-6s ' \$p
|
|
curl -s -m3 -o /dev/null -w 'HTTP %{http_code}' http://127.0.0.1:\$p/ 2>/dev/null || printf 'closed'
|
|
curl -s -m3 http://127.0.0.1:\$p/ 2>/dev/null | grep -qi 'sanad\|dashboard' && printf ' <- dashboard page'
|
|
echo
|
|
done"
|
|
|
|
hdr "project logs (-> PROJECT_LOG_CONTAINER; needs root)"
|
|
RUN "sudo -n docker ps --format ' {{.Names}} {{.Status}}' 2>/dev/null \
|
|
|| echo ' (needs sudo; the agent runs as root and can read these)'"
|
|
|
|
hdr "done"
|
|
echo "Set the values above in agent/.env, then: systemctl restart sanad-api-eng"
|