build-test-deploy / ci (push) Successful in 1h13m13s
FC协议(0827 docx): - 控制指令域:字节12,13/16,17由纵倾/横倾姿态数据2改为预留(编码恒0、解码忽略) - 状态反馈域:字节147,148由预留12改为剩余发电量(MWh),贯通JSON/网页显示 - PM→CCU链路:姿态字段4xuchar改为2xshort(数据1),结构体大小与线上布局不变 - 同步更新:CCU转发映射、SnapshotBuilder、pCCU网页、fuelcell网页、SQLite列描述、单测/模拟器 - 修正集成测试遗留断言(20B→24B、心跳d[19]→d[23])并增强预留字节校验 CCU地址可配置: - pPowerManger 支持 moos 配置项 ccuhost/ccuport(默认127.0.0.1:7000) - build-board.sh 增加 --ccu-host/--ccu-port 参数 文档:FC协议文档更新为0827版,清理过期协议docx
238 lines
10 KiB
Bash
Executable File
238 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
||
#=======================================================================
|
||
# FILE: scripts/build-board.sh
|
||
# DESC: 把源码同步到目标板卡 (RK3588 / Ubuntu 22.04),在板卡原生编译
|
||
# (aarch64 直编,比本地 QEMU 模拟快约 10 倍),并把产物部署到
|
||
# /root/work/h100/bin/,可选重启 systemd 服务。
|
||
#
|
||
# 用法:
|
||
# ./scripts/build-board.sh # 同步+编译+部署(不重启)
|
||
# ./scripts/build-board.sh --start # 编译后重启 3 个服务
|
||
# ./scripts/build-board.sh --clean # 板卡上重新 cmake 再编译
|
||
# ./scripts/build-board.sh --jobs 4 # 指定并行度(默认板卡 nproc)
|
||
#
|
||
# 参数:
|
||
# --host <ip> 目标主机(默认 192.168.0.223)
|
||
# --user <user> 登录用户(默认 root)
|
||
# --board-src <dir> 板卡源码目录(默认 /root/work/h100/src)
|
||
# --board-bin <dir> 板卡部署目录(默认 /root/work/h100/bin)
|
||
# --jobs <n> 编译并行度(默认板卡 nproc)
|
||
# --start 编译部署后重启服务
|
||
# --clean 先重新 cmake(配置变更时用)
|
||
# --ccu-host <ip> 覆盖 mission 中 pPowerManger 的 CCU 地址 (ccuhost)
|
||
# --ccu-port <n> 覆盖 mission 中 pPowerManger 的 CCU 端口 (ccuport)
|
||
# -h, --help 显示帮助
|
||
#
|
||
# 前置: 板卡已配免密 SSH,且有编译环境(cmake/g++/MOOS/jsoncpp),
|
||
# 源码已能本地编译(本脚本只负责同步+板卡编译)。
|
||
#
|
||
# !!!! 板卡网络配置(2026-08-26 联调定型,勿随意修改) !!!!
|
||
#
|
||
# 板卡与 FC 的组网为"单网卡 + /23 掩码"方案(依据《超滑FC和复合管控器
|
||
# 通讯协议-0821》1.1.1:CCU 192.168.0.140/23 <-> FC 192.168.1.162):
|
||
#
|
||
# enP3p49s0 192.168.0.223/23 (255.255.254.0) <- 唯一业务网口,接交换机
|
||
# /23 使 192.168.0.x 与 192.168.1.x 同子网直达,
|
||
# FC(192.168.1.162) 无需网关即可互通。
|
||
# NM 配置档案: "有线连接 1"(静态 manual,已持久化)
|
||
# enP4p65s0 已弃用(旧双网卡方案的 FC 专口,物理链路已断)
|
||
# 回环 lo pPowerManger(5001) <-> pCCU(7000) 同机 UDP 互通
|
||
#
|
||
# 关联端口:
|
||
# FC 状态: FC:7000 -> 板卡:6000 (pCCU 监听)
|
||
# FC 控制: 板卡:6000 -> FC:7000 (pCCU 发送)
|
||
# PM 指令: pPowerManger:5001 -> pCCU:7000 (127.0.0.1,
|
||
# 见 missions/h100.moos ccuhost/ccuport,默认值在 PowerManger.h CCUHOST)
|
||
# PM 状态: pCCU:7000 -> pPowerManger:5001 (127.0.0.1)
|
||
#
|
||
# 排障提示:
|
||
# - 若收不到 FC 状态,先在板卡上 `ethtool enP3p49s0` 看 Link detected,
|
||
# 再 `ping 192.168.1.162`;ping 不通通常是物理链路/交换机问题,
|
||
# 不要改回 /24 掩码或启用 enP4p65s0 来"修"网络。
|
||
# - 改 IP/掩码须用 `nmcli con mod "有线连接 1" ...` 持久化,
|
||
# 并保持掩码 /23。
|
||
#=======================================================================
|
||
|
||
set -uo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(dirname "${SCRIPT_DIR}")"
|
||
|
||
HOST="192.168.0.223"
|
||
USER="root"
|
||
BOARD_SRC="/root/work/h100/src"
|
||
BOARD_BIN="/root/work/h100/bin"
|
||
JOBS=""
|
||
DO_START=0
|
||
DO_CLEAN=0
|
||
CCU_HOST=""
|
||
CCU_PORT=""
|
||
|
||
SERVICES=(moosdb pPowerManger pPowerMangerHost pCCU)
|
||
|
||
info() { printf '\033[1;36m[build-board]\033[0m %s\n' "$*"; }
|
||
ok() { printf '\033[1;32m[build-board]\033[0m %s\n' "$*"; }
|
||
warn() { printf '\033[1;33m[build-board]\033[0m %s\n' "$*"; }
|
||
err() { printf '\033[1;31m[build-board]\033[0m %s\n' "$*"; }
|
||
|
||
usage() {
|
||
sed -n '2,31p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
|
||
exit 0
|
||
}
|
||
|
||
#-------------------------------------------------------------------
|
||
# 参数解析
|
||
#-------------------------------------------------------------------
|
||
while [ $# -gt 0 ]; do
|
||
case "$1" in
|
||
--host) [ $# -ge 2 ] || { err "--host 需要参数"; exit 1; }; HOST="$2"; shift 2 ;;
|
||
--user) [ $# -ge 2 ] || { err "--user 需要参数"; exit 1; }; USER="$2"; shift 2 ;;
|
||
--board-src) [ $# -ge 2 ] || { err "--board-src 需要参数"; exit 1; }; BOARD_SRC="$2"; shift 2 ;;
|
||
--board-bin) [ $# -ge 2 ] || { err "--board-bin 需要参数"; exit 1; }; BOARD_BIN="$2"; shift 2 ;;
|
||
--jobs) [ $# -ge 2 ] || { err "--jobs 需要参数"; exit 1; }; JOBS="$2"; shift 2 ;;
|
||
--start) DO_START=1; shift ;;
|
||
--clean) DO_CLEAN=1; shift ;;
|
||
--ccu-host) [ $# -ge 2 ] || { err "--ccu-host 需要参数"; exit 1; }; CCU_HOST="$2"; shift 2 ;;
|
||
--ccu-port) [ $# -ge 2 ] || { err "--ccu-port 需要参数"; exit 1; }; CCU_PORT="$2"; shift 2 ;;
|
||
-h|--help) usage ;;
|
||
*) err "未知参数: $1(见 --help)"; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
SSH_TARGET="${USER}@${HOST}"
|
||
SSH="ssh -o BatchMode=yes -o ConnectTimeout=5"
|
||
|
||
case "${CCU_PORT}" in
|
||
""|*[!0-9]*) [ -z "${CCU_PORT}" ] || { err "--ccu-port 必须是数字端口: ${CCU_PORT}"; exit 1; } ;;
|
||
esac
|
||
|
||
#-------------------------------------------------------------------
|
||
# 1. 前置检查
|
||
#-------------------------------------------------------------------
|
||
if ! ${SSH} "${SSH_TARGET}" 'true' 2>/dev/null; then
|
||
err "无法免密 SSH 到 ${SSH_TARGET}"
|
||
err "请先配置免密登录: ssh-copy-id ${SSH_TARGET}"
|
||
exit 1
|
||
fi
|
||
ok "SSH 连接正常: ${SSH_TARGET}"
|
||
|
||
#-------------------------------------------------------------------
|
||
# mission 中插入/替换 "key = value"(键已存在则替换,否则插到第一个
|
||
# 顶层 '}' 之前,即 pPowerManger 配置块末尾)
|
||
#-------------------------------------------------------------------
|
||
upsert_moos_param() {
|
||
local f="$1" key="$2" val="$3"
|
||
if grep -qE "^[[:space:]]*${key}[[:space:]]*=" "${f}"; then
|
||
sed -i -E "s|^([[:space:]]*)${key}[[:space:]]*=.*|\1${key} = ${val}|" "${f}"
|
||
else
|
||
awk -v kv=" ${key} = ${val}" \
|
||
'!d && /^[[:space:]]*}[[:space:]]*$/ { print kv; d=1 } { print }' \
|
||
"${f}" > "${f}.tmp" && mv "${f}.tmp" "${f}"
|
||
fi
|
||
}
|
||
|
||
#-------------------------------------------------------------------
|
||
# 2. 同步源码到板卡(排除构建产物 / git / 数据)
|
||
#-------------------------------------------------------------------
|
||
info "同步源码到板卡 ${BOARD_SRC} ..."
|
||
rsync -az --delete \
|
||
--exclude='build/' \
|
||
--exclude='build-arm64/' \
|
||
--exclude='build-native/' \
|
||
--exclude='build-nosa-test/' \
|
||
--exclude='bin/' \
|
||
--exclude='.git/' \
|
||
--exclude='.cache/' \
|
||
--exclude='.kilo/' \
|
||
--exclude='.vscode/' \
|
||
--exclude='docs/' \
|
||
--exclude='reports/' \
|
||
--exclude='*.log' \
|
||
--exclude='*.db' \
|
||
--exclude='CMakeCache.txt' \
|
||
"${PROJECT_ROOT}/" "${SSH_TARGET}:${BOARD_SRC}/" || { err "rsync 源码失败"; exit 1; }
|
||
ok "源码已同步"
|
||
|
||
if [ -f "${PROJECT_ROOT}/missions/h100.moos" ]; then
|
||
info "同步 mission h100.moos ..."
|
||
local_mission="${PROJECT_ROOT}/missions/h100.moos"
|
||
tmp_moos=""
|
||
if [ -n "${CCU_HOST}" ] || [ -n "${CCU_PORT}" ]; then
|
||
tmp_moos="$(mktemp)"
|
||
cp "${local_mission}" "${tmp_moos}"
|
||
[ -n "${CCU_HOST}" ] && upsert_moos_param "${tmp_moos}" ccuhost "${CCU_HOST}"
|
||
[ -n "${CCU_PORT}" ] && upsert_moos_param "${tmp_moos}" ccuport "${CCU_PORT}"
|
||
local_mission="${tmp_moos}"
|
||
info "CCU 地址覆盖: ccuhost=${CCU_HOST:-<保持原值>} ccuport=${CCU_PORT:-<保持原值>}"
|
||
fi
|
||
rsync -az "${local_mission}" \
|
||
"${SSH_TARGET}:/root/work/h100/missions/h100.moos" || { err "rsync mission 失败"; [ -n "${tmp_moos}" ] && rm -f "${tmp_moos}"; exit 1; }
|
||
[ -n "${tmp_moos}" ] && rm -f "${tmp_moos}"
|
||
ok "mission 已同步"
|
||
fi
|
||
|
||
#-------------------------------------------------------------------
|
||
# 3. 板卡原生编译
|
||
#-------------------------------------------------------------------
|
||
if [ "${DO_CLEAN}" = "1" ]; then
|
||
info "重新 cmake(--clean)..."
|
||
${SSH} "${SSH_TARGET}" "rm -rf ${BOARD_SRC}/build-native && mkdir -p ${BOARD_SRC}/build-native && \
|
||
cd ${BOARD_SRC}/build-native && cmake -DCMAKE_BUILD_TYPE=Release .." \
|
||
|| { err "cmake 失败"; exit 1; }
|
||
ok "cmake 完成"
|
||
else
|
||
${SSH} "${SSH_TARGET}" "mkdir -p ${BOARD_SRC}/build-native"
|
||
# 若首次未配置过则先 cmake
|
||
if ! ${SSH} "${SSH_TARGET}" "[ -f ${BOARD_SRC}/build-native/Makefile ]"; then
|
||
info "首次编译,先 cmake ..."
|
||
${SSH} "${SSH_TARGET}" "cd ${BOARD_SRC}/build-native && cmake -DCMAKE_BUILD_TYPE=Release .." \
|
||
|| { err "cmake 失败"; exit 1; }
|
||
ok "cmake 完成"
|
||
fi
|
||
fi
|
||
|
||
if [ -z "${JOBS}" ]; then
|
||
JOBS="$(${SSH} "${SSH_TARGET}" nproc)"
|
||
fi
|
||
|
||
info "板卡编译 (make -j${JOBS}) ..."
|
||
if ! ${SSH} "${SSH_TARGET}" "cd ${BOARD_SRC}/build-native && make -j${JOBS}"; then
|
||
err "板卡编译失败(见上方输出)"
|
||
exit 1
|
||
fi
|
||
ok "板卡编译完成"
|
||
|
||
#-------------------------------------------------------------------
|
||
# 4. 部署产物到板卡运行目录
|
||
#-------------------------------------------------------------------
|
||
info "部署产物到 ${BOARD_BIN}/ ..."
|
||
${SSH} "${SSH_TARGET}" "mkdir -p ${BOARD_BIN} && \
|
||
cp -f ${BOARD_SRC}/bin/pPowerManger ${BOARD_BIN}/pPowerManger && \
|
||
cp -f ${BOARD_SRC}/bin/pPowerMangerHost ${BOARD_BIN}/pPowerMangerHost && \
|
||
cp -f ${BOARD_SRC}/bin/pCCU ${BOARD_BIN}/pCCU && \
|
||
chmod +x ${BOARD_BIN}/pPowerManger ${BOARD_BIN}/pPowerMangerHost ${BOARD_BIN}/pCCU" \
|
||
|| { err "部署产物失败"; exit 1; }
|
||
ok "产物已部署"
|
||
|
||
echo ""
|
||
ok "产物: ${BOARD_BIN}/pPowerManger (aarch64)"
|
||
${SSH} "${SSH_TARGET}" "file ${BOARD_BIN}/pPowerManger | cut -c1-60"
|
||
|
||
#-------------------------------------------------------------------
|
||
# 5. 可选重启服务
|
||
#-------------------------------------------------------------------
|
||
if [ "${DO_START}" = "1" ]; then
|
||
info "重启服务 ..."
|
||
${SSH} "${SSH_TARGET}" "systemctl restart ${SERVICES[*]}" \
|
||
|| { err "重启服务失败"; exit 1; }
|
||
sleep 3
|
||
ok "服务状态: $(${SSH} "${SSH_TARGET}" "systemctl is-active ${SERVICES[*]}")"
|
||
else
|
||
echo ""
|
||
info "未重启服务。需要重启请加 --start 或手动:"
|
||
echo " systemctl restart ${SERVICES[*]}"
|
||
fi
|
||
|
||
echo ""
|
||
ok "完成。"
|