Initial commit
This commit is contained in:
Executable
+263
@@ -0,0 +1,263 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
INSTALL_DIR="${PLATFORM_AGENT_DIR:-/opt/platform-agent}"
|
||||
SERVICE_NAME="${PLATFORM_AGENT_SERVICE:-platform-agent}"
|
||||
CONFIG_PATH="${AGENT_CONFIG:-${INSTALL_DIR}/agent.config.json}"
|
||||
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
|
||||
|
||||
log() {
|
||||
printf '%s\n' "$*"
|
||||
}
|
||||
|
||||
need_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
as_root() {
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
"$@"
|
||||
elif need_cmd sudo; then
|
||||
sudo "$@"
|
||||
else
|
||||
log "Root privileges are required: $*"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_value() {
|
||||
var_name="$1"
|
||||
label="$2"
|
||||
current_value="$3"
|
||||
secret="${4:-false}"
|
||||
if [ "$secret" = "true" ]; then
|
||||
printf '%s [hidden, Enter keeps current]: ' "$label"
|
||||
stty -echo 2>/dev/null || true
|
||||
IFS= read -r answer || answer=""
|
||||
stty echo 2>/dev/null || true
|
||||
printf '\n'
|
||||
else
|
||||
printf '%s [%s]: ' "$label" "$current_value"
|
||||
IFS= read -r answer || answer=""
|
||||
fi
|
||||
if [ -n "$answer" ]; then
|
||||
eval "$var_name=\"\$answer\""
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_yes_no() {
|
||||
label="$1"
|
||||
default="${2:-no}"
|
||||
suffix="[y/N]"
|
||||
[ "$default" = "yes" ] && suffix="[Y/n]"
|
||||
printf '%s %s ' "$label" "$suffix"
|
||||
IFS= read -r answer || answer=""
|
||||
answer="$(printf '%s' "$answer" | tr '[:upper:]' '[:lower:]')"
|
||||
if [ -z "$answer" ]; then
|
||||
[ "$default" = "yes" ]
|
||||
return
|
||||
fi
|
||||
[ "$answer" = "y" ] || [ "$answer" = "yes" ]
|
||||
}
|
||||
|
||||
json_get() {
|
||||
key_path="$1"
|
||||
fallback="${2:-}"
|
||||
python3 - "$CONFIG_PATH" "$key_path" "$fallback" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
path, key_path, fallback = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as fp:
|
||||
value = json.load(fp)
|
||||
except Exception:
|
||||
print(fallback)
|
||||
raise SystemExit
|
||||
|
||||
for key in key_path.split("."):
|
||||
if not isinstance(value, dict):
|
||||
value = None
|
||||
break
|
||||
value = value.get(key)
|
||||
|
||||
if value is None:
|
||||
print(fallback)
|
||||
elif isinstance(value, bool):
|
||||
print("true" if value else "false")
|
||||
else:
|
||||
print(value)
|
||||
PY
|
||||
}
|
||||
|
||||
service_user() {
|
||||
if [ -f "$SERVICE_FILE" ]; then
|
||||
user_line="$(sed -n 's/^User=//p' "$SERVICE_FILE" | head -n 1)"
|
||||
[ -n "$user_line" ] && {
|
||||
printf '%s' "$user_line"
|
||||
return
|
||||
}
|
||||
fi
|
||||
id -un
|
||||
}
|
||||
|
||||
expand_path_for_user() {
|
||||
path="$1"
|
||||
run_user="$2"
|
||||
case "$path" in
|
||||
"~")
|
||||
if [ "$run_user" = "root" ]; then printf '/root'; else printf '/home/%s' "$run_user"; fi
|
||||
;;
|
||||
"~/"*)
|
||||
if [ "$run_user" = "root" ]; then printf '/root/%s' "${path#~/}"; else printf '/home/%s/%s' "$run_user" "${path#~/}"; fi
|
||||
;;
|
||||
*)
|
||||
printf '%s' "$path"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
write_config() {
|
||||
tmp_file="$(mktemp)"
|
||||
WORKSPACE_ROOT="$WORKSPACE_ROOT" \
|
||||
ROBOT_STACK="$ROBOT_STACK" \
|
||||
ROS_DOMAIN_ID="$ROS_DOMAIN_ID" \
|
||||
CAMERA_ENABLED="$CAMERA_ENABLED" \
|
||||
CAMERA_VIDEO_DEVICE="$CAMERA_VIDEO_DEVICE" \
|
||||
CAMERA_SIGNALING_URL="$CAMERA_SIGNALING_URL" \
|
||||
KASMVNC_GEOMETRY="$KASMVNC_GEOMETRY" \
|
||||
AGENT_GATEWAY_TOKEN="$AGENT_GATEWAY_TOKEN" \
|
||||
python3 - "$CONFIG_PATH" "$tmp_file" <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
source, target = sys.argv[1], sys.argv[2]
|
||||
with open(source, "r", encoding="utf-8") as fp:
|
||||
cfg = json.load(fp)
|
||||
|
||||
cfg.setdefault("workspace", {})
|
||||
cfg.setdefault("ros", {})
|
||||
cfg.setdefault("camera", {})
|
||||
cfg.setdefault("desktop", {})
|
||||
cfg.setdefault("security", {})
|
||||
|
||||
cfg["workspace"]["root"] = os.environ["WORKSPACE_ROOT"]
|
||||
cfg["ros"]["stack"] = "nav2" if os.environ["ROBOT_STACK"].lower() == "nav2" else "autoware"
|
||||
cfg["ros"]["domainId"] = os.environ["ROS_DOMAIN_ID"] if os.environ["ROS_DOMAIN_ID"].isdigit() else "0"
|
||||
cfg["camera"]["enabled"] = os.environ["CAMERA_ENABLED"].lower() in ("true", "1", "yes", "y", "on")
|
||||
cfg["camera"]["videoDevice"] = os.environ["CAMERA_VIDEO_DEVICE"]
|
||||
cfg["camera"]["signalingUrl"] = os.environ["CAMERA_SIGNALING_URL"]
|
||||
cfg["desktop"]["geometry"] = os.environ["KASMVNC_GEOMETRY"]
|
||||
if os.environ["AGENT_GATEWAY_TOKEN"]:
|
||||
cfg["security"]["gatewayToken"] = os.environ["AGENT_GATEWAY_TOKEN"]
|
||||
|
||||
with open(target, "w", encoding="utf-8") as fp:
|
||||
json.dump(cfg, fp, ensure_ascii=False, indent=2)
|
||||
fp.write("\n")
|
||||
PY
|
||||
as_root cp "$tmp_file" "$CONFIG_PATH"
|
||||
rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
restart_service() {
|
||||
if need_cmd systemctl; then
|
||||
as_root systemctl restart "$SERVICE_NAME"
|
||||
elif need_cmd service; then
|
||||
as_root service "$SERVICE_NAME" restart
|
||||
else
|
||||
log "No service manager found. Restart the agent manually."
|
||||
fi
|
||||
}
|
||||
|
||||
if ! need_cmd python3; then
|
||||
log "python3 is required to edit ${CONFIG_PATH}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
log "Config not found: ${CONFIG_PATH}"
|
||||
log "Set AGENT_CONFIG=/path/to/agent.config.json or install the agent first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RUN_USER="$(service_user)"
|
||||
WORKSPACE_ROOT="$(json_get workspace.root '~/autonomy-studio/workspaces')"
|
||||
ROBOT_STACK="$(json_get ros.stack autoware)"
|
||||
ROS_DOMAIN_ID="$(json_get ros.domainId 0)"
|
||||
CAMERA_ENABLED="$(json_get camera.enabled false)"
|
||||
CAMERA_VIDEO_DEVICE="$(json_get camera.videoDevice /dev/video0)"
|
||||
CAMERA_SIGNALING_URL="$(json_get camera.signalingUrl ws://127.0.0.1:3000)"
|
||||
KASMVNC_GEOMETRY="$(json_get desktop.geometry 1600x900)"
|
||||
AGENT_GATEWAY_TOKEN="$(json_get security.gatewayToken '')"
|
||||
|
||||
while :; do
|
||||
clear
|
||||
log "Autonomy Studio Platform Agent Settings"
|
||||
log "======================================="
|
||||
log "Config : ${CONFIG_PATH}"
|
||||
log "Service : ${SERVICE_NAME}"
|
||||
log ""
|
||||
log "1. Workspace root ${WORKSPACE_ROOT}"
|
||||
log "2. ROS stack ${ROBOT_STACK}"
|
||||
log "3. ROS_DOMAIN_ID ${ROS_DOMAIN_ID}"
|
||||
log "4. Camera enabled ${CAMERA_ENABLED}"
|
||||
log "5. Camera device ${CAMERA_VIDEO_DEVICE}"
|
||||
log "6. Camera signaling ${CAMERA_SIGNALING_URL}"
|
||||
log "7. KasmVNC resolution ${KASMVNC_GEOMETRY}"
|
||||
log "8. Gateway token $(if [ -n "$AGENT_GATEWAY_TOKEN" ]; then printf 'configured'; else printf 'empty'; fi)"
|
||||
log ""
|
||||
log "s. Save and restart"
|
||||
log "q. Quit"
|
||||
log ""
|
||||
printf 'Select: '
|
||||
IFS= read -r choice || choice=""
|
||||
case "$choice" in
|
||||
1)
|
||||
prompt_value WORKSPACE_ROOT "Workspace root" "$WORKSPACE_ROOT"
|
||||
;;
|
||||
2)
|
||||
prompt_value ROBOT_STACK "ROS stack (autoware/nav2)" "$ROBOT_STACK"
|
||||
case "$ROBOT_STACK" in
|
||||
nav2|NAV2) ROBOT_STACK="nav2" ;;
|
||||
*) ROBOT_STACK="autoware" ;;
|
||||
esac
|
||||
;;
|
||||
3)
|
||||
prompt_value ROS_DOMAIN_ID "ROS_DOMAIN_ID" "$ROS_DOMAIN_ID"
|
||||
ROS_DOMAIN_ID="$(printf '%s' "$ROS_DOMAIN_ID" | tr -cd '0-9')"
|
||||
[ -n "$ROS_DOMAIN_ID" ] || ROS_DOMAIN_ID="0"
|
||||
;;
|
||||
4)
|
||||
prompt_value CAMERA_ENABLED "Camera enabled true/false" "$CAMERA_ENABLED"
|
||||
;;
|
||||
5)
|
||||
prompt_value CAMERA_VIDEO_DEVICE "Camera device" "$CAMERA_VIDEO_DEVICE"
|
||||
;;
|
||||
6)
|
||||
prompt_value CAMERA_SIGNALING_URL "Camera signaling URL" "$CAMERA_SIGNALING_URL"
|
||||
;;
|
||||
7)
|
||||
prompt_value KASMVNC_GEOMETRY "KasmVNC resolution" "$KASMVNC_GEOMETRY"
|
||||
;;
|
||||
8)
|
||||
prompt_value AGENT_GATEWAY_TOKEN "Gateway token" "$AGENT_GATEWAY_TOKEN" true
|
||||
;;
|
||||
s|S)
|
||||
write_config
|
||||
workspace_path="$(expand_path_for_user "$WORKSPACE_ROOT" "$RUN_USER")"
|
||||
if prompt_yes_no "Create workspace directory ${workspace_path} if missing?" "yes"; then
|
||||
as_root mkdir -p "$workspace_path"
|
||||
as_root chown -R "$RUN_USER":"$RUN_USER" "$workspace_path" || true
|
||||
fi
|
||||
restart_service
|
||||
log ""
|
||||
log "Settings saved and service restarted."
|
||||
exit 0
|
||||
;;
|
||||
q|Q)
|
||||
log "Canceled."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Reference in New Issue
Block a user