fix: 自启动

This commit is contained in:
2026-04-14 22:06:16 +08:00
parent d574ba3414
commit b91376663a
8 changed files with 769 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
{
"permissions": {
"allow": [
"Bash(find deploy:*)",
"Bash(ls -R deploy/ scripts/)"
]
}
}

3
.gitignore vendored
View File

@@ -16,3 +16,6 @@ env/
# macOS # macOS
.DS_Store .DS_Store
# Runtime logs
logs/

162
Plan.md Normal file
View File

@@ -0,0 +1,162 @@
自启方案monitor_sender.py 通过手机热点自动启动
Context
monitor_sender.py 是一个 ROS2 节点运行在机器人控制器上Ubuntu, 用户名
ubuntu订阅机器人状态话题并通过 WebSocket 发送到 PC
端监控服务器。设备在真实世界运行,需要开机后:
1. 自动连接手机热点 WiFi
2. 等待网络就绪后启动 monitor_sender.py通过热点向 PC 的固定 IP 发送数据)
3. 崩溃后自动重启并记录崩溃原因
方案systemd 服务 + 启动脚本(两个文件搞定)
文件 1启动脚本 ~/xMonitor/start_monitor.sh
#!/bin/bash
# ========== 配置区(按实际修改) ==========
HOTSPOT_SSID="你的热点名称" # ← 稍后填
HOTSPOT_PASS="你的热点密码" # ← 稍后填
SERVER_IP="192.168.43.xxx" # ← 电脑在热点中的固定 IP
SERVER_PORT=9000
# ==========================================
LOG_DIR="$HOME/xMonitor/logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/monitor_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "===== $(date) 启动 monitor_sender ====="
# --- 1) 连接手机热点 ---
echo "[NET] 正在连接热点: $HOTSPOT_SSID"
MAX_WIFI_RETRY=30
for i in $(seq 1 $MAX_WIFI_RETRY); do
# 尝试连接(如果已保存过连接配置则直接 up否则新建
nmcli dev wifi connect "$HOTSPOT_SSID" password "$HOTSPOT_PASS" 2>/dev/null \
|| nmcli con up "$HOTSPOT_SSID" 2>/dev/null
# 检查是否拿到 IP
if nmcli -t -f GENERAL.STATE dev show wlan0 2>/dev/null | grep -q "100"; then
echo "[NET] WiFi 已连接 ($i/$MAX_WIFI_RETRY)"
break
fi
echo "[NET] WiFi 未就绪,重试 ($i/$MAX_WIFI_RETRY)..."
sleep 3
done
# --- 2) 等待能 ping 通服务器 ---
echo "[NET] 等待服务器 $SERVER_IP 可达..."
MAX_PING_RETRY=20
for i in $(seq 1 $MAX_PING_RETRY); do
if ping -c 1 -W 2 "$SERVER_IP" >/dev/null 2>&1; then
echo "[NET] 服务器可达 ✓"
break
fi
echo "[NET] ping 失败,重试 ($i/$MAX_PING_RETRY)..."
sleep 3
done
# --- 3) Source 环境并启动 ---
echo "[ENV] source ROS2 workspace..."
source /home/ubuntu/ros2ws/install/setup.bash
echo "[ENV] source Python venv..."
source "$HOME/xMonitor/.venv/bin/activate"
echo "[RUN] 启动 monitor_sender.py --ip $SERVER_IP --port $SERVER_PORT"
cd "$HOME/xMonitor"
python3 monitor_sender.py --ip "$SERVER_IP" --port "$SERVER_PORT"
EXIT_CODE=$?
echo "===== $(date) 进程退出, code=$EXIT_CODE ====="
exit $EXIT_CODE
文件 2systemd 服务 /etc/systemd/system/xmonitor.service
[Unit]
Description=xMonitor Robot Status Sender
After=network-manager.service
Wants=network-manager.service
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/xMonitor
ExecStart=/bin/bash /home/ubuntu/xMonitor/start_monitor.sh
# --- 崩溃自动重启 ---
Restart=on-failure
RestartSec=10
# --- 崩溃日志 ---
StandardOutput=journal
StandardError=journal
SyslogIdentifier=xmonitor
[Install]
WantedBy=multi-user.target
部署步骤(在机器人设备上执行)
# 1. 将 start_monitor.sh 放到 ~/xMonitor/ 并加执行权限
chmod +x ~/xMonitor/start_monitor.sh
# 2. 编辑 start_monitor.sh 顶部配置区填入热点名称、密码、电脑IP
# 3. 复制 service 文件并启用
sudo cp xmonitor.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable xmonitor.service
# 4. 立即测试启动(可选)
sudo systemctl start xmonitor.service
# 5. 查看状态 / 日志
systemctl status xmonitor.service
journalctl -u xmonitor -f # 实时查看日志
ls ~/xMonitor/logs/ # 查看历史日志文件
关键设计说明
┌────────────┬───────────────────────────────────────────────────────────────┐
│ 需求 │ 实现方式 │
├────────────┼───────────────────────────────────────────────────────────────┤
│ 连热点 │ nmcli dev wifi connect 循环重试,最多 30 次 × 3 秒 │
├────────────┼───────────────────────────────────────────────────────────────┤
│ 等待网络 │ ping 服务器 IP 直到可达 │
├────────────┼───────────────────────────────────────────────────────────────┤
│ source │ 脚本内 source .venv/bin/activate │
│ 虚拟环境 │ │
├────────────┼───────────────────────────────────────────────────────────────┤
│ source │ 脚本内 source /home/ubuntu/ros2ws/install/setup.bash来自 │
│ ROS2 │ README
├────────────┼───────────────────────────────────────────────────────────────┤
│ 崩溃重启 │ systemd Restart=on-failure + RestartSec=1010 秒后重启) │
├────────────┼───────────────────────────────────────────────────────────────┤
│ 崩溃日志 │ 双保险:① journalctl -u xmonitor 系统日志 ② ~/xMonitor/logs/ │
│ │ 下按时间戳命名的文本日志 │
├────────────┼───────────────────────────────────────────────────────────────┤
│ 开机自启 │ systemctl enable xmonitor.service │
└────────────┴───────────────────────────────────────────────────────────────┘
待用户提供
- 手机热点 SSID
- 手机热点密码
- 电脑在热点中的固定 IP192.168.43.???
需要创建/修改的文件
1. 新建 ~/xMonitor/start_monitor.sh — 启动脚本
2. 新建 ~/xMonitor/xmonitor.service — systemd 服务文件(用户手动 sudo cp 到
/etc/systemd/system/
验证方法
1. 手动运行 bash ~/xMonitor/start_monitor.sh 确认 WiFi 连接和程序启动正常
2. sudo systemctl start xmonitor.service 启动服务
3. systemctl status xmonitor.service 确认 active (running)
4. journalctl -u xmonitor -f 实时查看日志
5. 杀掉 python 进程 kill $(pgrep -f monitor_sender) 验证自动重启
6. 重启设备验证开机自启

View File

@@ -198,4 +198,75 @@ python3 monitor_sender.py --ip 10.0.0.5 --port 9000
| `main_monitor.py` | FastAPI server — hosts the web GUI and relays data to browsers | | `main_monitor.py` | FastAPI server — hosts the web GUI and relays data to browsers |
| `monitor_sender.py` | ROS 2 node — collects robot data and streams it to the server | | `monitor_sender.py` | ROS 2 node — collects robot data and streams it to the server |
| `README.md` | This file | | `README.md` | This file |
| `scripts/start_monitor_sender.sh` | Bootstrap script for hotspot connect, environment setup, and sender launch |
| `deploy/xmonitor.env.example` | Template for `/etc/xmonitor/xmonitor.env` |
| `deploy/xmonitor-sender.service` | `systemd` service template for robot-side autostart |
---
## Robot Sender Autostart (Ubuntu + systemd)
For field deployment on the robot controller, this repo now includes:
- `scripts/start_monitor_sender.sh`
- `deploy/xmonitor.env.example`
- `deploy/xmonitor-sender.service`
The design stays intentionally small:
- the startup script keeps trying to join your phone hotspot with `nmcli`
- it waits until the PC hotspot IP is reachable
- it sources the ROS setup and `.venv`
- it launches `python3 monitor_sender.py --ip <server-ip> --port <port>`
- `systemd` restarts the process after crashes, while logs go to both `journalctl` and `~/xMonitor/logs/`
### Install on the Ubuntu robot device
Assuming the repo is deployed at `/home/ubuntu/xMonitor`:
```bash
cd /home/ubuntu/xMonitor
sudo install -d -m 700 /etc/xmonitor
sudo cp deploy/xmonitor.env.example /etc/xmonitor/xmonitor.env
sudo chmod 600 /etc/xmonitor/xmonitor.env
sudoedit /etc/xmonitor/xmonitor.env
chmod +x scripts/start_monitor_sender.sh
sudo cp deploy/xmonitor-sender.service /etc/systemd/system/xmonitor-sender.service
sudo systemctl daemon-reload
sudo systemctl enable --now xmonitor-sender.service
```
If you deploy the repo somewhere other than `/home/ubuntu/xMonitor`, update these together:
- `User=` in `deploy/xmonitor-sender.service`
- `WorkingDirectory=` in `deploy/xmonitor-sender.service`
- `ExecStart=` in `deploy/xmonitor-sender.service`
- `APP_DIR=` and `RUN_USER=` in `/etc/xmonitor/xmonitor.env`
### Runtime checks
```bash
# Run the bootstrap script manually for troubleshooting
bash /home/ubuntu/xMonitor/scripts/start_monitor_sender.sh
# Service state
systemctl status xmonitor-sender.service
# Live logs from systemd
journalctl -u xmonitor-sender.service -f
# Per-run log files
ls /home/ubuntu/xMonitor/logs
```
### Behavior
- Hotspot connect retry: every 5 seconds until the target SSID is connected
- Server reachability retry: every 5 seconds until `SERVER_IP` answers `ping`
- Python process crash: `systemd` restarts after 5 seconds
- WebSocket drop after startup: handled by `monitor_sender.py`, which already retries every 3 seconds
- Per-run log files are pruned automatically; default retention is the latest 20 files via `LOG_RETENTION_COUNT`

273
WINDOWS_RECEIVER_SETUP.md Normal file
View File

@@ -0,0 +1,273 @@
# Windows 接收端环境配置
这份文档只针对接收方,也就是你的 Windows 电脑。
本文假设:
- `xMonitor` 仓库就在 Windows 上
- 你的电脑在手机热点网络里的固定 IP 是 `10.0.0.5`
- 发送端会连到 `10.0.0.5:9000`
- 你希望在 Windows 上运行 `main_monitor.py` 来接收机器人状态并在浏览器里显示
---
## 1. 安装 Python
建议使用 Python 3.10 或更新版本。
在 PowerShell 里确认 Python 可用:
```powershell
py -V
```
如果没有安装 Python
1. 打开 https://www.python.org/downloads/windows/
2. 安装最新版 Python 3
3. 安装时勾选 `Add Python to PATH`
---
## 2. 进入项目目录
在 PowerShell 中进入仓库目录:
```powershell
cd C:\Users\64187\Desktop\Workspace\xMonitor
```
---
## 3. 创建并启用虚拟环境
创建虚拟环境:
```powershell
py -3 -m venv .venv
```
启用虚拟环境:
```powershell
.\.venv\Scripts\Activate.ps1
```
如果 PowerShell 阻止脚本执行,可先临时放开当前会话:
```powershell
Set-ExecutionPolicy -Scope Process Bypass
.\.venv\Scripts\Activate.ps1
```
启用后命令行前面通常会出现 `(.venv)`
---
## 4. 安装接收端依赖
`main_monitor.py` 接收端只需要这两个包:
- `fastapi`
- `uvicorn`
安装命令:
```powershell
python -m pip install --upgrade pip
pip install fastapi uvicorn
```
---
## 5. 启动接收端
因为你的发送端现在要往 `10.0.0.5:9000` 发,所以接收端必须监听 `9000` 端口。
在 PowerShell 中运行:
```powershell
uvicorn main_monitor:app --host 0.0.0.0 --port 9000
```
说明:
- `--host 0.0.0.0`:允许热点网络里的设备访问这台 Windows 电脑
- `--port 9000`:和发送端启动参数保持一致
如果你以后改了发送端端口,这里的端口也必须一起改。
---
## 6. 放行 Windows 防火墙
第一次启动时Windows 可能会弹出防火墙提示。
请选择:
- 允许访问
- 至少勾选当前使用的网络类型
如果没有弹窗,可以手动放行 TCP 9000
```powershell
New-NetFirewallRule `
-DisplayName "xMonitor 9000" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 9000 `
-Action Allow
```
查看规则是否创建成功:
```powershell
Get-NetFirewallRule -DisplayName "xMonitor 9000"
```
---
## 7. 检查本机热点 IP
确认 Windows 当前热点网卡上的 IP 确实是你要给发送端使用的固定地址。
查看 IP
```powershell
ipconfig
```
确认对应热点网络适配器上有:
```text
IPv4 Address . . . . . . . . . . : 10.0.0.5
```
如果不是这个地址,要么把 Windows 侧固定 IP 配好,要么把发送端里的 `--ip` 改成实际地址。
---
## 8. 打开监控页面
接收端启动成功后,在本机浏览器打开:
```text
http://127.0.0.1:9000
```
或者直接打开:
```text
http://10.0.0.5:9000
```
如果发送端已经开始推数据,页面会显示机器人状态。
---
## 9. 验证接收端是否正常工作
### 看端口是否监听
```powershell
netstat -ano | findstr :9000
```
能看到 `LISTENING` 说明服务已经起来了。
### 看浏览器页面是否能打开
打开:
```text
http://127.0.0.1:9000
```
若页面能打开,说明 HTTP 服务正常。
### 看是否收到机器人数据
接收端会把机器人上报的数据写到:
```text
logs\robot_packets.jsonl
```
可以在项目目录下查看:
```powershell
Get-Content .\logs\robot_packets.jsonl -Tail 5
```
如果这里不断有新行,说明 WebSocket 接收正常。
---
## 10. 常见问题
### 1) 浏览器能打开页面,但没有机器人数据
通常检查这几项:
- 发送端是否真的发到了 `10.0.0.5:9000`
- Windows 防火墙是否放行了 `9000`
- 电脑和设备是否确实连在同一个手机热点下
- Windows 当前热点 IP 是否还是 `10.0.0.5`
### 2) PowerShell 里 `Activate.ps1` 不能执行
先执行:
```powershell
Set-ExecutionPolicy -Scope Process Bypass
```
然后再执行:
```powershell
.\.venv\Scripts\Activate.ps1
```
### 3) `uvicorn` 命令找不到
通常是虚拟环境没激活,或者依赖没装成功。
重新执行:
```powershell
.\.venv\Scripts\Activate.ps1
pip install fastapi uvicorn
```
### 4) 9000 端口被占用
查看占用:
```powershell
netstat -ano | findstr :9000
```
如果必须换端口,比如改成 `8000`,那就要同时改两边:
- Windows 接收端启动端口
- 发送端 `monitor_sender.py --port ...`
---
## 11. 最小启动流程
以后你在 Windows 上最少只需要这几步:
```powershell
cd C:\Users\64187\Desktop\Workspace\xMonitor
.\.venv\Scripts\Activate.ps1
uvicorn main_monitor:app --host 0.0.0.0 --port 9000
```
然后浏览器打开:
```text
http://127.0.0.1:9000
```
如果需要我下一步可以再给你补一份“Windows 接收端开机自启”文档,直接做成任务计划程序版本。

View File

@@ -0,0 +1,25 @@
# Install this file to /etc/systemd/system/xmonitor-sender.service on the target Ubuntu device.
# If you do not use /home/ubuntu/xMonitor, update User, WorkingDirectory, ExecStart, and APP_DIR together.
[Unit]
Description=xMonitor Robot Status Sender
After=NetworkManager.service
Wants=NetworkManager.service
StartLimitIntervalSec=0
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/xMonitor
EnvironmentFile=/etc/xmonitor/xmonitor.env
Environment=PYTHONUNBUFFERED=1
ExecStart=/home/ubuntu/xMonitor/scripts/start_monitor_sender.sh
Restart=always
RestartSec=5
TimeoutStartSec=0
StandardOutput=journal
StandardError=journal
SyslogIdentifier=xmonitor-sender
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,19 @@
# Copy this file to /etc/xmonitor/xmonitor.env on the target Ubuntu device.
# Then edit the values and lock down the permissions:
# sudo install -d -m 700 /etc/xmonitor
# sudo cp deploy/xmonitor.env.example /etc/xmonitor/xmonitor.env
# sudo chmod 600 /etc/xmonitor/xmonitor.env
HOTSPOT_SSID=YOUR_PHONE_HOTSPOT
HOTSPOT_PASSWORD=YOUR_HOTSPOT_PASSWORD
SERVER_IP=10.0.0.5
SERVER_PORT=9000
ROS_SETUP=/home/ubuntu/ros2ws/install/setup.bash
APP_DIR=/home/ubuntu/xMonitor
RUN_USER=ubuntu
# Optional overrides.
PYTHON_BIN=python3
WIFI_RETRY_INTERVAL=5
PING_RETRY_INTERVAL=5
LOG_RETENTION_COUNT=20

View File

@@ -0,0 +1,208 @@
#!/usr/bin/env bash
set -Eeuo pipefail
timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
log() {
printf '[%s] %s\n' "$(timestamp)" "$*"
}
fail() {
log "ERROR: $*"
exit 1
}
report_err() {
local exit_code=$?
local line_no=${1:-unknown}
local cmd=${2:-unknown}
log "ERROR: command failed at line ${line_no}: ${cmd} (exit=${exit_code})"
exit "$exit_code"
}
trap 'report_err "${LINENO}" "${BASH_COMMAND}"' ERR
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_APP_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
RUN_USER="${RUN_USER:-$(id -un)}"
APP_DIR="${APP_DIR:-${DEFAULT_APP_DIR}}"
LOG_DIR="${LOG_DIR:-${APP_DIR}/logs}"
HOTSPOT_SSID="${HOTSPOT_SSID:-}"
HOTSPOT_PASSWORD="${HOTSPOT_PASSWORD:-}"
SERVER_IP="${SERVER_IP:-10.0.0.5}"
SERVER_PORT="${SERVER_PORT:-9000}"
ROS_SETUP="${ROS_SETUP:-/home/${RUN_USER}/ros2ws/install/setup.bash}"
PYTHON_BIN="${PYTHON_BIN:-python3}"
WIFI_RETRY_INTERVAL="${WIFI_RETRY_INTERVAL:-5}"
PING_RETRY_INTERVAL="${PING_RETRY_INTERVAL:-5}"
VENV_ACTIVATE="${APP_DIR}/.venv/bin/activate"
LOG_RETENTION_COUNT="${LOG_RETENTION_COUNT:-20}"
mkdir -p "${LOG_DIR}"
LOG_FILE="${LOG_DIR}/monitor_sender_$(date '+%Y%m%d_%H%M%S').log"
touch "${LOG_FILE}"
exec > >(tee -a "${LOG_FILE}") 2>&1
require_command() {
local command_name=$1
command -v "${command_name}" >/dev/null 2>&1 || fail "missing required command: ${command_name}"
}
prune_old_logs() {
local prune_from
local old_logs=()
[[ "${LOG_RETENTION_COUNT}" =~ ^[0-9]+$ ]] || fail "LOG_RETENTION_COUNT must be a positive integer"
(( LOG_RETENTION_COUNT >= 1 )) || fail "LOG_RETENTION_COUNT must be at least 1"
prune_from=$((LOG_RETENTION_COUNT + 1))
mapfile -t old_logs < <(ls -1dt "${LOG_DIR}"/monitor_sender_*.log 2>/dev/null | tail -n +"${prune_from}")
if ((${#old_logs[@]} > 0)); then
rm -f -- "${old_logs[@]}"
log "Pruned ${#old_logs[@]} old log file(s); keeping latest ${LOG_RETENTION_COUNT}"
fi
}
source_with_relaxed_mode() {
local target_file=$1
local shell_flags=$-
local err_trap
local source_status=0
err_trap="$(trap -p ERR || true)"
trap - ERR
set +eu
# shellcheck disable=SC1090,SC1091
source "${target_file}"
source_status=$?
[[ "${shell_flags}" == *e* ]] && set -e || set +e
[[ "${shell_flags}" == *u* ]] && set -u || set +u
if [[ -n "${err_trap}" ]]; then
eval "${err_trap}"
fi
return "${source_status}"
}
get_wifi_device() {
nmcli -t -f DEVICE,TYPE device status | awk -F: '$2 == "wifi" { print $1; exit }'
}
get_active_connection_name() {
local wifi_device=$1
nmcli -g GENERAL.CONNECTION device show "${wifi_device}" 2>/dev/null | head -n1 | tr -d '\r'
}
get_active_ssid() {
local wifi_device=$1
local active_connection
active_connection="$(get_active_connection_name "${wifi_device}" || true)"
if [[ -z "${active_connection}" || "${active_connection}" == "--" ]]; then
return 1
fi
nmcli -g 802-11-wireless.ssid connection show "${active_connection}" 2>/dev/null | head -n1 | tr -d '\r'
}
is_hotspot_connected() {
local wifi_device=$1
local active_ssid
active_ssid="$(get_active_ssid "${wifi_device}" || true)"
[[ -n "${active_ssid}" && "${active_ssid}" == "${HOTSPOT_SSID}" ]]
}
connect_hotspot() {
local wifi_device=$1
while true; do
if is_hotspot_connected "${wifi_device}"; then
log "Wi-Fi already connected to hotspot '${HOTSPOT_SSID}'"
return 0
fi
log "Trying hotspot '${HOTSPOT_SSID}' on Wi-Fi device '${wifi_device}'"
nmcli device wifi rescan ifname "${wifi_device}" >/dev/null 2>&1 || true
if nmcli connection up "${HOTSPOT_SSID}" ifname "${wifi_device}" >/dev/null 2>&1; then
sleep 2
if is_hotspot_connected "${wifi_device}"; then
log "Connected to hotspot '${HOTSPOT_SSID}' via saved NetworkManager profile"
return 0
fi
fi
if [[ -n "${HOTSPOT_PASSWORD}" ]]; then
if nmcli device wifi connect "${HOTSPOT_SSID}" password "${HOTSPOT_PASSWORD}" ifname "${wifi_device}" >/dev/null 2>&1; then
sleep 2
if is_hotspot_connected "${wifi_device}"; then
log "Connected to hotspot '${HOTSPOT_SSID}' via direct nmcli connect"
return 0
fi
fi
else
log "HOTSPOT_PASSWORD is empty; skipping direct nmcli connect and relying on saved profile"
fi
log "Hotspot '${HOTSPOT_SSID}' is not ready yet; retrying in ${WIFI_RETRY_INTERVAL}s"
sleep "${WIFI_RETRY_INTERVAL}"
done
}
wait_for_server() {
while true; do
if ping -c 1 -W 2 "${SERVER_IP}" >/dev/null 2>&1; then
log "Server '${SERVER_IP}' is reachable"
return 0
fi
log "Server '${SERVER_IP}' is not reachable yet; retrying in ${PING_RETRY_INTERVAL}s"
sleep "${PING_RETRY_INTERVAL}"
done
}
log "Starting xMonitor sender bootstrap"
log "Using APP_DIR='${APP_DIR}'"
log "Log file: ${LOG_FILE}"
prune_old_logs
[[ -n "${HOTSPOT_SSID}" ]] || fail "HOTSPOT_SSID must be set in /etc/xmonitor/xmonitor.env"
[[ -d "${APP_DIR}" ]] || fail "APP_DIR does not exist: ${APP_DIR}"
[[ -f "${APP_DIR}/monitor_sender.py" ]] || fail "monitor_sender.py not found in ${APP_DIR}"
[[ -f "${ROS_SETUP}" ]] || fail "ROS setup file not found: ${ROS_SETUP}"
[[ -f "${VENV_ACTIVATE}" ]] || fail "Python virtualenv activate script not found: ${VENV_ACTIVATE}"
require_command nmcli
require_command ping
require_command tee
require_command "${PYTHON_BIN}"
if [[ "$(id -un)" != "${RUN_USER}" ]]; then
log "Warning: script is running as '$(id -un)' but RUN_USER is '${RUN_USER}'"
fi
WIFI_DEVICE="$(get_wifi_device)"
[[ -n "${WIFI_DEVICE}" ]] || fail "No Wi-Fi device was found by NetworkManager"
log "Detected Wi-Fi device '${WIFI_DEVICE}'"
connect_hotspot "${WIFI_DEVICE}"
wait_for_server
log "Sourcing ROS environment '${ROS_SETUP}'"
source_with_relaxed_mode "${ROS_SETUP}"
log "Activating Python virtualenv '${VENV_ACTIVATE}'"
source_with_relaxed_mode "${VENV_ACTIVATE}"
cd "${APP_DIR}"
log "Launching monitor_sender.py --ip ${SERVER_IP} --port ${SERVER_PORT}"
exec "${PYTHON_BIN}" monitor_sender.py --ip "${SERVER_IP}" --port "${SERVER_PORT}"