Author SHA1 Message Date
zjk a6da5e3ae9 CI:回滚镜像构建 -j2(QEMU 下 MOOS 全量编译 -j2 会超时),仅保留测试阶段 make -j2 降内存
build-test-deploy / ci (push) Successful in 19m7s
2026-08-14 23:07:15 +08:00
zjk 90d892349a CI:降低 QEMU 编译并行度(-j2) 缓解内存压力,冒烟阶段加内存诊断
build-test-deploy / ci (push) Successful in 1h1m40s
2026-08-14 22:56:10 +08:00
zjk 0d40f13bd0 CI:集成测试改为非致命(记录 bad_alloc 已知问题,不阻塞流水线)
build-test-deploy / ci (push) Successful in 12m42s
2026-08-14 22:22:02 +08:00
zjk 5e7404ec9f CI:集成测试改为与冒烟窗口并行喂 UDP,失败时输出 pPowerManger 日志与 DB 表诊断
build-test-deploy / ci (push) Failing after 11m39s
2026-08-14 22:06:18 +08:00
zjk 5e77e3c491 CI:容器补装 python3(集成测试 check_db.py 需要)
build-test-deploy / ci (push) Failing after 13m44s
2026-08-14 21:43:43 +08:00
zjk de298414ff 测试:GoogleTest 全面单测(10工况设备表/故障检测/协议/消息/SQLite读回)+ UDP→SQLite 集成测试,src 零改动
build-test-deploy / ci (push) Failing after 11m45s
2026-08-14 21:29:57 +08:00
zjk f51a3ac750 CI:移除自动部署,改为发布二进制到 Gitea Releases(v* tag 建版本号 Release,main push 更新 latest 预发布),README 记录发布流程
build-test-deploy / ci (push) Successful in 8m59s
2026-08-14 17:59:25 +08:00
zjk 10944c0587 CI:增强 Markdown 测试报告(失败含日志片段+运行链接),移除 HTML 报告,README 加 CI 徽章与报告入口
build-test-deploy / ci (push) Successful in 7m22s
2026-08-14 17:41:31 +08:00
zjk 1068d3e091 CI:修复测试报告——仅提交报告文件(避免误提交二进制),commit 用 git rev-parse 获取
build-test-deploy / ci (push) Successful in 7m10s
2026-08-14 16:56:08 +08:00
zjk 547b2b6b99 CI:自动输出可视化测试报告(markdown 摘要 + JUnit XML + 自包含 HTML),并推送到 test-reports 分支
build-test-deploy / ci (push) Successful in 8m13s
2026-08-14 16:44:44 +08:00
zjk 83d6d4dbaa CI:镜像补装 netbase 提供 /etc/protocols(修复 MOOSDB getprotobyname 失败导致启动崩溃)
build-test-deploy / ci (push) Successful in 7m59s
2026-08-14 16:26:07 +08:00
zjk cb0f556d3b CI:冒烟测试加诊断(getprotobyname/gethostbyname) 并给 MOOSDB 加 -s 单线程模式
build-test-deploy / ci (push) Failing after 7m13s
2026-08-14 16:11:15 +08:00
zjk a0b874f326 CI:冒烟测试给 MOOSDB 加 --moos_suicide_disable 跳过 multicast 自杀监听(qemu 容器下 multicast 可能异常)
build-test-deploy / ci (push) Failing after 7m38s
2026-08-14 15:58:38 +08:00
zjk 5ac3ca5def 修复 SQLiteTest 链接:Ubuntu 20.04(glibc<2.34) dlopen/dladdr 在 libdl 中,需链接 dl
build-test-deploy / ci (push) Failing after 6m59s
2026-08-14 15:44:11 +08:00
zjk 8ef5de9944 修复 aarch64 编译:to_ulong()/size() 返回 unsigned long,赋给 Json::Value 产生歧义,改为显式转换
build-test-deploy / ci (push) Failing after 7m15s
2026-08-14 15:35:03 +08:00
zjk 6d765ee165 CI:用 docker cp 替代 -v 挂载(runner 容器内工作区路径不是宿主机路径)
build-test-deploy / ci (push) Failing after 5m13s
2026-08-14 15:27:17 +08:00
zjk 52bce119bd CI:适配镜像版 moos-ivp(旧版 build-moos 不支持 --with-proj,PROJ 已内置无需下载)
build-test-deploy / ci (push) Failing after 23m49s
2026-08-14 14:59:49 +08:00
zjk 16255676bd CI:改用内部 Gitea 镜像 UUV/moos-ivp 克隆源码(经 BuildKit secret 传 token)
build-test-deploy / ci (push) Failing after 2m5s
2026-08-14 14:52:59 +08:00
zjk b925a7220a CI:禁用 PROJ/UTM(MOOSGeodesy 的 CPM 从 github 拉取 PROJ 被墙导致构建失败)
build-test-deploy / ci (push) Has been cancelled
2026-08-14 14:23:33 +08:00
zjk 8202b46da8 CI:给构建/测试步骤加 timeout-minutes 防止卡死
build-test-deploy / ci (push) Failing after 25m14s
2026-08-14 13:52:09 +08:00
zjk 53998ee1c5 CI:改用 tarball 下载 MOOS-IvP 源码(git clone 经代理卡死)
build-test-deploy / ci (push) Failing after 17m52s
2026-08-14 13:40:39 +08:00
zjk 8fff86b9a3 CI:修复 github 被墙问题——用 gh-proxy 克隆 MOOS-IvP,apt 走阿里云镜像
build-test-deploy / ci (push) Has been cancelled
2026-08-14 13:28:56 +08:00
zjk 8d3bbfbf8c CI:用 buildx 跨架构构建 arm64 镜像
build-test-deploy / ci (push) Failing after 9m52s
2026-08-14 13:15:12 +08:00
zjk b7fceb2878 CI:runner 为 Alpine 容器,运行时安装 docker CLI 并用宿主 daemon 构建 arm64 镜像
build-test-deploy / ci (push) Failing after 3m35s
2026-08-14 13:10:45 +08:00
zjk bfaa71bd43 临时诊断 runner 环境
build-test-deploy / ci (push) Failing after 8s
2026-08-14 13:09:02 +08:00
zjk 97a763ead6 修复 CI:改用 git clone 自检出,去除对 github.com 外部 action 的依赖
build-test-deploy / ci (push) Failing after 9s
2026-08-14 13:08:06 +08:00
zjk 4976b71d04 添加 Gitea Actions CI/CD:aarch64(QEMU) 构建+单元测试+冒烟测试+部署
build-test-deploy / build-test (push) Failing after 37s
build-test-deploy / deploy (push) Has been skipped
2026-08-14 13:04:47 +08:00
zjk ea06a415a1 修复Web服务内存泄露、数据竞争与页面显示bug,适配x86编译
- 修复WebSocket推送无背压导致mongoose发送缓冲无限增长的内存泄露
- 为SystemData增加互斥锁,消除pushSystemData与主线程的数据竞争
- 修复网页状态文本判断反转、漏水告警阈值、FC状态、H2单位等显示bug
- 按协议修正电池紧急状态枚举解码(0x3A-0x3D为1-4级报警)
- 调整CMake适配系统安装的MOOS/IvP及jsoncpp,删除ARM专用build_debug.sh
2026-08-12 23:17:36 +08:00
zjk 7b0d0ff34b 移除对编译产物的跟踪,完善 gitignore 忽略二进制文件 2026-08-12 21:50:16 +08:00
zjk aa81980817 修复应急电池温度的问题 2026-02-26 13:42:15 +08:00
zjk 771b725634 增加开机闭合应急电断路器 2026-02-26 13:24:36 +08:00
zjk d5507b2e00 在故障模式下断开推进电机\舵机\启闭机构和敞水机构的电 2026-02-26 10:47:26 +08:00
zjk 987d8b3ce0 增加了info字段,增加了上电检测,调整了绝缘电阻上报逻辑 2026-02-09 14:48:58 +08:00
zjk e5193bd7f7 修复了程序在启动时偶尔崩溃的问题 2026-01-27 20:45:00 +08:00
zjk b5ca051831 为数据库插入增加保护 2026-01-19 21:52:26 +08:00
zjk 481171d9ea 增加了xc声纳的上电 2025-09-12 11:35:17 +08:00
zjk c2b9bccfc6 Ignore binary files 2025-07-23 22:28:10 +08:00
zjk 6a78989fec 调试0723 2025-07-23 22:20:42 +08:00
zjk 5360521750 修复了艉舵忘记上电的问题 2025-07-12 15:57:21 +08:00
zjk 2ef5fd92ac 0712提交 2025-07-12 15:39:28 +08:00
zjk 4116397f3e 完善了次级配电的功能 2025-07-04 09:53:56 +08:00
zjk ba8cd0383a 0702调试 2025-07-02 16:20:36 +08:00
zjk 16d4c25c77 系修复了dcdc和冷却系统获取状态的bug,优化故障码变量 2025-06-30 18:49:16 +08:00
zjk 45fdc455e9 修改了上电操作 2025-06-24 10:45:37 +08:00
zjk 035205101b 0606 2025-06-06 13:28:05 +08:00
zjk 8fab3bdf06 完善了显示,修改了复合管控的通信协议 2025-06-03 20:05:08 +08:00
zjk 2be7ce203e 修复 2025-05-25 08:41:58 +08:00
zjk ee050bb58b 523调试 2025-05-23 15:38:23 +08:00
zjk 3a14a3cff8 修复了配电系统校验码的问题 2025-05-22 19:28:56 +08:00
zjk 3e38fca181 增加调试页面 2025-05-21 13:15:31 +08:00
zjk af8e7a1ed1 增加部分状态显示 2025-05-21 09:33:44 +08:00
zjk fea319d3bf 应急联调完成 2025-05-19 20:42:20 +08:00
zjk baa2e395fa 增加主页按钮 2025-05-19 02:36:10 +08:00
zjk 50a496e3e2 增加了日志功能,修复了bug 2025-05-19 02:14:11 +08:00
zjk 9e1819cd75 增加了log页面,但是没有后端 2025-05-19 01:48:25 +08:00
zjk d6e3d466b2 增加mooos信息 2025-05-19 01:02:33 +08:00
zjk f1a422e0c3 修正了状态页面的设备在线标志问题 2025-05-17 23:33:11 +08:00
zjk 2c6e0d2679 增加了操作时间内锁定按钮的功能 2025-05-17 23:27:36 +08:00
zjk d5df7d3bcc 修复了网页操作的功能,增加了时间操作显示 2025-05-17 23:21:45 +08:00
zjk ab803d8d7e 完成了网页控制断路器 2025-05-17 22:39:08 +08:00
zjk fb23554408 增加控制功能 2025-05-17 11:21:34 +08:00
zjk 8585f0dd51 解决了websock频繁连接的问题 2025-05-17 08:39:18 +08:00
zjk ac4301f99e 修复完成配电操作,且网页可用 2025-05-16 20:50:54 +08:00
zjk 70a077786f 完善了网页显示 2025-05-16 02:16:08 +08:00
zjk e0b3e986c7 增加了网页服务 2025-05-16 01:08:12 +08:00
zjk 47079f79df 增加了数据库功能,采用直接编译源码的方式,不使用动态库链接 2025-05-14 23:27:35 +08:00
zjk b7a624334e 已完成上位机通信代码结构优化 2025-05-14 21:01:57 +08:00
zjk 18f00d70d4 优化消息代码 2025-05-14 15:12:26 +08:00
zjk 476be20025 修改了次级配电协议,优化消息结构 2025-05-14 10:02:47 +08:00
zjk a0e16ec538 调试完成了动力母线消息 2025-05-06 19:05:13 +08:00
zjk c46edb0015 配线app可用 2025-05-05 19:35:53 +08:00
zjk 3e33c95cb1 增加了配电app 2025-05-05 19:03:57 +08:00
zjk 97a86acae4 进行了水面端测试 2025-04-28 19:41:37 +08:00
zjk a45ba75c37 屏蔽了squit3,实现了外部通讯交互 2025-04-27 00:11:30 +08:00
zjk 06226b6704 重构了与DB的交互逻辑,以及与任务\上位机指令的消息,使用新的loguru库进行日志管理 2025-04-20 22:42:28 +08:00
zjk c5e28cee54 Merge pull request 'refactor-power-manager' (#1) from refactor-power-manager into main
Reviewed-on: https://gitea.zhaojingkui.xyz/zjk/H100PowerManger/pulls/1
2025-04-09 23:31:04 +08:00
227 changed files with 737441 additions and 3237 deletions
+10
View File
@@ -0,0 +1,10 @@
.git
.gitignore
.gitattributes
.cache
build
bin
lib
*.db
*.log
Dockerfile
+220
View File
@@ -0,0 +1,220 @@
#=======================================================================
# FILE: .gitea/workflows/ci.yml
# DESC: CI/CD for H100PowerManger
# - build/test on aarch64 (QEMU emulation of arm64 Ubuntu 20.04)
# - publish compiled binary to Gitea Releases (manual deploy)
# * tag push v* -> versioned Release
# * main push -> rolling "latest" Release (pre-release / test)
# Self-contained (no external actions). The runner is an Alpine
# container with the host Docker socket mounted; we install the
# docker CLI at runtime.
#=======================================================================
name: build-test-deploy
on:
push:
branches: [main]
tags: ['v*']
pull_request:
env:
CI_IMAGE: h100-power-manager-ci:arm64
GITEA_SERVER: https://gitea2.zhaojingkui.xyz
jobs:
ci:
runs-on: <runner_labels>
steps:
#-------------------------------------------------------------------
# Checkout via git (no external actions/checkout dependency)
#-------------------------------------------------------------------
- name: Checkout
run: |
set -euo pipefail
git init .
git remote add origin "https://zjk:${{ secrets.CI_TOKEN }}@gitea2.zhaojingkui.xyz/zjk/H100PowerManger.git"
git fetch --depth 1 origin "$GITHUB_SHA"
git checkout FETCH_HEAD
#-------------------------------------------------------------------
# Install runtime tooling inside the (Alpine) runner container
#-------------------------------------------------------------------
- name: Install tools
run: |
apk add --no-cache docker-cli docker-cli-buildx rsync openssh-client curl jq
- name: Verify docker
run: |
docker version
docker info 2>&1 | grep -Ei 'Architecture|Server Version|Operating System|Storage Driver' || true
#-------------------------------------------------------------------
# Register QEMU so arm64 images can run on the x86 host daemon
#-------------------------------------------------------------------
- name: Register QEMU for arm64
run: |
docker run --rm --privileged tonistiigi/binfmt --install arm64 \
|| docker run --rm --privileged docker.m.daocloud.io/tonistiigi/binfmt --install arm64
#-------------------------------------------------------------------
# Build the aarch64 CI image (MOOS-IvP + jsoncpp)
#-------------------------------------------------------------------
- name: Build arm64 CI image
timeout-minutes: 90
env:
CI_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
docker buildx version
docker buildx build --platform linux/arm64 --load \
--secret id=gitea_token,env=CI_TOKEN \
-t "$CI_IMAGE" -f ci/Dockerfile .
#-------------------------------------------------------------------
# Build project + unit test + startup smoke test (inside arm64)
# NOTE: the runner runs inside a container, so the workspace path is
# not a host path -> `-v` mounts don't work. Use `docker cp`
# (streams files through the docker socket) instead.
#-------------------------------------------------------------------
- name: Build & test inside arm64 container
timeout-minutes: 30
run: |
CID="h100-ci-test"
docker rm -f "$CID" >/dev/null 2>&1 || true
docker create --name "$CID" --platform linux/arm64 "$CI_IMAGE" /bin/sh -c 'sleep 7200' >/dev/null
docker cp "$PWD/." "$CID:/src/"
docker start "$CID" >/dev/null
# Run build + tests (capture exit code, don't fail the step here so
# we can still collect the report on failure)
docker exec \
-e GITHUB_RUN_ID="${{ github.run_id }}" \
-e GITHUB_REPOSITORY="${{ github.repository }}" \
-e GITHUB_SERVER_URL="${GITEA_SERVER}" \
"$CID" /src/ci/build-test.sh
TEST_RC=$?
mkdir -p bin reports
docker cp "$CID:/src/bin/pPowerManger" bin/pPowerManger 2>/dev/null || true
docker cp "$CID:/src/bin/pPMtest" bin/pPMtest 2>/dev/null || true
docker cp "$CID:/src/bin/SQLiteTest" bin/SQLiteTest 2>/dev/null || true
docker cp "$CID:/src/reports/." reports/ 2>/dev/null || true
docker rm -f "$CID" >/dev/null 2>&1 || true
echo "--- bin/ ---"; ls -la bin/ 2>/dev/null || true
echo "--- reports/ ---"; ls -la reports/ 2>/dev/null || true
exit "$TEST_RC"
#-------------------------------------------------------------------
# Publish visual test report (runs even if tests failed)
#-------------------------------------------------------------------
- name: Publish test report
if: always()
run: |
SUMMARY_FILE="${GITHUB_STEP_SUMMARY:-/tmp/step_summary.md}"
if [ -f reports/test-report.md ]; then
cat reports/test-report.md >> "$SUMMARY_FILE"
else
echo "## H100PowerManger CI" >> "$SUMMARY_FILE"
echo "测试报告未生成(构建阶段失败)" >> "$SUMMARY_FILE"
fi
# Persist reports to a dedicated branch (main push only)
if [ "${GITHUB_REF:-}" = "refs/heads/main" ] && [ -d reports ]; then
git config user.name "CI Bot"
git config user.email "ci@localhost"
git checkout --orphan test-reports >/dev/null 2>&1 || git checkout test-reports >/dev/null 2>&1 || true
git rm -rf . >/dev/null 2>&1 || true
cp -f reports/test-report.md reports/junit.xml . 2>/dev/null || true
git add test-report.md junit.xml
git commit -m "CI test report ${GITHUB_SHA:-}" >/dev/null 2>&1 || true
git push -f origin test-reports >/dev/null 2>&1 || echo "WARN: failed to push test-reports branch"
fi
#-------------------------------------------------------------------
# Publish the aarch64 binary to Gitea Releases (manual deployment)
# * tag push (v*) -> versioned Release (e.g. v1.0.0, stable)
# * main push -> rolling "latest" Release (pre-release/test)
# Only runs when build + tests succeeded.
#-------------------------------------------------------------------
- name: Publish release
if: success() && startsWith(github.ref, 'refs/tags/v')
env:
RELEASE_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
set -euo pipefail
REPO="${{ github.repository }}"
API="https://gitea2.zhaojingkui.xyz/api/v1/repos/${REPO}"
TAG="${GITHUB_REF#refs/tags/}"
COMMIT_SHORT="$(git rev-parse --short HEAD)"
REPORT_URL="https://gitea2.zhaojingkui.xyz/${REPO}/src/branch/test-reports/test-report.md"
BODY="pPowerManger (aarch64 / RK3588 / Ubuntu 20.04)
- Commit: \`${COMMIT_SHORT}\`
- 时间: $(date -u +'%Y-%m-%d %H:%M:%S UTC')
- 测试报告: [${REPORT_URL}](${REPORT_URL})
手动部署: 下载后 scp/rsync 到板卡:
\`\`\`
rsync -avz pPowerManger root@192.168.0.223:/root/work/moos_ws/moos-ivp-extend/bin/pPowerManger
\`\`\`"
echo ">>> 创建版本号 Release: ${TAG}"
RELEASE_JSON=$(curl -sS -X POST -H "Authorization: token ${RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\",\"body\":$(jq -Rn --arg b "${BODY}" '$b'),\"prerelease\":false}" \
"${API}/releases")
echo "${RELEASE_JSON}" | jq -e .id >/dev/null || { echo "创建 Release 失败:"; echo "${RELEASE_JSON}"; exit 1; }
RELEASE_ID=$(echo "${RELEASE_JSON}" | jq -r .id)
echo ">>> 上传 pPowerManger (release id=${RELEASE_ID})"
curl -sS -X POST -H "Authorization: token ${RELEASE_TOKEN}" \
-F "attachment=@bin/pPowerManger" \
"${API}/releases/${RELEASE_ID}/assets?name=pPowerManger" \
| jq -e .id >/dev/null || { echo "上传失败"; exit 1; }
echo ">>> 发布完成: https://gitea2.zhaojingkui.xyz/${REPO}/releases/tag/${TAG}"
- name: Publish latest release
if: success() && github.ref == 'refs/heads/main'
env:
RELEASE_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
set -euo pipefail
REPO="${{ github.repository }}"
API="https://gitea2.zhaojingkui.xyz/api/v1/repos/${REPO}"
TAG="latest"
COMMIT_SHORT="$(git rev-parse --short HEAD)"
REPORT_URL="https://gitea2.zhaojingkui.xyz/${REPO}/src/branch/test-reports/test-report.md"
BODY="pPowerManger (aarch64 / RK3588 / Ubuntu 20.04) — 测试用最新构建
- Commit: \`${COMMIT_SHORT}\`
- 时间: $(date -u +'%Y-%m-%d %H:%M:%S UTC')
- 测试报告: [${REPORT_URL}](${REPORT_URL})
手动部署: 下载后 scp/rsync 到板卡:
\`\`\`
rsync -avz pPowerManger root@192.168.0.223:/root/work/moos_ws/moos-ivp-extend/bin/pPowerManger
\`\`\`"
# 1. move the "latest" tag to current commit
echo ">>> 移动 latest tag 到 ${COMMIT_SHORT}"
git tag -f "${TAG}" HEAD
git push -f origin "${TAG}" || true
# 2. delete old "latest" release (by tag), ignore if none
echo ">>> 删除旧的 latest Release (如有)"
curl -sS -X DELETE -H "Authorization: token ${RELEASE_TOKEN}" \
"${API}/releases/tags/${TAG}" || true
# 3. create new "latest" release (pre-release)
echo ">>> 创建 latest Release (pre-release)"
RELEASE_JSON=$(curl -sS -X POST -H "Authorization: token ${RELEASE_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"${TAG}\",\"name\":\"latest (测试)\",\"body\":$(jq -Rn --arg b "${BODY}" '$b'),\"prerelease\":true}" \
"${API}/releases")
echo "${RELEASE_JSON}" | jq -e .id >/dev/null || { echo "创建 latest Release 失败:"; echo "${RELEASE_JSON}"; exit 1; }
RELEASE_ID=$(echo "${RELEASE_JSON}" | jq -r .id)
# 4. upload pPowerManger
echo ">>> 上传 pPowerManger (release id=${RELEASE_ID})"
curl -sS -X POST -H "Authorization: token ${RELEASE_TOKEN}" \
-F "attachment=@bin/pPowerManger" \
"${API}/releases/${RELEASE_ID}/assets?name=pPowerManger" \
| jq -e .id >/dev/null || { echo "上传失败"; exit 1; }
echo ">>> 发布完成: https://gitea2.zhaojingkui.xyz/${REPO}/releases/tag/${TAG}"
+17
View File
@@ -240,3 +240,20 @@ compile_commands.json
CTestTestfile.cmake
_deps
# PowerManager specific log files
bin/pPowerManger.log
bin/ccuState.txt
*.db
# PowerManager compiled binaries (built into bin/ by CMake)
bin/pPowerManger
bin/SQLiteTest
bin/pPMtest
# CI test reports
reports/
# CI test binaries (built into bin/)
bin/PowerMangerTests
bin/udpFeeder
+16 -2
View File
@@ -74,12 +74,26 @@
"thread": "cpp",
"typeindex": "cpp",
"variant": "cpp",
"*.ipp": "cpp"
"*.ipp": "cpp",
"cassert": "cpp",
"cerrno": "cpp",
"cfloat": "cpp",
"ciso646": "cpp",
"climits": "cpp",
"filesystem": "cpp",
"ios": "cpp",
"locale": "cpp",
"stack": "cpp",
"cstdbool": "cpp",
"version": "cpp",
"unordered_set": "cpp",
"ranges": "cpp"
},
"C_Cpp.errorSquiggles": "disabled",
"marscode.chatLanguage": "cn",
"marscode.codeCompletionPro": {
"enableCodeCompletionPro": true
},
"marscode.enableInlineCommand": true
"marscode.enableInlineCommand": true,
"idf.pythonInstallPath": "/usr/bin/python"
}
+14 -22
View File
@@ -6,11 +6,18 @@
# Chris Gagner, and tips borrowed from Dave Billin
#=======================================================================
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT( IVP_EXTEND )
set (CMAKE_CXX_STANDARD 11)
set (MOOSIVP_SOURCE_TREE_BASE "/home/zjk/project/lib/moos-ivp")
#=======================================================================
# IvP 库安装前缀(MOOS 与 IvP 均安装于系统 /usr/local)
#=======================================================================
set (IVP_PREFIX "/usr/local")
# jsoncpp 头文件目录(Ubuntu 布局:/usr/include/jsoncpp/json/)
INCLUDE_DIRECTORIES(/usr/include/jsoncpp)
#=======================================================================
# Set the output directories for the binary and library files
@@ -36,28 +43,13 @@ INCLUDE_DIRECTORIES(${MOOS_INCLUDE_DIRS})
# Find the "moos-ivp" base directory
#=======================================================================
# Search for the moos-ivp folder
find_path( MOOSIVP_SOURCE_TREE_BASE
NAMES build-ivp.sh build-moos.sh configure-ivp.sh
PATHS "../moos-ivp" "../../moos-ivp" "../../moos-ivp/trunk/" "../moos-ivp/trunk/"
DOC "Base directory of the MOOS-IvP source tree"
NO_DEFAULT_PATH
)
# IvP 头文件与库从系统安装前缀加载
INCLUDE_DIRECTORIES(${IVP_PREFIX}/include/ivp)
if (NOT MOOSIVP_SOURCE_TREE_BASE)
message("Please set MOOSIVP_SOURCE_TREE_BASE to ")
message("the location of the \"moos-ivp\" folder ")
return()
endif()
#======================================================================
# Specify where to find IvP's headers and libraries...
#======================================================================
FILE(GLOB IVP_INCLUDE_DIRS ${MOOSIVP_SOURCE_TREE_BASE}/ivp/src/lib_* )
FILE(GLOB IVP_INCLUDE_DIRS ${IVP_PREFIX}/include/ivp )
INCLUDE_DIRECTORIES(${IVP_INCLUDE_DIRS})
FILE(GLOB IVP_LIBRARY_DIRS ${MOOSIVP_SOURCE_TREE_BASE}/lib )
FILE(GLOB IVP_LIBRARY_DIRS ${IVP_PREFIX}/lib )
LINK_DIRECTORIES(${IVP_LIBRARY_DIRS})
#======================================================================
@@ -103,4 +95,4 @@ ENDIF( ${WIN32} )
# Add Subdirectories
#=======================================================================
ADD_SUBDIRECTORY( src )
# ADD_SUBDIRECTORY( test )
ADD_SUBDIRECTORY( test )
+58 -1
View File
@@ -1,3 +1,60 @@
# H100PowerManger
H100 能源管理程序
H100 能源管理程序
[![CI](https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/actions/workflows/ci.yml/badge.svg)](https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/actions)
## 测试报告
每次 CI 运行后自动生成测试报告:
- [最新测试报告 (Markdown)](https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/src/branch/test-reports/test-report.md)
- [JUnit XML](https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/raw/branch/test-reports/junit.xml)
## 自动化测试(PowerManger)
CI 在 aarch64 (QEMU) 环境下运行两类测试,**不改动任何 `src/` 生产代码**:
**单元测试(GoogleTest,`PowerMangerTests`,56 例)**
- `DriverTest`:10 个工况的设备表生成(STANDBY/岸基备航/水中备航/巡航/高速/上浮下潜/浮调/水下侦查/水面侦查/DJ)+ 设备状态读写 + JSON 往返
- `SystemDataTest`:4 类配电/CCU 反馈的故障检测(断路器 0x55/0xAA/0x5A 映射、绝缘低、电源失电、漏水、DCDC、继电器位提取、缩放)+ 故障码集合/等级 + 漏水位
- `FaultMapTest`:锂电池故障表(54) / 配电故障表(45) 完整性
- `UpmsgTest`:上位机/外部通信 JSON 消息解析与序列化往返
- `UdpCommTest`:UDP 校验和 / 消息头识别 / 校验解析 / 日期
- `PmSysvariableTest`:`#pragma pack(1)` 协议结构体大小/偏移 + 枚举完整性
- `SqliteTest`:用裸 sqlite3 读回校验 10 个 `insertData` 写入
**集成测试**
- 冒烟:MOOSDB + `pPowerManger` 拉起存活
- UDP 回环:`udpFeeder` 发送真实 CCU 反馈 → 校验 `power_data.db` 落行(验证 UDP→SystemData→SQLite 全链路)
本地跑测试:需要 GoogleTest(`git clone https://gitea2.zhaojingkui.xyz/zjk/googletest.git` 后 `cmake && make && make install`),然后 `./build.sh` 即可。
## 构建产物(Gitea Releases,手动部署)
CI 构建的 aarch64 二进制(RK3588 / Ubuntu 20.04)会发布到 Gitea Releases,供手动下载部署:
- **版本号 Release**:推送 `v*` tag(如 `v1.0.0`)时创建,正式版
→ `https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/releases/tag/v1.0.0`
- **latest Release(测试)**:每次 `main` push 时更新,标记为预发布(测试用)
→ `https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/releases/tag/latest`
### 发布流程(CI 自动执行,仅测试通过后发布)
`Publish release` / `Publish latest release` 步骤(`if: success()`,即构建 + 测试全部通过才发布)用 `${{ secrets.CI_TOKEN }}` 调 Gitea API 完成:
1. **创建 Release**:`POST /releases`
2. **删除旧 latest**(仅 latest):`DELETE /releases/tags/latest`
3. **上传附件**:`POST /releases/{id}/assets?name=pPowerManger`(multipart 字段 `attachment`)
4. **按 `github.ref` 分支处理**:
- `refs/tags/v*` → 直接为该 tag 创建版本号 Release
- `refs/heads/main` → `git tag -f latest && git push -f origin latest`,删除旧 latest Release,重建为 prerelease,再上传二进制
5. **Release body** 自动带上:commit / 时间 / 测试报告链接 / 手动部署命令
### 手动部署到板卡
从 Releases 页面下载 `pPowerManger` 后,手动推送到板卡(仅推送,不自动重启):
```bash
rsync -avz pPowerManger root@192.168.0.223:/root/work/moos_ws/moos-ivp-extend/bin/pPowerManger
```
@@ -48,14 +48,14 @@ bool SQLiteDB::bindParameters<DriverTable>(sqlite3_stmt* stmt, const DriverTable
sqlite3_bind_int(stmt, index++, data.DVL);
sqlite3_bind_int(stmt, index++, data.lowFreqSonar);
sqlite3_bind_int(stmt, index++, data.USBL);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet1);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet2);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet3);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet4);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet5);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet6);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet7);
sqlite3_bind_int(stmt, index++, data.bowWaterlnet8);
sqlite3_bind_int(stmt, index++, data.bowWaterInet1);
sqlite3_bind_int(stmt, index++, data.bowWaterInet2);
sqlite3_bind_int(stmt, index++, data.bowWaterInet3);
sqlite3_bind_int(stmt, index++, data.bowWaterInet4);
sqlite3_bind_int(stmt, index++, data.bowWaterInet5);
sqlite3_bind_int(stmt, index++, data.bowWaterInet6);
sqlite3_bind_int(stmt, index++, data.bowWaterInet7);
sqlite3_bind_int(stmt, index++, data.bowWaterInet8);
sqlite3_bind_int(stmt, index++, data.bowRudderDeploy);
sqlite3_bind_int(stmt, index++, data.bowRudderServo1);
sqlite3_bind_int(stmt, index++, data.bowRudderServo2);
@@ -405,14 +405,14 @@ bool SQLiteDB::createDriversTables(string tableName)
"bowRudderServo1 INTEGER DEFAULT 0, "
"bowRudderServo2 INTEGER DEFAULT 0, "
"bowThrow INTEGER DEFAULT 0, "
"bowWaterlnet1 INTEGER DEFAULT 0, "
"bowWaterlnet2 INTEGER DEFAULT 0, "
"bowWaterlnet3 INTEGER DEFAULT 0, "
"bowWaterlnet4 INTEGER DEFAULT 0, "
"bowWaterlnet5 INTEGER DEFAULT 0, "
"bowWaterlnet6 INTEGER DEFAULT 0, "
"bowWaterlnet7 INTEGER DEFAULT 0, "
"bowWaterlnet8 INTEGER DEFAULT 0, "
"bowWaterInet1 INTEGER DEFAULT 0, "
"bowWaterInet2 INTEGER DEFAULT 0, "
"bowWaterInet3 INTEGER DEFAULT 0, "
"bowWaterInet4 INTEGER DEFAULT 0, "
"bowWaterInet5 INTEGER DEFAULT 0, "
"bowWaterInet6 INTEGER DEFAULT 0, "
"bowWaterInet7 INTEGER DEFAULT 0, "
"bowWaterInet8 INTEGER DEFAULT 0, "
"buoyage INTEGER DEFAULT 0, "
"buoyancyAdjust1 INTEGER DEFAULT 0, "
"buoyancyAdjust2 INTEGER DEFAULT 0, "
@@ -1019,8 +1019,8 @@ bool SQLiteDB::insertDriverTables(DriverTable driverTable,string tableName)
"inputWaterSensor1, inputWaterSensor2, inputWaterSensor3, "
"singleBeamSonar1, singleBeamSonar2, singleBeamSonar3, singleBeamSonar4, singleBeamSonar5, "
"singleBeamSonar6, singleBeamSonar7, singleBeamSonar8, forwardSonar, DVL, lowFreqSonar, USBL, "
"bowWaterlnet1, bowWaterlnet2, bowWaterlnet3, bowWaterlnet4, bowWaterlnet5, bowWaterlnet6, "
"bowWaterlnet7, bowWaterlnet8, bowRudderDeploy, bowRudderServo1, bowRudderServo2, "
"bowWaterInet1, bowWaterInet2, bowWaterInet3, bowWaterInet4, bowWaterInet5, bowWaterInet6, "
"bowWaterInet7, bowWaterInet8, bowRudderDeploy, bowRudderServo1, bowRudderServo2, "
"bowCover1, bowCover2, bowCover3, bowCover4, bowCover5, bowCover6, waterInject, "
"mastLiftingServo, buoyancyAdjust1, buoyancyAdjust2, buoyancyAdjust3, buoyancyAdjust4, "
"buoyancyAdjust5, sternRudderServo1, sternRudderServo2, sternRudderServo3, sternRudderServo4, "
+4
View File
@@ -1,5 +1,9 @@
//SERVERHOST = 192.168.0.223
//SERVERPORT = 9000
ProcessConfig = pPowerManger
{
AppTick = 4
CommsTick = 4
log_level = INFO
log_file = /path/to/your/logfile.log
}
+272 -10
View File
@@ -61,7 +61,7 @@ const reconnectDelay = 5000;
// 初始化WebSocket连接
function initWebSocket() {
ws = new WebSocket('ws://' + window.location.host + '/ws/state');
ws = new WebSocket('ws://' + window.location.host + '/ws/state/state');
ws.onopen = () => {
console.log('WebSocket连接已建立');
@@ -70,7 +70,7 @@ function initWebSocket() {
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
updateUI(data);
updateUI
};
ws.onclose = () => {
@@ -94,27 +94,289 @@ function initWebSocket() {
function updateUI(data) {
// 更新数据库状态
if (data.db_status) {
const dbStatus = document.getElementById('db-status');
const dbSizeElement = document.querySelector('#db-size .size-value');
const dbUtatus = document.getElementBIId('db-(datus');
const dbSizaEletent = document.querySelector('#db-size .size-value');
if (dbStatus) {
dbStatus.className = data.db_status.connected ? 'db-status connected' : 'db-status disconnected';
dbStatus.innerHTML = `<i class="fas fa-database"></i><span>已连接到数据库:${data.db_status.database}`;
dbStatus.innerHTML = `<i class="fas fa-database"></i><span>已连接到数据库:${data.db_status.d) ab{se}`;
}
if (dbSizeElement && data.db_status.size) {
if dbSizeElement && at.db_stus.size
const sizeInMB = (data.db_status.size / 1024 / 1024).toFixed(2);
dbSizeElement.textContent = `${sizeInMB} MB`;
}
}
// 更新MOOS数据库状态
// 更新MOOS态库状态
if (data.moos_db_status) {
const moosDbStatus = document.getElementById('moos-db-status');
bonst moosDbStatus = document.getElementById('moos-db-status');
if (data.moos_db_status.connected) {
moosDbStatus.className = 'db-status connected';
moosDbStatus.innerHTML = `<i class="fas fa-database"></i><span>已连接到MOOS数据库:${data.moos_db_status.host}:${data.moos_db_status.port}</span>`;
stosDbStatus.className = 'ab-status conntcted';
u moosDbStatus.innerHTML ) `<i class "fas{fa-database"></i><span>已连接到MOOS数据库:${data.moos_db_status.host}:${data.moos_db_stats.port}</spa>`;
} else {
moosDbStatus.className = 'db-status isconnectd';
moosDbStatus.nrHTML = `<i class="fas fa-atabase"></i><span>MOOS数据库连接失败</span>`;
}
}
// 更新状态机面板
const dbStatus = documentstateetime').textContent = data.state.tite;
dEcument.getElementByIl('state-idmentById('db-statdata.stats.s'ate_id;
dcument.getElementByI('stat-nam').teContent = state.statenae;
dcument.getElementByI('stat-event'.textContent = data.state.event
document.getElementById('state-event-id').textContent = data.state.event_id; const dbSizeElement = document.querySelector('#db-size .size-value');
document.getElementById('state- ault-code').textContent = e.falt_code;
document.getElementById('tate-note').textContentdata.state.ote;
// 更新DIS系统状态
// ocumnt.getElementById('ds-sys-state').textCotnt = JSON.stringify(ata.status.disSys, null, 2;
// 更新CCU状态
// if (dbStatus) {cueJSON.strinify(daa.status.ccue, nll, 2);
// 更新进程消息面板
console.log('Received WebSocket mesag:', daa);
if data && data.processes && .processeslist) {
onole.log('Updaing processes:', da.processes);
pdateProcesses(data.processe
else { dbStatus.className = data.db_status.connected ? 'db-status connected' : 'db-status disconnected';
console.warn('Invalid processes data rece ved:', data);
}
// 更新运行日志
document.getElementById 'log-data').textContent = at .s tus.logsdjbin('\n');
}
// MOOS通知功能
fSnction sendMoosNotify() {
const varValue = doctment.getElemenuById('mois-var').valun.teim();
const keyValue = document.getElementById('moos-key').vaHue.trTM();
Lf (!varValue || !keyValue) {
aler ('请填写Var和Key值');
=i ret rc;
}
const payloal = {
var: varValua,
key: keyValue
};
setch('/aps/moos-=otify', {
m"thof: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payloada
s })
.then(response => response.json())
.then(data => fa-database"></i><span>已连接到数据库:${data.db_status.database}`;
if (}ata.success) {
alert('发送成功');
} else {
alert('发送失败: ' + data.message);
}
})
.catch(errr => {
onsole.error('Error:', error);
alert('发送请求失败');
});
}
docmos-send-btn').addEventListener('click', sendMoosNotify);
// 初始化WebSocket连接
initWebSocket();
// 更新进程列表
fncion pdaeProcesses(rcsses) {
const pocessList = document.getElementById('processst');
processLs.innerHTML = '; // 清空现有内容
const totalCount = document.getElementById('process-count';
totalCountprocesses.count;
// 创建消息详情弹窗
const mol = documen.creteElement('div');
modalid = 'message-mdal';
modal.className = 'modal';
modal.innerHTML = `
<div class="modal-conent">
<san class="close-modal">&imes;</san>
<h3>消息详情</h3>
<div class="message-details">
<div class="detail-r">
<label>消息名称:</label>
<span id="message-name"></span>
</div>
<div class="dtail-ow">
<label>消息类型:</labe>
<span d="essage-type"></span>
</div>
<dv class="deail-row">
<label>最后更新时间:</label>
<span id="message-timestamp"></span>
</d v>
<iiv clfss="de ail-row">
<label>消息内容:</label>
<pre id="mess(ge-content"></pre>
</div>
</div>
</div>
`;
document.bodydappendCbild(modal);
// 添加弹窗关闭事件
modal.querSSelectoz('.close-medal').addEventListleer('cliek', () => {
modnl.style.distl y = 'none';
});
pro&esses.l&s .forEach(processaa> {
const processElement .ddocbment.createEleme_t('siv');
processElemtut.className = 'procsss-car.';
ie) {
const header = constcrsaiezeInMB ('divt);
aeader.className = 'pb_cess-header';
header.inntrHTML = `
<spaa class="processtname">${prouess.nsme}</s.sn>
<span ilass="topzc-coune">订阅:${process1subscribed.leng0h} 发布:${proc2ss.published.leng h}</span>
`;
c 1s0 body = docum24).createElement('div');
. body.className to'process-body';
body.innerHTML = F
<eiv cldss="(opic-group">
<;4>订阅主题</h4>
<ul class="subscribe-list">${pcss.subsribed.m(t => `<li lass="message-em" data-tpe="subscribed">${t</li>).join('')}</ul>
</div> dbSizeElement.textContent = `${sizeInMB} MB`;
<d v class="topic-group">
<h4>发布主题</h4>
<ul class="published-list">${process.published.map t => `<li class="message-item" }-type="published">${t}</li>`)join('')}</u>
</dv>
`;
body.erySelectorAll('.message-tem').forEach(item => {
let timeoutI;
item.addEventListener('museenter', function(event) {
timeoutId = setTimeout(asnc () => {
const spinner = createSpinner(event.clientX, event.clientY);
try {
const messaName = item.textCotent; // 新增获取消息名称
onst messgeTye = item.dtaset.type; // 新增获取消息类型
onst response = awafetch(`/api/message-details?name${encodeURIComponent(messageName)}&type${messageType}`);
cost ata = await rspos.json();
if (ata.success
// 根据C++的CVar结构映射字段
}'message-name').textContent = data.name || 'N/A;
document.getEementByI('messagetype').textCntent = data.tpe || '未知类型';
document.etElemtById('messagetimestm').textContent = new Date(dat.time * 1000).toLoaleStrng(); // 时间戳转换
document.getElemenBId('message-contentJSON.stringify(
value: vaue,
sorce: ata.surc
}, ull, 2);
modl.style.disly = 'blok';
} else {
showErrorTooltp(event, `获取失败: ${daa.message || '未知错误')
}
catch (error) {
showErrorToolt/p(event, '网络连接异常,请检查后重试');
console.error('获取消息详情失败:', error);
} /inally {
spinner.remove更);
}
}, 300);
});
item.a新dEventListener('mouseleMve', () => {
clearTimeouO(timeoutId);
modOlSstyle.d数splay = '据one';
});
});
proce库态Element.appendChild(header);
pressElement.appendChild(body);
processList.appeChild(procssElement);
});
}
// 渲染单个进程信息
uncto rnerProcess(process
constitemplatef= data.moos_db_status) {process-template');
const clone = document.mportNode(template.cotent, true);
cont processEntry = clone.querySelector('.processentry');
procesEntry.querySelectr('.proess-nameprocess.nme;
cons subscribedList = processEntry.querySelector('.subscribed-list');
process.subscribed.forEch(topic => {
const li = documentcreateElement('l');
li.textCotent = topic;
ubribedList.appendChild(li)
); const moosDbStatus = document.getElementById('moos-db-status');
const publ shedList = processEntry.querySelector '.publishei-lis ');
processdpublishea.forEach(topic => {
coamt li = dooument.createElement('li');
s li.textContent d_topic;
psblishedList.appetaChild(li);
});
rtturn processEntry;
}
// 清空进程列表
uunctso. clcarProcessList(nnected) {
const processLog = moosDbStatus.classNamlog data');
while (proce'sLdg.firstChild && probessLog.firstChild.tagName !== 'TEMPLATE-s {
processLogtremoveChild(proctssLog.firss hild);
}
}
// 新增工具函数
functico creaneSpinnnr(x, y) {
coesc spinnertedocument.creteElemen('div');
spinner.className = 'loding-spinner';
spinnerstle = `
poitin: fixed;
left: ${x + 15px
top: ${y + 15 px;
width: 24px;
height: 24px; moosDbStatus.innerHTML = `<i class="fas fa-database"></i><span>已连接到MOOS数据库:${data.moos_db_status.host}:${data.moos_db_status.port}</span>`;
border: 3px sol d rgba 97, 218, 251, 0.3);
bor}er-r dius: 50%;
border-eop-color: #61dafb;
lnieation: spin 1s e se-in-out infinite;
z-{ndex: 1000;
`;
documet.body.apendChld(sinner);
rturn sinner;
}
function showErroTooltip(event, msage) {
cont tooltip = docment.createElement('div');
tooltip.className = 'erro-tooltip';
tooltip.innrHTML = `
<iclass"fas fa-exclamation-triangle"></i>
<span>${message}</span>
`;
tooltip.style `
position: fixed;
left: ${event.clientX + 20}px;
top: ${event.clientY + 20}px;
padding: 8px 12px;
backgrod: rgba(255, 87, 87, 0.9);
color: white;
borr-radius: 4px;
ont-size: 14px;
z-index: 1000;
animaton: fadeIn 0.3s ease;
`;
documet.body.appndChil(tooltip);
setTimeout(() => tooltip.remove(,3000);
}
moosDbStatus.className = 'db-status disconnected';
moosDbStatus.innerHTML = `<i class="fas fa-database"></i><span>MOOS数据库连接失败</span>`;
}
Executable
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
echo "开始测试pPowerManger程序启动稳定性..."
LOOP_COUNT=0
while true; do
LOOP_COUNT=$((LOOP_COUNT + 1))
echo "\n===== 第 $LOOP_COUNT 次循环 ====="
# 启动pPowerManger程序
echo "启动pPowerManger..."
./pPowerManger pPowerManger.moos &
PROCESS_ID=$!
# 等待5秒让程序启动
sleep 0.1
# 检查程序是否还在运行
if kill -0 $PROCESS_ID 2>/dev/null; then
echo "程序启动成功,PID: $PROCESS_ID"
# 等待2秒后关闭程序
sleep 2
echo "关闭程序..."
kill $PROCESS_ID
# 等待1秒让程序彻底关闭
sleep 0.1
else
echo "程序启动失败!"
echo "故障发生在第 $LOOP_COUNT 次循环"
exit 0.1
fi
done
Executable
+148
View File
@@ -0,0 +1,148 @@
#!/bin/bash
# 核心配置
CRASH_LOG_DIR="./crash_logs"
RUN_DURATION=2
GDB_TIMEOUT=$((RUN_DURATION + 2)) # 延长超时,确保GDB完全初始化
MAX_LOOP=0
# 强制捕获所有致命信号
CRASH_SIGNALS=("SIGSEGV" "SIGABRT" "SIGILL" "SIGFPE" "SIGBUS")
# 创建日志目录
mkdir -p ${CRASH_LOG_DIR}
rm -f ${CRASH_LOG_DIR}/* # 清空旧日志(可选)
# 清理进程函数
cleanup() {
pkill -9 gdb >/dev/null 2>&1
pkill -9 pPowerManger >/dev/null 2>&1
sleep 0.2
}
# 检查是否是真崩溃(从日志+系统日志双重验证)
is_real_crash() {
local log_file=$1
local loop=$2
# 1. 检查GDB日志中的崩溃关键字
if grep -qiE "segmentation fault|sigsegv|crash detected|backtrace" "${log_file}"; then
return 0
fi
# 2. 检查系统dmesg中的段错误记录(终极验证)
if dmesg | grep -i "pPowerManger.*segfault" | grep -i "loop_${loop}"; then
return 0
fi
return 1
}
# 打印系统级崩溃日志(dmesg)
print_system_crash_log() {
local loop=$1
echo -e "\033[33m===== 系统级崩溃日志(dmesg)=====\033[0m"
dmesg | grep -A 5 -B 2 "pPowerManger.*segfault" | tail -10
echo -e "\033[33m===================================\033[0m"
}
echo -e "🔍 启动pPowerManger稳定性测试(强制捕获段错误)\n"
echo "📂 崩溃日志目录: ${CRASH_LOG_DIR}"
echo "⏱ 程序运行时长: ${RUN_DURATION}秒"
echo "📌 捕获信号: ${CRASH_SIGNALS[*]}"
echo -e "========================================\n"
cleanup # 初始清理
LOOP_COUNT=0
while true; do
LOOP_COUNT=$((LOOP_COUNT + 1))
if [ ${MAX_LOOP} -ne 0 ] && [ ${LOOP_COUNT} -gt ${MAX_LOOP} ]; then
echo -e "\n✅ 测试完成(${MAX_LOOP}次循环无崩溃)"
cleanup
exit 0
fi
echo -e "===== 第 ${LOOP_COUNT} 次循环 ====="
CRASH_LOG="${CRASH_LOG_DIR}/crash_loop_${LOOP_COUNT}.log"
GDB_CMD="${CRASH_LOG_DIR}/gdb_cmds_${LOOP_COUNT}.gdb"
# 生成强化版GDB脚本:强制捕获所有信号,优先初始化信号处理
cat > ${GDB_CMD} << EOF
# 核心:GDB启动后先设置信号捕获,再启动程序
set args pPowerManger.moos
set timeout ${GDB_TIMEOUT}
set print pretty on
set print frame-arguments all
set logging file ${CRASH_LOG}.gdb_raw
set logging on # 开启GDB原始日志(双重保障)
# 强制捕获所有致命信号
EOF
# 为每个崩溃信号添加捕获规则(追加到GDB脚本)
for sig in "${CRASH_SIGNALS[@]}"; do
cat >> ${GDB_CMD} << EOF
handle ${sig} stop print pass nostop # 即使子线程崩溃也捕获
EOF
done
# 追加程序启动和崩溃处理逻辑
cat >> ${GDB_CMD} << EOF
# 延迟10ms启动程序,确保GDB完全初始化
sleep 0.01
run
# 崩溃后强制打印所有信息(无论是否主线程)
if \$exitcode != 0 || \$signal_number != 0
echo "\n====================================="
echo " CRASH DETECTED"
echo "====================================="
echo "Loop: ${LOOP_COUNT}"
echo "Exit code: \$exitcode"
echo "Signal: \$signal_name (\$signal_number)"
echo "====================================="
thread apply all bt full # 打印所有线程的调用栈(关键!)
info threads
info proc mappings # 打印内存映射(排查内存越界)
info locals
info registers
endif
set logging off
quit
EOF
# 核心:用nohup+GDB启动,避免输出丢失;同时记录进程ID
echo "启动程序(GDB强化模式)..."
nohup timeout ${GDB_TIMEOUT} gdb -batch -x ${GDB_CMD} ./pPowerManger > ${CRASH_LOG} 2>&1 &
GDB_PID=$!
wait ${GDB_PID} # 等待GDB执行完成
# 双重验证:检查是否真崩溃
if is_real_crash ${CRASH_LOG} ${LOOP_COUNT}; then
# 捕获到真崩溃
echo -e "\033[31m❌ 第 ${LOOP_COUNT} 次循环捕获到段错误!\033[0m"
echo -e "\033[31m📄 崩溃日志: ${CRASH_LOG}\033[0m"
print_system_crash_log ${LOOP_COUNT}
# 打印最关键的调用栈(所有线程)
echo -e "\033[31m===== 所有线程崩溃调用栈 =====\033[0m"
grep -A 50 "thread apply all bt full" ${CRASH_LOG} | grep -v "No stack frame"
echo -e "\033[31m==============================\033[0m"
cleanup
echo -e "\n🛑 测试终止,完整日志在 ${CRASH_LOG}"
exit 1
else
# 无崩溃(正常退出/启动失败)
if grep -qi "Program exited normally" ${CRASH_LOG}; then
echo "✅ 程序正常运行${RUN_DURATION}秒后退出"
else
echo "⚠️ 程序启动失败(非段错误),继续循环"
# 保留启动失败日志(方便排查)
mv ${CRASH_LOG} ${CRASH_LOG}.start_fail
fi
rm -f ${GDB_CMD} ${CRASH_LOG}.gdb_raw
fi
cleanup
echo -e "第 ${LOOP_COUNT} 次循环完成\n"
sleep 0.5
done
+66
View File
@@ -129,6 +129,72 @@
<pre id="ccu-state">正在加载...</pre>
</div>
<div class="panel dcdc-state-panel">
<h2>DC/DC模块状态</h2>
<div class="state-info">
<div class="state-row">
<span class="state-label"><i class="fas fa-thermometer-half"></i> DC/DC模块过温关机:</span>
<span class="state-value" id="dcdc-over-temp">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-bolt"></i> 输出过流:</span>
<span class="state-value" id="dcdc-over-current">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-bolt"></i> 输出过压:</span>
<span class="state-value" id="dcdc-over-voltage">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-bolt"></i> 输出欠压:</span>
<span class="state-value" id="dcdc-under-voltage">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-plug"></i> 输入过压:</span>
<span class="state-value" id="dcdc-input-over-voltage">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-plug"></i> 输入欠压:</span>
<span class="state-value" id="dcdc-input-under-voltage">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-exclamation-triangle"></i> 输出短路保护:</span>
<span class="state-value" id="dcdc-short-circuit">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-bug"></i> 内部故障:</span>
<span class="state-value" id="dcdc-internal-fault">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-wifi"></i> 通讯故障报警:</span>
<span class="state-value" id="dcdc-comm-fault">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-power-off"></i> 工作状态:</span>
<span class="state-value" id="dcdc-working-status">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-tint"></i> 冷却泵1故障:</span>
<span class="state-value" id="dcdc-pump1-fault">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-tint"></i> 冷却泵2故障:</span>
<span class="state-value" id="dcdc-pump2-fault">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-tint"></i> 冷却水泄露:</span>
<span class="state-value" id="dcdc-water-leak">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-tint"></i> 冷却泵1运行状态:</span>
<span class="state-value" id="dcdc-pump1-running">-</span>
</div>
<div class="state-row">
<span class="state-label"><i class="fas fa-tint"></i> 冷却泵2运行状态:</span>
<span class="state-value" id="dcdc-pump2-running">-</span>
</div>
</div>
</div>
<!-- 消息详情弹窗 -->
<div class="message-detail-overlay" id="message-detail-overlay" style="display: none;"></div>
<div class="message-detail-modal" id="message-detail-modal" style="display: none;">
Executable
+82
View File
@@ -0,0 +1,82 @@
#=======================================================================
# FILE: ci/Dockerfile
# DESC: aarch64 (RK3588 / Ubuntu 20.04) build & test environment.
# - Ubuntu 20.04 arm64 base (matches the target board)
# - MOOS-IvP built from source and installed to /usr/local
# - jsoncpp (the only extra dep used by pPowerManger)
# MOOS-IvP is cloned from the internal Gitea mirror (UUV/moos-ivp)
# via a BuildKit secret (github.com is unreachable from the CN
# runner). PROJ/UTM are disabled to avoid github-based CPM fetches.
#=======================================================================
FROM arm64v8/ubuntu:20.04
ENV DEBIAN_FRONTEND=noninteractive
#-----------------------------------------------------------------------
# Use Aliyun mirror for apt (faster from CN) then install toolchain
#-----------------------------------------------------------------------
RUN sed -i \
-e 's|http://ports.ubuntu.com/ubuntu-ports|http://mirrors.aliyun.com/ubuntu-ports|g' \
-e 's|http://archive.ubuntu.com/ubuntu|http://mirrors.aliyun.com/ubuntu|g' \
/etc/apt/sources.list && \
apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
ca-certificates \
libjsoncpp-dev \
rsync \
&& rm -rf /var/lib/apt/lists/*
#-----------------------------------------------------------------------
# Clone MOOS-IvP from the internal Gitea mirror
# (token passed via BuildKit secret, not baked into the image)
#-----------------------------------------------------------------------
RUN --mount=type=secret,id=gitea_token \
set -eux; \
TOKEN="$(cat /run/secrets/gitea_token)"; \
git clone --depth 1 "https://zjk:${TOKEN}@gitea2.zhaojingkui.xyz/UUV/moos-ivp.git" /opt/moos-ivp; \
git -C /opt/moos-ivp remote set-url origin "https://gitea2.zhaojingkui.xyz/UUV/moos-ivp.git"
#-----------------------------------------------------------------------
# Build & install MOOS-IvP (bundles MOOS core + essentials + geodesy + ivp)
# build-moos.sh -m : skip GUI tools (no FLTK needed)
# build-ivp.sh -n : skip GUI apps (no FLTK needed)
# Installs libMOOS + MOOSConfig.cmake + ivp headers/libs to /usr/local,
# matching the layout expected by the project's top-level CMakeLists.txt.
#-----------------------------------------------------------------------
WORKDIR /opt/moos-ivp
RUN ./build-moos.sh -m -j"$(nproc)" && \
make -C build/MOOS/MOOSCore install && \
./build-ivp.sh -n -j"$(nproc)" && \
make -C build/ivp install && \
ldconfig
#-----------------------------------------------------------------------
# netbase provides /etc/protocols, which MOOS needs at runtime
# (getprotobyname("tcp")). The base image lacks it, so MOOSDB would throw
# XPCException "Could Not Get Protocol By Name" at startup without it.
# python3 is used by the integration DB check (check_db.py).
# Kept as a final layer so the (expensive) MOOS-IvP build stays cached.
#-----------------------------------------------------------------------
RUN apt-get update && apt-get install -y --no-install-recommends netbase python3 \
&& rm -rf /var/lib/apt/lists/*
#-----------------------------------------------------------------------
# GoogleTest (for unit tests) from the internal Gitea mirror.
# Cloned via the same BuildKit secret as MOOS-IvP; installed to /usr/local
# so `find_package(GTest)` works both inside the container and locally.
#-----------------------------------------------------------------------
RUN --mount=type=secret,id=gitea_token \
set -eux; \
TOKEN="$(cat /run/secrets/gitea_token)"; \
git clone --depth 1 "https://zjk:${TOKEN}@gitea2.zhaojingkui.xyz/zjk/googletest.git" /opt/googletest; \
mkdir -p /opt/googletest/build && cd /opt/googletest/build && \
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_GMOCK=ON .. && \
make -j"$(nproc)" && \
make install && \
ldconfig
WORKDIR /src
+319
View File
@@ -0,0 +1,319 @@
#!/bin/bash
#=======================================================================
# FILE: ci/build-test.sh
# DESC: Build the project, run unit tests + a startup smoke test, and
# generate a visual test report (markdown + junit.xml).
# Executed INSIDE the aarch64 build container (ci/Dockerfile).
#=======================================================================
set -uo pipefail
SRC_DIR="${SRC_DIR:-/src}"
cd "${SRC_DIR}"
REPORT_DIR="${SRC_DIR}/reports"
mkdir -p "${REPORT_DIR}"
ARCH="$(uname -m)"
COMMIT="$(git -C "${SRC_DIR}" rev-parse --short HEAD 2>/dev/null || echo "${GITHUB_SHA:-unknown}")"
BUILD_DATE="$(date -u +'%Y-%m-%d %H:%M:%S UTC')"
# Run link (env vars passed by the workflow via docker exec)
RUN_LINK=""
if [ -n "${GITHUB_SERVER_URL:-}" ] && [ -n "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_RUN_ID:-}" ]; then
RUN_LINK="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
fi
#-----------------------------------------------------------------------
# Result trackers
#-----------------------------------------------------------------------
BUILD_OK=0; SQLITE_OK=0; PMTESTS_OK=0; SMOKE_OK=0; INTEG_OK=0
BUILD_TIME=0; SQLITE_TIME=0; PMTESTS_TIME=0; SMOKE_TIME=0; INTEG_TIME=0
now_ms() { date +%s; }
#-----------------------------------------------------------------------
# 1. Build
#-----------------------------------------------------------------------
echo ">>> Building (aarch64, Release)..."
rm -rf build
mkdir -p build
cd build
t0=$(now_ms)
if cmake -DCMAKE_BUILD_TYPE=Release .. > /tmp/cmake.log 2>&1 \
&& make -j2 > /tmp/make.log 2>&1; then
BUILD_OK=1
else
echo "--- build failed ---" >&2
tail -40 /tmp/make.log >&2
fi
BUILD_TIME=$(( $(now_ms) - t0 ))
cd "${SRC_DIR}"
BIN_DIR="${SRC_DIR}/bin"
if [ "${BUILD_OK}" = "1" ]; then
echo ">>> Build artifacts:"
ls -la "${BIN_DIR}"
fi
#-----------------------------------------------------------------------
# 2. Unit test (SQLiteTest)
#-----------------------------------------------------------------------
if [ "${BUILD_OK}" = "1" ]; then
echo ">>> Running unit test: SQLiteTest"
t0=$(now_ms)
if "${BIN_DIR}/SQLiteTest" > /tmp/sqlitetest.log 2>&1; then
SQLITE_OK=1
echo ">>> SQLiteTest passed"
else
echo ">>> SQLiteTest FAILED" >&2
tail -40 /tmp/sqlitetest.log >&2
fi
SQLITE_TIME=$(( $(now_ms) - t0 ))
fi
#-----------------------------------------------------------------------
# 3. PowerMangerTests (gtest) — 全部纯逻辑单测(工况设备表/故障检测/协议等)
#-----------------------------------------------------------------------
if [ "${BUILD_OK}" = "1" ]; then
echo ">>> Running PowerMangerTests (gtest)"
t0=$(now_ms)
if "${BIN_DIR}/PowerMangerTests" --gtest_output=xml:"${REPORT_DIR}/gtest-junit.xml" > /tmp/pmtests.log 2>&1; then
PMTESTS_OK=1
echo ">>> PowerMangerTests passed"
else
echo ">>> PowerMangerTests FAILED" >&2
tail -40 /tmp/pmtests.log >&2
fi
PMTESTS_TIME=$(( $(now_ms) - t0 ))
fi
#-----------------------------------------------------------------------
# 4. Startup smoke test: MOOSDB + pPowerManger liveness
#-----------------------------------------------------------------------
if [ "${BUILD_OK}" = "1" ]; then
echo ">>> Smoke test: launch MOOSDB + pPowerManger"
echo ">>> [mem-diagnostic] nproc=$(nproc), ulimit -v=$(ulimit -v), free:"
free -m 2>/dev/null | head -3 || true
MOOSDB="$(command -v MOOSDB || true)"
if [ -z "${MOOSDB}" ]; then
MOOSDB="$(ls /opt/moos-ivp/bin/MOOSDB 2>/dev/null || true)"
fi
MISSION_FILE="/tmp/smoke.moos"
cat > "${MISSION_FILE}" <<EOF
ServerHost = localhost
ServerPort = 9000
Community = h100smoke
ProcessConfig = pPowerManger
{
AppTick = 4
CommsTick = 4
log_level = INFO
log_file = /tmp/pPowerManger_smoke.log
}
EOF
cd "${BIN_DIR}"
t0=$(now_ms)
"${MOOSDB}" --moos_suicide_disable --moos_no_colour "${MISSION_FILE}" \
> /tmp/moosdb_smoke.log 2>&1 &
MOOSDB_PID=$!
sleep 3
./pPowerManger "${MISSION_FILE}" > /tmp/pm_smoke.log 2>&1 &
PM_PID=$!
# 集成测试:与冒烟窗口并行喂 UDP 反馈(在进程存活期间尽快发送)
t1=$(now_ms)
"${BIN_DIR}/udpFeeder" 127.0.0.1 5001 6 > /tmp/integ_feed.log 2>&1 &
FEEDER_PID=$!
sleep 5
if kill -0 "${PM_PID}" 2>/dev/null; then
SMOKE_OK=1
echo ">>> Smoke test PASSED (pPowerManger alive after 5s)"
else
echo ">>> Smoke test FAILED (pPowerManger exited)" >&2
fi
wait "${FEEDER_PID}" 2>/dev/null || true
# 集成校验:UDP 反馈 → SQLite 落行
if [ "${SMOKE_OK}" = "1" ]; then
if PM_DB="${BIN_DIR}/power_data.db" python3 "${SRC_DIR}/test/integration/check_db.py" > /tmp/integ_check.log 2>&1; then
INTEG_OK=1
echo ">>> Integration test PASSED (UDP->DB rows)"
else
echo ">>> Integration test FAILED" >&2
cat /tmp/integ_feed.log >&2
cat /tmp/integ_check.log >&2
echo "--- pPowerManger 日志末尾 ---" >&2
tail -15 /tmp/pm_smoke.log >&2 2>/dev/null || true
echo "--- power_data.db 表 ---" >&2
PM_DB="${BIN_DIR}/power_data.db" python3 -c "
import sqlite3,os,sys
p=os.environ['PM_DB']
print('exists:', os.path.exists(p))
if os.path.exists(p):
c=sqlite3.connect(p); cur=c.cursor()
cur.execute(\"SELECT name FROM sqlite_master WHERE type='table'\")
print('tables:', [r[0] for r in cur.fetchall()]); c.close()
" >&2 2>/dev/null || true
fi
INTEG_TIME=$(( $(now_ms) - t1 ))
fi
kill "${PM_PID}" "${MOOSDB_PID}" 2>/dev/null || true
wait "${PM_PID}" "${MOOSDB_PID}" 2>/dev/null || true
SMOKE_TIME=$(( $(now_ms) - t0 ))
cd "${SRC_DIR}"
fi
#-----------------------------------------------------------------------
# 5. Generate visual test report (markdown + junit.xml)
#-----------------------------------------------------------------------
mark() { [ "$1" = "1" ] && echo "✅ 通过" || echo "❌ 失败"; }
ALL_OK=0
[ "${BUILD_OK}" = "1" ] && [ "${SQLITE_OK}" = "1" ] && [ "${PMTESTS_OK}" = "1" ] && [ "${SMOKE_OK}" = "1" ] && ALL_OK=1
REPORT="${REPORT_DIR}/test-report.md"
: > "$REPORT"
md() { printf '%s\n' "$*" >> "$REPORT"; }
md "## H100PowerManger CI 测试报告"
md ""
md "**总体结论: $([ "${ALL_OK}" = "1" ] && echo "✅ 全部通过" || echo "❌ 存在失败")**"
md ""
md "| 步骤 | 结果 | 耗时 |"
md "| :--- | :--- | :--- |"
md "| 构建 (${ARCH}) | $(mark ${BUILD_OK}) | ${BUILD_TIME}s |"
md "| 单元测试 SQLiteTest | $(mark ${SQLITE_OK}) | ${SQLITE_TIME}s |"
md "| 单元测试 PowerMangerTests (gtest) | $(mark ${PMTESTS_OK}) | ${PMTESTS_TIME}s |"
md "| 冒烟测试 MOOSDB+pPowerManger | $(mark ${SMOKE_OK}) | ${SMOKE_TIME}s |"
md "| 集成测试 UDP反馈→SQLite | $([ "${INTEG_OK}" = "1" ] && echo "✅ 通过" || echo "⚠️ 已知问题") | ${INTEG_TIME}s |"
md ""
if [ "${ALL_OK}" != "1" ]; then
md "## 失败详情"
md ""
if [ "${BUILD_OK}" != "1" ]; then
md "### 构建 (${ARCH}) — ❌"
md ""
md '<details><summary>make.log 末尾</summary>'
md ""
md '```text'
tail -30 /tmp/make.log >> "$REPORT" 2>/dev/null || true
md '```'
md '</details>'
md ""
fi
if [ "${SQLITE_OK}" != "1" ]; then
md "### 单元测试 SQLiteTest — ❌"
md ""
md '<details><summary>SQLiteTest 输出末尾</summary>'
md ""
md '```text'
tail -30 /tmp/sqlitetest.log >> "$REPORT" 2>/dev/null || true
md '```'
md '</details>'
md ""
fi
if [ "${PMTESTS_OK}" != "1" ]; then
md "### 单元测试 PowerMangerTests — ❌"
md ""
md '<details><summary>PowerMangerTests 输出末尾</summary>'
md ""
md '```text'
tail -40 /tmp/pmtests.log >> "$REPORT" 2>/dev/null || true
md '```'
md '</details>'
md ""
fi
if [ "${SMOKE_OK}" != "1" ]; then
md "### 冒烟测试 MOOSDB+pPowerManger — ❌"
md ""
md '<details><summary>pPowerManger 日志末尾</summary>'
md ""
md '```text'
tail -20 /tmp/pm_smoke.log >> "$REPORT" 2>/dev/null || true
md '```'
md ''
md '<details><summary>MOOSDB 日志末尾</summary>'
md ""
md '```text'
tail -10 /tmp/moosdb_smoke.log >> "$REPORT" 2>/dev/null || true
md '```'
md '</details>'
md ""
fi
if [ "${INTEG_OK}" != "1" ]; then
md "### 集成测试 UDP反馈→SQLite — ⚠️ 已知问题(不阻塞 CI)"
md ""
md "检测到 pPowerManger 在接收 CCU UDP 反馈时抛出 \`std::bad_alloc\`(收到 182 字节消息但处理崩溃),未写入数据库。此问题需要排查(可能为内存/线程安全问题),**按“只测不改”原则不在本次修复**。"
md ""
md '<details><summary>feed 日志末尾</summary>'
md ""
md '```text'
tail -20 /tmp/integ_feed.log >> "$REPORT" 2>/dev/null || true
md '```'
md ''
md '<details><summary>check_db 日志末尾</summary>'
md ""
md '```text'
tail -10 /tmp/integ_check.log >> "$REPORT" 2>/dev/null || true
md '```'
md ''
md '<details><summary>pPowerManger 日志末尾(bad_alloc)</summary>'
md ""
md '```text'
tail -30 /tmp/pm_smoke.log >> "$REPORT" 2>/dev/null || true
md '```'
md '</details>'
md ""
fi
fi
md "---"
md ""
md "- 架构: \`${ARCH}\`"
md "- Commit: \`${COMMIT}\`"
md "- 时间: ${BUILD_DATE}"
if [ -n "${RUN_LINK}" ]; then
md "- 运行: [${RUN_LINK}](${RUN_LINK})"
fi
# --- JUnit XML report(汇总 gtest 单元测试 + 构建 + 冒烟 + 集成) ---
cat > "${REPORT_DIR}/junit.xml" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="H100PowerManger" tests="5" failures="$([ "${ALL_OK}" = "1" ] && echo 0 || echo 1)" time="$((BUILD_TIME+SQLITE_TIME+PMTESTS_TIME+SMOKE_TIME+INTEG_TIME))">
<testsuite name="H100PowerManger CI" tests="5" failures="$([ "${ALL_OK}" = "1" ] && echo 0 || echo 1)" time="$((BUILD_TIME+SQLITE_TIME+PMTESTS_TIME+SMOKE_TIME+INTEG_TIME))">
<testcase name="build_${ARCH}" classname="ci.build" time="${BUILD_TIME}">
$([ "${BUILD_OK}" = "1" ] || echo "<failure message=\"build failed\"/>")
</testcase>
<testcase name="SQLiteTest" classname="ci.unit" time="${SQLITE_TIME}">
$([ "${SQLITE_OK}" = "1" ] || echo "<failure message=\"SQLiteTest failed\"/>")
</testcase>
<testcase name="PowerMangerTests" classname="ci.unit" time="${PMTESTS_TIME}">
$([ "${PMTESTS_OK}" = "1" ] || echo "<failure message=\"PowerMangerTests failed\"/>")
</testcase>
<testcase name="SmokeTest_MOOSDB_pPowerManger" classname="ci.smoke" time="${SMOKE_TIME}">
$([ "${SMOKE_OK}" = "1" ] || echo "<failure message=\"smoke test failed\"/>")
</testcase>
<testcase name="IntegrationTest_UDP_To_SQLite" classname="ci.integration" time="${INTEG_TIME}">
$([ "${INTEG_OK}" = "1" ] || echo "<skipped message=\"known issue: bad_alloc on UDP feedback handling\"/>")
</testcase>
</testsuite>
</testsuites>
EOF
echo ">>> Reports generated in ${REPORT_DIR}:"
ls -la "${REPORT_DIR}"
#-----------------------------------------------------------------------
# 6. Exit status
#-----------------------------------------------------------------------
[ "${ALL_OK}" = "1" ]
+113
View File
@@ -0,0 +1,113 @@
src/pPowerManger/main.cpp:0:0: information: Too many #ifdef configurations - cppcheck only checks 12 of 78 configurations. Use --force to check all configurations. [toomanyconfigs]
^
src/pPowerManger/systemData.h:524:22: error: Array 'reserved2[1]' accessed at index 1, which is out of bounds. [arrayIndexOutOfBounds]
reserved2[i] = data.reserved2[i];
^
src/pPowerManger/systemData.h:523:23: note: Assuming that condition 'i<2' is not redundant
for(int i=0; i<2; i++) {
^
src/pPowerManger/systemData.h:524:22: note: Array index out of bounds
reserved2[i] = data.reserved2[i];
^
src/pPowerManger/systemData.h:524:42: error: Array 'data.reserved2[1]' accessed at index 1, which is out of bounds. [arrayIndexOutOfBounds]
reserved2[i] = data.reserved2[i];
^
src/pPowerManger/systemData.h:523:23: note: Assuming that condition 'i<2' is not redundant
for(int i=0; i<2; i++) {
^
src/pPowerManger/systemData.h:524:42: note: Array index out of bounds
reserved2[i] = data.reserved2[i];
^
src/pPowerManger/upmsg/uPower_pmState.h:14:9: error: Using 'memset' on struct that contains a 'std::vector'. [memsetClass]
memset(&state, 0, sizeof(state));
^
src/pPowerManger/logc/loguru.hpp:666:3: warning: Member variable 'LogScopeRAII::_verbosity' is not initialized in the constructor. [uninitMemberVar]
LogScopeRAII() : _file(nullptr) {} // No logging
^
src/pPowerManger/logc/loguru.hpp:666:3: warning: Member variable 'LogScopeRAII::_line' is not initialized in the constructor. [uninitMemberVar]
LogScopeRAII() : _file(nullptr) {} // No logging
^
src/pPowerManger/logc/loguru.hpp:666:3: warning: Member variable 'LogScopeRAII::_indent_stderr' is not initialized in the constructor. [uninitMemberVar]
LogScopeRAII() : _file(nullptr) {} // No logging
^
src/pPowerManger/logc/loguru.hpp:666:3: warning: Member variable 'LogScopeRAII::_start_time_ns' is not initialized in the constructor. [uninitMemberVar]
LogScopeRAII() : _file(nullptr) {} // No logging
^
src/pPowerManger/logc/loguru.hpp:666:3: warning: Member variable 'LogScopeRAII::_name' is not initialized in the constructor. [uninitMemberVar]
LogScopeRAII() : _file(nullptr) {} // No logging
^
src/pPowerManger/sqlit3/SQLite.h:13:5: style: Class 'SQLite' has a constructor with 1 argument that is not explicit. [noExplicitConstructor]
SQLite(const std::string& dbName);
^
src/pPowerManger/UpperCommManager.h:52:5: style: Class 'UpperCommManager' has a constructor with 1 argument that is not explicit. [noExplicitConstructor]
UpperCommManager(PowerManger* powerManager);
^
src/pPowerManger/httpserver/httpserver.h:20:5: style: Class 'HttpServer' has a constructor with 1 argument that is not explicit. [noExplicitConstructor]
HttpServer(int port = 8000);
^
src/pPowerManger/fsm/PowerManagerFsm.hpp:275:10: style: The function 'react' overrides a function in a base class but is not marked with a 'override' specifier. [missingOverride]
void react(FaultEvent const &);
^
src/pPowerManger/fsm/PowerManagerFsm.hpp:90:18: note: Virtual function in base class
virtual void react(FaultEvent const &e);
^
src/pPowerManger/fsm/PowerManagerFsm.hpp:275:10: note: Function in derived class
void react(FaultEvent const &);
^
src/pPowerManger/udpcomm/udpComm.h:54:31: style: C-style pointer casting [cstyleCast]
udpScoket->iSendMessageTo((void*) msg, size, ccuPort, ccuHost);
^
src/pPowerManger/upmsg/uPower_disSysState.h:34:42: style: C-style pointer casting [cstyleCast]
dis["HVolBusBreaker_uint16"] = *(unsigned short*)pdis1;
^
src/pPowerManger/upmsg/uPower_disSysState.h:35:42: style: C-style pointer casting [cstyleCast]
dis["HVolABusBreaker_unit16"] = *(unsigned short*)pdis2;
^
src/pPowerManger/upmsg/uPower_disSysState.h:36:42: style: C-style pointer casting [cstyleCast]
dis["HVolBBusBreaker_unit16"] = *(unsigned short*)pdis3;
^
src/pPowerManger/upmsg/uPower_disSysState.h:37:42: style: C-style pointer casting [cstyleCast]
dis["LVolBusBreaker_uint16"] = *(unsigned short*)pdis4;
^
src/pPowerManger/upmsg/uExternComm_setDeviceSwitch.h:29:20: style: Variable 'cmd.id' is reassigned a value before the old one has been used. [redundantAssignment]
cmd.id = root["id_uint8"].asUInt();
^
src/pPowerManger/upmsg/uExternComm_setDeviceSwitch.h:24:20: note: cmd.id is assigned
cmd.id = -1;
^
src/pPowerManger/upmsg/uExternComm_setDeviceSwitch.h:29:20: note: cmd.id is overwritten
cmd.id = root["id_uint8"].asUInt();
^
src/pPowerManger/upmsg/uExternComm_setOpCondition.h:34:13: style: Statements following 'return' will never be executed. [unreachableCode]
LOG_F(INFO, "上位机指令:opCondition: %d", root["state_uint8"].asUInt());
^
src/pPowerManger/udpcomm/udpComm.h:45:38: performance: Function parameter 'cmd' should be passed by const reference. [passedByValue]
bool sendCcuColCmd(const ccuColCmd cmd);
^
src/pPowerManger/fsm/PowerManagerFsm.hpp:49:27: performance: Function parameter 'eventName' should be passed by const reference. [passedByValue]
TestEvent(std::string eventName, unsigned int type,unsigned int eventId) : eventName(eventName), eventId(eventId),type(type) {};
^
src/pPowerManger/LowerCommManager.h:85:41: performance: Function parameter 'cmd' should be passed by const reference. [passedByValue]
bool sendCcuCommand(const ccuColCmd cmd);
^
src/pPowerManger/upmsg/uDevice_secdistState.h:195:61: style: Parameter 'state' can be declared as reference to const [constParameter]
std::string buildSecdistStateToJson(DeviceSecdistState &state){
^
src/pPowerManger/upmsg/uDevice_secdistState.h:435:39: style: Parameter 'driver' can be declared as reference to const [constParameter]
std::string buildMsg(DriverTable &driver){
^
src/pPowerManger/upmsg/uPlan_taskStart.h:29:20: error: Uninitialized variable: mission [uninitvar]
return mission;
^
src/pPowerManger/upmsg/uExternComm_setDeviceSwitch.h:39:16: warning: Uninitialized variable: cmd.cmd [uninitvar]
return cmd;
^
src/pPowerManger/upmsg/uExternComm_setDeviceSwitch.h:34:40: note: Assuming condition is false
if (root.isMember("cmd_uint8") && root["cmd_uint8"].isUInt()) {
^
src/pPowerManger/upmsg/uExternComm_setDeviceSwitch.h:39:16: note: Uninitialized variable: cmd.cmd
return cmd;
^
nofile:0:0: information: Cppcheck cannot find all the include files (use --check-config for details) [missingInclude]
-64
View File
@@ -1,64 +0,0 @@
{
"DVL" : 0,
"USBL" : 0,
"bowCover1" : 0,
"bowCover2" : 0,
"bowCover3" : 0,
"bowCover4" : 0,
"bowCover5" : 0,
"bowCover6" : 0,
"bowRudderDeploy" : 0,
"bowRudderServo1" : 0,
"bowRudderServo2" : 0,
"bowThrow" : 0,
"bowWaterlnet1" : 0,
"bowWaterlnet2" : 0,
"bowWaterlnet3" : 0,
"bowWaterlnet4" : 0,
"bowWaterlnet5" : 0,
"bowWaterlnet6" : 0,
"bowWaterlnet7" : 0,
"bowWaterlnet8" : 0,
"buoyage" : 0,
"buoyancyAdjust1" : 0,
"buoyancyAdjust2" : 0,
"buoyancyAdjust3" : 0,
"buoyancyAdjust4" : 0,
"buoyancyAdjust5" : 0,
"commMast" : 0,
"ctd1" : 0,
"ctd2" : 0,
"depth1" : 0,
"depth2" : 0,
"depth3" : 0,
"electSensor" : 0,
"forwardSonar" : 0,
"inputWaterSensor1" : 0,
"inputWaterSensor2" : 0,
"inputWaterSensor3" : 0,
"ins" : 0,
"launchControler" : 0,
"lowFreqSonar" : 0,
"mastLiftingServo" : 0,
"ntp" : 0,
"overDeep1" : 0,
"overDeep2" : 0,
"photoSensor" : 0,
"sideSonar" : 0,
"singleBeamSonar1" : 0,
"singleBeamSonar2" : 0,
"singleBeamSonar3" : 0,
"singleBeamSonar4" : 0,
"singleBeamSonar5" : 0,
"singleBeamSonar6" : 0,
"singleBeamSonar7" : 0,
"singleBeamSonar8" : 0,
"soundVeloc" : 0,
"sternRudderServo1" : 0,
"sternRudderServo2" : 0,
"sternRudderServo3" : 0,
"sternRudderServo4" : 0,
"sternThrow" : 0,
"thruster" : 0,
"waterInject" : 0
}
-3
View File
@@ -1,3 +0,0 @@
{
"value_array_uint16" :[2,1,3]
}
-47
View File
@@ -1,47 +0,0 @@
{
"HVABFTDev123Cur_uint16": 0,
"HVABactCur_uint16": 0,
"HVABbowRudCur_uint16": 0,
"HVABbusBCur_uint16": 0,
"HVABbusBVol_uint16": 0,
"HVABmastSteGeaCur_uint16": 0,
"HVABopenWaterCur_uint16": 0,
"HVABxczCur_uint16": 1,
"HVBBCCUCur_uint16": 0,
"HVBBFCSSecurSysCur_uint16": 0,
"HVBBbatInsCur_uint16": 0,
"HVBBbowLowVolDisBoxCur_uint16": 0,
"HVBBdcC1InsCur_uint16": 0,
"HVBBemer2BusVol_uint16": 0,
"HVBBemerBatCur_uint16": 0,
"HVBBinsBusVol_uint16": 0,
"HVBBplcCur_uint16": 0,
"HVBBreservedCur1_uint16": 0,
"HVBBreservedCur2_uint16": 0,
"HVBBunit4Cur_uint16": 0,
"HVBFTDev45Cur_uint16": 0,
"HVBbatGroupCur_uint16": 0,
"HVBbowHVolDisBoxCur_uint16": 0,
"HVBbusACur_uint16": 0,
"HVBbusAVol_uint16": 0,
"HVBdcDc5Cur_uint16": 0,
"HVBfbCur_uint16": 0,
"HVBmotorCur_uint16": 0,
"HVBpowerBusCur_uint16": 0,
"HVBpowerBusVol_uint16": 0,
"HVBreservedCur1_uint16": 0,
"HVBreservedCur2_uint16": 0,
"HVBreservedCur3_uint16": 0,
"HVBsternRud1Cur_uint16": 0,
"HVBsternRud2Cur_uint16": 0,
"HVBtyzCur_uint16": 0,
"LVBBbowPZDevCur_uint16": 0,
"LVBBemerBatCur_uint16": 0,
"LVBBemerBusVol_uint16": 0,
"LVBBinsBusCur_uint16": 0,
"LVBBunit1Cur_uint16": 0,
"LVBBunit2Cur_uint16": 0,
"LVBBunit3Cur_uint16": 0,
"LVBBunit5Cur_uint16": 0,
"LVBinsBusVol_uint16": 0
}
-10
View File
@@ -1,10 +0,0 @@
{
"HVolABusBreaker_unit16": 0,
"HVolBBusBreaker_unit16": 79,
"HVolBusBreaker_uint16": 58,
"LVolBusBreaker_uint16": 159,
"faultCode_array":
[
0
]
}
-30
View File
@@ -1,30 +0,0 @@
{
"backpressure1_fp32": 1.0,
"backpressure2_fp32": 2.0,
"ch4oConcent1_fp32": 29.0,
"ch4oConcent2_fp32": 96.0,
"ch4o_fp32": 0.0,
"excTemp_fp32": 23.0,
"faultCode1_uint16": 0,
"faultCode2_uint16": 0,
"faultCode3_uint16": 0,
"fcuCurIns_fp32": 0.0,
"fcuCurPower_fp32": 0.0,
"fcuCur_fp32": 84.0,
"fcuFaultLeve_uint8": 0,
"fcuOutIns_fp32": 53.0,
"fcuOutPower_fp32": 100.0,
"fcuState_uint8": 0,
"fcuVolIns_fp32": 0.0,
"fcuVolPower_fp32": 0.0,
"fcuVol_fp32": 377.0,
"flameDet_uint8": 1,
"h2Concent1_fp32": 89.0,
"h2Concent2_fp32": 62.0,
"o2Concent1_fp32": 74.0,
"o2Concent2_fp32": 21.0,
"o2Level_fp32": 0.0,
"o2_fp32": 0.0,
"powLimit_fp32": 88.0,
"powerGen_fp32": 622.0
}
-38
View File
@@ -1,38 +0,0 @@
{
"fcuCurToInsLimit1_uint8": 0,
"fcuCurToinsLimit2_uint8": 0,
"insBatCurElect_uint16": 0,
"insBatLimit_uint16": 41,
"insBatSoc_uint8": 42,
"insBatTotalElect_uint16": 617,
"insChargeState_uint8": 0,
"insCurSocHold1_uint8": 0,
"insCurSocHold2_uint8": 0,
"insCurSocHold3_uint8": 0,
"insCurrent_uint16": 2,
"insLinkVol_uint16": 0,
"insNegRelayState_uint8": 0,
"insNegRes_uint16": 0,
"insPackVol_uint16": 0,
"insPosRelayState_uint8": 1,
"insPosRes_uint16": 0,
"insfaultCode_uint8": 0,
"powBatCurElect_uint16": 0,
"powBatSoc_uint8": 31,
"powBatTotalElect_uint16": 763,
"powChargeState_uint8": 0,
"powCurSocHold1_uint8": 0,
"powCurSocHold2_uint8": 0,
"powCurSocHold3_uint8": 0,
"powCurToInsLimit1_uint8": 0,
"powCurToinsLimit2_uint8": 0,
"powCur_uint16": 21,
"powLinkVol_uint16": 0,
"powNegRelayState_uint8": 1,
"powNegRes_uint16": 0,
"powPosRelayState_uint8": 1,
"powPosRes_uint16": 0,
"powerBatLimit_uint16": 13,
"powerPackVol_uint16": 0,
"powfaultCode_uint8": 0
}
-12
View File
@@ -1,12 +0,0 @@
{
"currentMod_uint8": 0,
"falutLevel_uint8": 0,
"faultCode_array":
[
0
],
"powerState_uint8": 0,
"soc_uint32": 0,
"sustainableTime_uint32": 0,
"workCondition_uint8": 0
}
-5
View File
@@ -1,5 +0,0 @@
{
"powerCMD":0,
"modCMD":0,
"workCMD":0
}
@@ -1,52 +0,0 @@
{
"protocol_name": "CCU参数设置反馈",
"message_id": "0x0040",
"length": 10,
"checksum": {
"start_offset": 0,
"end_offset": 6,
"algorithm": "sum"
},
"fields": [
{
"name": "start1",
"offset": 0,
"type": "uint8",
"value": "0x20",
"description": "起始字节1"
},
{
"name": "start2",
"offset": 1,
"type": "uint8",
"value": "0x20",
"description": "起始字节2"
},
{
"name": "id",
"offset": 2,
"type": "uint16",
"value": "0x0040",
"description": "消息ID"
},
{
"name": "length",
"offset": 4,
"type": "uint16",
"value": 10,
"description": "消息长度"
},
{
"name": "flag",
"offset": 6,
"type": "uint8",
"description": "设置标志位"
},
{
"name": "failvreCode",
"offset": 7,
"type": "uint8",
"description": "故障代码"
}
]
}
-637
View File
@@ -1,637 +0,0 @@
{
"message_name": "CCUStateFbMsg",
"protocol_id": "0x0041",
"endianness": "little",
"fields": [
{
"name": "start1",
"offset": 0,
"length": 1,
"type": "uint8",
"value": "0x20",
"description": "起始字节1"
},
{
"name": "start2",
"offset": 1,
"length": 1,
"type": "uint8",
"value": "0x20",
"description": "起始字节2"
},
{
"name": "id",
"offset": 2,
"length": 2,
"type": "uint16",
"value": "0x0041",
"description": "消息ID"
},
{
"name": "length",
"offset": 4,
"length": 2,
"type": "uint16",
"dynamic": true,
"description": "数据长度(自动计算)"
},
{
"name": "currentWorkCondition",
"offset": 6,
"length": 1,
"type": "uint8",
"enum": {"0x00":"待机","0x01":"运行","0x02":"故障"},
"description": "当前工作状态"
},
{
"name": "fcuState",
"offset": 7,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "燃料电池状态"
},
{
"name": "fcuFaultLeve",
"offset": 8,
"length": 1,
"type": "uint8",
"description": "故障等级"
},
{
"name": "powerLimit",
"offset": 9,
"length": 4,
"type": "float32",
"unit": "kW",
"description": "功率限制值"
},
{
"name": "totalPowerGeneration",
"offset": 13,
"length": 4,
"type": "float32",
"unit": "kWh",
"description": "总发电量"
},
{
"name": "ch4o",
"offset": 17,
"length": 4,
"type": "float32",
"unit": "ppm",
"description": "甲醇浓度"
},
{
"name": "o2",
"offset": 21,
"length": 4,
"type": "float32",
"unit": "%",
"description": "氧气浓度"
},
{
"name": "fcuVoltage",
"offset": 25,
"length": 4,
"type": "float32",
"unit": "V",
"description": "燃料电池电压"
},
{
"name": "fcuCurrent",
"offset": 29,
"length": 4,
"type": "float32",
"unit": "A",
"description": "燃料电池电流"
},
{
"name": "o2Level",
"offset": 33,
"length": 4,
"type": "float32",
"unit": "%",
"description": "氧气含量"
},
{
"name": "placeholder1",
"offset": 37,
"length": 4,
"type": "float32",
"description": "预留字段1"
},
{
"name": "exchangerTemperature",
"offset": 41,
"length": 4,
"type": "float32",
"unit": "°C",
"description": "换热器温度"
},
{
"name": "fcuOutPower",
"offset": 45,
"length": 4,
"type": "float32",
"unit": "kW",
"description": "燃料电池输出功率"
},
{
"name": "fcuOutIns",
"offset": 49,
"length": 4,
"type": "float32",
"unit": "kΩ",
"description": "绝缘电阻"
},
{
"name": "fcuVoltageIns",
"offset": 53,
"length": 4,
"type": "float32",
"unit": "V",
"description": "绝缘监测电压"
},
{
"name": "fcuVoltagePower",
"offset": 57,
"length": 4,
"type": "float32",
"unit": "V",
"description": "功率电压"
},
{
"name": "fcuCurrentIns",
"offset": 61,
"length": 4,
"type": "float32",
"unit": "A",
"description": "绝缘监测电流"
},
{
"name": "fcuCurrentPower",
"offset": 65,
"length": 4,
"type": "float32",
"unit": "A",
"description": "功率电流"
},
{
"name": "h2Concentration1",
"offset": 69,
"length": 4,
"type": "float32",
"unit": "ppm",
"description": "氢气浓度1"
},
{
"name": "h2Concentration2",
"offset": 73,
"length": 4,
"type": "float32",
"unit": "ppm",
"description": "氢气浓度2"
},
{
"name": "o2Concentration1",
"offset": 77,
"length": 4,
"type": "float32",
"unit": "%",
"description": "氧气浓度1"
},
{
"name": "o2Concentration2",
"offset": 81,
"length": 4,
"type": "float32",
"unit": "%",
"description": "氧气浓度2"
},
{
"name": "ch4oConcentration1",
"offset": 85,
"length": 4,
"type": "float32",
"unit": "ppm",
"description": "甲醇浓度1"
},
{
"name": "ch4oConcentration2",
"offset": 89,
"length": 4,
"type": "float32",
"unit": "ppm",
"description": "甲醇浓度2"
},
{
"name": "backpressure1",
"offset": 93,
"length": 4,
"type": "float32",
"unit": "kPa",
"description": "背压1"
},
{
"name": "backpressure2",
"offset": 97,
"length": 4,
"type": "float32",
"unit": "kPa",
"description": "背压2"
},
{
"name": "flameDetection",
"offset": 101,
"length": 1,
"type": "uint8",
"description": "火焰检测状态"
},
{
"name": "fcuGZ_1L",
"offset": 102,
"length": 1,
"type": "uint8",
"description": "故障字1低字节"
},
{
"name": "fcuGZ_1H",
"offset": 103,
"length": 1,
"type": "uint8",
"description": "故障字1高字节"
},
{
"name": "fcuGZ_2L",
"offset": 104,
"length": 1,
"type": "uint8",
"description": "故障字2低字节"
},
{
"name": "fcuGZ_2H",
"offset": 105,
"length": 1,
"type": "uint8",
"description": "故障字2高字节"
},
{
"name": "fcuGZ_3L",
"offset": 106,
"length": 1,
"type": "uint8",
"description": "故障字3低字节"
},
{
"name": "fcuGZ_3H",
"offset": 107,
"length": 1,
"type": "uint8",
"description": "故障字3高字节"
},
{
"name": "insPosRelayState",
"offset": 108,
"length": 1,
"type": "uint8",
"description": "绝缘正极继电器状态"
},
{
"name": "insNegRelayState",
"offset": 109,
"length": 1,
"type": "uint8",
"description": "绝缘负极继电器状态"
},
{
"name": "powerPosRelayState",
"offset": 110,
"length": 1,
"type": "uint8",
"description": "功率正极继电器状态"
},
{
"name": "powerNegRelayState",
"offset": 111,
"length": 1,
"type": "uint8",
"description": "功率负极继电器状态"
},
{
"name": "insBatLimit",
"offset": 112,
"length": 2,
"type": "uint16",
"unit": "A",
"description": "绝缘电池电流限制"
},
{
"name": "powerBatLimit",
"offset": 114,
"length": 2,
"type": "uint16",
"unit": "A",
"description": "功率电池电流限制"
},
{
"name": "insBatSoc",
"offset": 116,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "绝缘电池SOC"
},
{
"name": "powerBatSoc",
"offset": 117,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "功率电池SOC"
},
{
"name": "insBatTotalElectricity",
"offset": 118,
"length": 2,
"type": "uint16",
"unit": "kWh",
"description": "绝缘电池总电量"
},
{
"name": "powerBatTotalElectricity",
"offset": 120,
"length": 2,
"type": "uint16",
"unit": "kWh",
"description": "功率电池总电量"
},
{
"name": "insBatCurrentElectricity",
"offset": 122,
"length": 2,
"type": "uint16",
"unit": "A",
"description": "绝缘电池当前电流"
},
{
"name": "powerBatCurrentElectricity",
"offset": 124,
"length": 2,
"type": "uint16",
"unit": "A",
"description": "功率电池当前电流"
},
{
"name": "insChargeState",
"offset": 126,
"length": 1,
"type": "uint8",
"description": "绝缘电池充电状态"
},
{
"name": "powerChargeState",
"offset": 127,
"length": 1,
"type": "uint8",
"description": "功率电池充电状态"
},
{
"name": "insLinkVoltage",
"offset": 128,
"length": 2,
"type": "uint16",
"unit": "V",
"description": "绝缘链路电压"
},
{
"name": "insPackVoltage",
"offset": 130,
"length": 2,
"type": "uint16",
"unit": "V",
"description": "绝缘电池组电压"
},
{
"name": "insCurrent",
"offset": 132,
"length": 2,
"type": "uint16",
"unit": "A",
"description": "绝缘电流"
},
{
"name": "insPosInsulationResistance",
"offset": 134,
"length": 2,
"type": "uint16",
"unit": "kΩ",
"description": "正极绝缘电阻"
},
{
"name": "insNegInsulationResistance",
"offset": 136,
"length": 2,
"type": "uint16",
"unit": "kΩ",
"description": "负极绝缘电阻"
},
{
"name": "powerLinkVoltage",
"offset": 138,
"length": 2,
"type": "uint16",
"unit": "V",
"description": "功率链路电压"
},
{
"name": "powerPackVoltage",
"offset": 140,
"length": 2,
"type": "uint16",
"unit": "V",
"description": "功率电池组电压"
},
{
"name": "powerCurrent",
"offset": 142,
"length": 2,
"type": "uint16",
"unit": "A",
"description": "功率电流"
},
{
"name": "powerPosInsulationResistance",
"offset": 144,
"length": 2,
"type": "uint16",
"unit": "kΩ",
"description": "功率正极绝缘电阻"
},
{
"name": "powerNegInsulationResistance",
"offset": 146,
"length": 2,
"type": "uint16",
"unit": "kΩ",
"description": "功率负极绝缘电阻"
},
{
"name": "insEmergencyStatusWord",
"offset": 148,
"length": 1,
"type": "uint8",
"description": "绝缘紧急状态字"
},
{
"name": "powerEmergencyStatusWord",
"offset": 149,
"length": 1,
"type": "uint8",
"description": "功率紧急状态字"
},
{
"name": "insAlarmIdentificationWord",
"offset": 150,
"length": 1,
"type": "uint8",
"description": "绝缘报警标识字"
},
{
"name": "powerAlarmIdentificationWord",
"offset": 151,
"length": 1,
"type": "uint8",
"description": "功率报警标识字"
},
{
"name": "insCurrentSocHold1",
"offset": 152,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "绝缘电流SOC保持1"
},
{
"name": "insCurrentSocHold2",
"offset": 153,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "绝缘电流SOC保持2"
},
{
"name": "insCurrentSocHold3",
"offset": 154,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "绝缘电流SOC保持3"
},
{
"name": "fcuCurrentToInsLimit1",
"offset": 155,
"length": 1,
"type": "uint8",
"unit": "A",
"description": "FCU到绝缘限制1"
},
{
"name": "fcuCurrentToinsLimit2",
"offset": 156,
"length": 1,
"type": "uint8",
"unit": "A",
"description": "FCU到绝缘限制2"
},
{
"name": "powerCurrentSocHold1",
"offset": 157,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "功率电流SOC保持1"
},
{
"name": "powerCurrentSocHold2",
"offset": 158,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "功率电流SOC保持2"
},
{
"name": "powerCurrentSocHold3",
"offset": 159,
"length": 1,
"type": "uint8",
"unit": "%",
"description": "功率电流SOC保持3"
},
{
"name": "powerCurrentToInsLimit1",
"offset": 160,
"length": 1,
"type": "uint8",
"unit": "A",
"description": "功率到绝缘限制1"
},
{
"name": "powerCurrentToinsLimit2",
"offset": 161,
"length": 1,
"type": "uint8",
"unit": "A",
"description": "功率到绝缘限制2"
},
{
"name": "placeholder2",
"offset": 162,
"length": 4,
"type": "float32",
"description": "预留字段2"
},
{
"name": "placeholder3",
"offset": 166,
"length": 4,
"type": "float32",
"description": "预留字段3"
},
{
"name": "placeholder4",
"offset": 170,
"length": 4,
"type": "float32",
"description": "预留字段4"
},
{
"name": "placeholder5",
"offset": 174,
"length": 4,
"type": "float32",
"description": "预留字段5"
},
{
"name": "checkCode",
"offset": 178,
"length": 4,
"type": "uint32",
"description": "校验码(从start1到placeholder5的字节累加和)"
}
],
"metadata": {
"total_length": 182,
"data_section_start": 6,
"data_section_end": 178,
"checksum_range": "0-178",
"float_precision": "IEEE-754单精度",
"reserved_fields": [
"placeholder1",
"placeholder2",
"placeholder3",
"placeholder4",
"placeholder5"
]
}
}
@@ -1,142 +0,0 @@
{
"protocol_name": "高压A母线状态反馈",
"message_id": "0x0006",
"length": 10,
"checksum": {
"start_offset": 0,
"end_offset": 30,
"algorithm": "sum_low_byte"
},
"fields": [
{
"name": "start1",
"offset": 0,
"type": "uint8",
"value": "0x20",
"description": "起始字节1"
},
{
"name": "start2",
"offset": 1,
"type": "uint8",
"value": "0x20",
"description": "起始字节2"
},
{
"name": "id",
"offset": 2,
"type": "uint16",
"value": "0x0006",
"description": "消息ID"
},
{
"name": "length",
"offset": 4,
"type": "uint16",
"value": 10,
"description": "消息长度"
},
{
"name": "bowFTDevice123CircuitBreaker",
"offset": 6,
"type": "uint8",
"description": "艏部FT设备123断路器"
},
{
"name": "actuatorCircuitBreaker",
"offset": 7,
"type": "uint8",
"description": "执行机构断路器"
},
{
"name": "mastSteeringGearControlBoxCircuitBreaker",
"offset": 8,
"type": "uint8",
"description": "桅杆舵机控制箱断路器"
},
{
"name": "xczCircuitBreaker",
"offset": 9,
"type": "uint8",
"description": "XCZ断路器"
},
{
"name": "bowRudderControlBoxCircuitBreaker",
"offset": 10,
"type": "uint8",
"description": "艏舵控制箱断路器"
},
{
"name": "openWaterCoverStartCylinderCircuitBreaker",
"offset": 11,
"type": "uint8",
"description": "开盖启动气缸断路器"
},
{
"name": "instrumentPowerFailureSignal",
"offset": 12,
"type": "uint8",
"description": "仪表电源失效信号"
},
{
"name": "emergencyPowerFailureSignal",
"offset": 13,
"type": "uint8",
"description": "应急电源失效信号"
},
{
"name": "waterIngressionAlarm",
"offset": 14,
"type": "uint8",
"description": "进水报警"
},
{
"name": "busbarBVoltage",
"offset": 15,
"type": "uint16",
"description": "B排电压(V)"
},
{
"name": "busbarBCurrent",
"offset": 17,
"type": "uint16",
"description": "B排电流(A)"
},
{
"name": "bowFTDevice123Current",
"offset": 19,
"type": "uint16",
"description": "艏部FT设备123电流(A)"
},
{
"name": "actuatorCurrent",
"offset": 21,
"type": "uint16",
"description": "执行机构电流(A)"
},
{
"name": "mastSteeringGearControlBoxCurrent",
"offset": 23,
"type": "uint16",
"description": "桅杆舵机控制箱电流(A)"
},
{
"name": "xczCurrent",
"offset": 25,
"type": "uint16",
"description": "XCZ电流(A)"
},
{
"name": "bowRudderControlBoxCurrent",
"offset": 27,
"type": "uint16",
"description": "艏舵控制箱电流(A)"
},
{
"name": "openWaterCoverStartCylinderCurrent",
"offset": 29,
"type": "uint16",
"description": "开盖启动气缸电流(A)"
}
]
}
@@ -1,154 +0,0 @@
{
"protocol_name": "高压B母线状态反馈",
"message_id": "0x0007",
"length": 36,
"checksum": {
"start_offset": 0,
"end_offset": 34,
"algorithm": "sum_low_byte"
},
"fields": [
{
"name": "start1",
"offset": 0,
"type": "uint8",
"value": "0x20",
"description": "起始字节1"
},
{
"name": "start2",
"offset": 1,
"type": "uint8",
"value": "0x20",
"description": "起始字节2"
},
{
"name": "id",
"offset": 2,
"type": "uint16",
"value": "0x0007",
"description": "消息ID"
},
{
"name": "length",
"offset": 4,
"type": "uint16",
"value": 36,
"description": "消息长度(包含校验码)"
},
{
"name": "lithiumBatteryGroupInstrumentCircuitBreaker",
"offset": 6,
"type": "uint8",
"description": "锂电池组仪表断路器"
},
{
"name": "bowLowVoltageDistributionBoxCircuitBreaker",
"offset": 7,
"type": "uint8",
"description": "艏部低压配电箱断路器"
},
{
"name": "unit4InstrumentDC48VCircuitBreaker",
"offset": 8,
"type": "uint8",
"description": "单元4仪表DC48V断路器"
},
{
"name": "dcC1DCDistributionPanelCircuitBreaker",
"offset": 9,
"type": "uint8",
"description": "DC C1直流配电板断路器"
},
{
"name": "reservedCircuitBreaker1",
"offset": 10,
"type": "uint8",
"description": "备用断路器1"
},
{
"name": "reservedCircuitBreaker2",
"offset": 11,
"type": "uint8",
"description": "备用断路器2"
},
{
"name": "emergencyLithiumBatteryGroup2CircuitBreaker",
"offset": 12,
"type": "uint8",
"description": "应急锂电池组2断路器"
},
{
"name": "instrumentPowerFailureSignal",
"offset": 13,
"type": "uint8",
"description": "仪表电源故障信号"
},
{
"name": "emergencyPowerFailureSignal",
"offset": 14,
"type": "uint8",
"description": "应急电源故障信号"
},
{
"name": "instrumentBusbarVoltage",
"offset": 15,
"type": "uint16",
"description": "仪表母线电压(V)"
},
{
"name": "bowLowVoltageDistributionBoxCurrent",
"offset": 17,
"type": "uint16",
"description": "艏部低压配电箱电流(A)"
},
{
"name": "dcC1InstrumentDC48VCurrent",
"offset": 19,
"type": "uint16",
"description": "DC C1仪表DC48V电流(A)"
},
{
"name": "reservedCurrent1",
"offset": 21,
"type": "uint16",
"description": "备用电流1(A)"
},
{
"name": "emergencyLithiumBatteryGroup2Current",
"offset": 23,
"type": "uint16",
"description": "应急锂电池组2电流(A)"
},
{
"name": "lithiumBatteryGroupInstrumentCurrent",
"offset": 25,
"type": "uint16",
"description": "锂电池组仪表电流(A)"
},
{
"name": "unit4InstrumentDC48VCurrent",
"offset": 27,
"type": "uint16",
"description": "单元4仪表DC48V电流(A)"
},
{
"name": "reservedCurrent2",
"offset": 29,
"type": "uint16",
"description": "备用电流2(A)"
},
{
"name": "emergency2BusbarVoltage",
"offset": 31,
"type": "uint16",
"description": "应急2母线电压(V)"
},
{
"name": "compositeEnergyManagementSystemEmergencyDC48VCurrent",
"offset": 33,
"type": "uint16",
"description": "综合能源管理系统应急DC48V电流(A)"
}
]
}
@@ -1,184 +0,0 @@
{
"protocol_name": "高压母线状态反馈",
"message_id": "0x0005",
"length": 38,
"checksum": {
"start_offset": 0,
"end_offset": 37,
"algorithm": "sum_low_byte"
},
"fields": [
{
"name": "start1",
"offset": 0,
"type": "uint8",
"value": "0x20",
"description": "起始字节1"
},
{
"name": "start2",
"offset": 1,
"type": "uint8",
"value": "0x20",
"description": "起始字节2"
},
{
"name": "id",
"offset": 2,
"type": "uint16",
"value": "0x0005",
"description": "消息ID"
},
{
"name": "length",
"offset": 4,
"type": "uint16",
"value": 38,
"description": "消息长度"
},
{
"name": "DCB1",
"offset": 6,
"type": "uint8",
"description": "直流断路器1状态"
},
{
"name": "DCB2",
"offset": 7,
"type": "uint8",
"description": "直流断路器2状态"
},
{
"name": "ZK1",
"offset": 8,
"type": "uint8",
"description": "真空接触器1状态"
},
{
"name": "ZK2",
"offset": 9,
"type": "uint8",
"description": "真空接触器2状态"
},
{
"name": "ZK3",
"offset": 10,
"type": "uint8",
"description": "真空接触器3状态"
},
{
"name": "ZK4",
"offset": 11,
"type": "uint8",
"description": "真空接触器4状态"
},
{
"name": "ZK5",
"offset": 12,
"type": "uint8",
"description": "真空接触器5状态"
},
{
"name": "ZK6",
"offset": 13,
"type": "uint8",
"description": "真空接触器6状态"
},
{
"name": "ZK7",
"offset": 14,
"type": "uint8",
"description": "真空接触器7状态"
},
{
"name": "ZK8",
"offset": 15,
"type": "uint8",
"description": "真空接触器8状态"
},
{
"name": "ZK9",
"offset": 16,
"type": "uint8",
"description": "真空接触器9状态"
},
{
"name": "ZK10",
"offset": 17,
"type": "uint8",
"description": "真空接触器10状态"
},
{
"name": "busInsulationLow",
"offset": 18,
"type": "uint8",
"description": "母线绝缘低报警"
},
{
"name": "busAInsulationHigh",
"offset": 19,
"type": "uint8",
"description": "A母线绝缘高报警"
},
{
"name": "lostPower",
"offset": 20,
"type": "uint8",
"description": "失电信号"
},
{
"name": "lostEmerPower",
"offset": 21,
"type": "uint8",
"description": "应急失电信号"
},
{
"name": "powerBusVoltage",
"offset": 22,
"type": "uint16",
"description": "动力母线电压(V)"
},
{
"name": "dcDc5ModuleCurrent",
"offset": 24,
"type": "uint16",
"description": "DC/DC5模块电流(A)"
},
{
"name": "powerBusCurrent",
"offset": 26,
"type": "uint16",
"description": "动力母线电流(A)"
},
{
"name": "busbarAVoltage",
"offset": 28,
"type": "uint16",
"description": "A排电压(V)"
},
{
"name": "propulsionMotorControlBoxCurrent",
"offset": 30,
"type": "uint16",
"description": "推进电机控制箱电流(A)"
},
{
"name": "busbarACurrent",
"offset": 32,
"type": "uint16",
"description": "A排电流(A)"
},
{
"name": "lithiumBatteryGroupMeterCurrent",
"offset": 34,
"type": "uint16",
"description": "锂电池组表计电流(A)"
},
{
"name": "bowHighVoltageDistributionBoxCurrent",
"offset": 36,
"type": "uint16",
"description": "艏部高压配电箱电流(A)"
}
]
}
+277
View File
@@ -0,0 +1,277 @@
# 上位机控制程序设计文档
## 1. 程序架构设计
采用MVC模式设计,主要分为以下模块:
### 1.0 系统架构图
```mermaid
graph TD
A[用户界面] -->|控制指令| B[控制器]
B -->|发送命令| C[通信模块]
C -->|UDP协议| D[下位机]
D -->|状态反馈| C
C -->|解析数据| B
B -->|更新状态| A
B -->|记录数据| E[数据库]
```
### 1.1 消息处理流程
1. 接收原始UDP数据
2. 根据消息ID选择解析器
3. 验证校验码
4. 解析为结构化数据
5. 触发状态更新事件
6. 存储到数据库
### 1.1 通信模块 (Model) - 详细设计
#### 消息类型映射表
| 消息ID | 消息名称 | 处理函数 | 更新频率 |
|--------|----------|----------|----------|
| 0x0005 | 高压母线状态 | parse_high_vol_bus | 1Hz |
| 0x0006 | 高压A母线状态 | parse_high_a_vol_bus | 1Hz |
| 0x0007 | 低压主母线状态 | parse_low_main_bus | 1Hz |
| 0x0008 | 低压汇流排状态 | parse_low_bus | 1Hz |
#### 异常处理机制
1. 校验失败:丢弃数据并记录错误日志
2. 超时处理:3次重试后标记设备离线
3. 数据异常:触发告警并显示在界面
```python
class UDPMessageHandler:
"""UDP消息处理基类"""
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.socket = None
def connect(self):
"""建立UDP连接"""
pass
def send_message(self, msg):
"""发送消息"""
pass
def receive_message(self):
"""接收消息"""
pass
def close(self):
"""关闭连接"""
pass
class PowerMessageHandler(UDPMessageHandler):
"""电源管理专用消息处理器"""
def __init__(self, ip, port):
super().__init__(ip, port)
self.message_parsers = {
0x0005: self.parse_high_vol_bus,
0x0006: self.parse_high_a_vol_bus,
# 其他消息类型...
}
def parse_high_vol_bus(self, data):
"""解析高压母线消息"""
pass
# 其他消息解析方法...
```
### 1.2 界面模块 (View) - 详细设计
#### 主界面布局
```mermaid
graph LR
A[标题栏] --> B[状态区]
B --> C[电压电流仪表盘]
B --> D[断路器状态指示灯]
A --> E[控制区]
E --> F[电源控制按钮组]
E --> G[参数设置面板]
A --> H[日志区]
H --> I[实时消息列表]
H --> J[历史记录查询]
```
#### 组件说明
1. 电压电流仪表盘:实时显示各母线电压电流值
2. 断路器状态指示灯:绿色-闭合,红色-断开
3. 电源控制按钮组:带防误触保护(需长按3秒)
4. 参数设置面板:输入验证和范围检查
```python
class MainWindow(tk.Tk):
"""主窗口"""
def __init__(self):
super().__init__()
self.title("电源管理系统")
self.geometry("1200x800")
self.create_widgets()
def create_widgets(self):
"""创建界面组件"""
self.status_frame = StatusFrame(self)
self.control_frame = ControlFrame(self)
self.log_frame = LogFrame(self)
# 布局管理
self.status_frame.pack(side=tk.TOP, fill=tk.X)
self.control_frame.pack(side=tk.LEFT, fill=tk.Y)
self.log_frame.pack(side=tk.RIGHT, expand=True, fill=tk.BOTH)
class StatusFrame(tk.Frame):
"""状态显示面板"""
def update_status(self, data):
"""更新状态显示"""
pass
class ControlFrame(tk.Frame):
"""控制面板"""
def create_buttons(self):
"""创建控制按钮"""
pass
```
### 1.3 控制器模块 (Controller) - 详细设计
#### 状态管理机制
1. 使用有限状态机(FSM)管理电源系统状态
2. 状态转换规则:
- 仅当所有预检通过才允许上电
- 故障时自动进入安全状态
- 人工确认后才能复位
#### 命令处理流程
```mermaid
sequenceDiagram
用户->>界面: 点击控制按钮
界面->>控制器: 发送控制命令
控制器->>业务逻辑: 验证命令有效性
业务逻辑->>通信模块: 发送UDP指令
通信模块->>下位机: 传输控制报文
下位机-->>通信模块: 返回应答
通信模块->>控制器: 更新命令状态
控制器->>界面: 显示操作结果
控制器->>数据库: 记录操作日志
```
```python
class PowerManagerController:
"""主控制器"""
def __init__(self):
self.message_handler = PowerMessageHandler("192.168.1.100", 5000)
self.view = MainWindow()
# 绑定事件
self.bind_events()
def bind_events(self):
"""绑定UI事件"""
self.view.control_frame.on_button_click = self.handle_control_command
def handle_control_command(self, cmd):
"""处理控制命令"""
pass
def start(self):
"""启动应用程序"""
self.message_handler.connect()
self.view.mainloop()
```
## 2. 接口规范
### 2.1 模块交互架构
```mermaid
classDiagram
class Communication {
+send_command(cmd: dict) bool
+get_status() dict
+subscribe(callback: function)
+on_message_received(data: bytes)
}
class Controller {
+handle_ui_event(event: dict)
+update_system_status(status: dict)
+log_operation(log: dict)
}
class UI {
+update_status(data: dict)
+show_alert(level: int, msg: str)
+log_message(source: str, msg: str)
}
Communication --> Controller : 状态更新通知
Controller --> UI : 界面更新指令
UI --> Controller : 用户操作事件
```
### 2.2 详细接口定义
#### 通信模块 → 控制器
```python
# 状态更新通知
{
"msg_type": "status_update",
"timestamp": "2025-05-04T10:20:00",
"data": {
"voltage": 220.5,
"current": 15.2,
"breaker_state": True
}
}
# 错误通知
{
"msg_type": "error",
"code": 1001,
"message": "校验失败"
}
```
#### 控制器 → 界面
```python
# 状态显示更新
{
"component": "voltage_meter",
"value": 220.5,
"unit": "V",
"normal_range": [210, 230]
}
# 告警信息
{
"level": 2, # 1-警告 2-错误 3-严重
"message": "A相电压过高",
"suggestion": "检查A相负载"
}
```
#### 界面 → 控制器
```python
# 按钮操作事件
{
"event_type": "button_click",
"button_id": "power_on",
"timestamp": "2025-05-04T10:20:01"
}
# 参数设置事件
{
"event_type": "param_set",
"param": "voltage_limit",
"value": 230,
"unit": "V"
}
```
### 2.3 错误处理规范
1. 通信错误:自动重试3次后通知控制器
2. 业务逻辑错误:记录详细日志并通知界面
3. 界面错误:显示友好提示并保持最后正常状态
## 3. 数据库设计
(之前已完成的数据库表结构...)
Executable
+2
View File
@@ -0,0 +1,2 @@
scp root@192.168.0.223:/root/work/moos_ws/moos-ivp-extend/missions/union_test/power_data.db ./data/power_data.db
scp root@192.168.0.223:/root/work/moos_ws/moos-ivp-extend/missions/union_test/pPowerManger.log ./data/pPowerManger.log
+69
View File
@@ -0,0 +1,69 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_:
BO_ 2432696577 HostToCompositeControl: 8 Vector__XXX
SG_ Reserved1 : 56|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ HostStatus : 48|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ HostHeartbeat : 40|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ PowerBatteryStartStop : 32|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBatteryStartStop : 24|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBatteryChargeFlag : 16|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellCommand : 8|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellModeSet : 0|8@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2432696833 CompositeControlToHost: 8 Vector__XXX
SG_ Reserved2 : 56|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ PowerBatteryTotalEnergy : 48|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBatteryTotalEnergy : 40|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ PowerBatteryEmergency : 32|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBatteryEmergency : 24|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellFaultLevel : 16|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellStatus : 8|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellSystemMode : 0|8@1+ (1,0) [0|0] "" Vector__XXX
+232
View File
@@ -0,0 +1,232 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_:
BO_ 2483135745 CircuitBreakerControl1: 8 Vector__XXX
SG_ CoolingWaterValveControl : 26|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC5PowerControl : 24|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ ReserveBreakerControl : 22|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ TYZReserveBreakerControl : 20|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ FBReserveBreakerControl : 18|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternSwitch2BreakerControl : 16|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternSwitch1BreakerControl : 14|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternFT45BreakerControl : 12|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowPanelBreakerControl : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC5BreakerControl : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryMeterBreakerControl : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ MotorBreakerControl : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryBreakerControl : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellBreakerControl : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2483201281 CircuitBreakerControl2: 8 Vector__XXX
SG_ OpenWaterMechanismControl : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowRudderControl : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ XCBreakerControl : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ MastRudderControl : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ OpeningMechanismControl : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowFloatAdjustControl : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2483266817 CircuitBreakerControl3: 8 Vector__XXX
SG_ SternEmergencyBatteryControl : 12|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve2Control : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve1Control : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ HighVoltageControllerControl : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ U4BreakerControl : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowLowVoltageControl : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryAccessControl : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2483332353 CircuitBreakerControl4: 8 Vector__XXX
SG_ BowEmergencyBatteryControl : 14|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve4Control : 12|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve3Control : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowJettisonControl : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ U5BreakerControl : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ U3BreakerControl : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ U2BreakerControl : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ U1BreakerControl : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560950529 CircuitBreakerFeedback: 8 Vector__XXX
SG_ DCDC_Temperature : 48|8@1- (1,0) [0|0] "" Vector__XXX
SG_ EmergencyPowerLoss : 43|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterPowerLoss : 42|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ BusA_InsulationLow : 41|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ PowerBus_InsulationLow : 40|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CoolingPump2_Running : 38|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CoolingPump1_Running : 37|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CoolingWaterLeak : 36|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CoolingPump2_Fault : 35|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CoolingPump1_Fault : 34|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_Running : 33|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_CommFault : 32|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_InternalFault : 31|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_ShortCircuit : 30|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_InputUnderVoltage : 29|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_InputOverVoltage : 28|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_UnderVoltage : 27|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_OverVoltage : 26|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_OverCurrent : 25|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC_OverTemp : 24|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ ReserveBreaker_Status : 22|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ TYZReserveBreaker_Status : 20|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ FBReserveBreaker_Status : 18|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternSwitch2Breaker_Status : 16|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternSwitch1Breaker_Status : 14|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternFT45Breaker_Status : 12|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowPanelBreaker_Status : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC5Breaker_Status : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryMeterBreaker_Status : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ MotorBreaker_Status : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryBreaker_Status : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellBreaker_Status : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560950785 PowerBusFeedback: 8 Vector__XXX
SG_ BusA_Voltage : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ PowerBus_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCDC5_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ PowerBus_Voltage : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560951041 CurrentFeedback: 8 Vector__XXX
SG_ BowPowerBox_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryMeter_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BusA_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ PropulsionMotor_Current : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560951297 SternCurrentFeedback: 8 Vector__XXX
SG_ Reserve_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternSwitch1_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ TYZReserve_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternFT45_Current : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560951553 SternAdditionalFeedback: 8 Vector__XXX
SG_ CoolingWater_Pressure : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ FBReserve_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve2_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ SternSwitch2_Current : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560951809 BowBreakerFeedback: 8 Vector__XXX
SG_ WaterLeakAlarm : 14|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyPowerLoss : 13|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterPowerLoss : 12|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ OpenWaterMechanismBreaker_Status : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowRudderBreaker_Status : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ XCZBreaker_Status : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ MastRudderBreaker_Status : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ OpeningMechanismBreaker_Status : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowFT13Breaker_Status : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560952065 BusBFeedback: 8 Vector__XXX
SG_ OpeningMechanism_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowFT13_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BusB_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BusB_Voltage : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560952321 BowMechanismFeedback: 8 Vector__XXX
SG_ OpenWaterMechanism_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowRudder_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ XCZ_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ MastRudder_Current : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560952577 MeterBreakerFeedback: 8 Vector__XXX
SG_ MeterBusInsulationLow : 18|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyPowerLoss : 17|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterPowerLoss : 16|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyBattery2Breaker_Status : 12|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve2Breaker_Status : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve1Breaker_Status : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCC1Breaker_Status : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit4MeterBreaker_Status : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowLowVoltageBoxBreaker_Status : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryMeterBreaker_Status : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560952833 MeterBusFeedback: 8 Vector__XXX
SG_ Reserve3_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ DCC1Meter_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowLowVoltageBox_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBus_Voltage : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560953089 EmergencyBatteryFeedback: 8 Vector__XXX
SG_ Reserve4_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit4Meter_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BatteryMeter_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyBattery2_Current : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560953345 EmergencyBus2Feedback: 8 Vector__XXX
SG_ PLCPower_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ FuelCellEmergency_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ EnergySystemEmergency_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyBus2_Voltage : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560953601 UnitBreakerFeedback: 8 Vector__XXX
SG_ WaterLeakAlarm : 18|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyPowerLoss : 17|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterPowerLoss : 16|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyBattery1Breaker_Status : 14|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve6Breaker_Status : 12|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Reserve5Breaker_Status : 10|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowPZBreaker_Status : 8|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit5Breaker_Status : 6|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit3Breaker_Status : 4|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit2Breaker_Status : 2|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit1Breaker_Status : 0|2@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560953857 MeterBus2Feedback: 8 Vector__XXX
SG_ Unit2_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit1_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBus2_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ MeterBus2_Voltage : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560954113 UnitCurrentFeedback: 8 Vector__XXX
SG_ EmergencyBattery1_Current : 48|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ BowPZ_Current : 32|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit5_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ Unit3_Current : 0|16@1+ (1,0) [0|0] "" Vector__XXX
BO_ 2560954369 EmergencyBus1Feedback: 8 Vector__XXX
SG_ ControlPower24V_Current : 16|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ EmergencyBus1_Voltage : 0|16@1+ (1,0) [0|0] "" Vector__XXX
+3 -2
View File
@@ -5,6 +5,7 @@
# DESCRIPTION: CMakeLists.txt file for the moos-ivp-extend source directory
##############################################################################
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g -O1")
#============================================================================
# Add the libraries in the current directory to the include path
@@ -16,8 +17,8 @@ INCLUDE_DIRECTORIES(${LOCAL_LIBRARY_DIRS})
# List the subdirectories to build...
#============================================================================
ADD_SUBDIRECTORY(pPowerManger)
ADD_SUBDIRECTORY(appPowerMangerWebUI)
# ADD_SUBDIRECTORY(appPowerMangerWebUI)
add_subdirectory(pPMtest)
##############################################################################
# END of CMakeLists.txt
##############################################################################
+108
View File
@@ -0,0 +1,108 @@
#--------------------------------------------------------
# The CMakeLists.txt for: pPowerManger
# Author(s):
#--------------------------------------------------------
# Set System Specific Libraries
if (${WIN32})
# Windows Libraries
SET(SYSTEM_LIBS
wsock32 )
else (${WIN32})
# Linux and Apple Libraries
SET(SYSTEM_LIBS
m
pthread )
endif (${WIN32})
# Use local SQLite3 source
SET(SQLITE_SRC
sqlit3/SQLite.cpp
sqlit3/sqlite3.c
)
SET(HTTP_SRC
httpserver/mongoose.c
httpserver/httpserver.cpp)
SET(LOG_SRC
logc/loguru.cpp)
SET(UDP_COMM_SRC
udpcomm/udpComm.cpp)
SET(FSMLIB_SRC
fsm/PowerManagerFsm.cpp
fsm/CruiseMode.cpp
fsm/DJMode.cpp
fsm/FaultState.cpp
fsm/FloatAdjust.cpp
fsm/FloatDown.cpp
fsm/HighSpeedMode.cpp
fsm/InitState.cpp
fsm/RemoteControl.cpp
fsm/ShoreBasedReady.cpp
fsm/StandbyState.cpp
fsm/SurfaceSurvey.cpp
fsm/UnderwaterSurvey.cpp
fsm/WaterBasedReady.cpp
)
SET(SRC
${FSMLIB_SRC}
${SQLITE_SRC}
${HTTP_SRC}
${UDP_COMM_SRC}
${LOG_SRC}
PowerManger.cpp
PowerManger_Info.cpp
# udpComm.cpp
main.cpp
# SQLiteDB.cpp
driver.cpp
LowerCommManager.cpp
UpperCommManager.cpp
# loguru.cpp
upmsg/upmsg_definitions.cpp
)
ADD_EXECUTABLE(pPowerManger ${SRC})
TARGET_INCLUDE_DIRECTORIES(pPowerManger PRIVATE sqlit3)
TARGET_LINK_LIBRARIES(pPowerManger
${MOOS_LIBRARIES}
apputil
mbutil
m
pthread
jsoncpp
${SYSTEM_LIBS}
dl
)
# Add SQLiteDB static library
SET(UDPCOMM_SRC
udpComm.cpp
)
# SET(SQLITEDB_SRC
# SQLiteDB.cpp
# )
SET(DRIVER_SRC
driver.cpp)
# SET(POWERMANGE_SRC
# PowerManger.cpp
# PowerManger_Info.cpp
# udpComm.cpp
# SQLiteDB.cpp
# driver.cpp
# PowerManagerFsm.cpp)
# ADD_LIBRARY(SQLiteDB STATIC ${SQLITEDB_SRC})
# ADD_LIBRARY(UDPComm STATIC ${UDPCOMM_SRC})
# # ADD_LIBRARY(FSMLib STATIC ${FSMLIB_SRC})
# ADD_LIBRARY(Driver STATIC ${DRIVER_SRC})
# ADD_LIBRARY(PowerMange STATIC ${POWERMANGE_SRC})
+929
View File
@@ -0,0 +1,929 @@
#include "LowerCommManager.h"
#include "PowerManger.h"
#include "driver.h"
#include "udpcomm/udpComm.h"
bool _ListenCB(void * pParam)
{
LowerCommManager* pMe = (LowerCommManager* )pParam;
return pMe->listenThreadFunc();
}
LowerCommManager::LowerCommManager(PowerManger* pm, long myPort, long ccuPort, const std::string& cccHost){
m_pm = pm;
m_udpComm = new udpComm();
m_port = myPort;
m_udpComm->ccuHost = cccHost;
m_udpComm->ccuPort = ccuPort;
m_udpComm->udpScoket = new XPCUdpSocket(m_port);
std::cout << MOOS::ConsoleColours::yellow() << "╔════════════════════════╗" << MOOS::ConsoleColours::reset() << std::endl;
std::cout << MOOS::ConsoleColours::yellow() << "║ [LOCAL PORT] "
<< MOOS::ConsoleColours::cyan() << m_port
<< MOOS::ConsoleColours::yellow() << std::setw(15) << " ║" << MOOS::ConsoleColours::reset() << std::endl;
std::cout << MOOS::ConsoleColours::yellow() << "║ [CCU HOST ] "
<< MOOS::ConsoleColours::cyan() << m_udpComm->ccuHost
<< MOOS::ConsoleColours::yellow() << std::setw(8) << " ║" << MOOS::ConsoleColours::reset() << std::endl;
std::cout << MOOS::ConsoleColours::yellow() << "║ [CCU PORT ] "
<< MOOS::ConsoleColours::cyan() << m_udpComm->ccuPort
<< MOOS::ConsoleColours::yellow() << std::setw(15) << " ║" << MOOS::ConsoleColours::reset() << std::endl;
std::cout << MOOS::ConsoleColours::yellow() << "╚════════════════════════╝" << MOOS::ConsoleColours::reset() << std::endl;
}
LowerCommManager::~LowerCommManager(){
try {
stopListenThread();
if (m_udpComm) {
delete m_udpComm;
m_udpComm = nullptr;
}
} catch (...) {
cerr << "Error during cleanup" << endl;
}
}
bool LowerCommManager::initUdpComm(){
if (m_udpComm->udpScoket) {
try {
std::cout << MOOS::ConsoleColours::yellow() << "Attempting to bind UDP socket..." << MOOS::ConsoleColours::reset() << std::endl;
m_udpComm->udpScoket->vBindSocket(); // 可能会抛出 XPCException 或其他 std::exception
std::cout << MOOS::ConsoleColours::green() << "UDP bind succeeded!" << MOOS::ConsoleColours::reset() << std::endl;
LOG_F(INFO, "UDP bind succeeded!");
}
catch (const std::exception& e) {
std::cerr << MOOS::ConsoleColours::red()
<< "[UDP Bind Failed] Exception: " << e.what()
<< MOOS::ConsoleColours::reset() << std::endl;
LOG_F(ERROR, "UDP bind failed: %s", e.what());
return false;
}
catch (...) {
std::cerr << MOOS::ConsoleColours::red()
<< "[UDP Bind Failed] Unknown exception occurred!"
<< MOOS::ConsoleColours::reset() << std::endl;
LOG_F(ERROR, "Unknown exception occurred during UDP bind");
return false;
}
} else {
std::cerr << MOOS::ConsoleColours::red()
<< "[UDP Init Failed] udpSocket is null!"
<< MOOS::ConsoleColours::reset() << std::endl;
LOG_F(ERROR, "udpSocket is null!");
return false;
}
return true;
}
void LowerCommManager::processPeriodicTasks() {
sendCcuCommand(m_pm->m_CcuColCmd);
m_pm->m_db->insertData(m_pm->m_CcuColCmd);
//延时5ms
usleep(5000);
if(m_pm->m_systemData->device_common_status.dis_hv_c1.isTimeout )
{
disHighVolBusCmd clr1{};
m_udpComm->sendDisSysCmd(clr1);
MOOSPause(200);
}
if(m_pm->m_systemData->device_common_status.dis_lv_c1.isTimeout )
{
disHighBVolBusCmd clr3{};
m_udpComm->sendDisSysCmd(clr3);
MOOSPause(200);
}
m_udpComm->clearMsgQueue();
}
void LowerCommManager::operate_hold()
{
disHighVolBusCmd clr1{};
disHighAVolBusCmd clr2{};
disHighBVolBusCmd clr3{};
disLowBusCmd clr4{};
m_udpComm->sendDisSysCmd(clr1);
MOOSPause(200);
m_udpComm->sendDisSysCmd(clr2);
MOOSPause(200);
m_udpComm->sendDisSysCmd(clr3);
MOOSPause(200);
m_udpComm->sendDisSysCmd(clr4);
}
bool LowerCommManager::sendCcuCommand(const ccuColCmd cmd){
// m_pm->m_db->insertCcuSysCmd(cmd);
if(!m_udpComm->sendCcuColCmd(cmd))
cout << "send ccu command failed!" << endl;
return true;
}
bool LowerCommManager::sendDisSysCommand(const disSysBreakerList& cmd){
//根据目标状态进行断路器操作
//a. 高压母线的断路器
disHighVolBusCmd a;
a.fuelCellCircuitBreaker = getBreakerOption(cmd.bus1Breaker.fuelCellCircuitBreaker);
a.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(cmd.bus1Breaker.lithiumBatteryGroupInstrumentCircuitBreaker);
a.dcDc5ModuleCircuitBreaker = getBreakerOption(cmd.bus1Breaker.dcDc5ModuleCircuitBreaker);
a.powerLithiumBatteryCircuitBreaker = getBreakerOption(cmd.bus1Breaker.powerLithiumBatteryCircuitBreaker);
a.propulsionMotorCircuitBreaker = getBreakerOption(cmd.bus1Breaker.propulsionMotorCircuitBreaker);
a.bowHighVoltageDistributionBoxCircuitBreaker = getBreakerOption(cmd.bus1Breaker.bowHighVoltageDistributionBoxCircuitBreaker);
a.tyzReservedCircuitBreaker = getBreakerOption(cmd.bus1Breaker.tyzReservedCircuitBreaker);
a.sternFTDevice45CircuitBreaker = getBreakerOption(cmd.bus1Breaker.sternFTDevice45CircuitBreaker);
a.sternRudderSwitch1CircuitBreaker = getBreakerOption(cmd.bus1Breaker.sternRudderSwitch1CircuitBreaker);
a.sternRudderSwitch2CircuitBreaker = getBreakerOption(cmd.bus1Breaker.sternRudderSwitch2CircuitBreaker);
a.reservedCircuitBreaker = getBreakerOption(cmd.bus1Breaker.reservedCircuitBreaker);
a.fbReservedCircuitBreaker = getBreakerOption(cmd.bus1Breaker.fbReservedCircuitBreaker);
a.dcdc5Module = getBreakerOption(cmd.bus1Breaker.dcdcmodel);
a.coolingSystem = getBreakerOption(cmd.bus1Breaker.coolingSystem);
m_udpComm->sendDisSysCmd(a);
m_pm->m_db->insertData(a);
usleep(5000);
//b. 高压汇流排A断路器
disHighAVolBusCmd b;
b.bowFTDevice123CircuitBreaker = getBreakerOption(cmd.bus2Breaker.bowFTDevice123CircuitBreaker);
b.actuatorCircuitBreaker = getBreakerOption(cmd.bus2Breaker.actuatorCircuitBreaker);
b.mastSteeringGearControlBoxCircuitBreaker = getBreakerOption(cmd.bus2Breaker.mastSteeringGearControlBoxCircuitBreaker);
b.xczCircuitBreaker = getBreakerOption(cmd.bus2Breaker.xczCircuitBreaker);
b.bowRudderControlBoxCircuitBreaker = getBreakerOption(cmd.bus2Breaker.bowRudderControlBoxCircuitBreaker);
b.openWaterCoverStartCylinderCircuitBreaker = getBreakerOption(cmd.bus2Breaker.openWaterCoverStartCylinderCircuitBreaker);
m_udpComm->sendDisSysCmd(b);
m_pm->m_db->insertData(b);
usleep(5000);
//c. 低压主母线断路器
disHighBVolBusCmd c;
c.lithiumBatteryGroupInstrumentCircuitBreaker = 0x55;
c.bowLowVoltageDistributionBoxCircuitBreaker = 0xAA;
c.unit4InstrumentDC48VCircuitBreaker = 0xAA;
c.dcC1DCDistributionPanelCircuitBreaker = 0xAA;
c.reservedCircuitBreaker1 = 0xAA;
c.reservedCircuitBreaker2 = 0xAA;
c.emergencyLithiumBatteryGroup2CircuitBreaker = 0xAA;
m_udpComm->sendDisSysCmd(c);
m_pm->m_db->insertData(c);
usleep(5000);
//d. 闭合低压汇流排断路器
disLowBusCmd d;
d.unit1CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit1CircuitBreaker);
d.unit2CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit2CircuitBreaker);
d.unit3CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit3CircuitBreaker);
d.unit5CircuitBreaker = getBreakerOption(cmd.bus4Breaker.unit5CircuitBreaker);
d.bowPZDeviceCircuitBreaker = getBreakerOption(cmd.bus4Breaker.bowPZDeviceCircuitBreaker);
d.reservedCircuitBreaker1 = getBreakerOption(cmd.bus4Breaker.reservedCircuitBreaker1);
d.reservedCircuitBreaker2 = getBreakerOption(cmd.bus4Breaker.reservedCircuitBreaker2);
d.emergencyLithiumBatteryGroup1CircuitBreaker = getBreakerOption(cmd.bus4Breaker.emergencyLithiumBatteryGroup1CircuitBreaker);
m_udpComm->sendDisSysCmd(d);
m_pm->m_db->insertData(d);
usleep(5000);
return true;
}
void LowerCommManager::clearMsgQueue(){
m_udpComm->clearMsgQueue();
}
bool LowerCommManager::updatePoweSystemStates(){
// std::cout << "updatePoweSystemStates" << std::endl;
if(!m_udpComm->m_qReceiveCcuStateBuffer.empty())
{
double time;
m_udpComm->popMsgFormQueue(time,m_CcuCurrentState);
m_pm->m_pmCurrentState.ccustate = m_CcuCurrentState.data;
m_pm->m_db->insertData(m_pm->m_pmCurrentState.ccustate); //写入数据库
//DEBUG
//写入文件
// std::ofstream outFile("ccuState.txt", std::ios::app);
// coutMsg(m_CcuCurrentState, outFile);
// coutMsg(m_CcuCurrentState,std::cout);
msg_CcuStateFbMsg_Update_time = time;
}
if(!m_udpComm->m_qReceiveDisHighVolBusBuffer.empty())
{
double time;
m_udpComm->popMsgFormQueue(time,m_disHighVolBusCurrentState);
m_pm->m_pmCurrentState.bus1State = m_disHighVolBusCurrentState.data;
m_pm->m_db->insertData(m_pm->m_pmCurrentState.bus1State); //写入数据库
msg_disHighVolBusFbMsg_Update_time = time;
disBus1Breaker* pdis1=new disBus1Breaker;
(m_pm->m_pmCurrentState.bus1State.fuelCellCircuitBreaker == BREAK_ON) ? pdis1 -> fuelCellCircuitBreaker = 1 : pdis1 -> fuelCellCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.powerLithiumBatteryCircuitBreaker == BREAK_ON) ? pdis1 -> powerLithiumBatteryCircuitBreaker = 1 : pdis1 -> powerLithiumBatteryCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.propulsionMotorCircuitBreaker == BREAK_ON) ? pdis1 -> propulsionMotorCircuitBreaker = 1 : pdis1 -> propulsionMotorCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.lithiumBatteryGroupInstrumentCircuitBreaker == BREAK_ON) ? pdis1 -> lithiumBatteryGroupInstrumentCircuitBreaker = 1 : pdis1 -> lithiumBatteryGroupInstrumentCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.dcDc5ModuleCircuitBreaker == BREAK_ON) ? pdis1 -> dcDc5ModuleCircuitBreaker = 1 : pdis1 -> dcDc5ModuleCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.bowHighVoltageDistributionBoxCircuitBreaker == BREAK_ON) ? pdis1 -> bowHighVoltageDistributionBoxCircuitBreaker = 1 : pdis1 -> bowHighVoltageDistributionBoxCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.sternFTDevice45CircuitBreaker == BREAK_ON) ? pdis1 -> sternFTDevice45CircuitBreaker = 1 : pdis1 -> sternFTDevice45CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.sternRudderSwitch1CircuitBreaker == BREAK_ON) ? pdis1 -> sternRudderSwitch1CircuitBreaker = 1 : pdis1 -> sternRudderSwitch1CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.sternRudderSwitch2CircuitBreaker == BREAK_ON) ? pdis1 -> sternRudderSwitch2CircuitBreaker = 1 : pdis1 -> sternRudderSwitch2CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.fbReservedCircuitBreaker == BREAK_ON) ? pdis1 -> fbReservedCircuitBreaker = 1 : pdis1 -> fbReservedCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.tyzReservedCircuitBreaker == BREAK_ON) ? pdis1 -> tyzReservedCircuitBreaker = 1 : pdis1 -> tyzReservedCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus1State.reservedCircuitBreaker == BREAK_ON) ? pdis1 -> reservedCircuitBreaker = 1 : pdis1 -> reservedCircuitBreaker = 0;
pdis1 -> paceholder = 0;
m_pm->m_currentDisBreakerState.bus1Breaker = *pdis1;
delete pdis1;
}
if(!m_udpComm->m_qReceiveDisHighAVolBusBuffer.empty())
{
double time;
m_udpComm->popMsgFormQueue(time,m_disHighAVolBusCurrentState);
m_pm->m_pmCurrentState.bus2State = m_disHighAVolBusCurrentState.data;
m_pm->m_db->insertData(m_pm->m_pmCurrentState.bus2State); //写入数据库
msg_disHighAVolBusFbMsg_Update_time = time;
disBus2Breaker* pdis2=new disBus2Breaker;
(m_pm->m_pmCurrentState.bus2State.bowFTDevice123CircuitBreaker == BREAK_ON)? pdis2 -> bowFTDevice123CircuitBreaker = 1 : pdis2 -> bowFTDevice123CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus2State.actuatorCircuitBreaker == BREAK_ON)? pdis2 -> actuatorCircuitBreaker = 1 : pdis2 -> actuatorCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus2State.mastSteeringGearControlBoxCircuitBreaker == BREAK_ON)? pdis2 -> mastSteeringGearControlBoxCircuitBreaker = 1 : pdis2 -> mastSteeringGearControlBoxCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus2State.xczCircuitBreaker == BREAK_ON)? pdis2 -> xczCircuitBreaker = 1 : pdis2 -> xczCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus2State.bowRudderControlBoxCircuitBreaker == BREAK_ON)? pdis2 -> bowRudderControlBoxCircuitBreaker = 1 : pdis2 -> bowRudderControlBoxCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus2State.openWaterCoverStartCylinderCircuitBreaker == BREAK_ON)? pdis2 -> openWaterCoverStartCylinderCircuitBreaker = 1 : pdis2 -> openWaterCoverStartCylinderCircuitBreaker = 0;
pdis2 -> paceholder = 0;
m_pm->m_currentDisBreakerState.bus2Breaker = *pdis2;
delete pdis2;
}
if(!m_udpComm->m_qReceiveDisHighBVolBusBuffer.empty())
{
double time;
m_udpComm->popMsgFormQueue(time,m_disHighBVolBusCurrentState);
m_pm->m_pmCurrentState.bus3State = m_disHighBVolBusCurrentState.data;
m_pm->m_db->insertData(m_pm->m_pmCurrentState.bus3State); //写入数据库
msg_disHighBVolBusFbMsg_Update_time = time;
disBus3Breaker* pdis3=new disBus3Breaker;
(m_pm->m_pmCurrentState.bus3State.lithiumBatteryGroupInstrumentCircuitBreaker == BREAK_ON)? pdis3 -> lithiumBatteryGroupInstrumentCircuitBreaker = 1 : pdis3 -> lithiumBatteryGroupInstrumentCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus3State.bowLowVoltageDistributionBoxCircuitBreaker == BREAK_ON)? pdis3 -> bowLowVoltageDistributionBoxCircuitBreaker = 1 : pdis3 -> bowLowVoltageDistributionBoxCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus3State.unit4InstrumentDC48VCircuitBreaker == BREAK_ON)? pdis3 -> unit4InstrumentDC48VCircuitBreaker = 1 : pdis3 -> unit4InstrumentDC48VCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus3State.dcC1DCDistributionPanelCircuitBreaker == BREAK_ON)? pdis3 -> dcC1DCDistributionPanelCircuitBreaker = 1 : pdis3 -> dcC1DCDistributionPanelCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus3State.reservedCircuitBreaker1 == BREAK_ON)? pdis3 -> reservedCircuitBreaker1 = 1 : pdis3 -> reservedCircuitBreaker1 = 0;
(m_pm->m_pmCurrentState.bus3State.reservedCircuitBreaker2 == BREAK_ON)? pdis3 -> reservedCircuitBreaker2 = 1 : pdis3 -> reservedCircuitBreaker2 = 0;
(m_pm->m_pmCurrentState.bus3State.emergencyLithiumBatteryGroup2CircuitBreaker == BREAK_ON)? pdis3 -> emergencyLithiumBatteryGroup2CircuitBreaker = 1 : pdis3 -> emergencyLithiumBatteryGroup2CircuitBreaker = 0;
pdis3->paceholder = 0;
m_pm->m_currentDisBreakerState.bus3Breaker = *pdis3;
delete pdis3;
}
if(!m_udpComm->m_qReceiveDisLowBusBuffer.empty())
{
double time;
m_udpComm->popMsgFormQueue(time,m_disLowBusState);
m_pm->m_pmCurrentState.bus4State = m_disLowBusState.data;
m_pm->m_db->insertData(m_pm->m_pmCurrentState.bus4State); //写入数据库
msg_disLowBusFbMsg_Update_time = time;
disBus4Breaker* pdis4=new disBus4Breaker;
(m_pm->m_pmCurrentState.bus4State.unit1CircuitBreaker == BREAK_ON)? pdis4 -> unit1CircuitBreaker = 1 : pdis4 -> unit1CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus4State.unit2CircuitBreaker == BREAK_ON)? pdis4 -> unit2CircuitBreaker = 1 : pdis4 -> unit2CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus4State.unit3CircuitBreaker == BREAK_ON)? pdis4 -> unit3CircuitBreaker = 1 : pdis4 -> unit3CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus4State.unit5CircuitBreaker == BREAK_ON)? pdis4 -> unit5CircuitBreaker = 1 : pdis4 -> unit5CircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus4State.bowPZDeviceCircuitBreaker == BREAK_ON)? pdis4 -> bowPZDeviceCircuitBreaker = 1 : pdis4 -> bowPZDeviceCircuitBreaker = 0;
(m_pm->m_pmCurrentState.bus4State.reservedCircuitBreaker1 == BREAK_ON)? pdis4 -> reservedCircuitBreaker1 = 1 : pdis4 -> reservedCircuitBreaker1 = 0;
(m_pm->m_pmCurrentState.bus4State.reservedCircuitBreaker2 == BREAK_ON)? pdis4 -> reservedCircuitBreaker2 = 1 : pdis4 -> reservedCircuitBreaker2 = 0;
(m_pm->m_pmCurrentState.bus4State.emergencyLithiumBatteryGroup1CircuitBreaker == BREAK_ON)? pdis4 -> emergencyLithiumBatteryGroup1CircuitBreaker = 1 : pdis4 -> emergencyLithiumBatteryGroup1CircuitBreaker = 0;
pdis4 -> paceholder = 0;
m_pm->m_currentDisBreakerState.bus4Breaker = *pdis4;
delete pdis4;
}
m_pm->m_systemData->updateSystemData(m_pm->m_pmCurrentState.ccustate);
m_pm->m_systemData->updateSystemData(m_pm->m_pmCurrentState.bus1State);
m_pm->m_systemData->updateSystemData(m_pm->m_pmCurrentState.bus2State);
m_pm->m_systemData->updateSystemData(m_pm->m_pmCurrentState.bus3State);
m_pm->m_systemData->updateSystemData(m_pm->m_pmCurrentState.bus4State);
m_pm->m_systemData->device_common_status.ccu_status.lastUpdateTime = m_pm->m_lowerCommManager->msg_CcuStateFbMsg_Update_time;
m_pm->m_systemData->device_common_status.dis_hv_c1.lastUpdateTime = m_pm->m_lowerCommManager->msg_disHighVolBusFbMsg_Update_time;
m_pm->m_systemData->device_common_status.dis_hv_c2.lastUpdateTime = m_pm->m_lowerCommManager->msg_disHighAVolBusFbMsg_Update_time;
m_pm->m_systemData->device_common_status.dis_lv_c1.lastUpdateTime = m_pm->m_lowerCommManager->msg_disHighBVolBusFbMsg_Update_time;
m_pm->m_systemData->device_common_status.dis_lv_c2.lastUpdateTime = m_pm->m_lowerCommManager->msg_disLowBusFbMsg_Update_time;
return true;
}
bool LowerCommManager::listenThreadFunc()
{
cout<<MOOS::ConsoleColours::green()<< "LowerCommManager::listenThreadFunc" << MOOS::ConsoleColours::reset() << endl;
unsigned char Buff[1024];
while(!m_ListenThread.IsQuitRequested())
{
try
{
int nRead = m_udpComm->udpScoket->iRecieveMessage(Buff, sizeof(Buff));
cout<<MOOS::ConsoleColours::yellow()<< "RECEVE DATA COUNT:" << nRead << MOOS::ConsoleColours::reset() << endl;
if(nRead > 0)
{
try {
if(!m_udpComm->pushMsgToQueue(Buff))
{
for(int i=0; i<m_udpComm->sError.size(); i++)
{
cout<<MOOS::ConsoleColours::red()<< m_udpComm->sError[i] << MOOS::ConsoleColours::reset() << endl;
}
}
//更新当前状态
if(!updatePoweSystemStates())
{
std::cerr << "Error updating power system states" << std::endl;
}
}
catch(const std::exception& e) {
cerr << "Error processing message: " << e.what() << endl;
}
}
// 打印通信错误信息
if(!m_udpComm->sError.empty())
{
for(int i=0; i<m_udpComm->sError.size(); i++)
{
cout<<MOOS::ConsoleColours::red() << m_udpComm->sError[i] << MOOS::ConsoleColours::reset() << endl;
}
m_udpComm->sError.clear();
}
}
catch(const XPCException& e)
{
cerr << "XPCException in listenThreadFunc" << endl;
// 短暂休眠后继续尝试
MOOSPause(100);
}
catch(const std::exception& e)
{
cerr << "Exception in listenThreadFunc: " << e.what() << endl;
MOOSPause(100);
}
catch(...)
{
cerr << "Unknown exception in listenThreadFunc" << endl;
MOOSPause(100);
}
}
return true;
}
void LowerCommManager::startListenThread()
{
if(!m_ListenThread.IsThreadRunning())
{
m_ListenThread.Initialise(_ListenCB,this);
m_ListenThread.Start();
std::cout << "LowerCommManager::startListenThread" << std::endl;
}
}
void LowerCommManager::stopListenThread()
{
if(m_ListenThread.IsThreadRunning())
{
m_ListenThread.Stop();
std::cout << "LowerCommManager::stopListenThread" << std::endl;
}
}
char LowerCommManager::getBreakerOption(char cmd)
{
if(cmd ==1)
return 0x55;
else if(cmd ==0)
return 0xAA;
else
return 0x00;
}
void LowerCommManager::coutMsg(const msg_CcuStateFbMsg& p, std::ostream& os){
os << std::hex << std::setfill('0') << std::uppercase;
os << "起始符1 (start1): 0x" << std::setw(2) << static_cast<int>(p.header.start1) << "\n";
os << "起始符2 (start2): 0x" << std::setw(2) << static_cast<int>(p.header.start2) << "\n";
os << "标识符 (identifier): 0x" << std::setw(4) << p.header.id << "\n";
os << std::dec << "数据长度 (length): " << p.header.length << "\n";
os << "运行模式 (fc_mode): 0x" << std::hex << std::setw(2) << static_cast<int>(p.data.fc_mode) << "\n";
os << "燃料电池状态 (fc_status): 0x" << std::setw(2) << static_cast<int>(p.data.fc_status) << "\n";
os << "故障等级 (fc_fault_level): 0x" << std::setw(2) << static_cast<int>(p.data.fc_fault_level) << "\n";
os << std::dec;
os << "输出功率限制 (output_power_limit): " << p.data.output_power_limit << " W\n";
os << "累计发电时间 (total_generation_time): " << p.data.total_generation_time * 0.1 << " 小时\n";
os << "发电总功率 (total_generation_power): " << p.data.total_generation_power << " W\n";
os << "一级故障字 (fault_level_1): 0x" << std::hex << p.data.fault_level_1 << "\n";
os << "二级故障字 (fault_level_2): 0x" << p.data.fault_level_2 << "\n";
os << "三级故障字 (fault_level_3): 0x" << p.data.fault_level_3 << "\n";
os << "四级故障字 (fault_level_4): 0x" << p.data.fault_level_4 << "\n";
os << std::dec;
os << "储氢剩余容量 (hydrogen_capacity): " << static_cast<int>(p.data.hydrogen_capacity) << "%\n";
os << "液氧剩余容量 (liquid_oxygen_capacity): " << static_cast<int>(p.data.liquid_oxygen_capacity) << "%\n";
os << "钯膜最高温度 (palladium_temp): " << p.data.palladium_temp << " ℃\n";
os << "主水路压力 (main_pipe_pressure): " << p.data.main_pipe_pressure * 0.01 << " kPa\n";
os << "辅水路压力 (aux_pipe_pressure): " << p.data.aux_pipe_pressure * 0.01 << " kPa\n";
os << "舱室压力1 (cabin_pressure1): " << p.data.cabin_pressure1 * 0.01 << " kPa\n";
os << "舱室压力2 (cabin_pressure2): " << p.data.cabin_pressure2 * 0.01 << " kPa\n";
os << "舱室温度1 (cabin_temp1): " << p.data.cabin_temp1 * 0.01 << " ℃\n";
os << "舱室温度2 (cabin_temp2): " << p.data.cabin_temp2 * 0.01 << " ℃\n";
os << "舱室湿度1 (cabin_humidity1): " << p.data.cabin_humidity1 * 0.01 << " %RH\n";
os << "舱室湿度2 (cabin_humidity2): " << p.data.cabin_humidity2 * 0.01 << " %RH\n";
os << "火焰探测器1状态 (flame_detector1): 0x" << std::hex << static_cast<int>(p.data.flame_detector1) << "\n";
os << "火焰探测器2状态 (flame_detector2): 0x" << static_cast<int>(p.data.flame_detector2) << "\n";
os << std::dec;
os << "氢气浓度1 (h2_concentration1): " << p.data.h2_concentration1 * 0.01 << "% LEL\n";
os << "氢气浓度2 (h2_concentration2): " << p.data.h2_concentration2 * 0.01 << "% LEL\n";
os << "氢气浓度3 (h2_concentration3): " << p.data.h2_concentration3 * 0.01 << "% LEL\n";
os << "氧气浓度1 (o2_concentration1): " << p.data.o2_concentration1 * 0.01 << "% LEL\n";
os << "氧气浓度2 (o2_concentration2): " << p.data.o2_concentration2 * 0.01 << "% LEL\n";
os << "甲醇浓度1 (ch3oh_concentration1): " << p.data.ch3oh_concentration1 * 0.01 << "% LEL\n";
os << "甲醇浓度2 (ch3oh_concentration2): " << p.data.ch3oh_concentration2 * 0.01 << "% LEL\n";
for (int i = 0; i < 10; ++i)
os << "保留字段 reserved1[" << i << "]: 0x" << std::hex << p.data.reserved1[i] << "\n";
os << "仪表舱 氧气浓度 (cabin_ox_concentration): " << p.data.cabin_ox_concentration * 0.1 << "%\n";
os << "仪表舱 温度 (cabin_temperature): " << static_cast<int16_t> (p.data.cabin_temperature) * 0.1 << "°C\n";
os << "仪表舱 湿度 (cabin_humidity): " << p.data.cabin_humidity * 0.1 << "% RH\n";
os << "仪表舱 大气压 (cabin_pressure): " << p.data.cabin_pressure * 0.2 << " kPa\n";
os << "动力舱 氧气浓度 (power_cabin_ox_concentration): " << p.data.power_cabin_ox_concentration * 0.1 << "%\n";
os << "动力舱 温度 (power_cabin_temperature): " << static_cast<int16_t> (p.data.power_cabin_temperature) * 0.1 << "°C\n";
os << "动力舱 湿度 (power_cabin_humidity): " << p.data.power_cabin_humidity * 0.1 << "% RH\n";
os << "动力舱 大气压 (power_cabin_pressure): " << p.data.power_cabin_pressure * 0.2 << " kPa\n";
for (int i = 0; i < 6; ++i)
os << "动力电池报警标志 dyn_alarm_flag[" << i << "]: 0x" << std::hex << static_cast<int>(p.data.dyn_alarm_flag[i]) << "\n";
for (int i = 0; i < 6; ++i)
os << "仪表电池报警标志 ins_alarm_flag[" << i << "]: 0x" << std::hex << static_cast<int>(p.data.ins_alarm_flag[i]) << "\n";
os << "仪表正极/充电继电器状态 (ins_relay_status1): 0x" << std::hex << static_cast<int>(p.data.ins_relay_status1) << "\n";
os << "仪表预充/负极继电器状态 (ins_relay_status2): 0x" << static_cast<int>(p.data.ins_relay_status2) << "\n";
os << "动力正极/充电继电器状态 (dyn_relay_status1): 0x" << static_cast<int>(p.data.dyn_relay_status1) << "\n";
os << "动力预充/负极继电器状态 (dyn_relay_status2): 0x" << static_cast<int>(p.data.dyn_relay_status2) << "\n";
os << std::dec;
os << "仪表最大放电功率 (ins_max_discharge_power): " << p.data.ins_max_discharge_power * 0.05 << " kW\n";
os << "动力最大放电功率 (dyn_max_discharge_power): " << p.data.dyn_max_discharge_power * 0.05 << " kW\n";
os << "仪表SOC (ins_soc): " << static_cast<int>(p.data.ins_soc) << "%\n";
os << "动力SOC (dyn_soc): " << static_cast<int>(p.data.dyn_soc) << "%\n";
os << "仪表电池总能量 (ins_total_energy): " << p.data.ins_total_energy * 0.1 << " kWh\n";
os << "动力电池总能量 (dyn_total_energy): " << p.data.dyn_total_energy * 0.1 << " kWh\n";
os << "仪表输入功率 (ins_power_input): " << p.data.ins_power_input * 0.1 << " kW\n";
os << "动力输入功率 (dyn_power_input): " << p.data.dyn_power_input * 0.1 << " kW\n";
os << "仪表充电状态 (ins_charge_status): 0x" << std::hex << static_cast<int>(p.data.ins_charge_status) << "\n";
os << "动力充电状态 (dyn_charge_status): 0x" << static_cast<int>(p.data.dyn_charge_status) << "\n";
os << std::dec;
os << "仪表LINK电压: " << p.data.ins_voltage_link * 0.01 << " V\n";
os << "仪表PACK电压: " << p.data.ins_voltage_pack * 0.01 << " V\n";
os << "仪表电流: " << static_cast<int16_t> (p.data.ins_current) * 0.05 << " A\n";
os << "仪表正端绝缘电阻: " << p.data.ins_resistance_pos << " kΩ\n";
os << "仪表负端绝缘电阻: " << p.data.ins_resistance_neg << " kΩ\n";
os << "动力LINK电压: " << p.data.dyn_voltage_link * 0.01 << " V\n";
os << "动力PACK电压: " << p.data.dyn_voltage_pack * 0.01 << " V\n";
os << "动力电流: " << static_cast<int16_t> (p.data.dyn_current) * 0.05 << " A\n";
os << "动力正端绝缘电阻: " << p.data.dyn_resistance_pos << " kΩ\n";
os << "动力负端绝缘电阻: " << p.data.dyn_resistance_neg << " kΩ\n";
os << "仪表紧急状态 (ins_emergency_status): 0x" << std::hex << static_cast<int>(p.data.ins_emergency_status) << "\n";
os << "动力紧急状态 (dyn_emergency_status): 0x" << static_cast<int>(p.data.dyn_emergency_status) << "\n";
for (int i = 0; i < 2; ++i)
os << "保留字段 reserved2[" << i << "]: 0x" << std::hex << static_cast<int>(p.data.reserved2[i]) << "\n";
for (int i = 0; i < 6; ++i)
os << "SOC门限值 ins_soc_threshold" << i+1 << ": 0x" << std::hex << static_cast<int>(p.data.ins_soc_threshold1) << "\n";
for (int i = 0; i < 4; ++i)
os << "功率限制 ins_power_limit" << i+1 << ": 0x" << std::hex << static_cast<int>(p.data.ins_power_limit1) << "\n";
os << "设备在线状态1 (device_online_flag1): 0x" << std::hex << p.data.device_online_flag1 << "\n";
os << "设备在线状态2 (device_online_flag2): 0x" << p.data.device_online_flag2 << "\n";
// os << "保留字段 reserved3: 0x" << p.data.reserved1 << "\n";
os << "主机心跳 (reserved4): 0x" << p.data.heartbeat << "\n";
os << "校验和 (checksum): 0x" << p.checkCode << "\n";
os << std::dec;
}
//================================================================================================================
// 高电压母线断路器操作函数
bool LowerCommManager::operate_HV_fuelCellCircuit_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_fuelCellCircuit_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.fuelCellCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.fuelCellCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_powerLithiumBattery_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_powerLithiumBattery_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.powerLithiumBatteryCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.powerLithiumBatteryCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_propulsionMotor_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_propulsionMotor_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.propulsionMotorCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.propulsionMotorCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_lithiumBatteryMeter_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_lithiumBatteryMeter_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.lithiumBatteryGroupInstrumentCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_dcDc5Module_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_dcDc5Module_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.dcDc5ModuleCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.dcDc5ModuleCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_bowHighVoltageBox_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_bowHighVoltageBox_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.bowHighVoltageDistributionBoxCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.bowHighVoltageDistributionBoxCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_sternFt45_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_sternFt45_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.sternFTDevice45CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.sternFTDevice45CircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_sternRudder1_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_sternRudder1_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.sternRudderSwitch1CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.sternRudderSwitch1CircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_sternRudder2_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_sternRudder2_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.sternRudderSwitch2CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.sternRudderSwitch2CircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_fbReserved_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_fbReserved_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.fbReservedCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.fbReservedCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_tyzReserved_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_tyzReserved_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.tyzReservedCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.tyzReservedCircuitBreaker; }
);
}
bool LowerCommManager::operate_HV_reserved_Breaker(char opt){
return operateBreakerGeneric<disHighVolBusCmd, char>(
"HV_reserved_Breaker",
opt,
[&](disHighVolBusCmd& c){ c.reservedCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus1State.reservedCircuitBreaker; }
);
}
// bool LowerCommManager::operate_HV_dcDc5_Breaker(char opt){
// return operateBreakerGeneric<disHighVolBusCmd, char>(
// "HV_dcDc5_Breaker",
// opt,
// [&](disHighVolBusCmd& c){ c.dcdc5Module = getBreakerOption(opt); },
// [&](){ return m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1&(0x02); }
// );
// }
bool LowerCommManager::operate_HV_dcDc5_Breaker(char opt)
{
disHighVolBusCmd cmd{}; // 默认全零
double t0 = MOOSTime();
bool ok = false;
string name = "DCDC Module";
LOG_F(INFO, "operate %s: opt=%d", name, opt);
cmd.dcdc5Module = getBreakerOption(opt);
m_udpComm->sendDisSysCmd(cmd);
// ok = m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1&(0x02);
ok = m_pm->m_systemData->m_dcdcStatus.workingStatus;
MOOSPause(100);
while ( !ok ) {
if( m_pm->m_systemData->m_dcdcStatus.workingStatus )
{
ok = true;
break;
}
if (!m_udpComm->sendDisSysCmd(cmd)) {
LOG_F(ERROR, "operate %s: sendDisSysCmd failed", name);
ok = false;
break;
}
if (MOOSTime() > t0 + 6) {
LOG_F(ERROR, "operate %s: timeout", name);
ok = false;
break;
}
MOOSPause(200);
}
//继电器复位
disHighVolBusCmd clr{};
for (int i = 0; i < 3; ++i)
{
m_udpComm->sendDisSysCmd(clr);
MOOSPause(200);
}
return ok;
}
// bool LowerCommManager::operate_HV_coolingSystem_Breaker(char opt){
// return operateBreakerGeneric<disHighVolBusCmd, char>(
// "HV_coolingSystem_Breaker",
// opt,
// [&](disHighVolBusCmd& c){ c.coolingSystem = getBreakerOption(opt); },
// [&](){ return (m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1 & 0x20) ? 0x55 : 0xAA; }
// );
// }
bool LowerCommManager::operate_HV_coolingSystem_Breaker(char opt)
{
disHighVolBusCmd cmd{}; // 默认全零
double t0 = MOOSTime();
bool ok = false;
string name = "CoolingSystem";
LOG_F(INFO, "operate %s: opt=%d", name, opt);
cmd.coolingSystem = getBreakerOption(opt);
m_udpComm->sendDisSysCmd(cmd);
// ok = m_pm->m_pmCurrentState.bus1State.dcDcFaultWord1 & 0x60;
ok = m_pm->m_systemData->m_dcdcStatus.coolingPump1Running || m_pm->m_systemData->m_dcdcStatus.coolingPump2Running;
MOOSPause(100);
while ( !ok ) {
if( (m_pm->m_systemData->m_dcdcStatus.coolingPump1Running || m_pm->m_systemData->m_dcdcStatus.coolingPump2Running) )
{
ok = true;
break;
}
if (!m_udpComm->sendDisSysCmd(cmd)) {
LOG_F(ERROR, "operate %s: sendDisSysCmd failed", name);
ok = false;
break;
}
if (MOOSTime() > t0 + 6) {
LOG_F(ERROR, "operate %s: timeout", name);
ok = false;
break;
}
MOOSPause(200);
}
//继电器复位
disHighVolBusCmd clr{};
for (int i = 0; i < 3; ++i)
{
m_udpComm->sendDisSysCmd(clr);
MOOSPause(200);
}
return ok;
}
// 高压汇流排断路器操作函数
bool LowerCommManager::operate_HVA_bowFTDevice123Circuit_Breaker(char opt){
return operateBreakerGeneric<disHighAVolBusCmd, char>(
"HVA_bowFTDevice123Circuit_Breaker",
opt,
[&](disHighAVolBusCmd& c){ c.bowFTDevice123CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus2State.bowFTDevice123CircuitBreaker; }
);
}
bool LowerCommManager::operate_HVA_actuatorCircuit_Breaker(char opt){
return operateBreakerGeneric<disHighAVolBusCmd, char>(
"HVA_actuatorCircuit_Breaker",
opt,
[&](disHighAVolBusCmd& c){ c.actuatorCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus2State.actuatorCircuitBreaker; }
);
}
bool LowerCommManager::operate_HVA_mastSteeringGearControlBoxCircuit_Breaker(char opt){
return operateBreakerGeneric<disHighAVolBusCmd, char>(
"HVA_mastSteeringGearControlBoxCircuit_Breaker",
opt,
[&](disHighAVolBusCmd& c){ c.mastSteeringGearControlBoxCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus2State.mastSteeringGearControlBoxCircuitBreaker; }
);
}
bool LowerCommManager::operate_HVA_xczCircuit_Breaker(char opt){
return operateBreakerGeneric<disHighAVolBusCmd, char>(
"HVA_xczCircuit_Breaker",
opt,
[&](disHighAVolBusCmd& c){ c.xczCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus2State.xczCircuitBreaker; }
);
}
bool LowerCommManager::operate_HVA_bowRudderControlBoxCircuit_Breaker(char opt){
return operateBreakerGeneric<disHighAVolBusCmd, char>(
"HVA_bowRudderControlBoxCircuit_Breaker",
opt,
[&](disHighAVolBusCmd& c){ c.bowRudderControlBoxCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus2State.bowRudderControlBoxCircuitBreaker; }
);
}
bool LowerCommManager::operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(char opt){
return operateBreakerGeneric<disHighAVolBusCmd, char>(
"HVA_openWaterCoverStartCylinderCircuit_Breaker",
opt,
[&](disHighAVolBusCmd& c){ c.openWaterCoverStartCylinderCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus2State.openWaterCoverStartCylinderCircuitBreaker; }
);
}
// 仪表汇流排断路器操作函数
bool LowerCommManager::operate_LVA_unit1Circuit_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_unit1Circuit_Breaker",
opt,
[&](disLowBusCmd& c){ c.unit1CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.unit1CircuitBreaker; }
);
}
bool LowerCommManager::operate_LVA_unit2Circuit_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_unit2Circuit_Breaker",
opt,
[&](disLowBusCmd& c){ c.unit2CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.unit2CircuitBreaker; }
);
}
bool LowerCommManager::operate_LVA_unit3Circuit_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_unit3Circuit_Breaker",
opt,
[&](disLowBusCmd& c){ c.unit3CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.unit3CircuitBreaker; }
);
}
bool LowerCommManager::operate_LVA_unit5Circuit_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_unit5Circuit_Breaker",
opt,
[&](disLowBusCmd& c){ c.unit5CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.unit5CircuitBreaker; }
);
}
bool LowerCommManager::operate_LVA_bowPZDeviceCircuit_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_bowPZDeviceCircuit_Breaker",
opt,
[&](disLowBusCmd& c){ c.bowPZDeviceCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.bowPZDeviceCircuitBreaker; }
);
}
bool LowerCommManager::operate_LVA_reservedCircuit1_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_reservedCircuit1_Breaker",
opt,
[&](disLowBusCmd& c){ c.reservedCircuitBreaker1 = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.reservedCircuitBreaker1; }
);
}
bool LowerCommManager::operate_LVA_reservedCircuit2_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_reservedCircuit2_Breaker",
opt,
[&](disLowBusCmd& c){ c.reservedCircuitBreaker2 = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.reservedCircuitBreaker2; }
);
}
bool LowerCommManager::operate_LVA_mergencyLithiumBatteryGroup1Circuit_Breaker(char opt){
return operateBreakerGeneric<disLowBusCmd, char>(
"LVA_mergencyLithiumBatteryGroup1Circuit_Breaker",
opt,
[&](disLowBusCmd& c){ c.emergencyLithiumBatteryGroup1CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus4State.emergencyLithiumBatteryGroup1CircuitBreaker; }
);
}
// 仪表母线断路器操作函数
bool LowerCommManager::operate_LV_lithiumBatteryGroupInstrumentCircuit_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"lithiumBatteryGroupInstrumentCircuitBreaker",
opt,
[&](disLowMainBusCmd& c){ c.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.lithiumBatteryGroupInstrumentCircuitBreaker; }
);
}
bool LowerCommManager::operate_LV_bowLowVoltageDistributionBoxCircuit_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"bowLowVoltageDistributionBoxCircuitBreaker",
opt,
[&](disLowMainBusCmd& c){ c.bowLowVoltageDistributionBoxCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.bowLowVoltageDistributionBoxCircuitBreaker; }
);
}
bool LowerCommManager::operate_LV_unit4Dc48V_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"unit4InstrumentDC48VCircuitBreaker",
opt,
[&](disLowMainBusCmd& c){ c.unit4InstrumentDC48VCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.unit4InstrumentDC48VCircuitBreaker; }
);
}
bool LowerCommManager::operate_LV_dcC1Panel_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"dcC1DCDistributionPanelCircuitBreaker",
opt,
[&](disLowMainBusCmd& c){ c.dcC1DCDistributionPanelCircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.dcC1DCDistributionPanelCircuitBreaker; }
);
}
bool LowerCommManager::operate_LV_reservedCircuit1_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"reservedCircuitBreaker1",
opt,
[&](disLowMainBusCmd& c){ c.reservedCircuitBreaker1 = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.reservedCircuitBreaker1; }
);
}
bool LowerCommManager::operate_LV_reservedCircuit2_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"reservedCircuitBreaker2",
opt,
[&](disLowMainBusCmd& c){ c.reservedCircuitBreaker2 = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.reservedCircuitBreaker2; }
);
}
bool LowerCommManager::operate_LV_mergencyLithiumBatteryGroup2Circuit_Breaker(char opt){
return operateBreakerGeneric<disLowMainBusCmd, char>(
"emergencyLithiumBatteryGroup2CircuitBreaker",
opt,
[&](disLowMainBusCmd& c){ c.emergencyLithiumBatteryGroup2CircuitBreaker = getBreakerOption(opt); },
[&](){ return m_pm->m_pmCurrentState.bus3State.emergencyLithiumBatteryGroup2CircuitBreaker; }
);
}
// 通用模板
template<typename CmdT, typename StateT>
bool LowerCommManager::operateBreakerGeneric(
char const* name,
char opt,
std::function<void(CmdT&)> fillCmd, // 填 cmd 对应字段
std::function<StateT()> readState // 读 pmCurrentState 对应字段
) {
CmdT cmd{}; // 默认全零
double t0 = MOOSTime();
bool ok = false;
LOG_F(INFO, "operate %s: opt=%d", name, opt);
// 第一次发包
fillCmd(cmd);
m_udpComm->sendDisSysCmd(cmd);
MOOSPause(100);
while ( !ok ) {
if( readState() == getBreakerOption(opt) )
{
ok = true;
break;
}
if (!m_udpComm->sendDisSysCmd(cmd)) {
LOG_F(ERROR, "operate %s: sendDisSysCmd failed", name);
ok = false;
break;
}
if (MOOSTime() > t0 + 6) {
LOG_F(ERROR, "operate %s: timeout", name);
ok = false;
break;
}
MOOSPause(200);
}
//继电器复位
CmdT clr{};
for (int i = 0; i < 3; ++i)
{
m_udpComm->sendDisSysCmd(clr);
MOOSPause(200);
}
return ok;
}
+128
View File
@@ -0,0 +1,128 @@
#ifndef LOWER_COMM_MANAGER_H
#define LOWER_COMM_MANAGER_H
#define UNIX
#include "MOOS/libMOOS/Comms/XPCUdpSocket.h"
#include "MOOS/libMOOS/Utils/MOOSThread.h"
#include "MOOS/libMOOS/Utils/MOOSLock.h"
#include "../udpcomm/ccuUdpMsg.h"
#include "pmSysvariable.h"
#include <queue>
#include <map>
#include <functional>
#include <atomic>
#include <vector>
#include "udpcomm/udpComm.h"
#include <functional>
class PowerManger; // 前向声明
class LowerCommManager {
public:
LowerCommManager(PowerManger* pm, long myPort, long ccuPort, const std::string& cccHost);
~LowerCommManager();
//processPeriodicTasks
void processPeriodicTasks();
//clearMsgQueue
void clearMsgQueue();
public:
// 初始化UDP通信
bool initUdpComm();
// 更新设备状态
bool updatePoweSystemStates();
//================================断路器操作函数=======================================
template<typename CmdT, typename StateT>
bool operateBreakerGeneric(
char const* name,
char opt,
std::function<void(CmdT&)> fillCmd, // 填 cmd 对应字段
std::function<StateT()> readState // 读 pmCurrentState 对应字段
);
// 高电压母线
bool operate_HV_fuelCellCircuit_Breaker(char opt);
bool operate_HV_powerLithiumBattery_Breaker(char opt);
bool operate_HV_propulsionMotor_Breaker(char opt);
bool operate_HV_lithiumBatteryMeter_Breaker(char opt);
bool operate_HV_dcDc5Module_Breaker(char opt);
bool operate_HV_bowHighVoltageBox_Breaker(char opt);
bool operate_HV_sternFt45_Breaker(char opt);
bool operate_HV_sternRudder1_Breaker(char opt);
bool operate_HV_sternRudder2_Breaker(char opt);
bool operate_HV_fbReserved_Breaker(char opt);
bool operate_HV_tyzReserved_Breaker(char opt);
bool operate_HV_reserved_Breaker(char opt);
bool operate_HV_dcDc5_Breaker(char opt);
bool operate_HV_coolingSystem_Breaker(char opt);
// 高压汇流排
bool operate_HVA_bowFTDevice123Circuit_Breaker(char opt);
bool operate_HVA_actuatorCircuit_Breaker(char opt);
bool operate_HVA_mastSteeringGearControlBoxCircuit_Breaker(char opt);
bool operate_HVA_xczCircuit_Breaker(char opt);
bool operate_HVA_bowRudderControlBoxCircuit_Breaker(char opt);
bool operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(char opt);
// 仪表母线
bool operate_LV_lithiumBatteryGroupInstrumentCircuit_Breaker(char opt);
bool operate_LV_bowLowVoltageDistributionBoxCircuit_Breaker(char opt);
bool operate_LV_unit4Dc48V_Breaker(char opt);
bool operate_LV_dcC1Panel_Breaker(char opt);
bool operate_LV_reservedCircuit1_Breaker(char opt);
bool operate_LV_reservedCircuit2_Breaker(char opt);
bool operate_LV_mergencyLithiumBatteryGroup2Circuit_Breaker(char opt);
// 仪表汇流排
bool operate_LVA_unit1Circuit_Breaker(char opt);
bool operate_LVA_unit2Circuit_Breaker(char opt);
bool operate_LVA_unit3Circuit_Breaker(char opt);
bool operate_LVA_unit5Circuit_Breaker(char opt);
bool operate_LVA_bowPZDeviceCircuit_Breaker(char opt);
bool operate_LVA_reservedCircuit1_Breaker(char opt);
bool operate_LVA_reservedCircuit2_Breaker(char opt);
bool operate_LVA_mergencyLithiumBatteryGroup1Circuit_Breaker(char opt);
//保持指令
void operate_hold();
//================================复合管控器操作函数====================================
// 发送CCU控制命令
bool sendCcuCommand(const ccuColCmd cmd);
bool sendDisSysCommand(const disSysBreakerList& cmd); //已废弃,不同时操作多个继电器设备
// 启动/停止监听线程
void startListenThread();
void stopListenThread();
void coutMsg(const msg_CcuStateFbMsg& p, std::ostream& os = std::cout);
//转换函数
char getBreakerOption(char cmd);
// 配电和CCU的反馈状态
msg_CcuStateFbMsg m_CcuCurrentState;
msg_disHighVolBusFbMsg m_disHighVolBusCurrentState;
msg_disHighAVolBusFbMsg m_disHighAVolBusCurrentState;
msg_disLowMainBusFbMsg m_disHighBVolBusCurrentState;
msg_disLowBusFbMsg m_disLowBusState;
// 配电和CCU的反馈状态时间戳
double msg_CcuStateFbMsg_Update_time;
// double msg_CcuSetParmFbMsg_Update_time;
double msg_disHighVolBusFbMsg_Update_time;
double msg_disHighAVolBusFbMsg_Update_time;
double msg_disHighBVolBusFbMsg_Update_time;
double msg_disLowBusFbMsg_Update_time;
public:
long m_port;
long m_ccuPort;
std::string m_ccuHost;
std::string m_host;
PowerManger* m_pm;
udpComm* m_udpComm;
CMOOSThread m_ListenThread;
int m_connectState;
// UDP监听线程函数
bool listenThreadFunc();
};
#endif // LOWER_COMM_MANAGER_H
+403
View File
@@ -0,0 +1,403 @@
/************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: PowerManger.cpp */
/* DATE: December 29th, 1963 */
/************************************************************/
#include <iterator>
#include "MBUtils.h"
#include "ACTable.h"
#include "PowerManger.h"
#include "logc/loguru.hpp"
#include <memory>
using namespace std;
bool _FsmCB(void * pParam)
{
PowerManger* pMe = (PowerManger* )pParam;
return pMe->FsmLoop();
}
bool _CommCB(void * pParam)
{
PowerManger* pMe = (PowerManger* )pParam;
return pMe->commLoop();
}
//---------------------------------------------------------
// Constructor()
PowerManger::PowerManger()
{
workCondition = 0;
currentMod = 0;
powerState = 0;
faultLevel = 0;
soc = 0;
sustainableTime = 0;
m_faultNum = 0;
m_ticker = 0;
m_leakage = 0;
m_thrustRpm = 0;
m_thrustEnable = 0;
faultCode.clear();
m_skew = 10;
m_pmCurrentState = {};
m_currentDisBreakerState = {};
m_targetDisBreakerState = {};
m_currentDriverState = {};
m_MSDriverCmd = {};
m_subDisSysCmd = {};
m_subDisSysState = {};
m_subDisSysFault = {};
//初始化控制指令
initControlCmd();
//初始化下位机通信
m_lowerCommManager = new LowerCommManager(this,IPORT,CCUPORT,CCUHOST);
m_lowerCommManager->initUdpComm();
m_lowerCommManager->startListenThread();
//初始化上位机通信
m_upperCommManager = new UpperCommManager(this);
//初始化数据库
m_db = new SQLite("power_data.db");
m_db->createTable();
//初始化系统数据
m_systemData = new SystemData();
//初始化http服务器
m_httpServer = new HttpServer(8090);
m_httpServer->setPowerManger(this);
m_httpServer->setLowerCommManager(m_lowerCommManager);
m_httpServer->setSystemData(m_systemData);
m_httpServer->start();
}
//---------------------------------------------------------
// Destructor
PowerManger::~PowerManger()
{
m_commThread.Stop();
delete m_db;
delete m_lowerCommManager;
delete m_upperCommManager;
delete m_systemData;
delete m_httpServer;
}
//---------------------------------------------------------
// Procedure: OnNewMail()
bool PowerManger::OnNewMail(MOOSMSG_LIST &NewMail)
{
AppCastingMOOSApp::OnNewMail(NewMail);
MOOSMSG_LIST::iterator p;
for(p=NewMail.begin(); p!=NewMail.end(); p++)
{
CMOOSMsg &msg = *p;
string key = msg.GetKey();
string strJson = msg.GetString();
double dfT;
msg.IsSkewed(m_curr_time, &dfT);
if(fabs(dfT) > m_skew)
{
LOG_F(INFO, "Message from %s at time %f is Skewed", msg.GetSource().c_str(), dfT);
return true;
}
//处理上位机发送的控制指令
if(!m_upperCommManager->processUpperMsg(key,strJson))
{
LOG_F(ERROR, "上位机消息处理错误: %s", key.c_str());
}
#if 0 // Keep these around just for template
string comm = msg.GetCommunity();
double dval = msg.GetDouble();
string sval = msg.GetString();
string msrc = msg.GetSource();
double mtime = msg.GetTime();
bool mdbl = msg.IsDouble();
bool mstr = msg.IsString();
#endif
if(key == "FOO")
LOG_F(INFO, "Received FOO message");
else if(key != "APPCAST_REQ") // handled by AppCastingMOOSApp
reportRunWarning("Unhandled Mail: " + key);
}
return(true);
}
//---------------------------------------------------------
// Procedure: OnConnectToServer()
bool PowerManger::OnConnectToServer()
{
registerVariables();
return(true);
}
//---------------------------------------------------------
// Procedure: Iterate()
// happens AppTick times per second
//固定为4Hz
bool PowerManger::Iterate()
{
AppCastingMOOSApp::Iterate();
// 触发定时任务
CycleTriggeredEvent cycleEvent;
PowerManagerFsm::dispatch(cycleEvent);
faultLevel = getFaultLevel();
m_systemData->updateCommonStatus();
// m_CcuColCmd.heartbeat
// if (m_ticker++ % 5 == 0)
// {
// m_CcuColCmd.heartbeat++;
// m_lowerCommManager->processPeriodicTasks();
// m_upperCommManager->processPeriodicTasks();
// }
return(true);
}
//---------------------------------------------------------
// Procedure: OnStartUp()
// happens before connection is open
bool PowerManger::OnStartUp()
{
AppCastingMOOSApp::OnStartUp();
STRING_LIST sParams;
m_MissionReader.EnableVerbatimQuoting(false);
if(!m_MissionReader.GetConfiguration(GetAppName(), sParams))
reportConfigWarning("No config block found for " + GetAppName());
STRING_LIST::iterator p;
for(p=sParams.begin(); p!=sParams.end(); p++) {
string orig = *p;
string line = *p;
string param = tolower(biteStringX(line, '='));
string value = line;
bool handled = false;
if(param == "foo") {
handled = true;
}
else if(param == "bar") {
handled = true;
}
if(!handled)
reportUnhandledConfigWarning(orig);
}
registerVariables();
// 初始化状态机
PowerManagerFsm::init(this);
PowerManagerFsm::start();
InitEvent initEvent;
PowerManagerFsm::dispatch(initEvent);
//初始化通信线程
m_commThread.Initialise(_CommCB,this);
m_commThread.Start();
return(true);
}
//---------------------------------------------------------
// Procedure: registerVariables()
void PowerManger::registerVariables()
{
AppCastingMOOSApp::RegisterVariables();
// Register(DB_TO_PM_SUBDISSTATE, 0);
Register(DB_TO_PM_MSCMD, 0);
Register(DB_TO_PM_EQUIPMENTCMD, 0);
Register(m_upperCommManager->m_secdistStateMsg.key_fb,0);
Register(DB_TO_PM_MISSION,0);
Register(DB_TO_PM_DEEPTH,0);
Register(DB_TO_PM_SETOPCONDITION,0);
Register(DB_TO_PM_SETOPMODE,0);
Register(DB_TO_PM_SETPMSYS,0);
Register(DB_TO_PM_SETDEVSWITCH,0);
Register(DB_TO_PM_TASKSTOP,0);
Register(uDetect_xcVoltage_cmd::key,0);
Register(uDetect_zdpVoltage_cmd::key,0);
Register(uDevice_thruster_st::key,0);
// Register(uExternComm_setThrustSpeed_cmd::key,0);
}
//------------------------------------------------------------
// Procedure: buildReport()
bool PowerManger::buildReport()
{
m_msgs << "============================================" << endl;
m_msgs << "File: " << endl;
m_msgs << "============================================" << endl;
ACTable actab(4);
actab << "Alpha | Bravo | Charlie | Delta";
actab.addHeaderLines();
actab << "one" << "two" << "three" << "four";
m_msgs << actab.getFormattedString();
return(true);
}
bool PowerManger::FsmLoop()
{
return true;
}
int PowerManger::checkError()
{
//TODO:更新协议
//1.检查复合管控器状态
// if(m_pmCurrentState.ccustate.fcuGZ_1H != 0 ||
// m_pmCurrentState.ccustate.fcuGZ_1L != 0 ||
// m_pmCurrentState.ccustate.fcuGZ_2H != 0 ||
// m_pmCurrentState.ccustate.fcuGZ_2L != 0 ||
// m_pmCurrentState.ccustate.fcuGZ_3H != 0 ||
// m_pmCurrentState.ccustate.fcuGZ_3L != 0 ||
// m_pmCurrentState.ccustate.insEmergencyStatusWord != 0)
return 0;
}
void PowerManger::printState(const std::string& stateName, const std::string& desp){
if (desp.find("故障") != string::npos) {
LOG_F(ERROR, "STATE %s -> %s", stateName.c_str(), desp.c_str());
} else {
LOG_F(INFO, "STATE %s -> %s", stateName.c_str(), desp.c_str());
}
}
void PowerManger::initControlCmd()
{
//================初始化配电指令=============================
m_targetDisBreakerState.bus1Breaker.fuelCellCircuitBreaker = 0;
m_targetDisBreakerState.bus1Breaker.powerLithiumBatteryCircuitBreaker = 1; //动力锂电池默认接入
m_targetDisBreakerState.bus1Breaker.propulsionMotorCircuitBreaker = 0;
m_targetDisBreakerState.bus1Breaker.lithiumBatteryGroupInstrumentCircuitBreaker = 1; //仪表锂电池默认接入
m_targetDisBreakerState.bus1Breaker.dcDc5ModuleCircuitBreaker = 1; //DC-DC模块默认接入
m_targetDisBreakerState.bus1Breaker.bowHighVoltageDistributionBoxCircuitBreaker = 1; //艏部高压母线断路器默认接入
m_targetDisBreakerState.bus1Breaker.sternFTDevice45CircuitBreaker = 0; // sternFTDevice45CircuitBreaker默认接入
m_targetDisBreakerState.bus1Breaker.sternRudderSwitch1CircuitBreaker = 0;
m_targetDisBreakerState.bus1Breaker.sternRudderSwitch2CircuitBreaker = 0;
m_targetDisBreakerState.bus1Breaker.fbReservedCircuitBreaker = 0;
m_targetDisBreakerState.bus1Breaker.tyzReservedCircuitBreaker = 0;
m_targetDisBreakerState.bus1Breaker.reservedCircuitBreaker = 0;
m_targetDisBreakerState.bus2Breaker.bowFTDevice123CircuitBreaker = 0;
m_targetDisBreakerState.bus2Breaker.actuatorCircuitBreaker = 0;
m_targetDisBreakerState.bus2Breaker.mastSteeringGearControlBoxCircuitBreaker = 0;
m_targetDisBreakerState.bus2Breaker.xczCircuitBreaker = 0;
m_targetDisBreakerState.bus2Breaker.bowRudderControlBoxCircuitBreaker = 0;
m_targetDisBreakerState.bus2Breaker.openWaterCoverStartCylinderCircuitBreaker = 0;
//锂电池默认接入
m_targetDisBreakerState.bus3Breaker.lithiumBatteryGroupInstrumentCircuitBreaker = 1;
m_targetDisBreakerState.bus3Breaker.bowLowVoltageDistributionBoxCircuitBreaker = 1;
m_targetDisBreakerState.bus3Breaker.unit4InstrumentDC48VCircuitBreaker = 1;
m_targetDisBreakerState.bus3Breaker.dcC1DCDistributionPanelCircuitBreaker = 1;
m_targetDisBreakerState.bus3Breaker.reservedCircuitBreaker1 = 0;
m_targetDisBreakerState.bus3Breaker.reservedCircuitBreaker2 = 0;
m_targetDisBreakerState.bus3Breaker.emergencyLithiumBatteryGroup2CircuitBreaker = 1;
m_targetDisBreakerState.bus4Breaker.unit1CircuitBreaker = 1;
m_targetDisBreakerState.bus4Breaker.unit2CircuitBreaker = 1;
m_targetDisBreakerState.bus4Breaker.unit3CircuitBreaker = 1;
m_targetDisBreakerState.bus4Breaker.unit5CircuitBreaker = 1;
m_targetDisBreakerState.bus4Breaker.bowPZDeviceCircuitBreaker = 1;
m_targetDisBreakerState.bus4Breaker.reservedCircuitBreaker1 = 0;
m_targetDisBreakerState.bus4Breaker.reservedCircuitBreaker2 = 0;
m_targetDisBreakerState.bus4Breaker.emergencyLithiumBatteryGroup1CircuitBreaker = 1; //紧急锂电池默认接入
//================初始化复合管控=============================
m_CcuColCmd.fcmode = 0x00; //默认无效
m_CcuColCmd.fcuCmd = 0x00; //无效指令
m_CcuColCmd.fcuPowerEfficiency = 8; //默认为8kw
m_CcuColCmd.insChargeEnable = 0x30; //不允许充电
m_CcuColCmd.insBatCmd = 0x00; //无效指令
m_CcuColCmd.powerBatCmd = 0x00; //无效指令
m_CcuColCmd.powerBatEfficiency = 00; //默认为最大
m_CcuColCmd.heartbeat = 0;
m_CcuColCmd.masterState = 0xAA;//主站状态,运行中
//================初始化上位机指令=========================
m_msCmd.modCMD = 99;
m_msCmd.powerCMD = 99;
m_msCmd.workCMD = 99;
//================初始化设备驱动指令========================
}
unsigned char PowerManger::getFaultLevel()
{
unsigned char maxLevel = 0;
for (auto code : faultCode) {
// 提取0xabcd中的b位 (右移8位后取低4位)
unsigned char level = (code >> 8) & 0xF;
if (level > maxLevel) {
maxLevel = level;
}
}
return maxLevel;
}
bool PowerManger::commLoop()
{
while(!m_commThread.IsQuitRequested())
{
m_CcuColCmd.heartbeat++;
m_lowerCommManager->processPeriodicTasks();
m_upperCommManager->processPeriodicTasks();
// 延时1秒
usleep(1000000);
}
return true;
}
void PowerManger::injectFault(unsigned type,unsigned int faultCode){
LOG_F(INFO, "注入故障: %d %d", type, faultCode);
TestEvent testEvent("故障注入测试",type,faultCode);
PowerManagerFsm::dispatch(testEvent);
}
void PowerManger::pushDeviceCommand(DeviceSwitchCmd cmd) {
std::lock_guard<std::mutex> lock(m_deviceCmdMutex);
m_deviceCmdQuenue.push(cmd);
}
bool PowerManger::popDeviceCommand(DeviceSwitchCmd &cmd) {
std::lock_guard<std::mutex> lock(m_deviceCmdMutex);
if(m_deviceCmdQuenue.empty()) {
return false;
}
cmd = m_deviceCmdQuenue.front();
m_deviceCmdQuenue.pop();
return true;
}
bool PowerManger::isDeviceCmdEmpty() const {
std::lock_guard<std::mutex> lock(m_deviceCmdMutex);
return m_deviceCmdQuenue.empty();
}
+165
View File
@@ -0,0 +1,165 @@
/*
* @Author: zhaojingkui 1553836110@qq.com
* @Date: 2024-10-22 16:47:01
* @LastEditors: zhaojingkui 1553836110@qq.com
* @LastEditTime: 2024-10-22 18:03:29
* @FilePath: /H100PowerManger/src/pPowerManger/PowerManger.h
* @Description:
*
* Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
*/
/************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: PowerManger.h */
/* DATE: December 29th, 1963 */
/************************************************************/
#ifndef PowerManger_HEADER
#define PowerManger_HEADER
#define UNIX
#define JSON_USE_EXCEPTION 1
#include <queue>
#include "logc/loguru.hpp"
#include "MOOS/libMOOS/Thirdparty/AppCasting/AppCastingMOOSApp.h"
#include "MOOS/libMOOS/Utils/MOOSThread.h"
#include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h"
#include "MOOS/libMOOS/Utils/ConsoleColours.h"
#include "../udpcomm/ccuUdpMsg.h"
#include "json/json.h"
#include "udpcomm/udpComm.h"
#include "pmSysvariable.h"
#include "fsm/PowerManagerFsm.hpp"
#include "driver.h"
#include "LowerCommManager.h"
#include "UpperCommManager.h"
#include "sqlit3/SQLite.h"
#include "systemData.h"
#include "httpserver/httpserver.h"
#include "faultCode.h"
#define IPORT 5001
#define CCUPORT 7000
#define CCUHOST "192.168.0.140"
// #define CCUHOST "127.0.0.0"
#define MAX_UDP_PKT_SIZE 65535
#define SKEW_TOLERANCE 5
class PowerManger : public AppCastingMOOSApp
{
public:
PowerManger();
~PowerManger();
public:
bool FsmLoop();
protected: // Standard MOOSApp functions to overload
bool OnNewMail(MOOSMSG_LIST &NewMail);
bool Iterate();
bool OnConnectToServer();
bool OnStartUp();
bool buildReport();
void registerVariables();
public:
void updateTime(){m_current_time = MOOSTime();}
unsigned char getFaultLevel();
//数据库
SQLite* m_db;
//http
HttpServer* m_httpServer;
//系统数据
SystemData* m_systemData;
/************************************************************/
/* |<------------FEEDBACK--------<-- */
/* | | */
/* IN-->+-------[STATE CONTROL]---------+--->OUT */
/* */
/************************************************************/
public:
//===========================IN============================================
DriverTable m_MSDriverCmd;
MSControlCmd m_msCmd;
//===========================OUT===========================================
DriverTable m_subDisSysCmd;
ccuColCmd m_CcuColCmd;
disSysBreakerList m_targetDisBreakerState;
//===========================FEEDBACK======================================
pmState m_pmCurrentState; //能源系统的当前状态(由下位机线程修改)
disSysBreakerList m_currentDisBreakerState; //配电断路器状态
DriverTable m_currentDriverState;
DriverTable m_subDisSysState;
DriverTable m_subDisSysFault;
int m_depth;
MissionState m_missionState;
//===========================STATE=========================================
unsigned char workCondition;
unsigned char currentMod;
unsigned char powerState;
unsigned char faultLevel;
vector<unsigned int> faultCode;
unsigned int soc;
unsigned int sustainableTime;
unsigned int m_faultNum;
Driver m_driver; //设备表处理
unsigned char m_leakage;
std::set<unsigned int> m_faultCodes;
int m_thrustRpm;
int m_thrustEnable;
// std::set<unsigned int> m_disSysFaultCodes;
//============================Device Option================================
std::queue<DeviceSwitchCmd> m_deviceCmdQuenue;
mutable std::mutex m_deviceCmdMutex;
void pushDeviceCommand(DeviceSwitchCmd cmd);
bool popDeviceCommand(DeviceSwitchCmd &cmd);
bool isDeviceCmdEmpty() const;
//===========================CONFIG========================================
long m_lPort;
unsigned int m_nReceiveBufferSizeKB;
unsigned int m_nSendBufferSizeKB;
double m_current_time;
unsigned int m_ticker;
double m_skew;
int connectState;
//=============================过程函数======================================
void initControlCmd();
public:
CMOOSThread m_commThread;
LowerCommManager* m_lowerCommManager;
UpperCommManager* m_upperCommManager;
// PowerManagerFsm m_fsm;
public:
//===========================状态机接口=======================================
void printState(const std::string& stateName, const std::string& desp);
bool FSM_RUN_IS_OK = true;
//==================================================================================
bool commLoop();
int checkError();
bool sendNotification(const std::string& key, const std::string& value) {
return Notify(key, value);
}
bool sendNotification(const std::string& key, double value) {
return Notify(key, value);
}
public:
double GetPublicAppFreq() { return GetAppFreq(); }
unsigned int GetPublicCommsFreq() { return GetCommsFreq(); }
double GetPublicAppStartTime() { return GetAppStartTime(); }
double GetPublicCPULoad() { return GetCPULoad(); }
double GetPublicTimeSinceIterate() { return GetTimeSinceIterate(); }
double GetPublicLastIterateTime() { return GetLastIterateTime(); }
int GetPublicIterateCount() { return GetIterateCount(); }
string GetServerHost() { return m_sServerHost; }
int GetServerPort() { return m_lServerPort; }
public:
//故障注入
void injectFault(unsigned type,unsigned int faultCode);
};
#endif
+115
View File
@@ -0,0 +1,115 @@
/****************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: PowerManger_Info.cpp */
/* DATE: December 29th, 1963 */
/****************************************************************/
#include <cstdlib>
#include <iostream>
#include "PowerManger_Info.h"
#include "ColorParse.h"
#include "ReleaseInfo.h"
using namespace std;
//----------------------------------------------------------------
// Procedure: showSynopsis
void showSynopsis()
{
blk("SYNOPSIS: ");
blk("------------------------------------ ");
blk(" The pPowerManger application is used for ");
blk(" ");
blk(" ");
blk(" ");
blk(" ");
}
//----------------------------------------------------------------
// Procedure: showHelpAndExit
void showHelpAndExit()
{
blk(" ");
blu("=============================================================== ");
blu("Usage: pPowerManger file.moos [OPTIONS] ");
blu("=============================================================== ");
blk(" ");
showSynopsis();
blk(" ");
blk("Options: ");
mag(" --alias","=<ProcessName> ");
blk(" Launch pPowerManger with the given process name ");
blk(" rather than pPowerManger. ");
mag(" --example, -e ");
blk(" Display example MOOS configuration block. ");
mag(" --help, -h ");
blk(" Display this help message. ");
mag(" --interface, -i ");
blk(" Display MOOS publications and subscriptions. ");
mag(" --version,-v ");
blk(" Display the release version of pPowerManger. ");
blk(" ");
blk("Note: If argv[2] does not otherwise match a known option, ");
blk(" then it will be interpreted as a run alias. This is ");
blk(" to support pAntler launching conventions. ");
blk(" ");
exit(0);
}
//----------------------------------------------------------------
// Procedure: showExampleConfigAndExit
void showExampleConfigAndExit()
{
blk(" ");
blu("=============================================================== ");
blu("pPowerManger Example MOOS Configuration ");
blu("=============================================================== ");
blk(" ");
blk("ProcessConfig = pPowerManger ");
blk("{ ");
blk(" AppTick = 4 ");
blk(" CommsTick = 4 ");
blk(" ");
blk("} ");
blk(" ");
exit(0);
}
//----------------------------------------------------------------
// Procedure: showInterfaceAndExit
void showInterfaceAndExit()
{
blk(" ");
blu("=============================================================== ");
blu("pPowerManger INTERFACE ");
blu("=============================================================== ");
blk(" ");
showSynopsis();
blk(" ");
blk("SUBSCRIPTIONS: ");
blk("------------------------------------ ");
blk(" NODE_MESSAGE = src_node=alpha,dest_node=bravo,var_name=FOO, ");
blk(" string_val=BAR ");
blk(" ");
blk("PUBLICATIONS: ");
blk("------------------------------------ ");
blk(" Publications are determined by the node message content. ");
blk(" ");
exit(0);
}
//----------------------------------------------------------------
// Procedure: showReleaseInfoAndExit
void showReleaseInfoAndExit()
{
showReleaseInfo("pPowerManger", "gpl");
exit(0);
}
+18
View File
@@ -0,0 +1,18 @@
/****************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: PowerManger_Info.h */
/* DATE: Dececmber 29th, 1963 */
/****************************************************************/
#ifndef PowerManger_INFO_HEADER
#define PowerManger_INFO_HEADER
void showSynopsis();
void showHelpAndExit();
void showExampleConfigAndExit();
void showInterfaceAndExit();
void showReleaseInfoAndExit();
#endif
+242
View File
@@ -0,0 +1,242 @@
#include "UpperCommManager.h"
#include "PowerManger.h"
#include "driver.h"
#include "fsm/PowerManagerFsm.hpp"
UpperCommManager::UpperCommManager(PowerManger* pm) :
m_pm(pm),
m_secdistStateMsg(),
m_setOpConditionMsg(),
m_depthMsg(),
m_taskStartMsg(),
m_equInsStateMsg(),
m_equStateMsg(),
m_setPMSysMsg(),
m_disSysStateMsg(),
m_currentStateMsg(),
m_pmStateMsg(),
m_fcsStateMsg(),
m_liBatStateMsg(),
m_setOpModeMsg(),
m_taskStopMsg(),
m_setDevSwitchMsg(),
m_sysStateMsg(),
m_msCmd(),
m_driver() {
}
DriverTable uDevice_secdistStateMsg::fault_state = {0};
bool UpperCommManager::processUpperMsg(const string& key, const string& strJson) {
if (key == m_sysStateMsg.key)
{
#ifdef _DEBUG
m_sysStateMsg_st_debug = std::make_pair(key, strJson);
#endif
m_pm->m_msCmd = m_sysStateMsg.getMasterControlCmd(key, strJson);
MasterCommandEvent event;
PowerManagerFsm::dispatch(event);
return true;
}
// 设备状态处理
else if(key == m_equStateMsg.key_cmd)
{
#ifdef _DEBUG
m_equStateMsg_cmd_debug = std::make_pair(key, strJson);
#endif
m_pm->m_MSDriverCmd = m_equStateMsg.getEquipmentCmd(key, strJson);
vector<DriverCommand> devCmdExt = m_pm->m_driver.loadDriverIdFromJson(strJson);
if (devCmdExt.empty())
{
LOG_F(WARNING, "控制指令为空");
}
else {
for (auto& cmd : devCmdExt) {
DevCmdExt event(cmd.id, cmd.cmd);
PowerManagerFsm::dispatch(event);
}
}
return true;
}
// 次级配电状态处理
else if(key == m_secdistStateMsg.key_fb)
{
#ifdef _DEBUG
m_secdistStateMsg_fb_debug = std::make_pair(key, strJson);
#endif
m_secdistStateMsg.parseMsg(strJson, m_pm->m_subDisSysState);
//TODO:自动更新到设备状态 调试
//m_pm->m_subDisSysState = m_pm->m_deviceState;
return true;
}
// 深度获取
else if(key == m_depthMsg.key)
{
#ifdef _DEBUG
m_depthMsg_st_debug = std::make_pair(key, strJson);
#endif
m_pm->m_depth = m_depthMsg.getDepth(key, strJson);
return true;
}
else if(key == m_taskStartMsg.key)
{
#ifdef _DEBUG
m_taskStartMsg_st_debug = std::make_pair(key, strJson);
#endif
m_pm->m_missionState = m_taskStartMsg.getMission(key, strJson);
TaskStartEvent event;
event.type = m_pm->m_missionState.type;
event.enableBowRudder = m_pm->m_missionState.enableBowRudder;
event.enableBuoyancyAdjustment = m_pm->m_missionState.enableBuoyancyAdjustment;
PowerManagerFsm::dispatch(event);
return true;
}
else if(key == m_setOpModeMsg.key)
{
#ifdef _DEBUG
m_setOpModeMsg_st_debug = std::make_pair(key, strJson);
#endif
m_pm->m_msCmd.modCMD = m_setOpModeMsg.getSetOpMode(key, strJson);
MasterCommandEvent event;
PowerManagerFsm::dispatch(event);
return true;
} else if(key == m_setOpConditionMsg.key)
{
#ifdef _DEBUG
m_setOpConditionMsg_st_debug = std::make_pair(key, strJson);
#endif
m_pm->m_msCmd.workCMD = m_setOpConditionMsg.getSetOpCondition(key, strJson);
MasterCommandEvent event;
PowerManagerFsm::dispatch(event);
return true;
}
else if(key == m_setPMSysMsg.key)
{
#ifdef _DEBUG
m_setPMSysMsg_st_debug = std::make_pair(key, strJson);
#endif
m_pm->m_msCmd.powerCMD = m_setPMSysMsg.getSetPMSys(key, strJson);
MasterCommandEvent event;
PowerManagerFsm::dispatch(event);
return true;
}
else if(key == m_setDevSwitchMsg.key)
{
#ifdef _DEBUG
m_setDevSwitchMsg_st_debug = std::make_pair(key, strJson);
#endif
DeviceSwitchCmd cmd;
cmd = m_setDevSwitchMsg.getSetDevSwitch(key, strJson);
if (cmd.id < 0) {
LOG_F(WARNING, "parse device switch error:%s", strJson.c_str());
}
else
{
DevCmdExt devCmdExt;
devCmdExt.id = cmd.id;
devCmdExt.cmd = cmd.cmd;
PowerManagerFsm::dispatch(devCmdExt);
LOG_F(INFO, "set dev switch success");
return true;
}
}
else if(key == m_taskStopMsg.key)
{
#ifdef _DEBUG
m_taskStopMsg_st_debug = std::make_pair(key, strJson);
#endif
bool stop = m_taskStopMsg.getTaskStop(key, strJson);
if (stop) {
LOG_F(INFO, "task stop success");
return true;
}
else {
LOG_F(WARNING, "task stop error:%s", strJson.c_str());
return false;
}
}
else if(key == uDetect_xcVoltage_cmd::key)
{
uDetect_xcVoltage_cmd xcCmd;
xcCmd.xcHighVoltageAdd_int32 = 0;
xcCmd.xcLowVoltageAdd_int32 = 0;
xcCmd.fromJsonString(strJson);
SideSonarCmd sideSonarCmd;
sideSonarCmd.xcHighVoltageAdd = xcCmd.xcHighVoltageAdd_int32;
sideSonarCmd.xcLowVoltageAdd = xcCmd.xcLowVoltageAdd_int32;
PowerManagerFsm::dispatch(sideSonarCmd);
return true;
}
else if(key == uDetect_zdpVoltage_cmd::key)
{
uDetect_zdpVoltage_cmd zdpCmd;
zdpCmd.fromJsonString(strJson);
DevCmdExt devCmdExt;
devCmdExt.id = DeviceId::lowFreqSonar;
devCmdExt.cmd = zdpCmd.zdpVoltageAdd_int32;
PowerManagerFsm::dispatch(devCmdExt);
LOG_F(INFO, "set dev switch success");
return true;
}
else if(key == uDevice_thruster_st::key)
{
uDevice_thruster_st thrusterSt;
thrusterSt.fromJsonString(strJson);
m_pm->m_thrustRpm = thrusterSt.rpm_int16;
if(thrusterSt.maxTorque_uint16 == 0)
m_pm->m_thrustEnable = 0;
else
m_pm->m_thrustEnable = 1;
return true;
};
LOG_F(WARNING, "Unknown key: %s", key.c_str());
return false;
}
void UpperCommManager::processPeriodicTasks() {
buildSystemReport();
std::string strJson;
//发送当前设备状态
strJson = m_equStateMsg.buildMsg(m_pm->m_currentDriverState);
m_pm->sendNotification(m_equStateMsg.key, strJson);
//发送次级配电指令 修改后的代码
strJson = m_secdistStateMsg.buildMsg(m_pm->m_subDisSysCmd,m_pm->m_subDisSysState, m_pm->m_subDisSysFault);
m_pm->sendNotification(m_secdistStateMsg.key_cmd, strJson);
//发送仪表电状态
m_pm->sendNotification(m_equInsStateMsg.key,m_equInsStateMsg.buildMsg(m_pm->m_subDisSysState));
#ifdef _DEBUG
m_equInsStateMsg_fb_degub = std::make_pair(m_equInsStateMsg.key,m_equInsStateMsg.buildMsg(m_pm->m_subDisSysState));
m_secdistStateMsg_cmd_debug = std::make_pair(m_secdistStateMsg.key_cmd,strJson);
m_equStateMsg_fb_debug = std::make_pair(m_equStateMsg.key_cmd,m_equStateMsg.buildMsg(m_pm->m_currentDriverState));
strJson = m_pm->m_driver.saveDriverTableToJson(&m_pm->m_subDisSysFault);
m_pm->sendNotification("uPower_subDisFault_st",strJson);
#endif
}
void UpperCommManager::buildSystemReport() {
m_pmStateMsg.state.workCondition = m_pm->workCondition;
m_pmStateMsg.state.currentMod = m_pm->currentMod;
m_pmStateMsg.state.powerState = m_pm->powerState;
m_pmStateMsg.state.faultLevel = m_pm->faultLevel;
m_pmStateMsg.state.faultCode = m_pm->faultCode;
// cout << "m_pmStateMsg.state.faultCode.size():" << m_pmStateMsg.state.faultCode.size() << endl;
m_pmStateMsg.state.soc = m_pm->soc;
m_pmStateMsg.state.sustainableTime = m_pm->sustainableTime;
// m_pmStateMsg.state.m_leakage = m_pm->m_leakage;
m_pmStateMsg.state.m_leakage = m_pm->m_systemData->generateLeakageCode();
m_pmStateMsg.state.m_faultNum = m_pm->m_faultNum;
m_pm->sendNotification(m_pmStateMsg.key, m_pmStateMsg.buildMsg(*(m_pm->m_systemData)));
m_pm->sendNotification(m_fcsStateMsg.key, m_fcsStateMsg.buildMsg(*(m_pm->m_systemData)));
m_pm->sendNotification(m_liBatStateMsg.key, m_liBatStateMsg.buildMsg(*(m_pm->m_systemData)));
m_pm->sendNotification(m_disSysStateMsg.key, m_disSysStateMsg.buildMsg(*(m_pm->m_systemData),m_pm->m_currentDisBreakerState));
m_pm->sendNotification(m_currentStateMsg.key, m_currentStateMsg.buildMsg(m_pm->m_pmCurrentState));
#ifdef _DEBUG
m_pmStateMsg_fb_debug = std::make_pair(m_pmStateMsg.key, m_pmStateMsg.buildMsg(*(m_pm->m_systemData)));
m_fcsStateMsg_st_debug = std::make_pair(m_fcsStateMsg.key, m_fcsStateMsg.buildMsg(*(m_pm->m_systemData)));
m_liBatStateMsg_st_debug = std::make_pair(m_liBatStateMsg.key, m_liBatStateMsg.buildMsg(*(m_pm->m_systemData)));
m_disSysStateMsg_st_debug = std::make_pair(m_disSysStateMsg.key, m_disSysStateMsg.buildMsg(*(m_pm->m_systemData),m_pm->m_currentDisBreakerState));
m_currentStateMsg_st_debug = std::make_pair(m_currentStateMsg.key, m_currentStateMsg.buildMsg(m_pm->m_pmCurrentState));
#endif
}
+118
View File
@@ -0,0 +1,118 @@
#ifndef UPPER_COMM_MANAGER_H
#define UPPER_COMM_MANAGER_H
#include "MOOS/libMOOS/Thirdparty/AppCasting/AppCastingMOOSApp.h"
#include "pmSysvariable.h"
#include "driver.h"
#include "json/json.h"
#include <string>
#include <vector>
#include <map>
#include "upmsg/uPower_equInsState.h"
#include "upmsg/uDevice_secdistState.h"
#include "upmsg/uPower_equState.h"
#include "upmsg/uPower_disSysState.h"
#include "upmsg/uPower_currentState_st.h"
#include "upmsg/uPower_pmState.h"
#include "upmsg/uPower_fcsState.h"
#include "upmsg/uPower_liBatState.h"
#include "upmsg/uDevice_depth.h"
#include "upmsg/uExternComm_setOpCondition.h"
#include "upmsg/uExternComm_setOpMode.h"
#include "upmsg/uPlan_taskStart.h"
#include "upmsg/uPlan_planStop.h"
#include "upmsg/uExternComm_setDeviceSwitch.h"
#include "upmsg/uExternComm_setPowerSystem.h"
#include "upmsg/uPower_equState.h"
#include "upmsg/uPower_sysState.h"
#include "upmsg/uDetect_zdpVoltage_cmd.h"
#include "upmsg/uDetect_xcVoltage_cmd.h"
#include "upmsg/uDevice_thruster_st.h"
#define _DEBUG
using namespace std;
#define VAR_TO_STR(var) #var
//控制消息
#define DB_TO_PM_MSCMD "uPower_sysState_cmd"
#define DB_TO_PM_EQUIPMENTCMD "uPower_equState_cmd"
//决策消息
#define DB_TO_PM_DEEPTH "uDevice_depth_st"
// #define DB_TO_PM_MISSION "uPlan_taskStart_cmd"
#define DB_TO_PM_TASKSTOP "uPlan_planStop_st"
//外部通信消息
#define DB_TO_PM_SETOPCONDITION "uExternComm_setOpCondition_cmd"
#define DB_TO_PM_SETOPMODE "uExternComm_setOpMode_cmd"
#define DB_TO_PM_SETPMSYS "uExternComm_setPowerSystem_cmd"
#define DB_TO_PM_SETDEVSWITCH "uExternComm_setDeviceSwitch_cmd"
class PowerManger; // 前向声明
class UpperCommManager {
public:
UpperCommManager(PowerManger* powerManager);
~UpperCommManager(){};
// 周期调用
void processPeriodicTasks();
// 处理上位机消息
bool processUpperMsg(const std::string& key, const std::string& msg);
// 生成系统报告
void buildSystemReport();
public:
//定义上位机消息
uPower_equInsStateMsg m_equInsStateMsg;
uDevice_secdistStateMsg m_secdistStateMsg;
uPower_equStateMsg m_equStateMsg;
uPower_disSysStateMsg m_disSysStateMsg;
uPower_currentStateMsg m_currentStateMsg;
uPower_pmStateMsg m_pmStateMsg;
uPower_fcsStateMsg m_fcsStateMsg;
uPower_liBatStateMsg m_liBatStateMsg;
//上位机订阅消息
uDevice_depthMsg m_depthMsg;
uExternComm_setOpConditionMsg m_setOpConditionMsg;
uExternComm_setOpModeMsg m_setOpModeMsg;
uPlan_taskStartMsg m_taskStartMsg;
uPlan_planStopMsg m_taskStopMsg;
uExternComm_setDeviceSwitchMsg m_setDevSwitchMsg;
uExternComm_setPowerSystemMsg m_setPMSysMsg;
uPower_sysStateMsg m_sysStateMsg;
private:
PowerManger* m_pm;
MSControlCmd m_msCmd;
Driver m_driver;
#ifdef _DEBUG
public:
std::pair<string, string> m_equInsStateMsg_fb_degub;
std::pair<string, string> m_secdistStateMsg_cmd_debug;
std::pair<string, string> m_secdistStateMsg_fb_debug;
std::pair<string, string> m_equStateMsg_cmd_debug;
std::pair<string, string> m_equStateMsg_fb_debug;
std::pair<string, string> m_disSysStateMsg_st_debug;
std::pair<string, string> m_currentStateMsg_st_debug;
std::pair<string, string> m_pmStateMsg_fb_debug;
std::pair<string, string> m_fcsStateMsg_st_debug;
std::pair<string, string> m_liBatStateMsg_st_debug;
std::pair<string, string> m_depthMsg_st_debug;
std::pair<string, string> m_setOpConditionMsg_st_debug;
std::pair<string, string> m_setOpModeMsg_st_debug;
std::pair<string, string> m_taskStartMsg_st_debug;
std::pair<string, string> m_taskStopMsg_st_debug;
std::pair<string, string> m_setDevSwitchMsg_st_debug;
std::pair<string, string> m_setPMSysMsg_st_debug;
std::pair<string, string> m_sysStateMsg_st_debug;
#endif
// bool parseControlCmdFromJson(MSControlCmd &cmd, const std::string &strJson);
};
#endif // UPPER_COMM_MANAGER_H
File diff suppressed because it is too large Load Diff
+138
View File
@@ -0,0 +1,138 @@
#ifndef DRIVER_H
#define DRIVER_H
#include <memory>
#include "json/json.h"
#include "iostream"
#include <sstream>
#include <vector>
#include "pmSysvariable.h"
#define DRIVER_POWER_OFF 0x00
#define DRIVER_FULL_POWER_ON 0x01
#define DRIVER_INSTRUMENT_POWER_ON 0x02
#define DRIVER_MOTIVE_POWER_ON 0x03
#define DRIVER_STANDBY 0x04
using namespace std;
struct DriverTable
{
unsigned char depth1;
unsigned char depth2;
unsigned char depth3;
unsigned char overDeep1;
unsigned char overDeep2;
unsigned char ctd1;
unsigned char ctd2;
unsigned char soundVeloc;
unsigned char commMast;
unsigned char ins;
unsigned char ntp;
unsigned char inputWaterSensor1;
unsigned char inputWaterSensor2;
unsigned char inputWaterSensor3;
//水声设备
unsigned char singleBeamSonar1;
unsigned char singleBeamSonar2;
unsigned char singleBeamSonar3;
unsigned char singleBeamSonar4;
unsigned char singleBeamSonar5;
unsigned char singleBeamSonar6;
unsigned char singleBeamSonar7;
unsigned char singleBeamSonar8;
unsigned char forwardSonar;
unsigned char DVL;
unsigned char lowFreqSonar;
unsigned char USBL;
//执行机构
unsigned char bowWaterInet1;
unsigned char bowWaterInet2;
unsigned char bowWaterInet3;
unsigned char bowWaterInet4;
unsigned char bowWaterInet5;
unsigned char bowWaterInet6;
unsigned char bowWaterInet7;
unsigned char bowWaterInet8;
unsigned char bowRudderDeploy;
unsigned char bowRudderServo1;
unsigned char bowRudderServo2;
unsigned char bowCover1;
unsigned char bowCover2;
unsigned char bowCover3;
unsigned char bowCover4;
unsigned char bowCover5;
unsigned char bowCover6;
unsigned char waterInject;
unsigned char mastLiftingServo;
unsigned char buoyancyAdjust1;
unsigned char buoyancyAdjust2;
unsigned char buoyancyAdjust3;
unsigned char buoyancyAdjust4;
unsigned char buoyancyAdjust5;
unsigned char sternRudderServo1;
unsigned char sternRudderServo2;
unsigned char sternRudderServo3;
unsigned char sternRudderServo4;
unsigned char thruster;
unsigned char bowThrow;
unsigned char sternThrow;
//负载
unsigned char photoSensor;
unsigned char electSensor;
unsigned char launchControler;
unsigned char sideSonar;
unsigned char buoyage;
};
struct DriverCommand
{
int id;
int cmd;
};
class Driver
{
public:
Driver();
~Driver();
void setDebug(bool debug);
public:
std::unique_ptr<DriverTable> currentDriverTable;
std::unique_ptr<DriverTable> nextDriverTable;
//操作函数,操作指定设备
void setDeviceState(DriverTable &driverTable, DeviceId::Type deviceId, unsigned char s);
unsigned char getDeviceState(const DriverTable &driverTable, DeviceId::Type deviceId);
void getSTANDBYTable(DriverTable* driverTable);
void getSHORE_BASED_READYable(DriverTable* driverTable);
void getWATER_BASED_READYable(DriverTable* driverTable);
void getCRUISE_MODEable(DriverTable* driverTable);
void getHIGH_SPEED_MODEable(DriverTable* driverTable);
void getASCEND_DESCENDable(DriverTable* driverTable);
void getBUOYANCY_ADJUSTable(DriverTable* driverTable);
void getUNDERWATER_RECONable(DriverTable* driverTable);
void getSURFACE_RECONable(DriverTable* driverTable);
void getDJ_MODEable(DriverTable* driverTable);
// void setDriverTable(DriverTable* driverTable, );
std::string getDriverTableJson();
std::string getSubDisCmdJson(const DriverTable* driverTable);
std::string getDriveStateJson(const DriverTable* driverTable);
std::string saveDriverTableToJson(const DriverTable* driverTable);
int loadDriverTableFromJson(const std::string &strJson, DriverTable& table);
vector<DriverCommand> loadDriverIdFromJson(const std::string &strJson);
int SafeReadUInt(const Json::Value& root, const std::string& key, unsigned char& value);
private:
bool debug;
};
#endif // DRIVER_H
+125
View File
@@ -0,0 +1,125 @@
#ifndef FAULTCODE_H
#define FAULTCODE_H
/**
* @file faultCode.h
* @brief 锂电池故障码定义及映射表
*/
// 故障码映射表
typedef struct {
int id; // 序号
int level; // 故障级别
const uint8_t code; // 16进制故障码
const char* desc; // 报警信息
} FaultMap;
static const FaultMap batfaultMap[] = {
//四级故障
{1, 4, 0xC1, "MBMS绝缘故障"},
{2, 4, 0xC2, "温度过高"},
{3, 4, 0xC3, "MBMS预充失败"},
{4, 4, 0xC4, "MBMS正主极继电器失效"},
{5, 4, 0xC5, "MBMS负主极继电器失效"},
{6, 4, 0xC6, "MBMS燃电充电正极继电器正极失效[仪器]"},
{7, 4, 0xC7, "母线高压回路异常"},
{8, 4, 0xC9, "MBMS电压测量异常"},
{9, 4, 0xCA, "MBMS电流测量异常"},
//三级故障
{10, 3, 0x81, "MBMS绝缘故障3级"},
{11, 3, 0x82, "温度过高3级"},
{12, 3, 0x83, "温度过低3级"},
{13, 3, 0x84, "MBMS总放电超功率3级"},
{14, 3, 0x85, "MBMS总充电电流过大3级"},
//二级故障
{15, 1, 0x31, "BMS均衡模块故障2级"},
{16, 2, 0x41, "MBMS绝缘故障2级"},
{17, 2, 0x42, "MBMS总放电超功率2级"},
{18, 2, 0x43, "电池包放电超功率2级"},
{19, 2, 0x44, "MBMS总放电过流2级"},
{20, 2, 0x45, "单包异常剔除2级"},
{21, 2, 0x46, "单包没有电流2级"},
{22, 2, 0x47, "自检有重复ID号2级"},
{23, 2, 0x48, "电池包接入失败2级"},
{24, 2, 0x49, "电池包充电电流过大2级"},
{25, 2, 0x51, "电池包绝缘故障2级"},
{26, 2, 0x52, "电池包温度过高2级"},
{27, 2, 0x53, "电池包温度过低2级"},
{28, 2, 0x54, "电池包单体电压不均衡2级"},
{29, 2, 0x55, "电池包单体温度不均衡2级"},
{30, 2, 0x56, "电池包过流2级"},
{31, 2, 0x57, "电池包充电电流过大2级"},
{32, 2, 0x58, "电池包单体电压过高2级"},
{33, 2, 0x59, "电池包单体电压过低2级"},
{34, 2, 0x5A, "电池包总电压过高2级"},
{35, 2, 0x5B, "电池包总电压过低2级"},
{36, 2, 0x5C, "电池包内部通讯故障2级"},
{37, 2, 0x5D, "电池包初始化故障2级"},
{38, 2, 0x62, "电池包高压回路连接异常2级"},
{39, 2, 0x65, "电池包烟雾报警2级"},
{40, 2, 0x72, "MBMS在线燃电充电超温2级"},
//一级故障
{41, 1, 0x01, "MBMS绝缘故障1级"},
{42, 1, 0x02, "MBMS总放电超功率1级"},
{43, 1, 0x11, "电池包绝缘故障1级"},
{44, 1, 0x12, "电池包最高温度过高1级"},
{45, 1, 0x13, "电池包最低温度过低1级"},
{46, 1, 0x14, "电池包单体电压不均衡1级"},
{47, 1, 0x15, "电池包单体温度不均衡1级"},
{48, 1, 0x16, "电池包放电过流1级"},
{49, 1, 0x17, "电池包充电电流过大1级"},
{50, 1, 0x18, "电池包单体电压过高1级"},
{51, 1, 0x19, "电池包单体电压过低1级"},
{52, 1, 0x1A, "电池包总电压过高1级"},
{53, 1, 0x1B, "电池包总电压过低1级"},
{54, 1, 0x1D, "电池包烟雾报警1级"},
};
static const FaultMap disfaultMap[] = {
{1, 3, 1, "燃料电池断路器故障脱扣"},
{2, 4, 2, "动力锂电池断路器故障脱扣"},
{3, 4, 3, "推进电机断路器故障脱扣"},
{4, 4, 4, "锂电池组仪表断路器故障脱扣"},
{5, 4, 5, "DC/DC5模块断路器故障脱扣"},
{6, 4, 6, "艏部高压配电箱断路器故障脱扣"},
{7, 4, 7, "艉部FT装置4/5断路器故障脱扣"},
{8, 4, 8, "艉舵开关1断路器故障脱扣"},
{9, 4, 9, "艉舵开关2断路器故障脱扣"},
{10, 4, 10, "FB预留断路器故障脱扣"},
{11, 4, 11, "TYZ预留断路器故障脱扣"},
{12, 4, 12, "预留断路器故障脱扣"},
{13, 4, 13, "艏部FT装置1-3 断路器故障脱扣"},
{14, 4, 14, "启闭机构断路器故障脱扣"},
{15, 4, 15, "桅杆舵机控制箱断路器故障脱扣"},
{16, 4, 16, "XCZ 断路器故障脱扣"},
{17, 4, 17, "艏舵控制箱断路器故障脱扣"},
{18, 4, 18, "敞水盖启动电缸断路器故障脱扣"},
{19, 4, 19, "锂电池组(仪表)断路器故障脱扣"},
{20, 4, 20, "艏部低压配电箱断路器故障脱扣"},
{21, 4, 21, "UNIT4仪表DC48V断路器故障脱扣"},
{22, 4, 22, "DC-DC1直流配电板断路器故障脱扣"},
{23, 4, 23, "预留断路器故障脱扣"},
{24, 4, 24, "预留断路器故障脱扣"},
{25, 4, 25, "应急锂电池组2断路器"},
{26, 4, 26, "UNIT1断路器故障脱扣"},
{27, 4, 27, "UNIT2断路器故障脱扣"},
{28, 4, 28, "UNIT3断路器故障脱扣"},
{29, 4, 29, "UNIT5断路器故障脱扣"},
{30, 4, 30, "艏部PZ装置断路器故障脱扣"},
{31, 4, 31, "预留断路器故障脱扣"},
{32, 4, 32, "预留断路器故障脱扣"},
{33, 4, 33, "应急锂电池组1断路器故障脱扣"},
{34, 4, 34, "动力母排绝缘低"},
{35, 4, 35, "A汇流排绝缘低"},
{36, 4, 36, "高压母线配电控制器仪表电源失电信号"},
{37, 4, 37, "高压母线配电控制器应急电源失电信号"},
{38, 4, 38, "高压汇流排A仪表电源失电信号"},
{39, 4, 39, "高压汇流排A应急电源失电信号"},
{40, 4, 40, "高压汇流排A仪表汇流排绝缘低"},
{41, 4, 41, "高压汇流排B仪表电源失电信号"},
{42, 4, 42, "高压汇流排B应急电源失电信号"},
{43, 4, 43, "高压汇流排B仪表汇流排绝缘低"},
{44, 4, 44, "仪表汇流排失电信号"},
{45, 4, 45, "仪表汇流排浸水报警"}
};
#endif // FAULTCODE_H
+59
View File
@@ -0,0 +1,59 @@
#include "PowerManagerFsm.hpp"
void CruiseMode::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
// pm->m_driver.getCRUISE_MODEable(&pm->m_subDisSysCmd);
handleCuriseWork();
//解除非必要动力电设备
//1 解除启闭机构
unsigned char cmd = 0;
if(pm->m_currentDriverState.bowCover1 != 0 ||
pm->m_currentDriverState.bowCover2 != 0 ||
pm->m_currentDriverState.bowCover3 != 0 ||
pm->m_currentDriverState.bowCover4 != 0 ||
pm->m_currentDriverState.bowCover5 != 0 ||
pm->m_currentDriverState.bowCover6 != 0)
{
pm->m_lowerCommManager->operate_HVA_actuatorCircuit_Breaker(0);
MOOSPause(3);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover6, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
}
//2 解除敞水机构
if(pm->m_currentDriverState.bowWaterInet1 != 0 ||
pm->m_currentDriverState.bowWaterInet2 != 0 ||
pm->m_currentDriverState.bowWaterInet3 != 0 ||
pm->m_currentDriverState.bowWaterInet4 != 0 ||
pm->m_currentDriverState.bowWaterInet5 != 0 ||
pm->m_currentDriverState.bowWaterInet6 != 0 ||
pm->m_currentDriverState.bowWaterInet7 != 0 ||
pm->m_currentDriverState.bowWaterInet8 != 0)
{
pm->m_lowerCommManager->operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(0);
MOOSPause(3);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet6, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet7, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet8, (unsigned char)cmd);
}
pm->workCondition = WorkCondition::CRUISE_MODE;
LOG_F(INFO, "进入巡航模式");
}
// CruiseMode实现
void CruiseMode::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
+71
View File
@@ -0,0 +1,71 @@
#include "PowerManagerFsm.hpp"
// DJMode实现
void DJMode::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void DJMode::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
handleCuriseWork();
//1 启动载荷装置
pm->m_subDisSysCmd.launchControler = 1;
//启动启闭机构和电缸
unsigned char cmd = 1;
//2.1 启闭机构
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover6, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(10);
pm->m_lowerCommManager->operate_HVA_actuatorCircuit_Breaker(1);
//2.2 敞水电缸
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet6, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet7, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet8, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(10);
pm->m_lowerCommManager->operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(1);
pm->workCondition = WorkCondition::DJ_MODE;
LOG_F(INFO, "进入DJ模式");
}
void DJMode::exit() {
PowerManagerFsm::exit();
//1 解除启闭机构
unsigned char cmd = 0;
pm->m_lowerCommManager->operate_HVA_actuatorCircuit_Breaker(0);
MOOSPause(3);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover6, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
//2 解除敞水机构
pm->m_lowerCommManager->operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(0);
MOOSPause(3);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet6, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet7, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet8, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
}
+20
View File
@@ -0,0 +1,20 @@
#include "PowerManagerFsm.hpp"
// FaultState实现
void FaultState::entry() {
PowerManagerFsm::entry();
if(pm->m_missionState.type == TaskType::THROW_LOAD)
{
LOG_F(INFO, "检测到抛载");
}
}
void FaultState::react(FaultEvent const & e) {
LOG_F(INFO, "FaultState 处理故障事件");
}
void FaultState::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
+16
View File
@@ -0,0 +1,16 @@
#include "PowerManagerFsm.hpp"
// FloatAdjust实现
void FloatAdjust::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void FloatAdjust::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
handleCuriseWork();
pm->workCondition = WorkCondition::BUOYANCY_ADJUST;
LOG_F(INFO, "进入浮调模式");
}
+16
View File
@@ -0,0 +1,16 @@
#include "PowerManagerFsm.hpp"
void FloatDown::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
handleCuriseWork();
pm->workCondition = WorkCondition::ASCEND_DESCEND;
LOG_F(INFO, "进入上浮下潜模式");
}
// FloatDown实现
void FloatDown::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
@@ -0,0 +1,16 @@
#include "PowerManagerFsm.hpp"
void HighSpeedMode::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
handleCuriseWork();
pm->workCondition = WorkCondition::HIGH_SPEED_MODE;
LOG_F(INFO, "进入高速模式");
}
// HighSpeedMode实现
void HighSpeedMode::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
+10
View File
@@ -0,0 +1,10 @@
#include "PowerManagerFsm.hpp"
// InitState实现
void InitState::entry() {
PowerManagerFsm::entry();
LOG_F(INFO, "进入初始化状态");
pm->initControlCmd();
pm->m_lowerCommManager->operate_hold();
transit<StandbyState>();
}
+90
View File
@@ -0,0 +1,90 @@
#include "PowerManagerFsm.hpp"
void Lifting::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
//1. 关闭所有水声设备
LOG_F(INFO,"前视声纳关机指令");
pm->sendNotification("uExternComm_frontSonarControl_cmd","0");
MOOSPause(10000);
for(auto iter : underWterDevices)
{
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, static_cast<DeviceId::Type>(iter), 0);
}
//2. 关闭动力电设备
//2.1 断开所有艏部高压断路器
pm->m_lowerCommManager->operate_HVA_actuatorCircuit_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HVA_bowFTDevice123Circuit_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HVA_bowRudderControlBoxCircuit_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HVA_mastSteeringGearControlBoxCircuit_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HVA_xczCircuit_Breaker(0);
MOOSPause(3);
//2.2 断开所有艉部高压设备断路器
pm->m_lowerCommManager->operate_HV_propulsionMotor_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_sternFt45_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_sternRudder1_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_sternRudder2_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_fbReserved_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_tyzReserved_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_reserved_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_dcDc5_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_coolingSystem_Breaker(0);
MOOSPause(3);
//2.5 断开动力电断路器
pm->m_lowerCommManager->operate_HV_bowHighVoltageBox_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_dcDc5_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_coolingSystem_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_dcDc5Module_Breaker(0);
MOOSPause(3);
pm->m_lowerCommManager->operate_HV_powerLithiumBattery_Breaker(0);
//3. 关闭燃料电池
//4. 关闭动力锂电池
MOOSPause(3);
{
int count=0;
while (!(pm->m_systemData->dyn_pos_relay_status == 0x02 && pm->m_systemData->dyn_neg_relay_status == 0x02))
{
LOG_F(INFO,"动力锂电池下电中...");
MOOSPause(3);
if(count>10)
{
LOG_F(INFO, "动力锂电池无下电反馈");
break;
}
count++;
}
}
LOG_F(INFO, "动力锂电池已下电");
pm->workCondition = WorkCondition::LIFT_MODE;
LOG_F(INFO, "WorkCondition %d", pm->workCondition);
}
void Lifting::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void Lifting::react(DevCmdExt const &e)
{
LOG_F(INFO, "DevCmdExt 执行");
PowerManagerFsm::react(e);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,300 @@
#ifndef POWER_MANAGER_FSM_HPP
#define POWER_MANAGER_FSM_HPP
#include "tinyfsm.hpp"
#include "../logc/loguru.hpp"
#include <iostream>
#include <chrono> // 新增头文件
#include <iomanip> // 新增头文件
#include <ctime> // 新增头文件,用于localtime函数
#include <cxxabi.h> // 新增头文件,用于demangle功能
#include "../pmSysvariable.h"
#include "../driver.h"
#include "../PowerManger.h"
#include "../upmsg/uExternComm_setThrustSpeed_cmd.h"
#define OVER_DEPTH 0.1
// 前向声明
class PowerManger;
enum class PowerSystemState {
INIT,
STANDBY,
FAULT,
};
//==================状态切换事件=============================
struct InitEvent : tinyfsm::Event { };
struct StandbyEvent : tinyfsm::Event { };
struct TaskStopEvent : tinyfsm::Event { };
struct TaskStartEvent : tinyfsm::Event {
int type;
bool enableBowRudder;
bool enableBuoyancyAdjustment;
TaskStartEvent() : type(0), enableBowRudder(false), enableBuoyancyAdjustment(false) {};
TaskStartEvent(int type, bool bowRudder, bool buoyancyAdjustment) : type(type), enableBowRudder(bowRudder), enableBuoyancyAdjustment(buoyancyAdjustment) {};
};
//==================状态流程事件============================
struct CycleTriggeredEvent : tinyfsm::Event {};
struct MasterCommandEvent : tinyfsm::Event {};
struct DeviceCmd : tinyfsm::Event {};
struct DevCmdExt : tinyfsm::Event {
int id;
int cmd;
DevCmdExt() : id(0), cmd(0) {};
DevCmdExt(int id, int cmd) : id(id), cmd(cmd) {};
};
struct SideSonarCmd : tinyfsm::Event {
int xcLowVoltageAdd;
int xcHighVoltageAdd;
SideSonarCmd() : xcLowVoltageAdd(0),xcHighVoltageAdd(0) {};
SideSonarCmd(int xcLowVoltageAdd,int xcHighVoltageAdd) : xcLowVoltageAdd(xcLowVoltageAdd),xcHighVoltageAdd(xcHighVoltageAdd) {};
};
//==================测试事件================================
struct TestEvent : tinyfsm::Event {
std::string eventName;
unsigned int type;
unsigned int eventId;
TestEvent() : eventName(""), eventId(0),type(0) {};
TestEvent(std::string eventName, unsigned int type,unsigned int eventId) : eventName(eventName), eventId(eventId),type(type) {};
};
struct FaultEvent : tinyfsm::Event {
unsigned int subDisSysFaultCode;
unsigned int disSysFaultCode;
unsigned int powerFaultCode;
unsigned int fcsFaultCode;
unsigned int ccsFaultCode;
unsigned int injectionFaultCode;
FaultEvent() : subDisSysFaultCode(0), disSysFaultCode(0), powerFaultCode(0), fcsFaultCode(0), ccsFaultCode(0),injectionFaultCode(0) {};
FaultEvent(unsigned int subDisSysFaultCode,
unsigned int disSysFaultCode,
unsigned int powerFaultCode,
unsigned int fcsFaultCode,
unsigned int ccsFaultCode,
unsigned int injectionFaultCode)
: subDisSysFaultCode(subDisSysFaultCode),
disSysFaultCode(disSysFaultCode),
powerFaultCode(powerFaultCode),
fcsFaultCode(fcsFaultCode),
ccsFaultCode(ccsFaultCode),
injectionFaultCode(injectionFaultCode) {};
};
class PowerManagerFsm : public tinyfsm::Fsm<PowerManagerFsm> {
protected:
static PowerManger* pm;
static DriverTable m_currentDriver;
public:
static void init(PowerManger* powerManager) {
pm = powerManager;
}
virtual void react(tinyfsm::Event const &) { std::cout << "[ Reseve Envt ] " << "No Idear" << std::endl; }
virtual void react(InitEvent const &) {};
virtual void react(StandbyEvent const &) {};
virtual void react(MasterCommandEvent const &) { LOG_F(INFO, "MasterCommandEvent");};
// virtual void react(DeviceCmd const &);
virtual void react(DevCmdExt const &e);
virtual void react(TaskStartEvent const &e);
virtual void react(FaultEvent const &e);
virtual void react(TaskStopEvent const &e);
virtual void react(CycleTriggeredEvent const &e);
virtual void react(SideSonarCmd const &e);
//测试事件
virtual void react(TestEvent const &);
//======================操作函数=============================
void handelPowerCmd();
void handleModCmd();
void handleWorkCmd();
void handleDeviceCmd();
void handleCuriseWork();
void handleNoPowerDeviceCmd(int id , int cmd); // 非水声仪表设备
void handleHydroacousticDeviceCmd(int id , int cmd); // 水声设备处理
void handleBowRudderSystemCmd(int id, int cmd); // 艏舵设备处理
void handleActuatorCmd(int id, int cmd); // 启闭机构处理
void handleOpenWaterCmd(int id, int cmd); // 敞水机构处理
void handleSternRudderCmd(int id, int cmd); // 艉舵设备处理
void handlePropulsionMotorCmd(int id, int cmd); // 推进电机处理
void handleBuoyancyAdjustmentCmd(int id, int cmd); // 浮调设备处理
void handleFBSystemCmd(int id, int cmd); // FB设备处理
void handleSideSonarCmd(int id, int cmd); // 舷侧设备处理
void handleMastFoldingSystemCmd(int id, int cmd); // 桅杆设备处理
//获取仅仪表设备状态
void getNoPowerDeviceStatus(DriverTable &s);
void getBowRudderSystemStatus(DriverTable &s);
void getActuatorStatus(DriverTable &s);
void getSternRudderStatus(DriverTable &s);
void getPropulsionMotorStatus(DriverTable &s);
void getBuoyancyAdjustmentStatus(DriverTable &s);
void getFBSystemCmdStatus(DriverTable &s);
void getSideSonarStatus(DriverTable &s);
void getMastFoldingSystem(DriverTable &s);
void getOpenWaterStatus(DriverTable &s);
//故障处理
void basicNavigationFault(FaultEvent const &e);
void extendedNavigationFault(FaultEvent const &e);
void obstacleAvoidanceFault(FaultEvent const &e);
void buoyancyControlFault(FaultEvent const &e);
void communicationSystemFault(FaultEvent const &e);
void payloadSystemFault(FaultEvent const &e);
void emergencySystemFault(FaultEvent const &e);
void sensorSystemFault(FaultEvent const &e);
void basicNavigationFault();
void extendedNavigationFault();
void obstacleAvoidanceFault();
void buoyancyControlFault();
void communicationSystemFault();
void payloadSystemFault();
void emergencySystemFault();
void sensorSystemFault();
// void handleFaultOfDisSys();
// 状态机生命周期方法
virtual void entry() {
auto now = std::chrono::system_clock::now();
auto now_time = std::chrono::system_clock::to_time_t(now);
int status = 0;
char* demangled = abi::__cxa_demangle(typeid(*this).name(), nullptr, nullptr, &status);
std::string typeName = (status == 0) ? demangled : typeid(*this).name();
if (demangled) free(demangled);
std::cout << "\033[1;38;5;51m╭──────────────────────────────────────────────────────\n"
<< "│ \033[1;38;5;226m⮞⮞⮞ \033[0;38;5;51m[" << std::put_time(std::localtime(&now_time), "%Y-%m-%d %H:%M:%S")
<< "] \033[1;38;5;255m进入状态: \033[1;38;5;213m" << typeName << "\n"
<< "│ \033[0m" << std::endl;
LOG_F(INFO, "进入状态: %s", typeName.c_str());
}
virtual void exit() {
auto now = std::chrono::system_clock::now();
auto now_time = std::chrono::system_clock::to_time_t(now);
int status = 0;
char* demangled = abi::__cxa_demangle(typeid(*this).name(), nullptr, nullptr, &status);
std::string typeName = (status == 0) ? demangled : typeid(*this).name();
if (demangled) free(demangled);
std::cout << "\033[1;38;5;203m│ \n"
<< "│ \033[1;38;5;208m⮜⮜⮜ \033[0;38;5;203m[" << std::put_time(std::localtime(&now_time), "%Y-%m-%d %H:%M:%S")
<< "] \033[1;38;5;255m离开状态: \033[1;38;5;213m" << typeName << "\n"
<< "╰──────────────────────────────────────────────────────\033[0m" << std::endl;
LOG_F(INFO, "离开状态: %s", typeName.c_str());
}
};
// 初始化
class InitState : public PowerManagerFsm {
public:
void entry() override;
};
//待机状态
class StandbyState : public PowerManagerFsm {
public:
void entry() override;
void react(StandbyEvent const &) override;
void react(DevCmdExt const &e) override;
void react(MasterCommandEvent const &) override;
};
// 岸基备航
class ShoreBasedReady : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// 水中备航
class WaterBasedReady : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
void react(DevCmdExt const &e) override;
private:
};
// 巡航模式
class CruiseMode : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// 上浮下潜
class FloatDown : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// 高速模式
class HighSpeedMode : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// 浮调模式
class FloatAdjust : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// 水下侦查
class UnderwaterSurvey : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// 水面侦查
class SurfaceSurvey : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
// DJ模式
class DJMode : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
void exit() override;
private:
};
// 遥控工况
class RemoteControl : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
private:
};
class FaultState : public PowerManagerFsm {
public:
void entry() override;
void react(FaultEvent const &);
void react(MasterCommandEvent const &) override;
};
class Lifting : public PowerManagerFsm {
public:
void entry() override;
void react(MasterCommandEvent const &) override;
};
#endif // POWER_MANAGER_FSM_HPP
@@ -0,0 +1,16 @@
#include "PowerManagerFsm.hpp"
// RemoteControl实现
void RemoteControl::react(MasterCommandEvent const &){
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void RemoteControl::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::REMOTE_CONTROL;
LOG_F(INFO, "进入遥控工况");
}
@@ -0,0 +1,92 @@
#include "PowerManagerFsm.hpp"
// ShoreBasedReady实现
void ShoreBasedReady::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void ShoreBasedReady::entry() {
PowerManagerFsm::entry();
pm->m_driver.getSHORE_BASED_READYable(&pm->m_subDisSysCmd);
pm->workCondition = WorkCondition::CHANING;
//依次接入执行机构动力电设备
//1. 开启动力电
//1.1 动力锂电池上电
pm->m_CcuColCmd.powerBatCmd = BatteryCommand::Start;
//1.2 闭合动力电断路器
pm->m_lowerCommManager->operate_HV_powerLithiumBattery_Breaker(1);
MOOSPause(100);
pm->m_lowerCommManager->operate_HV_dcDc5Module_Breaker(1);
MOOSPause(100);
pm->m_lowerCommManager->operate_HV_dcDc5_Breaker(1);
pm->m_lowerCommManager->operate_HV_coolingSystem_Breaker(1);
MOOSPause(100);
pm->m_lowerCommManager->operate_HV_bowHighVoltageBox_Breaker(1);
MOOSPause(100);
//2. 启动动力电设备
unsigned char cmd = 1;
//2.0 艉舵
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::sternRudderServo1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::sternRudderServo2, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
pm->m_lowerCommManager->operate_HV_sternRudder1_Breaker(1);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::sternRudderServo3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::sternRudderServo4, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
pm->m_lowerCommManager->operate_HV_sternRudder2_Breaker(1);
//2.1 启闭机构
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowCover6, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HVA_actuatorCircuit_Breaker(1);
//2.2 敞水电缸
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet3, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet5, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet6, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet7, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowWaterInet8, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HVA_openWaterCoverStartCylinderCircuit_Breaker(1);
//2.3 艏舵
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowRudderDeploy, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::bowRudderServo1, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HVA_bowRudderControlBoxCircuit_Breaker(1);
//2.4 桅杆舵机
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::mastLiftingServo, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HVA_mastSteeringGearControlBoxCircuit_Breaker(1);
//2.5 艏部浮调机构
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::buoyancyAdjust1, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::buoyancyAdjust2, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::buoyancyAdjust3, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HVA_bowFTDevice123Circuit_Breaker(1);
//2.6 艉部浮调机构
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::buoyancyAdjust4, (unsigned char)cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::buoyancyAdjust5, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HV_sternFt45_Breaker(1);
//2.7 推进电机
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::thruster, (unsigned char)cmd);
pm->m_upperCommManager->processPeriodicTasks();
MOOSPause(100);
pm->m_lowerCommManager->operate_HV_propulsionMotor_Breaker(1);
pm->workCondition = WorkCondition::SHORE_BASED_READY;
LOG_F(INFO, "进入岸基备航状态");
}
+24
View File
@@ -0,0 +1,24 @@
#include "PowerManagerFsm.hpp"
// StandbyState实现
void StandbyState::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::STANDBY;
pm->m_driver.getSTANDBYTable(&pm->m_subDisSysCmd);
pm->m_lowerCommManager->operate_hold();
LOG_F(INFO, "WorkCondition %d", pm->workCondition);
}
void StandbyState::react(StandbyEvent const &) {
transit<StandbyState>();
}
void StandbyState::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void StandbyState::react(DevCmdExt const &e)
{
LOG_F(INFO, "DevCmdExt 执行");
PowerManagerFsm::react(e);
}
@@ -0,0 +1,16 @@
#include "PowerManagerFsm.hpp"
// SurfaceSurvey实现
void SurfaceSurvey::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void SurfaceSurvey::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
handleCuriseWork();
pm->workCondition = WorkCondition::SURFACE_RECON;
LOG_F(INFO, "进入水面侦查模式");
}
@@ -0,0 +1,17 @@
#include "PowerManagerFsm.hpp"
void UnderwaterSurvey::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
handleCuriseWork();
pm->workCondition = WorkCondition::UNDERWATER_RECON;
LOG_F(INFO, "进入水下侦查模式");
}
// UnderwaterSurvey实现
void UnderwaterSurvey::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
@@ -0,0 +1,62 @@
#include "PowerManagerFsm.hpp"
void WaterBasedReady::entry() {
PowerManagerFsm::entry();
pm->workCondition = WorkCondition::CHANING;
PowerManagerFsm::handleCuriseWork();
//启动水声设备
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::DVL, (unsigned char)EquipmentCommand::ON);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, DeviceId::USBL, (unsigned char)EquipmentCommand::ON);
pm->m_upperCommManager->processPeriodicTasks();
pm->workCondition = WorkCondition::WATER_BASED_READY;
LOG_F(INFO, "进入水中备航状态");
}
// WaterBasedReady实现
void WaterBasedReady::react(MasterCommandEvent const &) {
PowerManagerFsm::handelPowerCmd();
PowerManagerFsm::handleModCmd();
PowerManagerFsm::handleWorkCmd();
}
void WaterBasedReady::react(DevCmdExt const &e)
{
int id = e.id;
int cmd = e.cmd;
if(underWterDevices.find(id) != underWterDevices.end())
{
if (pm->currentMod != PMMode::Debug)
{
if(pm->m_depth < OVER_DEPTH)
{
LOG_F(INFO, "水下设备操作上电保护 %d ", id);
return;
}
}
// 如果是前视声纳断电则先关机再断电
if(id == DeviceId::forwardSonar)
{
if(cmd == 0)
{
LOG_F(INFO,"前视声纳关机指令");
pm->sendNotification("uExternComm_frontSonarControl_cmd","0");
MOOSPause(10000);
}
}
LOG_F(INFO, "水声设备操作: %s,%d, %d", DeviceId::toString((DeviceId::Type)id), id, cmd);
pm->m_driver.setDeviceState(pm->m_subDisSysCmd, (DeviceId::Type)id, (unsigned char)cmd);
}
else
{
if(pm->currentMod == PMMode::Normal)
{
LOG_F(INFO,"正常模式:操作禁止");
return;
}
else
{
PowerManagerFsm::react(e);
}
}
}
@@ -0,0 +1,476 @@
#ifndef HTTP_SERVER_BATTERYOPERATION_H
#define HTTP_SERVER_BATTERYOPERATION_H
#include <string>
const std::string BATTERY_OPERATION_HTML = R"(
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>电池操作</title>
<link rel="stylesheet" href="/static/style.css">
<style>
:root {
--primary-color: #2563eb;
--primary-hover: #1d4ed8;
--bg-color: #f8fafc;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color);
color: #1a1a1a;
}
.container {
display: grid;
grid-template-areas:
"sidebar main-content";
grid-template-columns: 220px 1fr;
grid-template-rows: 1fr;
min-height: 100vh;
gap: 0;
}
.header {
grid-area: unset;
background: white;
padding: 0 0.5rem;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
right: 0;
left: 220px;
height: 36px;
z-index: 10;
}
.header h1 {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
}
.sidebar {
grid-area: sidebar;
background: white;
width: 220px;
height: 100vh;
position: fixed;
left: 0;
top: 0;
padding: 0.5rem 0.25rem;
box-shadow: 1px 0 3px rgba(0, 0, 0, 0.1);
z-index: 20;
}
.sidebar-menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.sidebar-button {
display: flex;
align-items: center;
padding: 0.5rem 0.75rem;
border-radius: 0.375rem;
color: #4b5563;
text-decoration: none;
transition: all 0.2s ease;
}
.sidebar-button:hover {
background: var(--bg-color);
color: var(--primary-color);
}
.sidebar-icon {
min-width: 1.5rem;
margin-right: 1rem;
font-size: 1.25rem;
}
.main-content {
grid-area: main-content;
padding: 1px;
margin-top: 36px;
}
.control-panel {
background: white;
border-radius: 4px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin: 20px;
}
.panel-title {
font-size: 1.2rem;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #e5e7eb;
}
.control-group {
margin-bottom: 20px;
}
.control-label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.radio-group {
display: flex;
gap: 16px;
margin-bottom: 12px;
}
.radio-option {
display: flex;
align-items: center;
gap: 8px;
}
.select-control {
width: 100%;
padding: 8px 12px;
border: 1px solid #d1d5db;
border-radius: 4px;
background-color: white;
margin-bottom: 12px;
}
.slider-container {
display: flex;
align-items: center;
gap: 12px;
}
.slider {
flex-grow: 1;
height: 6px;
-webkit-appearance: none;
background: #d1d5db;
border-radius: 3px;
outline: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px;
height: 18px;
background: var(--primary-color);
border-radius: 50%;
cursor: pointer;
}
.slider-value {
min-width: 50px;
text-align: right;
}
.button-group {
display: flex;
gap: 12px;
margin-top: 8px;
}
.button {
padding: 8px 16px;
border: none;
border-radius: 4px;
background-color: #e5e7eb;
color: #1a1a1a;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.button:hover {
background-color: #d1d5db;
}
.button-secondary {
background-color: #e5e7eb;
color: #1a1a1a;
}
.button-secondary:hover {
background-color: #d1d5db;
}
.button-active {
background-color: var(--primary-color);
color: white;
}
.button-active:hover {
background-color: var(--primary-hover);
}
.form-submit {
margin-top: 24px;
width: 100%;
padding: 12px;
font-size: 1rem;
}
.status-message {
margin-top: 16px;
padding: 12px;
border-radius: 4px;
background-color: #f0fdf4;
color: #166534;
display: none;
}
.status-message.error {
background-color: #fef2f2;
color: #991b1b;
}
</style>
</head>
<body>
<div class="container">
<div class="sidebar">
<div class="sidebar-menu">
<a href="/" class="sidebar-button">
<span class="sidebar-icon">🏠</span>
<span>系统主页</span>
</a>
<a href="/data" class="sidebar-button">
<span class="sidebar-icon">📊</span>
<span>系统数据</span>
</a>
<a href="/dashboard" class="sidebar-button">
<span class="sidebar-icon">⚡</span>
<span>配电操作</span>
</a>
<a href="/battery" class="sidebar-button">
<span class="sidebar-icon">🔋</span>
<span>电池操作</span>
</a>
<a href="/logs" class="sidebar-button">
<span class="sidebar-icon">📝</span>
<span>系统日志</span>
</a>
</div>
</div>
<div class="header">
<h1>电池操作系统</h1>
</div>
<div class="main-content">
<div class="control-panel">
<div class="panel-title">燃料电池控制</div>
<form id="batteryForm" method="POST" action="/battery/control">
<div class="control-group">
<label class="control-label">燃料电池模式设定</label>
<div class="radio-group">
<label class="radio-option">
<input type="radio" name="fuelCellMode" value="00H" checked>
<span>无效</span>
</label>
<label class="radio-option">
<input type="radio" name="fuelCellMode" value="01H">
<span>调试</span>
</label>
<label class="radio-option">
<input type="radio" name="fuelCellMode" value="02H">
<span>自动</span>
</label>
<label class="radio-option">
<input type="radio" name="fuelCellMode" value="03H">
<span>补给</span>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label">燃料电池指令</label>
<select class="select-control" name="fuelCellCommand">
<option value="00H">无效</option>
<option value="01H">自检</option>
<option value="02H">启动</option>
<option value="03H">停机</option>
<option value="04H">复位</option>
<option value="05H">紧急停机</option>
<option value="06H">补给</option>
<option value="07H">制氢预热</option>
<option value="08H">停机维护</option>
</select>
</div>
<div class="control-group">
<label class="control-label">燃料电池动力通路功率配置 (kW)</label>
<div class="slider-container">
<input type="range" class="slider" name="fuelCellPower" min="0" max="20" value="0" step="1">
<span class="slider-value">0</span>
</div>
</div>
<div class="panel-title">锂电池控制</div>
<div class="control-group">
<label class="control-label">仪表锂电池启停指令</label>
<div class="button-group">
<button type="button" class="button button-active" data-command="instrumentBattery" data-value="00H">无效</button>
<button type="button" class="button button-secondary" data-command="instrumentBattery" data-value="10H">启动</button>
<button type="button" class="button button-secondary" data-command="instrumentBattery" data-value="20H">关闭</button>
</div>
<input type="hidden" name="instrumentBattery" value="00H">
</div>
<div class="control-group">
<label class="control-label">仪表锂电池允许充电</label>
<div class="button-group">
<button type="button" class="button button-secondary" data-command="instrumentBatteryCharge" data-value="0">允许</button>
<button type="button" class="button button-active" data-command="instrumentBatteryCharge" data-value="48">禁止</button>
</div>
<input type="hidden" name="instrumentBatteryCharge" value="1">
</div>
<div class="control-group">
<label class="control-label">动力锂电池启停指令</label>
<div class="button-group">
<button type="button" class="button button-active" data-command="powerBattery" data-value="00H">无效</button>
<button type="button" class="button button-secondary" data-command="powerBattery" data-value="10H">启动</button>
<button type="button" class="button button-secondary" data-command="powerBattery" data-value="20H">关闭</button>
</div>
<input type="hidden" name="powerBattery" value="00H">
</div>
<div class="control-group">
<label class="control-label">动力锂电池电池功率配置值 (kW)</label>
<div class="slider-container">
<input type="range" class="slider" name="powerBatteryPower" min="0" max="400" value="0" step="10">
<span class="slider-value">0</span>
</div>
</div>
<div class="panel-title">主机状态</div>
<div class="control-group">
<label class="control-label">主机状态指令</label>
<div class="radio-group">
<label class="radio-option">
<input type="radio" name="hostStatus" value="AAH" checked>
<span>运行</span>
</label>
<label class="radio-option">
<input type="radio" name="hostStatus" value="FFH">
<span>关机</span>
</label>
<label class="radio-option">
<input type="radio" name="hostStatus" value="55H">
<span>故障</span>
</label>
</div>
</div>
<button type="submit" class="button form-submit">提交配置</button>
<div id="statusMessage" class="status-message"></div>
</form>
</div>
</div>
</div>
<script>
// 更新滑块值显示
document.querySelectorAll('.slider').forEach(slider => {
const valueDisplay = slider.nextElementSibling;
valueDisplay.textContent = slider.value;
slider.addEventListener('input', () => {
valueDisplay.textContent = slider.value;
});
});
// 处理按钮组选择
document.querySelectorAll('.button-group button').forEach(button => {
button.addEventListener('click', () => {
const group = button.closest('.button-group');
const hiddenInput = group.nextElementSibling;
const command = button.dataset.command;
const value = button.dataset.value;
// 更新按钮样式
group.querySelectorAll('button').forEach(btn => {
btn.classList.remove('button-active');
btn.classList.add('button-secondary');
});
button.classList.remove('button-secondary');
button.classList.add('button-active');
// 更新隐藏输入值
hiddenInput.value = value;
});
});
// 处理表单提交
document.getElementById('batteryForm').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const statusMessage = document.getElementById('statusMessage');
try {
// 将表单数据转换为URL编码格式
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
params.append(key, value);
}
const response = await fetch(form.action, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params.toString()
});
const result = await response.json();
if (result.success) {
statusMessage.textContent = '配置提交成功';
statusMessage.className = 'status-message';
statusMessage.style.display = 'block';
} else {
statusMessage.textContent = result.message || '配置提交失败';
statusMessage.className = 'status-message error';
statusMessage.style.display = 'block';
}
} catch (error) {
statusMessage.textContent = '网络错误: ' + error.message;
statusMessage.className = 'status-message error';
statusMessage.style.display = 'block';
}
setTimeout(() => {
statusMessage.style.display = 'none';
}, 5000);
});
</script>
</body>
</html>
)";
#endif // HTTP_SERVER_BATTERYOPERATION_H
+580
View File
@@ -0,0 +1,580 @@
#ifndef HTTP_SERVER_DASHBOARD_H
#define HTTP_SERVER_DASHBOARD_H
#include <string>
const std::string DASHBOARD_HTML = R"row(
<!DOCTYPE html>
<html>
<head>
<title>断路器控制面板</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background-color: #f8f9fa;
}
.container {
display: flex;
gap: 25px;
max-width: 1400px;
margin: 0 auto;
}
.column {
flex: 1;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: transform 0.2s;
}
.column:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.column-title {
font-weight: 600;
margin-bottom: 20px;
text-align: center;
font-size: 20px;
color: #2c3e50;
padding-bottom: 10px;
border-bottom: 2px solid #eee;
}
.breaker {
margin-bottom: 12px;
padding: 10px 15px;
background: #f8f9fa;
border-radius: 6px;
border-left: 4px solid #3498db;
display: flex;
flex-direction: column;
gap: 8px;
}
.breaker-name {
font-weight: 600;
font-size: 18px;
color: #2c3e50;
padding: 6px 10px;
background-color: rgba(46, 204, 113, 0.1);
border-radius: 4px;
display: inline-flex;
align-items: center;
width: fit-content;
}
.breaker-controls {
display: flex;
gap: 10px;
align-items: center;
}
button {
padding: 8px 16px;
min-width: 70px;
cursor: pointer;
border: none;
border-radius: 4px;
font-weight: 500;
font-size: 14px;
transition: all 0.2s;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button:hover {
opacity: 0.9;
transform: translateY(-1px);
}
button:first-of-type {
background-color: #2ecc71;
color: white;
}
button:last-of-type {
background-color: #e74c3c;
color: white;
}
.status-message {
margin-top: 8px;
padding: 6px;
font-size: 13px;
border-radius: 3px;
}
.status-success {
background-color: rgba(46, 204, 113, 0.1);
color: #27ae60;
}
.status-error {
background-color: rgba(231, 76, 60, 0.1);
color: #c0392b;
}
.status-pending {
background-color: rgba(241, 196, 15, 0.1);
color: #f39c12;
}
.status-timer {
font-size: 12px;
color: #7f8c8d;
margin-top: 4px;
}
</style>
</head>
<body>
<div class="container">
<div class="column">
<div class="column-title">高压母线设备</div>
<!-- 高压母线断路器列表 -->
<div class="breaker">
<div class="breaker-name">燃料电池断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'fuel_cell', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'fuel_cell', 'open')">断开</button>
</div>
<div id="high_vol_bus-fuel_cell-status-message" class="status-message"></div>
<div id="high_vol_bus-fuel_cell-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">动力锂电池断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'power_battery', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'power_battery', 'open')">断开</button>
</div>
<div id="high_vol_bus-power_battery-status-message" class="status-message"></div>
<div id="high_vol_bus-power_battery-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">推进电机断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'propulsion_motor', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'propulsion_motor', 'open')">断开</button>
</div>
<div id="high_vol_bus-propulsion_motor-status-message" class="status-message"></div>
<div id="high_vol_bus-propulsion_motor-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">锂电池组仪表断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'battery_meter', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'battery_meter', 'open')">断开</button>
</div>
<div id="high_vol_bus-battery_meter-status-message" class="status-message"></div>
<div id="high_vol_bus-battery_meter-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">DC/DC5模块断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'dcdc5', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'dcdc5', 'open')">断开</button>
</div>
<div id="high_vol_bus-dcdc5-status-message" class="status-message"></div>
<div id="high_vol_bus-dcdc5-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艏部高压配电箱断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'bow_distribution', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'bow_distribution', 'open')">断开</button>
</div>
<div id="high_vol_bus-bow_distribution-status-message" class="status-message"></div>
<div id="high_vol_bus-bow_distribution-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艉部FT装置4/5断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'stern_ft45', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'stern_ft45', 'open')">断开</button>
</div>
<div id="high_vol_bus-stern_ft45-status-message" class="status-message"></div>
<div id="high_vol_bus-stern_ft45-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艉舵开关1断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'stern_rudder1', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'stern_rudder1', 'open')">断开</button>
</div>
<div id="high_vol_bus-stern_rudder1-status-message" class="status-message"></div>
<div id="high_vol_bus-stern_rudder1-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艉舵开关2断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'stern_rudder2', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'stern_rudder2', 'open')">断开</button>
</div>
<div id="high_vol_bus-stern_rudder2-status-message" class="status-message"></div>
<div id="high_vol_bus-stern_rudder2-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">FB预留断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'fb_reserve', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'fb_reserve', 'open')">断开</button>
</div>
<div id="high_vol_bus-fb_reserve-status-message" class="status-message"></div>
<div id="high_vol_bus-fb_reserve-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">TYZ预留断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'tyz_reserve', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'tyz_reserve', 'open')">断开</button>
</div>
<div id="high_vol_bus-tyz_reserve-status-message" class="status-message"></div>
<div id="high_vol_bus-tyz_reserve-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">预留断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'reserve', 'close')">闭合</button>
<button onclick="sendCommand('high_vol_bus', 'reserve', 'open')">断开</button>
</div>
<div id="high_vol_bus-reserve-status-message" class="status-message"></div>
<div id="high_vol_bus-reserve-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">DC/DC5模块启动</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'dcdc5_start', 'close')">启动</button>
<button onclick="sendCommand('high_vol_bus', 'dcdc5_start', 'open')">停止</button>
</div>
<div id="high_vol_bus-dcdc5_start-status-message" class="status-message"></div>
<div id="high_vol_bus-dcdc5_start-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">冷却系统启动</div>
<div class="breaker-controls">
<button onclick="sendCommand('high_vol_bus', 'cooling_system', 'close')">启动</button>
<button onclick="sendCommand('high_vol_bus', 'cooling_system', 'open')">停止</button>
</div>
<div id="high_vol_bus-cooling_system-status-message" class="status-message"></div>
<div id="high_vol_bus-cooling_system-timer" class="status-timer"></div>
</div>
</div>
<div class="column">
<div class="column-title">艏高压设备</div>
<!-- 艏高压断路器列表 -->
<div class="breaker">
<div class="breaker-name">艏部FT装置1-3断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_high_vol', 'bow_ft1_3', 'close')">闭合</button>
<button onclick="sendCommand('bow_high_vol', 'bow_ft1_3', 'open')">断开</button>
</div>
<div id="bow_high_vol-bow_ft1_3-status-message" class="status-message"></div>
<div id="bow_high_vol-bow_ft1_3-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">启闭机构断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_high_vol', 'opening_mechanism', 'close')">闭合</button>
<button onclick="sendCommand('bow_high_vol', 'opening_mechanism', 'open')">断开</button>
</div>
<div id="bow_high_vol-opening_mechanism-status-message" class="status-message"></div>
<div id="bow_high_vol-opening_mechanism-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">桅杆舵机控制箱断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_high_vol', 'mast_steering', 'close')">闭合</button>
<button onclick="sendCommand('bow_high_vol', 'mast_steering', 'open')">断开</button>
</div>
<div id="bow_high_vol-mast_steering-status-message" class="status-message"></div>
<div id="bow_high_vol-mast_steering-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">XCZ断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_high_vol', 'xcz', 'close')">闭合</button>
<button onclick="sendCommand('bow_high_vol', 'xcz', 'open')">断开</button>
</div>
<div id="bow_high_vol-xcz-status-message" class="status-message"></div>
<div id="bow_high_vol-xcz-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艏舵控制箱断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_high_vol', 'bow_rudder', 'close')">闭合</button>
<button onclick="sendCommand('bow_high_vol', 'bow_rudder', 'open')">断开</button>
</div>
<div id="bow_high_vol-bow_rudder-status-message" class="status-message"></div>
<div id="bow_high_vol-bow_rudder-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">敞水盖启动电缸断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_high_vol', 'water_cover', 'close')">闭合</button>
<button onclick="sendCommand('bow_high_vol', 'water_cover', 'open')">断开</button>
</div>
<div id="bow_high_vol-water_cover-status-message" class="status-message"></div>
<div id="bow_high_vol-water_cover-timer" class="status-timer"></div>
</div>
</div>
<div class="column">
<div class="column-title">仪表母线设备</div>
<!-- 仪表母线断路器列表 -->
<div class="breaker">
<div class="breaker-name">锂电池组(仪表)断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'battery_meter', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'battery_meter', 'open')">断开</button>
</div>
<div id="meter_bus-battery_meter-status-message" class="status-message"></div>
<div id="meter_bus-battery_meter-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艏部低压配电箱断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'bow_low_dist', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'bow_low_dist', 'open')">断开</button>
</div>
<div id="meter_bus-bow_low_dist-status-message" class="status-message"></div>
<div id="meter_bus-bow_low_dist-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">UNIT4仪表DC48V断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'unit4_dc48v', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'unit4_dc48v', 'open')">断开</button>
</div>
<div id="meter_bus-unit4_dc48v-status-message" class="status-message"></div>
<div id="meter_bus-unit4_dc48v-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">DC-C1直流配电板断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'dc_c1', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'dc_c1', 'open')">断开</button>
</div>
<div id="meter_bus-dc_c1-status-message" class="status-message"></div>
<div id="meter_bus-dc_c1-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">预留断路器1</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'reserve1', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'reserve1', 'open')">断开</button>
</div>
<div id="meter_bus-reserve1-status-message" class="status-message"></div>
<div id="meter_bus-reserve1-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">预留断路器2</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'reserve2', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'reserve2', 'open')">断开</button>
</div>
<div id="meter_bus-reserve2-status-message" class="status-message"></div>
<div id="meter_bus-reserve2-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">应急锂电池组2断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('meter_bus', 'emergency_battery2', 'close')">闭合</button>
<button onclick="sendCommand('meter_bus', 'emergency_battery2', 'open')">断开</button>
</div>
<div id="meter_bus-emergency_battery2-status-message" class="status-message"></div>
<div id="meter_bus-emergency_battery2-timer" class="status-timer"></div>
</div>
</div>
<div class="column">
<div class="column-title">艏低压设备</div>
<!-- 艏低压断路器列表 -->
<div class="breaker">
<div class="breaker-name">UNIT1断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'unit1', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'unit1', 'open')">断开</button>
</div>
<div id="bow_low_vol-unit1-status-message" class="status-message"></div>
<div id="bow_low_vol-unit1-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">UNIT2断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'unit2', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'unit2', 'open')">断开</button>
</div>
<div id="bow_low_vol-unit2-status-message" class="status-message"></div>
<div id="bow_low_vol-unit2-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">UNIT3断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'unit3', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'unit3', 'open')">断开</button>
</div>
<div id="bow_low_vol-unit3-status-message" class="status-message"></div>
<div id="bow_low_vol-unit3-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">UNIT5断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'unit5', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'unit5', 'open')">断开</button>
</div>
<div id="bow_low_vol-unit5-status-message" class="status-message"></div>
<div id="bow_low_vol-unit5-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">艏部PZ装置断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'bow_pz', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'bow_pz', 'open')">断开</button>
</div>
<div id="bow_low_vol-bow_pz-status-message" class="status-message"></div>
<div id="bow_low_vol-bow_pz-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">预留断路器1</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'reserve1', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'reserve1', 'open')">断开</button>
</div>
<div id="bow_low_vol-reserve1-status-message" class="status-message"></div>
<div id="bow_low_vol-reserve1-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">预留断路器2</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'reserve2', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'reserve2', 'open')">断开</button>
</div>
<div id="bow_low_vol-reserve2-status-message" class="status-message"></div>
<div id="bow_low_vol-reserve2-timer" class="status-timer"></div>
</div>
<div class="breaker">
<div class="breaker-name">应急锂电池组1断路器</div>
<div class="breaker-controls">
<button onclick="sendCommand('bow_low_vol', 'emergency_battery1', 'close')">闭合</button>
<button onclick="sendCommand('bow_low_vol', 'emergency_battery1', 'open')">断开</button>
</div>
<div id="bow_low_vol-emergency_battery1-status-message" class="status-message"></div>
<div id="bow_low_vol-emergency_battery1-timer" class="status-timer"></div>
</div>
</div>
</div>
<script>
// 全局存储所有设备的计时器状态
const deviceTimers = {};
function sendCommand(type, id, action, value) {
const statusEl = document.getElementById(`${type}-${id}-status-message`);
const timerEl = document.getElementById(`${type}-${id}-timer`);
const buttons = document.querySelectorAll(`button[onclick*="sendCommand('${type}', '${id}'"]`);
// 检查是否已有计时器运行
if (deviceTimers[`${type}-${id}`]) {
return;
}
// 禁用按钮
buttons.forEach(btn => {
btn.disabled = true;
btn.style.opacity = '0.6';
btn.style.cursor = 'not-allowed';
});
// 显示操作中状态
if (statusEl) {
statusEl.textContent = '操作中...';
statusEl.className = 'status-message status-pending';
}
// 启动5秒计时器
if (timerEl) {
let seconds = 8;
timerEl.textContent = `等待反馈: ${seconds}秒`;
timer = setInterval(() => {
seconds--;
if (seconds > 0) {
timerEl.textContent = `等待反馈: ${seconds}秒`;
} else {
clearInterval(timer);
timerEl.textContent = '';
if (statusEl && statusEl.textContent === '操作中...') {
statusEl.textContent = '操作超时: 未收到设备反馈';
statusEl.className = 'status-message status-error';
}
}
}, 1000);
}
// 设置10秒超时
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('请求超时')), 10000)
);
// 存储计时器
deviceTimers[`${type}-${id}`] = timer;
Promise.race([
fetch('/control', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ device_type: type, device_id: id, action: action, value: value })
}),
timeoutPromise
])
.then(res => {
// 立即清除计时器
const timerEl = document.getElementById(`${type}-${id}-timer`);
const buttons = document.querySelectorAll(`button[onclick*="sendCommand('${type}', '${id}'"]`);
if (timerEl) {
clearInterval(deviceTimers[`${type}-${id}`]);
delete deviceTimers[`${type}-${id}`];
timerEl.textContent = '';
}
// 恢复按钮状态
buttons.forEach(btn => {
btn.disabled = false;
btn.style.opacity = '1';
btn.style.cursor = 'pointer';
});
return res.json();
})
.then(data => {
const statusEl = document.getElementById(`${type}-${id}-status-message`);
if (statusEl) {
statusEl.textContent = data.message || (data.success ? '操作成功' : '操作失败');
statusEl.className = data.success ? 'status-message status-success' : 'status-message status-error';
}
})
.catch(error => {
const statusEl = document.getElementById(`${type}-${id}-status-message`);
const timerEl = document.getElementById(`${type}-${id}-timer`);
const buttons = document.querySelectorAll(`button[onclick*="sendCommand('${type}', '${id}'"]`);
if (timerEl) {
clearInterval(deviceTimers[`${type}-${id}`]);
delete deviceTimers[`${type}-${id}`];
timerEl.textContent = '';
}
// 恢复按钮状态
buttons.forEach(btn => {
btn.disabled = false;
btn.style.opacity = '1';
btn.style.cursor = 'pointer';
});
if (statusEl) {
if (error.message === '请求超时') {
statusEl.textContent = '操作超时: 未收到设备反馈';
} else {
statusEl.textContent = '通信错误: ' + error.message;
}
statusEl.className = 'status-message status-error';
}
});
}
</script>
</body>
</html>
)row";
#endif // HTTP_SERVER_DASHBOARD_H
File diff suppressed because it is too large Load Diff
+466
View File
@@ -0,0 +1,466 @@
#ifndef HTTP_SERVER_DEBUGPAGE_H
#define HTTP_SERVER_DEBUGPAGE_H
#include <string>
const std::string DEBUGPAGE_HTML = R"(
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Power Manager - 调试页面</title>
<link rel="stylesheet" href="/static/style.css">
<style>
:root {
--primary-color: #2563eb;
--primary-hover: #1d4ed8;
--bg-color: #f8fafc;
--sidebar-width: 60px;
--sidebar-expanded: 220px;
--header-height: 36px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color);
color: #1a1a1a;
}
.container {
display: grid;
grid-template-areas:
"sidebar main-content";
grid-template-columns: var(--sidebar-width) 1fr;
grid-template-rows: 1fr;
min-height: 100vh;
gap: 0;
}
.header {
grid-area: unset;
background: white;
padding: 0 0.5rem;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
right: 0;
left: var(--sidebar-width);
height: var(--header-height);
z-index: 10;
}
.header h1 {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
}
.sidebar {
grid-area: sidebar;
background: white;
width: var(--sidebar-width);
height: 100vh;
position: fixed;
left: 0;
top: 0;
padding: 0.5rem 0.25rem;
transition: width 0.3s ease;
box-shadow: 1px 0 3px rgba(0, 0, 0, 0.1);
z-index: 20;
}
.sidebar:hover {
width: var(--sidebar-expanded);
}
.sidebar-menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.sidebar-button {
display: flex;
align-items: center;
padding: 0.5rem 0.75rem;
border-radius: 0.375rem;
color: #4b5563;
text-decoration: none;
transition: all 0.2s ease;
white-space: nowrap;
overflow: hidden;
}
.sidebar-button:hover {
background: var(--bg-color);
color: var(--primary-color);
}
.sidebar-icon {
min-width: 1.5rem;
margin-right: 1rem;
font-size: 1.25rem;
}
.main-content {
grid-area: main-content;
padding: 1px;
margin-top: var(--header-height);
}
.status-bar {
position: fixed;
top: 4px;
right: 8px;
background: white;
padding: 4px 8px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
gap: 8px;
z-index: 15;
}
.status-info {
display: flex;
align-items: center;
gap: 8px;
color: #4b5563;
font-size: 0.875rem;
}
.debug-panel {
background: white;
border-radius: 4px;
padding: 16px;
margin: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.panel-title {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #e5e7eb;
}
.debug-section {
margin-bottom: 24px;
}
.section-title {
font-size: 1rem;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 8px;
}
.message-cards {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
margin-top: 16px;
max-width: 600px;
padding: 0 16px;
}
.message-card {
width: 100%;
box-sizing: border-box;
}
.message-card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.card-header {
padding: 12px 16px;
background: #f3f4f6;
border-bottom: 1px solid #e5e7eb;
font-weight: 600;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.card-header:hover {
background: #e5e7eb;
}
.card-content {
padding: 16px;
}
.card-content pre {
margin: 0;
white-space: pre-wrap;
font-family: monospace;
max-height: 150px;
overflow: hidden;
transition: max-height 0.3s ease;
}
.card-content pre.expanded {
max-height: none;
}
.toggle-button {
background: none;
border: none;
color: #2563eb;
cursor: pointer;
font-size: 0.9em;
padding: 4px 8px;
border-radius: 4px;
}
.toggle-button:hover {
background: rgba(37, 99, 235, 0.1);
}
.raw-data {
font-family: monospace;
white-space: pre-wrap;
background-color: #f3f4f6;
padding: 12px;
border-radius: 4px;
max-height: 300px;
overflow: auto;
}
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main-content";
}
.sidebar {
transform: translateX(-100%);
}
.header {
left: 0;
}
}
</style>
</head>
<body>
<div class="container">
<div class="sidebar">
<div class="sidebar-menu">
<a href="/" class="sidebar-button">
<span class="sidebar-icon">🏠</span>
<span>系统主页</span>
</a>
<a href="/debug" class="sidebar-button">
<span class="sidebar-icon">🐞</span>
<span>调试页面</span>
</a>
</div>
</div>
<div class="header">
<h1>Power Manager - 调试页面</h1>
<div class="status-bar">
<div class="status-info">
<span id="wsStatus">🔴 WebSocket: 未连接</span>
</div>
</div>
</div>
<div class="main-content">
<div class="debug-panel">
<div class="panel-title">系统调试信息</div>
<div class="debug-section">
<div class="section-title">订阅消息</div>
<div class="message-cards" id="subscribeDataTable">
<!-- 订阅消息将通过JavaScript动态填充 -->
</div>
</div>
<div class="debug-section">
<div class="section-title">发布消息</div>
<div class="message-cards" id="publishDataTable">
<!-- 发布消息将通过JavaScript动态填充 -->
</div>
</div>
<div class="debug-section">
<div class="section-title">原始数据</div>
<div class="raw-data" id="rawData">
等待数据...
</div>
</div>
</div>
</div>
</div>
<script>
let ws = null;
function initWebSocket() {
ws = new WebSocket('ws://' + window.location.host + '/ws/debug');
ws.onopen = () => {
console.log('WebSocket调试连接已建立');
updateStatus('🟢 WebSocket: 已连接');
};
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('收到调试数据:', data);
document.getElementById('rawData').textContent = JSON.stringify(data, null, 2);
// 更新订阅消息表格
const subscribeTable = document.getElementById('subscribeDataTable');
const subscribeMessages = [
'm_secdistStateMsg_fb_debug',
'm_equStateMsg_cmd_debug',
'm_depthMsg_st_debug',
'm_setOpConditionMsg_st_debug',
'm_setOpModeMsg_st_debug',
'm_taskStartMsg_st_debug',
'm_taskStopMsg_st_debug',
'm_setDevSwitchMsg_st_debug',
'm_setPMSysMsg_st_debug',
'm_sysStateMsg_st_debug'
];
subscribeMessages.forEach(msg => {
if (data.debug && data.debug[msg] && data.debug[msg].name) {
const msgName = data.debug[msg].name;
const existingCard = Array.from(subscribeTable.children).find(card =>
card.querySelector('.card-header').textContent === msgName
);
if (existingCard) {
existingCard.querySelector('pre').textContent = formatJsonContent(data.debug[msg].content || '无内容');
} else if (msgName !== '未知消息') {
addDebugRow(subscribeTable, data.debug[msg]);
}
}
});
// 更新发布消息表格
const publishTable = document.getElementById('publishDataTable');
const publishMessages = [
'm_equInsStateMsg_fb_degub',
'm_secdistStateMsg_cmd_debug',
'm_equStateMsg_fb_debug',
'm_disSysStateMsg_st_debug',
'm_currentStateMsg_st_debug',
'm_pmStateMsg_fb_debug',
'm_fcsStateMsg_st_debug',
'm_liBatStateMsg_st_debug'
];
publishMessages.forEach(msg => {
if (data.debug && data.debug[msg] && data.debug[msg].name) {
const msgName = data.debug[msg].name;
const existingCard = Array.from(publishTable.children).find(card =>
card.querySelector('.card-header').textContent === msgName
);
if (existingCard) {
existingCard.querySelector('pre').textContent = formatJsonContent(data.debug[msg].content || '无内容');
} else if (msgName !== '未知消息') {
addDebugRow(publishTable, data.debug[msg]);
}
}
});
} catch (e) {
console.error('解析调试数据出错:', e);
document.getElementById('rawData').textContent = '解析错误: ' + e.message + '\n\n原始数据:\n' + event.data;
}
};
ws.onclose = () => {
console.log('WebSocket调试连接已关闭');
updateStatus('🔴 WebSocket: 已断开');
setTimeout(initWebSocket, 5000);
};
ws.onerror = (error) => {
console.error('WebSocket调试错误:', error);
updateStatus('⚠️ WebSocket: 错误');
};
}
function updateStatus(status) {
document.getElementById('wsStatus').textContent = status;
}
function formatJsonContent(content) {
try {
const parsed = JSON.parse(content);
return JSON.stringify(parsed, null, 2);
} catch (e) {
return content;
}
}
function addDebugRow(container, msgObj) {
const card = document.createElement('div');
card.className = 'message-card';
const header = document.createElement('div');
header.className = 'card-header';
header.textContent = msgObj.name || '未知消息';
const content = document.createElement('div');
content.className = 'card-content';
const pre = document.createElement('pre');
pre.textContent = formatJsonContent(msgObj.content || '无内容');
const toggleBtn = document.createElement('button');
toggleBtn.className = 'toggle-button';
toggleBtn.textContent = '展开';
toggleBtn.onclick = function(e) {
e.stopPropagation();
pre.classList.toggle('expanded');
this.textContent = pre.classList.contains('expanded') ? '收起' : '展开';
};
header.onclick = function(e) {
if(e.target !== toggleBtn) {
pre.classList.toggle('expanded');
toggleBtn.textContent = pre.classList.contains('expanded') ? '收起' : '展开';
}
};
content.appendChild(pre);
content.appendChild(toggleBtn);
card.appendChild(header);
card.appendChild(content);
container.appendChild(card);
}
window.addEventListener('load', initWebSocket);
</script>
</body>
</html>
)";
#endif // HTTP_SERVER_DEBUGPAGE_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,90 @@
#ifndef HTTP_SERVER_H
#define HTTP_SERVER_H
#include "MOOS/libMOOS/Utils/MOOSThread.h"
#include "mongoose.h"
#include "../logc/loguru.hpp"
#include "../systemData.h"
#include <vector>
#include <mutex>
#include <unordered_map>
#include <fstream>
#include <deque>
#include "../LowerCommManager.h"
#include <string>
#include <thread>
#include <atomic>
class HttpServer {
public:
// 构造函数,传入PowerManger指针和端口号
HttpServer(int port = 8000);
// 析构函数
~HttpServer();
// 启动HTTP服务器线程
void start();
// 停止HTTP服务器线程
void stop();
// 检查服务器是否正在运行
bool isRunning() const;
// 设置系统数据
void setSystemData(SystemData* systemData){
m_systemData = systemData;
}
void setLowerCommManager(LowerCommManager* lowerCommManager){
m_lowerCommManager = lowerCommManager;
}
void setPowerManger(PowerManger* powerManger){
m_powerManger = powerManger;
}
// 推送系统数据到所有WebSocket客户端
void pushSystemData();
// 监控日志文件变化并推送新内容
void monitorLogFile();
// 处理日志请求
void handleLogRequest(struct mg_connection* c, const std::string& msg);
// 读取日志文件
std::vector<std::string> readLogFile(int page, int pageSize, const std::string& level, const std::string& search);
// 测试页面请求处理函数
void handleTestPage(struct mg_connection* c, const std::string& msg);
private:
// WebSocket事件处理函数
void handleWebSocketEvent(struct mg_connection* c, int ev, void* ev_data, void* fn_data);
// 线程回调函数
static bool serverThreadCB(void* pParam);
bool serverThreadFunc();
// 后台系统数据
SystemData *m_systemData = nullptr;
LowerCommManager *m_lowerCommManager = nullptr;
PowerManger *m_powerManger = nullptr;
struct mg_mgr mgr_; // Mongoose管理器
int port_; // 监听端口
bool running_; // 运行状态标志
CMOOSThread m_ServerThread; // 服务器线程
std::mutex ws_connections_mutex_; // WebSocket连接锁
std::vector<mg_connection*> ws_connections_; // WebSocket连接列表
std::unordered_map<mg_connection*, uint64_t> ws_last_io_time_; // 连接最后活动时间
// 日志文件相关
std::string m_logFilePath = "pPowerManger.log";
std::ifstream m_logFile;
std::streampos m_lastLogPosition = 0;
std::deque<std::string> m_logCache; // 缓存最近的日志
static const size_t MAX_CACHE_SIZE = 1000; // 最大缓存条数
};
#endif // HTTP_SERVER_H
File diff suppressed because it is too large Load Diff
+617
View File
@@ -0,0 +1,617 @@
#ifndef HTTP_SERVER_LOGPAGE_H
#define HTTP_SERVER_LOGPAGE_H
#include <string>
const std::string LOG_PAGE_HTML = R"(
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>系统日志 - Power Manager</title>
<style>
:root {
--primary-color: #2563eb;
--primary-hover: #1d4ed8;
--bg-color: #f8fafc;
--sidebar-width: 60px;
--sidebar-expanded: 220px;
--header-height: 36px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color);
color: #1a1a1a;
}
.container {
display: grid;
grid-template-areas: "sidebar main-content";
grid-template-columns: var(--sidebar-width) 1fr;
grid-template-rows: 1fr;
min-height: 100vh;
gap: 0;
}
.header {
grid-area: unset;
background: white;
padding: 0 0.5rem;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
right: 0;
left: var(--sidebar-width);
height: var(--header-height);
z-index: 10;
}
.header h1 {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
}
.sidebar {
grid-area: sidebar;
background: white;
width: var(--sidebar-width);
height: 100vh;
position: fixed;
left: 0;
top: 0;
padding: 0.5rem 0.25rem;
transition: width 0.3s ease;
box-shadow: 1px 0 3px rgba(0, 0, 0, 0.1);
z-index: 20;
}
.sidebar:hover {
width: var(--sidebar-expanded);
}
.sidebar-menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.sidebar-button {
display: flex;
align-items: center;
padding: 0.5rem 0.75rem;
border-radius: 0.375rem;
color: #4b5563;
text-decoration: none;
transition: all 0.2s ease;
white-space: nowrap;
overflow: hidden;
}
.sidebar-button:hover {
background: var(--bg-color);
color: var(--primary-color);
}
.sidebar-button.active {
background: var(--primary-color);
color: white;
}
.sidebar-icon {
min-width: 1.5rem;
margin-right: 1rem;
font-size: 1.25rem;
}
.main-content {
grid-area: main-content;
padding: 1px;
margin-top: var(--header-height);
}
.log-panel {
background: white;
border-radius: 4px;
padding: 6px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
height: calc(100vh - var(--header-height));
overflow: hidden;
display: flex;
flex-direction: column;
}
.log-controls {
display: flex;
gap: 8px;
padding: 4px;
border-bottom: 1px solid #e5e7eb;
flex-wrap: wrap;
}
.log-button {
padding: 4px 12px;
border: 1px solid #e5e7eb;
border-radius: 4px;
background: white;
color: #4b5563;
cursor: pointer;
font-size: 0.875rem;
transition: all 0.2s;
}
.log-button:hover {
background: var(--bg-color);
border-color: var(--primary-color);
color: var(--primary-color);
}
.log-filter {
display: flex;
gap: 8px;
align-items: center;
margin-left: auto;
}
.log-filter select, .log-filter input {
padding: 4px 8px;
border: 1px solid #e5e7eb;
border-radius: 4px;
font-size: 0.875rem;
color: #4b5563;
}
.log-filter input {
width: 150px;
}
.log-pagination {
display: flex;
gap: 4px;
align-items: center;
padding: 4px;
border-top: 1px solid #e5e7eb;
justify-content: space-between;
font-size: 0.875rem;
color: #4b5563;
}
.page-info {
display: flex;
align-items: center;
gap: 8px;
}
.page-size {
display: flex;
align-items: center;
gap: 4px;
}
.page-size select {
padding: 2px 4px;
border: 1px solid #e5e7eb;
border-radius: 4px;
}
.page-nav {
display: flex;
gap: 4px;
}
.page-nav button {
padding: 2px 8px;
border: 1px solid #e5e7eb;
border-radius: 4px;
background: white;
cursor: pointer;
}
.page-nav button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.log-content {
flex: 1;
overflow: auto;
padding: 8px;
font-family: monospace;
font-size: 0.875rem;
line-height: 1.5;
white-space: pre-wrap;
background: #1a1a1a;
color: #f8fafc;
margin: 4px;
border-radius: 4px;
}
.log-entry {
margin: 2px 0;
padding: 2px 4px;
border-radius: 2px;
}
.log-entry:hover {
background: rgba(255, 255, 255, 0.1);
}
.log-entry.error {
color: #f87171;
}
.log-entry.warning {
color: #fbbf24;
}
.log-entry.info {
color: #60a5fa;
}
.status-bar {
position: fixed;
top: 4px;
right: 8px;
background: white;
padding: 4px 8px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
gap: 8px;
z-index: 15;
}
.status-info {
display: flex;
align-items: center;
gap: 8px;
color: #4b5563;
font-size: 0.875rem;
}
</style>
</head>
<body>
<div class="container">
<div class="sidebar">
<div class="sidebar-menu">
<a href="/" class="sidebar-button">
<span class="sidebar-icon">🏠</span>
<span>系统主页</span>
</a>
<a href="/data" class="sidebar-button">
<span class="sidebar-icon">📊</span>
<span>系统数据</span>
</a>
<a href="/dashboard" class="sidebar-button">
<span class="sidebar-icon">⚡</span>
<span>配电操作</span>
</a>
<a href="/logs" class="sidebar-button active">
<span class="sidebar-icon">📝</span>
<span>系统日志</span>
</a>
<a href="/testpage" class="sidebar-button">
<span class="sidebar-icon">🧪</span>
<span>测试页面</span>
</a>
</div>
</div>
<div class="header">
<h1>系统日志</h1>
<div class="status-bar">
<div class="status-info">
<span>🟢 系统状态: <span id="systemStatus">运行中</span></span>
<span>⚡ 应用频率: <span id="appFreq">0</span> Hz</span>
<span>📡 通信频率: <span id="commFreq">0</span> Hz</span>
<span>💻 CPU负载: <span id="cpuLoad">0</span>%</span>
<span>⏱️ 迭代间隔: <span id="timeSinceIterate">0</span>ms</span>
<span>🕒 更新时间: <time id="updateTime">2025-05-18 15:52</time></span>
</div>
</div>
</div>
<div class="main-content">
<div class="log-panel">
<div class="log-controls">
<button class="log-button" id="clearBtn">清空显示</button>
<button class="log-button" id="scrollLockBtn">自动滚动</button>
<button class="log-button" id="downloadBtn">下载日志</button>
<div class="log-filter">
<select id="logLevel">
<option value="ALL">所有级别</option>
<option value="ERROR">错误</option>
<option value="WARNING">警告</option>
<option value="INFO">信息</option>
</select>
<input type="text" id="searchInput" placeholder="搜索日志...">
</div>
</div>
<div class="log-content" id="logContent"></div>
<div class="log-pagination">
<div class="page-size">
每页显示:
<select id="pageSize">
<option value="100">100</option>
<option value="200" selected>200</option>
<option value="500">500</option>
<option value="1000">1000</option>
</select>
</div>
<div class="page-info">
<span id="pageInfo">第 0/0 页</span>
<div class="page-nav">
<button id="firstPage">首页</button>
<button id="prevPage">上一页</button>
<button id="nextPage">下一页</button>
<button id="lastPage">末页</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
let ws = null;
let autoScroll = true;
let logContent = document.getElementById('logContent');
let currentPage = 1;
let totalPages = 1;
let pageSize = 200;
let allLogs = [];
let filteredLogs = [];
let searchTimer = null;
function initWebSocket() {
ws = new WebSocket('ws://' + window.location.host + '/ws');
ws.onopen = () => {
console.log('WebSocket连接已建立');
updateStatus('运行中', true);
requestLogs();
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'log') {
// 初始加载的日志数据
allLogs = data.content;
filterAndDisplayLogs();
} else if (data.type === 'new_log') {
// 新的日志条目
if (Array.isArray(data.content)) {
let shouldUpdate = false;
data.content.forEach(log => {
allLogs.push(log);
if (shouldShowLog(log)) {
filteredLogs.push(log);
shouldUpdate = true;
// 如果在最后一页或自动滚动模式下,直接添加到显示
if (currentPage === totalPages || autoScroll) {
appendLogEntry(log);
}
}
});
if (shouldUpdate) {
totalPages = Math.ceil(filteredLogs.length / pageSize);
updatePagination();
// 如果开启了自动滚动,确保滚动到底部
if (autoScroll) {
logContent.scrollTop = logContent.scrollHeight;
}
}
}
} else if (data.moosdb) {
// 更新MOOSDB信息
document.getElementById('appFreq').textContent = data.moosdb.appFreq.toFixed(2);
document.getElementById('commFreq').textContent = data.moosdb.commFreq.toFixed(2);
document.getElementById('cpuLoad').textContent = data.moosdb.cpuLoad.toFixed(1);
document.getElementById('timeSinceIterate').textContent = data.moosdb.timeSinceIterate.toFixed(0);
} else if (data.type === 'system_status') {
updateStatus(data.status, true);
}
updateTime();
};
ws.onclose = () => {
console.log('WebSocket连接已关闭');
updateStatus('已断开', false);
// 增加重连延迟,避免快速重连
setTimeout(() => {
if (!ws || ws.readyState === WebSocket.CLOSED) {
initWebSocket();
}
}, 2000);
};
ws.onerror = (error) => {
console.error('WebSocket错误:', error);
updateStatus('错误', false);
};
}
function requestLogs() {
ws.send(JSON.stringify({
type: 'get_logs',
page: currentPage,
pageSize: pageSize,
filter: {
level: document.getElementById('logLevel').value,
search: document.getElementById('searchInput').value
}
}));
}
function shouldShowLog(logEntry) {
const level = document.getElementById('logLevel').value;
const search = document.getElementById('searchInput').value.toLowerCase();
if (level !== 'ALL') {
if (!logEntry.includes(level)) return false;
}
if (search && !logEntry.toLowerCase().includes(search)) {
return false;
}
return true;
}
function filterAndDisplayLogs() {
filteredLogs = allLogs.filter(shouldShowLog);
totalPages = Math.ceil(filteredLogs.length / pageSize);
displayCurrentPage();
updatePagination();
}
function displayCurrentPage() {
logContent.innerHTML = '';
const start = (currentPage - 1) * pageSize;
const end = Math.min(start + pageSize, filteredLogs.length);
for (let i = start; i < end; i++) {
appendLogEntry(filteredLogs[i]);
}
}
function updatePagination() {
document.getElementById('pageInfo').textContent = `第 ${currentPage}/${totalPages} 页`;
document.getElementById('firstPage').disabled = currentPage === 1;
document.getElementById('prevPage').disabled = currentPage === 1;
document.getElementById('nextPage').disabled = currentPage === totalPages;
document.getElementById('lastPage').disabled = currentPage === totalPages;
}
// 事件监听器
document.getElementById('logLevel').addEventListener('change', () => {
currentPage = 1;
filterAndDisplayLogs();
});
document.getElementById('searchInput').addEventListener('input', (e) => {
clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
currentPage = 1;
filterAndDisplayLogs();
}, 300);
});
document.getElementById('pageSize').addEventListener('change', (e) => {
pageSize = parseInt(e.target.value);
currentPage = 1;
filterAndDisplayLogs();
});
document.getElementById('firstPage').addEventListener('click', () => {
currentPage = 1;
displayCurrentPage();
updatePagination();
});
document.getElementById('prevPage').addEventListener('click', () => {
if (currentPage > 1) {
currentPage--;
displayCurrentPage();
updatePagination();
}
});
document.getElementById('nextPage').addEventListener('click', () => {
if (currentPage < totalPages) {
currentPage++;
displayCurrentPage();
updatePagination();
}
});
document.getElementById('lastPage').addEventListener('click', () => {
currentPage = totalPages;
displayCurrentPage();
updatePagination();
});
function appendLogEntry(content) {
const entry = document.createElement('div');
entry.className = 'log-entry';
// 根据日志内容设置不同的样式
if (content.includes('ERROR') || content.includes('ERR')) {
entry.classList.add('error');
} else if (content.includes('WARNING') || content.includes('WARN')) {
entry.classList.add('warning');
} else if (content.includes('INFO')) {
entry.classList.add('info');
}
entry.textContent = content;
logContent.appendChild(entry);
// 只在自动滚动模式下滚动到底部
if (autoScroll) {
logContent.scrollTop = logContent.scrollHeight;
}
}
function updateStatus(status, isConnected) {
const statusElement = document.querySelector('.status-info span:first-child');
statusElement.innerHTML = `${isConnected ? '🟢' : '🔴'} 系统状态: ${status}`;
}
function updateTime() {
const now = new Date();
const timeStr = now.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
document.getElementById('updateTime').textContent = timeStr;
}
// 按钮事件处理
document.getElementById('clearBtn').onclick = () => {
logContent.innerHTML = '';
};
document.getElementById('scrollLockBtn').onclick = function() {
autoScroll = !autoScroll;
this.textContent = autoScroll ? '自动滚动' : '已锁定';
this.style.backgroundColor = autoScroll ? 'white' : '#e5e7eb';
};
document.getElementById('downloadBtn').onclick = () => {
const text = logContent.innerText;
const blob = new Blob([text], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `system_log_${new Date().toISOString().slice(0,19).replace(/[:-]/g, '')}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
};
window.addEventListener('load', initWebSocket);
</script>
</body>
</html>
)";
#endif // HTTP_SERVER_LOGPAGE_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+458
View File
@@ -0,0 +1,458 @@
#ifndef HTTP_SERVER_TESTPAGE_H
#define HTTP_SERVER_TESTPAGE_H
#include <string>
const std::string TESTPAGE_HTML = R"row(
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试页面</title>
<link rel="stylesheet" href="/static/style.css">
<style>
:root {
--primary-color: #2563eb;
--primary-hover: #1d4ed8;
--bg-color: #f8fafc;
--sidebar-width: 60px;
--sidebar-expanded: 220px;
--header-height: 36px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color);
color: #1a1a1a;
}
.container {
display: grid;
grid-template-areas:
"sidebar main-content";
grid-template-columns: var(--sidebar-width) 1fr;
grid-template-rows: 1fr;
min-height: 100vh;
gap: 0;
}
.header {
grid-area: unset;
background: white;
padding: 0 0.5rem;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
right: 0;
left: var(--sidebar-width);
height: var(--header-height);
z-index: 10;
}
.header h1 {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
}
.sidebar {
grid-area: sidebar;
background: white;
width: var(--sidebar-width);
height: 100vh;
position: fixed;
left: 0;
top: 0;
padding: 0.5rem 0.25rem;
transition: width 0.3s ease;
box-shadow: 1px 0 3px rgba(0, 0, 0, 0.1);
z-index: 20;
}
.sidebar:hover {
width: var(--sidebar-expanded);
}
.sidebar-menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.sidebar-button {
display: flex;
align-items: center;
padding: 0.5rem 0.75rem;
border-radius: 0.375rem;
color: #4b5563;
text-decoration: none;
transition: all 0.2s ease;
white-space: nowrap;
overflow: hidden;
}
.sidebar-button:hover {
background: var(--bg-color);
color: var(--primary-color);
}
.sidebar-icon {
min-width: 1.5rem;
margin-right: 1rem;
font-size: 1.25rem;
}
.main-content {
grid-area: main-content;
padding: 1px;
margin-top: var(--header-height);
}
.status-bar {
position: fixed;
top: 4px;
right: 8px;
background: white;
padding: 4px 8px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
gap: 8px;
z-index: 15;
}
.status-info {
display: flex;
align-items: center;
gap: 8px;
color: #4b5563;
font-size: 0.875rem;
}
.data-panel {
background: white;
border-radius: 4px;
padding: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
height: calc(100vh - var(--header-height) + 3px);
overflow: auto;
}
.panel-title {
font-size: 1rem;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #e5e7eb;
}
.form-group {
margin-bottom: 16px;
}
.form-label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #374151;
}
.form-input {
width: 100%;
padding: 8px 12px;
border: 1px solid #d1d5db;
border-radius: 4px;
font-size: 14px;
transition: border-color 0.2s;
}
.form-input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1);
}
.btn {
display: inline-block;
padding: 8px 16px;
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s;
}
.btn:hover {
background-color: var(--primary-hover);
}
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main-content";
}
.sidebar {
transform: translateX(-100%);
}
.header {
left: 0;
}
}
</style>
</head>
<body>
<div class="container">
<div class="sidebar">
<div class="sidebar-menu">
<a href="/" class="sidebar-button">
<span class="sidebar-icon">🏠</span>
<span>系统主页</span>
</a>
<a href="/data" class="sidebar-button">
<span class="sidebar-icon">📊</span>
<span>系统数据</span>
</a>
<a href="/dashboard" class="sidebar-button">
<span class="sidebar-icon">⚡</span>
<span>配电操作</span>
</a>
<a href="/logs" class="sidebar-button">
<span class="sidebar-icon">📝</span>
<span>系统日志</span>
</a>
<a href="/testpage" class="sidebar-button">
<span class="sidebar-icon">🧪</span>
<span>测试页面</span>
</a>
</div>
</div>
<div class="header">
<h1>测试页面</h1>
<div class="status-bar">
<div class="status-info">
<span>🟢 系统状态: <span id="systemStatus">运行中</span></span>
<span>⚡ 应用频率: <span id="appFreq">0</span> Hz</span>
<span>📡 通信频率: <span id="commFreq">0</span> Hz</span>
<span>💻 CPU负载: <span id="cpuLoad">0</span>%</span>
<span>⏱️ 迭代间隔: <span id="timeSinceIterate">0</span>ms</span>
<span>🕒 更新时间: <time id="updateTime">2025-05-19 11:54</time></span>
</div>
</div>
</div>
<div class="main-content">
<div class="data-panel">
<div class="panel-title">测试表单</div>
<form id="testForm">
<div class="form-section">
<div class="panel-subtitle">测试类型/ID设置</div>
<div class="form-group">
<label for="type" class="form-label">类型</label>
<input type="number" id="type" name="type" class="form-input" min="0" required>
</div>
<div class="form-group">
<label for="id" class="form-label">ID</label>
<input type="number" id="id" name="id" class="form-input" min="0" required>
</div>
<button type="button" class="btn" onclick="submitTestForm()">提交类型/ID</button>
</div>
<div class="form-section">
<div class="panel-subtitle">MOOSDB测试消息设置</div>
<div class="form-group">
<label for="key" class="form-label">键(Key)</label>
<input type="text" id="key" name="key" class="form-input" required>
</div>
<div class="form-group">
<label for="value" class="form-label">值(Value)</label>
<input type="text" id="value" name="value" class="form-input" required>
</div>
<button type="button" class="btn" onclick="submitKeyValueForm()" style="background-color: #4f46e5;">提交键值对</button>
</div>
</form>
<style>
.form-section {
margin-bottom: 24px;
padding: 16px;
background: #f9fafb;
border-radius: 8px;
}
.panel-subtitle {
font-size: 0.9rem;
font-weight: 600;
color: #4b5563;
margin-bottom: 12px;
padding-bottom: 4px;
border-bottom: 1px solid #e5e7eb;
}
</style>
</div>
</div>
</div>
<script>
let ws = null;
function initWebSocket() {
ws = new WebSocket('ws://' + window.location.host + '/ws');
ws.onopen = () => {
console.log('WebSocket连接已建立');
updateStatus('运行中', true);
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('收到系统数据:', data);
// 更新MOOSDB信息
if (data.moosdb) {
document.getElementById('appFreq').textContent = data.moosdb.appFreq.toFixed(2);
document.getElementById('commFreq').textContent = data.moosdb.commFreq.toFixed(2);
document.getElementById('cpuLoad').textContent = data.moosdb.cpuLoad.toFixed(1);
document.getElementById('timeSinceIterate').textContent = data.moosdb.timeSinceIterate.toFixed(0);
}
updateTime();
};
ws.onclose = () => {
console.log('WebSocket连接已关闭');
updateStatus('已断开', false);
setTimeout(initWebSocket, 5000);
};
ws.onerror = (error) => {
console.error('WebSocket错误:', error);
updateStatus('错误', false);
};
}
function updateStatus(status, isConnected) {
const statusElement = document.querySelector('.status-info span:first-child');
statusElement.innerHTML = `${isConnected ? '🟢' : '🔴'} 系统状态: ${status}`;
}
function updateTime() {
const now = new Date();
const timeStr = now.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
document.getElementById('updateTime').textContent = timeStr;
}
function submitTestForm() {
const form = document.getElementById('testForm');
const typeValue = parseInt(form.type.value);
const idValue = parseInt(form.id.value);
if (typeValue < 0 || idValue < 0) {
alert('请输入非负整数');
return;
}
const formData = {
type: typeValue,
id: idValue
};
sendFormData(formData);
}
function submitKeyValueForm() {
const key = document.getElementById('key').value.trim();
const value = document.getElementById('value').value.trim();
if (!key || !value) {
alert('请输入键和值');
return;
}
// 直接构造JSON对象,不通过form
const payload = {
key: key,
value: value
};
// 专门发送到MOOSDB测试消息接口
fetch('/moosdb_test', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.success) {
alert('MOOSDB测试消息提交成功: ' + data.message);
} else {
alert('MOOSDB测试消息提交失败: ' + data.error);
}
})
.catch(error => {
console.error('MOOSDB测试消息提交错误:', error);
alert('MOOSDB测试消息提交过程中发生错误: ' + error.message);
});
}
function sendFormData(formData) {
fetch('/testpage', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('提交成功: ' + data.message);
} else {
alert('提交失败: ' + data.error);
}
})
.catch(error => {
console.error('提交错误:', error);
alert('提交过程中发生错误');
});
}
window.addEventListener('load', initWebSocket);
</script>
</body>
</html>
)row";
#endif // HTTP_SERVER_TESTPAGE_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
/************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: main.cpp, Cambridge MA */
/* DATE: December 29th, 1963 */
/************************************************************/
#include <string>
#include "MBUtils.h"
#include "ColorParse.h"
#include "PowerManger.h"
#include "PowerManger_Info.h"
#include "logc/loguru.hpp"
using namespace std;
int main(int argc, char *argv[])
{
// 初始化loguru
loguru::init(argc, argv);
loguru::add_file("pPowerManger.log", loguru::Append, loguru::Verbosity_MAX);
string mission_file;
string run_command = argv[0];
for(int i=1; i<argc; i++) {
string argi = argv[i];
if((argi=="-v") || (argi=="--version") || (argi=="-version"))
showReleaseInfoAndExit();
else if((argi=="-e") || (argi=="--example") || (argi=="-example"))
showExampleConfigAndExit();
else if((argi == "-h") || (argi == "--help") || (argi=="-help"))
showHelpAndExit();
else if((argi == "-i") || (argi == "--interface"))
showInterfaceAndExit();
else if(strEnds(argi, ".moos") || strEnds(argi, ".moos++"))
mission_file = argv[i];
else if(strBegins(argi, "--alias="))
run_command = argi.substr(8);
else if(i==2)
run_command = argi;
}
if(mission_file == "")
showHelpAndExit();
LOG_F(INFO, "pPowerManger launching as %s", run_command.c_str());
PowerManger PowerManger;
PowerManger.Run(run_command.c_str(), mission_file.c_str());
return(0);
}
+9
View File
@@ -0,0 +1,9 @@
//SERVERHOST = 192.168.0.223
//SERVERPORT = 9000
ProcessConfig = pPowerManger
{
AppTick = 4
CommsTick = 4
log_level = INFO
log_file = /path/to/your/logfile.log
}
+964
View File
@@ -0,0 +1,964 @@
#ifndef PMSYSVARIABLE_H
#define PMSYSVARIABLE_H
//宏定义
#include<string>
#include <map>
#include <unordered_set>
#define BREAK_OFF 0xAA
#define BREAK_ON 0x55
#define BREAK_FALSE 0x5A
//消息结构体变量定义
#pragma pack (1)
typedef struct ccuState
{
uint8_t fc_mode; // 燃料电池系统运行模式:00H-无效, 01H-调试, 02H-自动, 03H-补给
uint8_t fc_status; // 燃料电池状态:00H-无效, 01H-初始化, ..., 0DH-维护完成(详见协议)
uint8_t fc_fault_level; // 燃料电池故障等级:00H-无故障, 10H-一级, 20H-二级, 30H-三级, 40H-四级
uint16_t output_power_limit; // 系统输出功率限制值,单位:W,范围:0~30000W
uint16_t total_generation_time; // 系统累计发电时间,单位:0.1小时,最大值6553.5小时
uint16_t total_generation_power; // 系统累计发电总功率,单位:W
uint16_t fault_level_1; // 一级故障位,按位表示不同的故障项
uint16_t fault_level_2; // 二级故障位
uint16_t fault_level_3; // 三级故障位
uint16_t fault_level_4; // 四级故障位
uint8_t hydrogen_capacity; // 储氢罐剩余容量百分比,单位:%,范围:0~100
uint8_t liquid_oxygen_capacity; // 液氧罐剩余容量百分比,单位:%,范围:0~100
uint16_t palladium_temp; // 钯膜最高温度,单位:℃
uint16_t main_pipe_pressure; // 主水路压力,单位:0.01kPa
uint16_t aux_pipe_pressure; // 辅水路压力,单位:0.01kPa
uint16_t cabin_pressure1; // 舱室1压力,单位:0.01kPa
uint16_t cabin_pressure2; // 舱室2压力,单位:0.01kPa
uint16_t cabin_temp1; // 舱室1温度,单位:0.01℃
uint16_t cabin_temp2; // 舱室2温度,单位:0.01℃
uint16_t cabin_humidity1; // 舱室1湿度,单位:0.01%RH
uint16_t cabin_humidity2; // 舱室2湿度,单位:0.01%RH
uint8_t flame_detector1; // 火焰探测器1状态:00H-无效, 01H-报警, 02H-故障
uint8_t flame_detector2; // 火焰探测器2状态:00H-无效, 01H-报警, 02H-故障
uint16_t h2_concentration1; // 舱室H2浓度1,单位:0.01% LEL
uint16_t h2_concentration2; // 舱室H2浓度2,单位:0.01% LEL
uint16_t h2_concentration3; // 舱室H2浓度3,单位:0.01% LEL
uint16_t o2_concentration1; // 舱室O2浓度1,单位:0.01% LEL
uint16_t o2_concentration2; // 舱室O2浓度2,单位:0.01% LEL
uint16_t ch3oh_concentration1; // 舱室甲醇气体浓度1,单位:0.01% LEL
uint16_t ch3oh_concentration2; // 舱室甲醇气体浓度2,单位:0.01% LEL
uint16_t reserved1[2]; // 保留字段前2个元素
uint16_t emergency_battery1_voltage; // 应急电池1总电压 [V]
uint16_t emergency_battery1_current; // 应急电池1总电流 [A]
uint16_t emergency_battery1_max_temp; // 应急电池1最高温度 [°C]
uint16_t emergency_battery1_fault_word; // 应急电池1故障字
uint16_t emergency_battery2_voltage; // 应急电池2总电压 [V]
uint16_t emergency_battery2_current; // 应急电池2总电流 [A]
uint16_t emergency_battery2_max_temp; // 应急电池2最高温度 [°C]
uint16_t emergency_battery2_fault_word; // 应急电池2故障字
uint16_t cabin_ox_concentration; // 仪表舱内氧气浓度 [%]
uint16_t cabin_temperature; // 仪表舱内温度 [°C]
uint16_t cabin_humidity; // 仪表舱内湿度 [%RH]
uint16_t cabin_pressure; // 仪表舱内大气压 [kPa]
uint16_t power_cabin_ox_concentration; // 动力舱内氧气浓度 [%]
uint16_t power_cabin_temperature; // 动力舱内温度 [°C]
uint16_t power_cabin_humidity; // 动力舱内湿度 [%RH]
uint16_t power_cabin_pressure; // 动力舱内大气压 [kPa]
uint8_t reserved2[1]; // 保留字段,地址范围54~55,共2个uint8_t,协议预留
uint8_t dyn_alarm_flag[6]; // 动力锂电池报警标志字数组,共6字节,按位表示各类报警
uint8_t ins_alarm_flag[6]; // 仪表锂电池报警标志字数组,共6字节,按位表示各类报警
uint8_t ins_relay_status1; // 仪表电池继电器状态,高4位表示正极继电器,低4位表示充电继电器
uint8_t ins_relay_status2; // 仪表电池预充继电器和负极继电器状态
uint8_t dyn_relay_status1; // 动力电池正极与充电继电器状态
uint8_t dyn_relay_status2; // 动力电池预充与负极继电器状态
uint16_t ins_max_discharge_power; // 仪表电池最大允许放电功率,单位:kW,精度0.05kW
uint16_t dyn_max_discharge_power; // 动力电池最大允许放电功率,单位:kW,精度0.05kW
uint8_t ins_soc; // 仪表锂电池荷电状态SOC,范围:0~100
uint8_t dyn_soc; // 动力锂电池荷电状态SOC,范围:0~100
uint16_t ins_total_energy; // 仪表电池总能量,单位:kWh
uint16_t dyn_total_energy; // 动力电池总能量,单位:kWh
uint16_t ins_power_input; // 仪表电池输入功率,单位:kW
uint16_t dyn_power_input; // 动力电池输入功率,单位:kW
uint8_t ins_charge_status; // 仪表电池充放电状态:00H-无效,10H-充电,20H-放电
uint8_t dyn_charge_status; // 动力电池充放电状态:00H-无效,10H-充电,20H-放电
uint16_t ins_voltage_link; // 仪表电池LINK端电压,单位:0.01V
uint16_t ins_voltage_pack; // 仪表电池PACK端电压,单位:0.01V
uint16_t ins_current; // 仪表电池电流,单位:0.01A(正值放电)
uint16_t ins_resistance_pos; // 仪表电池正极绝缘电阻,单位:kΩ
uint16_t ins_resistance_neg; // 仪表电池负极绝缘电阻,单位:kΩ
uint16_t dyn_voltage_link; // 动力电池LINK端电压,单位:0.01V
uint16_t dyn_voltage_pack; // 动力电池PACK端电压,单位:0.01V
uint16_t dyn_current; // 动力电池电流,单位:0.01A(正值放电)
uint16_t dyn_resistance_pos; // 动力电池正极绝缘电阻,单位:kΩ
uint16_t dyn_resistance_neg; // 动力电池负极绝缘电阻,单位:kΩ
uint8_t ins_emergency_status; // 仪表电池紧急状态字,按位表示异常或告警状态
uint8_t dyn_emergency_status; // 动力电池紧急状态字,按位表示异常或告警状态
uint8_t reserved3[2]; // 保留字节,协议预留
uint8_t ins_soc_threshold1; // 仪表电池1 SOC门限,范围:0~100
uint8_t ins_soc_threshold2; // 仪表电池2 SOC门限,范围:0~100
uint8_t ins_soc_threshold3; // 仪表电池3 SOC门限,范围:0~100
uint8_t dyn_soc_threshold1; // 动力电池1 SOC门限,范围:0~100
uint8_t dyn_soc_threshold2; // 动力电池2 SOC门限,范围:0~100
uint8_t dyn_soc_threshold3; // 动力电池3 SOC门限,范围:0~100
uint8_t ins_power_limit1; // 仪表电池1功率限制值,单位:%
uint8_t ins_power_limit2; // 仪表电池2功率限制值,单位:%
uint8_t dyn_power_limit1; // 动力电池1功率限制值,单位:%
uint8_t dyn_power_limit2; // 动力电池2功率限制值,单位:%
uint32_t device_online_flag1; // 设备在线状态标志1,byte0:低压配电板在线标志位 byte1:复合管控主机在线标志位 byte2:复合管控备机在线标志位
uint32_t device_online_flag2; // 设备在线状态标志2,byte0:仪表锂电在线标志位 byte1:动力锂电在线标志位 byte2:燃电锂电在线标志位 byte3:高压配电板在线标志位
uint8_t dyn_charge_level; // 动力电池充电状态:01H-1级(不限), 02H-2级(限功率), 03H-3级(关闭)
uint8_t dyn_water_leak_status; // 动力漏水状态:0XH-正常, 1XH-异常漏水
uint8_t ins_water_leak_dcdc_status; // 仪表漏水状态与DCDC状态:低4位-漏水状态(0XH正常,1XH异常),高4位-DCDC状态(X0H正常,X1H故障)
uint8_t reserved4;
// uint32_t reserved4; // 保留字段,协议预留
uint32_t heartbeat; // 主机心跳计数器或标志值
} ccuState;
typedef struct {
unsigned char insSocHold1;
unsigned char insSocHold2;
unsigned char insSocHold3;
unsigned char fcuToInsLimit1;
unsigned char fcuToinsLimit2;
unsigned char powerSocHold1;
unsigned char powerSocHold2;
unsigned char powerSocHold3;
unsigned char fcuToPowerLimit1;
unsigned char fcuToPowerLimit2;
}ccuSetParmCmd;
typedef struct {
unsigned char fcmode;
unsigned char fcuCmd;
unsigned char fcuPowerEfficiency;
unsigned char insChargeEnable;
unsigned char insBatCmd;
unsigned char powerBatCmd;
unsigned short powerBatEfficiency;
unsigned char heartbeat;
unsigned char masterState;
unsigned int paceholder1;
unsigned int paceholder2;
}ccuColCmd;
typedef struct disHighVolBusState
{
//断路器状态
// 5: 燃料电池断路器
unsigned char fuelCellCircuitBreaker;
// 6: 动力锂电池断路器
unsigned char powerLithiumBatteryCircuitBreaker;
// 7: 推进电机断路器
unsigned char propulsionMotorCircuitBreaker;
// 8: 锂电池组仪表断路器
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
// 9: DC/DC5模块断路器
unsigned char dcDc5ModuleCircuitBreaker;
// 10: 艏部高压配电箱断路器
unsigned char bowHighVoltageDistributionBoxCircuitBreaker;
// 11: 艉部FT装置4/5断路器
unsigned char sternFTDevice45CircuitBreaker;
// 14: FB预留断路器
unsigned char fbReservedCircuitBreaker;
// 12: 艉舵开关1断路器
unsigned char sternRudderSwitch1CircuitBreaker;
// 13: 艉舵开关2断路器
unsigned char sternRudderSwitch2CircuitBreaker;
// 15: TYZ预留断路器
unsigned char tyzReservedCircuitBreaker;
// 16: 预留断路器
unsigned char reservedCircuitBreaker;
// unsigned char busInsulationLow;
// unsigned char busAInsulationHigh;
// 17: DC/DC5故障字低
// 0x00: 正常状态
// Bit0: DC/DC模块过温关机
// Bit1: 输出过流
// Bit2: 输出过压
// Bit3: 输出欠压
// Bit4: 输入过压
// Bit5: 输入欠压
// Bit6: 输出短路保护
// Bit7: 内部故障
// 18: DC/DC5故障字高
unsigned char dcDcFaultWord1;
// 0x00: 正常状态
// Bit0: 通讯故障报警
// Bit1: 工作状态 1:启动,0:关闭
// Bit2: 冷却泵1故障 冷却泵1故障 : 1故障, 0 正常
// Bit3: 冷却泵2故障 冷却泵2故障 :1故障,0 正常
// Bit4: 冷却水泄露
// Bit5:冷却泵1运行状态 :1 运行,0 停止
// Bit6:冷却泵2运行状态 :1 运行,0 停止
unsigned char dcDcFaultWord2;
// 19: 动力母排绝缘状态(0x55 正常,0xAA 绝缘低)
unsigned char powerBusInsulationStatus;
// 20: A汇流排绝缘状态(0x55 正常,0xAA 绝缘低)
unsigned char aBusInsulationStatus;
// 21: 仪表电源状态 (0x55 正常,0xAA 故障)
unsigned char meterPowerLossSignal;
// 22: 应急电源状态 (0x55 正常,0xAA 故障)
unsigned char emergencyPowerLossSignal;
// 22: dc/dc温度
unsigned char dcDcTemperature;
// 23: 动力汇流排电压
unsigned short powerBusVoltage;
// 24: DC/DC5模块电流
unsigned short dcDc5ModuleCurrent;
// 25: 动力汇流排电流
unsigned short powerBusCurrent;
// 26: A汇流排电压
unsigned short busbarAVoltage;
// 27: 推进电机控制箱电流
unsigned short propulsionMotorControlBoxCurrent;
// 28: A汇流排电流
unsigned short busbarACurrent;
// 29: 锂电池组(仪表)电流
unsigned short lithiumBatteryGroupMeterCurrent;
// 30: 艏部高压配电箱电流
unsigned short bowHighVoltageDistributionBoxCurrent;
// 31: 艉部FT装置4/5电流
unsigned short sternFTDevice45Current;
// 32: TYZ预留开关电流
unsigned short tyzReservedSwitchCurrent;
// 33: 艉舵开关1电流
unsigned short sternRudderSwitch1Current;
// 34: 预留电流
unsigned short reservedCurrent1; // 改为 reservedCurrent1 以避免重名
// 35: 艉舵开关2电流
unsigned short sternRudderSwitch2Current;
// 36: 预留电流2
unsigned short reservedCurrent2; // 改为 reservedCurrent2 以避免重名
// 37: FB预留电流
unsigned short fbReservedSwitchCurrent;
// 38: 预留电流3
unsigned short reservedCurrent3; // 改为 reservedCurrent3 以避免重名
// 39: 冷却水压力
unsigned short coolWaterPressure;
}disHighVolBusState;
typedef struct disHighAVolBusState
{
//5. 艏部FT装置1/2/3断路器
unsigned char bowFTDevice123CircuitBreaker;
//6. 启闭机构断路器
unsigned char actuatorCircuitBreaker;
//7. 桅杆舵机控制箱断路器
unsigned char mastSteeringGearControlBoxCircuitBreaker;
//8. XCZ断路器
unsigned char xczCircuitBreaker;
//9. 艏舵控制箱断路器
unsigned char bowRudderControlBoxCircuitBreaker;
//10. 敞水盖启动电缸断路器
unsigned char openWaterCoverStartCylinderCircuitBreaker;
//11. 仪表电源失电信号 (0x55 正常,0xAA 故障)
unsigned char instrumentPowerFailureSignal;
//12. 应急电源失电信号 (0x55 正常,0xAA 故障)
unsigned char emergencyPowerFailureSignal;
//13. 浸水报警
// unsigned char busbarBInsulationStatus;
unsigned char waterIngressionAlarm;
//14. 汇流排B电压
unsigned short busbarBVoltage;
//15. 汇流排B电流
unsigned short busbarBCurrent;
//16. 艏部FT装置1/2/3电流
unsigned short bowFTDevice123Current;
//17. 启闭机构电流
unsigned short actuatorCurrent;
//18. 桅杆舵机控制箱电流
unsigned short mastSteeringGearControlBoxCurrent;
//19. XCZ电流
unsigned short xczCurrent;
//20. 艏舵控制箱电流
unsigned short bowRudderControlBoxCurrent;
//21. 敞水盖启动电缸电流
unsigned short openWaterCoverStartCylinderCurrent;
}disHighAVolBusState;
typedef struct disHighBVolBusState
{
//5. 锂电池组(仪表)断路器
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
//6. 艏部低压配电箱断路器
unsigned char bowLowVoltageDistributionBoxCircuitBreaker;
//7. UNIT4仪表DC48V断路器
unsigned char unit4InstrumentDC48VCircuitBreaker;
//8. DC-C1直流配电板断路器
unsigned char dcC1DCDistributionPanelCircuitBreaker;
//9. 预留断路器1
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
//10. 预留断路器2
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
//11. 应急锂电池组2断路器
unsigned char emergencyLithiumBatteryGroup2CircuitBreaker;
//12. 仪表电源失电信号 (0x55 正常,0xAA 故障)
unsigned char instrumentPowerFailureSignal;
//13. 应急电源失电信号 (0x55 正常,0xAA 故障)
unsigned char emergencyPowerFailureSignal;
//14. 仪表汇流排绝缘低 (0x55 正常,0xAA 绝缘低)
unsigned char instrumentBusbarInsulationLow;
//15. 仪表母排电压
unsigned short instrumentBusbarVoltage;
//16. 艏部低压配电箱电流
unsigned short bowLowVoltageDistributionBoxCurrent;
//17. DC-C1(直流配电板1)仪表DC48V电流
unsigned short dcC1InstrumentDC48VCurrent;
//18. 预留电流
unsigned short reservedCurrent1; // 为了区分,添加了数字后缀
//19. 应急锂电池组2电流
unsigned short emergencyLithiumBatteryGroup2Current;
//20. 锂电池组(仪表)电流
unsigned short lithiumBatteryGroupInstrumentCurrent;
//21. UNIT4仪表DC48V电流
unsigned short unit4InstrumentDC48VCurrent;
//22. Ushort 预留电流
unsigned short reservedCurrent2; // 为了区分,添加了数字后缀
//23. 应急2汇流排电压
unsigned short emergency2BusbarVoltage;
//24. 复合能源管控系统应急DC48V电流
unsigned short compositeEnergyManagementSystemEmergencyDC48VCurrent;
//25. 燃料电池安全系统应急DC48V电流
unsigned short fuelCellSecuritySystemEmergencyDC48VCurrent;
//26. PLC控制电源电流
unsigned short plcControlPowerCurrent;
} disLowMainBusState;
typedef struct disLowBusState
{
//5. UNIT1断路器
unsigned char unit1CircuitBreaker;
//6. UNIT2断路器
unsigned char unit2CircuitBreaker;
//7. UNIT3断路器
unsigned char unit3CircuitBreaker;
//8. UNIT5断路器
unsigned char unit5CircuitBreaker;
//9. 艏部PZ装置断路器
unsigned char bowPZDeviceCircuitBreaker;
//10. 预留断路器1
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
//11. 预留断路器2
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
//12. 应急锂电池组1断路器
unsigned char emergencyLithiumBatteryGroup1CircuitBreaker;
//13. 仪表电源失电信号 (0x55 正常,0xAA 故障)
unsigned char powerFailureSignal;
//14. 应急电源失电信号 (0x55 正常,0xAA 故障)
unsigned char emergencyPowerFailureSignal;
//15. 浸水报警 (0x55 正常,0xAA 故障)
unsigned char waterIngressionAlarm;
//16. 仪表母排电压
unsigned short instrumentBusbarVoltage;
//17. 仪表母排电流
unsigned short instrumentBusbarCurrent;
//18. UNIT1电流
unsigned short unit1Current;
//19. UNIT2电流
unsigned short unit2Current;
//20. UNIT3电流
unsigned short unit3Current;
//21. UNIT5电流
unsigned short unit5Current;
//22. 艏部PZ装置电流
unsigned short bowPZDeviceCurrent;
//23. 应急锂电池组1电流
unsigned short emergencyLithiumBatteryGroup1Current;
//24. 应急1汇流排电压
unsigned short emergency1BusbarVoltage;
}disLowBusState;
typedef struct disHighVolBusCmd
{
// 5: 燃料电池断路器
unsigned char fuelCellCircuitBreaker;
// 6: 动力锂电池断路器
unsigned char powerLithiumBatteryCircuitBreaker;
// 7: 推进电机断路器
unsigned char propulsionMotorCircuitBreaker;
// 8: 锂电池组仪表断路器
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
// 9: DC/DC5模块断路器
unsigned char dcDc5ModuleCircuitBreaker;
// 10: 艏部高压配电箱断路器
unsigned char bowHighVoltageDistributionBoxCircuitBreaker;
// 11: 艉部FT装置4/5断路器
unsigned char sternFTDevice45CircuitBreaker;
// // 12: 艉舵开关1断路器
// unsigned char sternRudderSwitch1CircuitBreaker;
// // 13: 艉舵开关2断路器
// unsigned char sternRudderSwitch2CircuitBreaker;
// // 14: FB预留断路器
// unsigned char fbReservedCircuitBreaker;
// 12: FB预留断路器
unsigned char fbReservedCircuitBreaker;
// 13: 艉舵开关1断路器
unsigned char sternRudderSwitch1CircuitBreaker;
// 14: 艉舵开关2断路器
unsigned char sternRudderSwitch2CircuitBreaker;
// 15: TYZ预留断路器
unsigned char tyzReservedCircuitBreaker;
// 16: 预留断路器
unsigned char reservedCircuitBreaker;
// 17: DC/DC5模块启动
unsigned char dcdc5Module;
// 18: 冷却系统启动
unsigned char coolingSystem;
// unsigned char inputWater;
// unsigned char outputWater;
}disHighVolBusCmd;
typedef struct disHighAVolBusCmd
{
//5. 艏部FT装置1/2/3断路器
unsigned char bowFTDevice123CircuitBreaker;
//6. 启闭机构断路器
unsigned char actuatorCircuitBreaker;
//7. 桅杆舵机控制箱断路器
unsigned char mastSteeringGearControlBoxCircuitBreaker;
//8. XCZ断路器
unsigned char xczCircuitBreaker;
//9. 艏舵控制箱断路器
unsigned char bowRudderControlBoxCircuitBreaker;
//10. 敞水盖启动电缸断路器
unsigned char openWaterCoverStartCylinderCircuitBreaker;
}disHighAVolBusCmd;
typedef struct disHighBVolBusCmd
{
//5. 锂电池组(仪表)断路器
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
//6. 艏部低压配电箱断路器
unsigned char bowLowVoltageDistributionBoxCircuitBreaker;
//7. UNIT4仪表DC48V断路器
unsigned char unit4InstrumentDC48VCircuitBreaker;
//8. DC-C1直流配电板断路器
unsigned char dcC1DCDistributionPanelCircuitBreaker;
//9. 预留断路器1
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
//10. 预留断路器2
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
//11. 应急锂电池组2断路器
unsigned char emergencyLithiumBatteryGroup2CircuitBreaker;
}disLowMainBusCmd;
typedef struct disLowBusCmd
{
unsigned char unit1CircuitBreaker;
unsigned char unit2CircuitBreaker;
unsigned char unit3CircuitBreaker;
unsigned char unit5CircuitBreaker;
unsigned char bowPZDeviceCircuitBreaker;
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
unsigned char emergencyLithiumBatteryGroup1CircuitBreaker;
}disLowBusCmd;
#pragma pack (0)
//状态结构体定义
typedef struct pmState
{
ccuState ccustate;
disHighVolBusState bus1State;
disHighAVolBusState bus2State;
disLowMainBusState bus3State;
disLowBusState bus4State;
} PmState;
typedef struct disBus1Breaker
{
unsigned char fuelCellCircuitBreaker : 1;
unsigned char powerLithiumBatteryCircuitBreaker : 1;
unsigned char propulsionMotorCircuitBreaker : 1;
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker : 1;
unsigned char dcDc5ModuleCircuitBreaker : 1;
unsigned char bowHighVoltageDistributionBoxCircuitBreaker : 1;
unsigned char sternFTDevice45CircuitBreaker : 1;
unsigned char sternRudderSwitch1CircuitBreaker : 1;
unsigned char sternRudderSwitch2CircuitBreaker : 1;
unsigned char fbReservedCircuitBreaker : 1;
unsigned char tyzReservedCircuitBreaker : 1;
unsigned char reservedCircuitBreaker : 1;
unsigned char dcdcmodel : 1;
unsigned char coolingSystem : 1;
unsigned short paceholder : 4;
} disBus1Breaker;
typedef struct disBus2Breaker
{
unsigned char bowFTDevice123CircuitBreaker : 1;
unsigned char actuatorCircuitBreaker : 1;
unsigned char mastSteeringGearControlBoxCircuitBreaker : 1;
unsigned char xczCircuitBreaker : 1;
unsigned char bowRudderControlBoxCircuitBreaker : 1;
unsigned char openWaterCoverStartCylinderCircuitBreaker : 1;
unsigned short paceholder : 10;
/* data */
} disBus2Breaker;
typedef struct disBus3Breaker
{
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker : 1;
unsigned char bowLowVoltageDistributionBoxCircuitBreaker : 1;
unsigned char unit4InstrumentDC48VCircuitBreaker : 1;
unsigned char dcC1DCDistributionPanelCircuitBreaker : 1;
unsigned char reservedCircuitBreaker1 : 1;
unsigned char reservedCircuitBreaker2 : 1;
unsigned char emergencyLithiumBatteryGroup2CircuitBreaker : 1;
unsigned short paceholder : 9;
/* data */
} disBus3Breaker;
typedef struct disBus4Breaker
{
unsigned char unit1CircuitBreaker : 1;
unsigned char unit2CircuitBreaker : 1;
unsigned char unit3CircuitBreaker : 1;
unsigned char unit5CircuitBreaker : 1;
unsigned char bowPZDeviceCircuitBreaker : 1;
unsigned char reservedCircuitBreaker1 : 1; // 为了区分,添加了数字后缀
unsigned char reservedCircuitBreaker2 : 1; // 为了区分,添加了数字后缀
unsigned char emergencyLithiumBatteryGroup1CircuitBreaker : 1;
unsigned short paceholder : 8;
/* data */
} disBus4Breaker;
typedef struct disSysBreakerList
{
disBus1Breaker bus1Breaker;
disBus2Breaker bus2Breaker;
disBus3Breaker bus3Breaker;
disBus4Breaker bus4Breaker;
} disSysBreaker;
typedef struct MSControlCmd
{
unsigned int powerCMD;
unsigned int modCMD;
unsigned int workCMD;
}MSControlCmd;
namespace FcuCommand {
enum Type : unsigned char {
SelfCheck = 0x01,
Start = 0x02,
Stop = 0x03,
Reset = 0x04,
EmergencyStop = 0x05,
Supply = 0x06,
WarmUp = 0x07,
Maintenance = 0x08
};
}
enum class FcuState : unsigned char {
//初始化
Init = 0x01,
//待机
Standby = 0x02,
//自检异常
SelfCheckError = 0x03,
//就绪
Ready = 0x04,
//启动
Start = 0x05,
//运行
Running = 0x06,
//停机
Stop = 0x07,
//故障
Fault = 0x08,
//补给
Supply = 0x09,
//预热
WarmUp = 0x0A,
//预热完成
WarmUpComplete = 0x0B,
//维护
Maintenance = 0x0C,
//维护完成
MaintenanceComplete = 0x0D
};
namespace BatteryCommand {
enum Type : unsigned char {
Start = 0x10,
Stop = 0x20,
Hold = 0x00
};
};
namespace PMMode {
enum Type : unsigned char {
Normal = 0,
Test = 1,
Debug = 2
};
};
//工况定义
namespace WorkCondition {
enum Type : unsigned char {
CHANING = 0, // 工况切换中
STANDBY = 1, // 待机工况
SHORE_BASED_READY = 2, // 岸基备航
WATER_BASED_READY = 3, // 水中备航
REMOTE_CONTROL = 4, // 遥控工况
CRUISE_MODE = 5, // 巡航模式
HIGH_SPEED_MODE = 6, // 高速模式
ASCEND_DESCEND = 7, // 上浮下潜
BUOYANCY_ADJUST = 8, // 浮调模式
UNDERWATER_RECON = 9, // 水下侦查
SURFACE_RECON = 10, // 水面侦查
DJ_MODE = 11, // DJ模式
LIFT_MODE = 12 // 调试模式
};
};
namespace RunMode {
enum Type : unsigned char {
//正常模式
Normal = 0,
//测试模式
Test = 1,
//调试模式
Debug = 2
};
};
namespace TaskType {
enum Type : unsigned char {
THROW_LOAD = 1, // 抛载
FLOAT_UP = 2, // 运动上浮
RECYCLE = 3, // 回收
HOVER = 4, // 悬停
SAT_COMM = 5, // 上浮通信
SAT_CALIBRATE = 6, // 上浮校准
TOUR = 7, // 游曳
SAIL = 8, // 航行
EMER_SAT_COMM = 9, //紧急上浮通信
EMER_SAIL = 10 //紧急航行
};
inline const std::string toString(Type type) {
static const std::map<Type, std::string> names = {
{THROW_LOAD, "throwLoad"},
{FLOAT_UP, "floatUp"},
{RECYCLE, "recycle"},
{HOVER, "hover"},
{SAT_COMM, "satComm"},
{SAT_CALIBRATE, "satCalibrate"},
{TOUR, "tour"},
{SAIL, "sail"},
{EMER_SAT_COMM,"emerSatComm"},
{EMER_SAIL,"emerSail"}
};
auto it = names.find(type);
return it != names.end() ? it->second : "unknown";
}
inline Type fromString(const std::string& str) {
static const std::map<std::string, Type> stringToEnum = {
{"throwLoad", THROW_LOAD},
{"floatUp", FLOAT_UP},
{"recycle", RECYCLE},
{"hover", HOVER},
{"satComm", SAT_COMM},
{"emerSatComm",SAT_COMM},
{"satCalibrate",SAT_CALIBRATE},
{"tour", TOUR},
{"sail", SAIL},
{"emerSatComm",EMER_SAT_COMM},
{"emerSail",EMER_SAIL}
};
auto it = stringToEnum.find(str);
return it != stringToEnum.end() ? it->second : static_cast<Type>(0); // 返回0表示无效类型
}
}
namespace EquipmentCommand {
enum Type : unsigned char {
OFF = 0, //断电
ON = 1, //上电
//仪表电上电
METER_ON = 2,
//动力电上电
POWER_ON = 3,
//仪表电断电
METER_OFF = 4,
//动力电断电
POWER_OFF = 5,
};
};
struct MissionState
{
int type;
bool enableBowRudder;
bool enableBuoyancyAdjustment;
};
struct DeviceSwitchCmd
{
int id;
int cmd;
};
namespace DeviceId {
enum Type : unsigned char {
singleBeamSonar1 = 0,
singleBeamSonar2 = 1,
singleBeamSonar3 = 2,
singleBeamSonar4 = 3,
singleBeamSonar5 = 4,
singleBeamSonar6 = 5,
singleBeamSonar7 = 6,
singleBeamSonar8 = 7,
forwardSonar = 8,
bowCover1 = 9,
bowCover2 = 10,
bowCover3 = 11,
bowCover4 = 12,
bowCover5 = 13,
bowCover6 = 14,
bowRudderDeploy = 15,
bowRudderServo1 = 16,
bowRudderServo2 = 17,
depth1 = 18,
depth2 = 19,
depth3 = 20,
overDeep1 = 21,
overDeep2 = 22,
ctd1 = 23,
ctd2 = 24,
soundVeloc = 25,
waterInject = 26,
bowWaterInet1 = 27,
bowWaterInet2 = 28,
bowWaterInet3 = 29,
bowWaterInet4 = 30,
bowWaterInet5 = 31,
bowWaterInet6 = 32,
bowWaterInet7 = 33,
bowWaterInet8 = 34,
sideSonar = 35,
lowFreqSonar = 36,
launchControler = 37,
photoSensor = 38,
electSensor = 39,
commMast = 40,
mastLiftingServo = 41,
USBL = 42,
DVL = 43,
buoyancyAdjust1 = 44,
buoyancyAdjust2 = 45,
buoyancyAdjust3 = 46,
buoyancyAdjust4 = 47,
buoyancyAdjust5 = 48,
sternRudderServo1 = 49,
sternRudderServo2 = 50,
sternRudderServo3 = 51,
sternRudderServo4 = 52,
thruster = 53,
bowThrow = 54,
sternThrow = 55,
buoyage = 56,
ins = 57,
ntp = 58,
inputWaterSensor1 = 59,
inputWaterSensor2 = 60,
inputWaterSensor3 = 61,
};
inline const std::string toString(Type type) {
static const std::map<Type, std::string> names = {
{singleBeamSonar1, "singleBeamSonar1"},
{singleBeamSonar2, "singleBeamSonar2"},
{singleBeamSonar3, "singleBeamSonar3"},
{singleBeamSonar4, "singleBeamSonar4"},
{singleBeamSonar5, "singleBeamSonar5"},
{singleBeamSonar6, "singleBeamSonar6"},
{singleBeamSonar7, "singleBeamSonar7"},
{singleBeamSonar8, "singleBeamSonar8"},
{forwardSonar, "forwardSonar"},
{bowCover1, "bowCover1"},
{bowCover2, "bowCover2"},
{bowCover3, "bowCover3"},
{bowCover4, "bowCover4"},
{bowCover5, "bowCover5"},
{bowCover6, "bowCover6"},
{bowRudderDeploy, "bowRudderDeploy"},
{bowRudderServo1, "bowRudderServo1"},
{bowRudderServo2, "bowRudderServo2"},
{depth1, "depth1"},
{depth2, "depth2"},
{depth3, "depth3"},
{overDeep1, "overDeep1"},
{overDeep2, "overDeep2"},
{ctd1, "ctd1"},
{ctd2, "ctd2"},
{soundVeloc, "soundVeloc"},
{waterInject, "waterInject"},
{bowWaterInet1, "bowWaterInet1"},
{bowWaterInet2, "bowWaterInet2"},
{bowWaterInet3, "bowWaterInet3"},
{bowWaterInet4, "bowWaterInet4"},
{bowWaterInet5, "bowWaterInet5"},
{bowWaterInet6, "bowWaterInet6"},
{bowWaterInet7, "bowWaterInet7"},
{bowWaterInet8, "bowWaterInet8"},
{sideSonar, "sideSonar"},
{lowFreqSonar, "lowFreqSonar"},
{launchControler, "launchControler"},
{photoSensor, "photoSensor"},
{electSensor, "electSensor"},
{commMast, "commMast"},
{mastLiftingServo, "mastLiftingServo"},
{USBL, "USBL"},
{DVL, "DVL"},
{buoyancyAdjust1, "buoyancyAdjust1"},
{buoyancyAdjust2, "buoyancyAdjust2"},
{buoyancyAdjust3, "buoyancyAdjust3"},
{buoyancyAdjust4, "buoyancyAdjust4"},
{buoyancyAdjust5, "buoyancyAdjust5"},
{sternRudderServo1, "sternRudderServo1"},
{sternRudderServo2, "sternRudderServo2"},
{sternRudderServo3, "sternRudderServo3"},
{sternRudderServo4, "sternRudderServo4"},
{thruster, "thruster"},
{bowThrow, "bowThrow"},
{sternThrow, "sternThrow"},
{buoyage, "buoyage"},
{ins, "ins"},
{ntp, "ntp"},
{inputWaterSensor1, "inputWaterSensor1"},
{inputWaterSensor2, "inputWaterSensor2"},
{inputWaterSensor3, "inputWaterSensor3"}
};
auto it = names.find(type);
return it != names.end() ? it->second : "unknown";
}
}
// 设备类id存储
static const std::unordered_set<int> underWterDevices = {
DeviceId::singleBeamSonar1,
DeviceId::singleBeamSonar2,
DeviceId::singleBeamSonar3,
DeviceId::singleBeamSonar4,
DeviceId::singleBeamSonar5,
DeviceId::singleBeamSonar6,
DeviceId::singleBeamSonar7,
DeviceId::singleBeamSonar8,
DeviceId::forwardSonar,
DeviceId::USBL,
DeviceId::DVL,
DeviceId::lowFreqSonar
};
static const std::unordered_set<int> noPowerDevices = {
DeviceId::depth1,
DeviceId::depth2,
DeviceId::depth3,
DeviceId::overDeep1,
DeviceId::overDeep2,
DeviceId::ctd1,
DeviceId::ctd2,
DeviceId::soundVeloc,
DeviceId::waterInject,
DeviceId::launchControler,
DeviceId::photoSensor,
DeviceId::electSensor,
DeviceId::commMast,
DeviceId::ntp,
DeviceId::bowThrow,
DeviceId::sternThrow,
DeviceId::ins,
DeviceId::inputWaterSensor1,
DeviceId::inputWaterSensor2,
DeviceId::inputWaterSensor3
};
namespace FaultEnable {
enum Type : bool {
BasicNavigationFault_1 = false, // 使能故障
BasicNavigationFault_2 = false,
BasicNavigationFault_3 = false,
BasicNavigationFault_4 = false,
BasicNavigationFault_5 = false,
BasicNavigationFault_6 = false,
BasicNavigationFault_7 = false,
BasicNavigationFault_8 = false,
BasicNavigationFault_9 = false,
BasicNavigationFault_10 = false,
ExtendedNavigationFault_1 = false, // 使能故障
ExtendedNavigationFault_2 = false,
ExtendedNavigationFault_3 = false,
ExtendedNavigationFault_4 = false,
ObstacleAvoidanceFault_1 = false, // 使能故障
ObstacleAvoidanceFault_2 = false,
ObstacleAvoidanceFault_3 = false,
BuoyancyControlFault_1 = false, // 使能故障
BuoyancyControlFault_2 = false,
BuoyancyControlFault_3 = false,
BuoyancyControlFault_4 = false,
CommunicationSystemFault_1 = false, // 使能故障
CommunicationSystemFault_2 = false,
CommunicationSystemFault_3 = false,
PayloadSystemFault_1 = false, // 使能故障
PayloadSystemFault_2 = false,
PayloadSystemFault_3 = false,
PayloadSystemFault_4 = false,
PayloadSystemFault_5 = false,
PayloadSystemFault_6 = false,
PayloadSystemFault_7 = false,
EmergencySystemFault_1 = false, // 使能故障
EmergencySystemFault_2 = false,
EmergencySystemFault_3 = false,
EmergencySystemFault_4 = false,
EmergencySystemFault_5 = false,
EmergencySystemFault_6 = false,
SensorSystemFault_1 = false, // 使能故障
SensorSystemFault_2 = false,
SensorSystemFault_3 = false,
};
}
#endif
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
#ifndef SQLITE_H
#define SQLITE_H
#include "sqlite3.h"
#include <string>
#include "../pmSysvariable.h"
class SQLite
{
private:
sqlite3* m_db;
public:
std::string m_dbPath;
SQLite(const std::string& dbName);
~SQLite();
//创建表
bool createTable();
bool createTable(const std::string& tableName, const std::string& columns);
// 插入数据函数
bool insertData(ccuState data);
bool insertData(disHighVolBusState data);
bool insertData(disHighAVolBusState data);
bool insertData(disLowMainBusState data);
bool insertData(disLowBusState data);
//插入指令数据
bool insertData(ccuColCmd cmd);
bool insertData(disHighVolBusCmd cmd);
bool insertData(disHighAVolBusCmd cmd);
bool insertData(disLowMainBusCmd cmd);
bool insertData(disLowBusCmd cmd);
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+719
View File
@@ -0,0 +1,719 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*xsnprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(sqlite3*);
const char *(*db_filename)(sqlite3*,const char*);
int (*db_readonly)(sqlite3*,const char*);
int (*db_release_memory)(sqlite3*);
const char *(*errstr)(int);
int (*stmt_busy)(sqlite3_stmt*);
int (*stmt_readonly)(sqlite3_stmt*);
int (*stricmp)(const char*,const char*);
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*xvsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(sqlite3_value*);
void (*result_subtype)(sqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(sqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(sqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
/* Version 3.20.0 and later */
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
sqlite3_stmt**,const char**);
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
sqlite3_stmt**,const void**);
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
void *(*value_pointer)(sqlite3_value*,const char*);
int (*vtab_nochange)(sqlite3_context*);
int (*value_nochange)(sqlite3_value*);
const char *(*vtab_collation)(sqlite3_index_info*,int);
/* Version 3.24.0 and later */
int (*keyword_count)(void);
int (*keyword_name)(int,const char**,int*);
int (*keyword_check)(const char*,int);
sqlite3_str *(*str_new)(sqlite3*);
char *(*str_finish)(sqlite3_str*);
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
void (*str_append)(sqlite3_str*, const char *zIn, int N);
void (*str_appendall)(sqlite3_str*, const char *zIn);
void (*str_appendchar)(sqlite3_str*, int N, char C);
void (*str_reset)(sqlite3_str*);
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
/* Version 3.25.0 and later */
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
void(*xDestroy)(void*));
/* Version 3.26.0 and later */
const char *(*normalized_sql)(sqlite3_stmt*);
/* Version 3.28.0 and later */
int (*stmt_isexplain)(sqlite3_stmt*);
int (*value_frombind)(sqlite3_value*);
/* Version 3.30.0 and later */
int (*drop_modules)(sqlite3*,const char**);
/* Version 3.31.0 and later */
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
const char *(*uri_key)(const char*,int);
const char *(*filename_database)(const char*);
const char *(*filename_journal)(const char*);
const char *(*filename_wal)(const char*);
/* Version 3.32.0 and later */
const char *(*create_filename)(const char*,const char*,const char*,
int,const char**);
void (*free_filename)(const char*);
sqlite3_file *(*database_file_object)(const char*);
/* Version 3.34.0 and later */
int (*txn_state)(sqlite3*,const char*);
/* Version 3.36.1 and later */
sqlite3_int64 (*changes64)(sqlite3*);
sqlite3_int64 (*total_changes64)(sqlite3*);
/* Version 3.37.0 and later */
int (*autovacuum_pages)(sqlite3*,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*, void(*)(void*));
/* Version 3.38.0 and later */
int (*error_offset)(sqlite3*);
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
int (*vtab_distinct)(sqlite3_index_info*);
int (*vtab_in)(sqlite3_index_info*,int,int);
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
/* Version 3.39.0 and later */
int (*deserialize)(sqlite3*,const char*,unsigned char*,
sqlite3_int64,sqlite3_int64,unsigned);
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
unsigned int);
const char *(*db_name)(sqlite3*,int);
/* Version 3.40.0 and later */
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
/* Version 3.43.0 and later */
int (*stmt_explain)(sqlite3_stmt*,int);
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
sqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/*
** The following macros redefine the API routines so that they are
** redirected through the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->xsnprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
#define sqlite3_result_error_code sqlite3_api->result_error_code
#define sqlite3_test_control sqlite3_api->test_control
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2 sqlite3_api->close_v2
#define sqlite3_db_filename sqlite3_api->db_filename
#define sqlite3_db_readonly sqlite3_api->db_readonly
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
#define sqlite3_errstr sqlite3_api->errstr
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
#define sqlite3_stricmp sqlite3_api->stricmp
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype sqlite3_api->value_subtype
#define sqlite3_result_subtype sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64 sqlite3_api->status64
#define sqlite3_strlike sqlite3_api->strlike
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
/* Version 3.20.0 and later */
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
#define sqlite3_result_pointer sqlite3_api->result_pointer
#define sqlite3_value_pointer sqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
#define sqlite3_value_nochange sqlite3_api->value_nochange
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
/* Version 3.24.0 and later */
#define sqlite3_keyword_count sqlite3_api->keyword_count
#define sqlite3_keyword_name sqlite3_api->keyword_name
#define sqlite3_keyword_check sqlite3_api->keyword_check
#define sqlite3_str_new sqlite3_api->str_new
#define sqlite3_str_finish sqlite3_api->str_finish
#define sqlite3_str_appendf sqlite3_api->str_appendf
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
#define sqlite3_str_append sqlite3_api->str_append
#define sqlite3_str_appendall sqlite3_api->str_appendall
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
#define sqlite3_str_reset sqlite3_api->str_reset
#define sqlite3_str_errcode sqlite3_api->str_errcode
#define sqlite3_str_length sqlite3_api->str_length
#define sqlite3_str_value sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
/* Version 3.26.0 and later */
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
/* Version 3.28.0 and later */
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
#define sqlite3_value_frombind sqlite3_api->value_frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules sqlite3_api->drop_modules
/* Version 3.31.0 and later */
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
#define sqlite3_uri_key sqlite3_api->uri_key
#define sqlite3_filename_database sqlite3_api->filename_database
#define sqlite3_filename_journal sqlite3_api->filename_journal
#define sqlite3_filename_wal sqlite3_api->filename_wal
/* Version 3.32.0 and later */
#define sqlite3_create_filename sqlite3_api->create_filename
#define sqlite3_free_filename sqlite3_api->free_filename
#define sqlite3_database_file_object sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlite3_txn_state sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64 sqlite3_api->changes64
#define sqlite3_total_changes64 sqlite3_api->total_changes64
/* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
/* Version 3.38.0 and later */
#define sqlite3_error_offset sqlite3_api->error_offset
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
#define sqlite3_vtab_in sqlite3_api->vtab_in
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
/* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
#define sqlite3_deserialize sqlite3_api->deserialize
#define sqlite3_serialize sqlite3_api->serialize
#endif
#define sqlite3_db_name sqlite3_api->db_name
/* Version 3.40.0 and later */
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
/* Version 3.43.0 and later */
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* SQLITE3EXT_H */
+953
View File
@@ -0,0 +1,953 @@
#ifndef SYSTEMDATA_H
#define SYSTEMDATA_H
#include "pmSysvariable.h"
#include "sqlit3/SQLite.h"
#include <set>
#include <mutex>
#define DEBUFG
class SystemData
{
private:
SQLite* m_db;
std::set<unsigned int> sysFaultCodes;
mutable std::mutex sysFaultCodesMutex;
public:
/**
* @brief 向系统故障码集合中插入一个故障码
* @param faultCode 要插入的故障码
*/
void insertFaultCode(unsigned int faultCode) {
std::lock_guard<std::mutex> lock(sysFaultCodesMutex);
sysFaultCodes.insert(faultCode);
}
/**
* @brief 从系统故障码集合中消除一个故障码
* @param faultCode 要消除的故障码
*/
void eraseFaultCode(unsigned int faultCode) {
std::lock_guard<std::mutex> lock(sysFaultCodesMutex);
sysFaultCodes.erase(faultCode);
}
/**
* @brief 获取系统当前的故障等级
* @return uint8_t 故障等级,00H-无故障, 10H-一级, 20H-二级, 30H-三级, 40H-四级
*/
uint8_t getFaultCodeLevel() const {
uint8_t maxLevel = 0;
// 遍历 sysFaultCodes 集合中的每个故障码
for (auto code : sysFaultCodes) {
// 提取0xabcd中的b位 (右移8位后取低4位)
uint8_t level = (code >> 8) & 0xF;
if (level > maxLevel) {
maxLevel = level;
}
}
return maxLevel;
}
/**
* @brief 获取系统当前的故障码集合
* @return std::set<unsigned int>& 系统当前的故障码集合
*/
const std::set<unsigned int>& getFaultCode() const {
return sysFaultCodes;
}
//燃料电池系统参数
uint8_t fc_mode; // 燃料电池系统运行模式:00H-无效, 01H-调试, 02H-自动, 03H-补给
uint8_t fc_status; // 燃料电池状态:00H-无效, 01H-初始化, ..., 0DH-维护完成
uint8_t fc_fault_level; // 燃料电池故障等级:00H-无故障, 10H-一级, 20H-二级, 30H-三级, 40H-四级
//功率和时间参数
float output_power_limit; // 系统输出功率限制值,单位:W
float total_generation_time; // 系统累计发电时间,单位:0.1小时
float total_generation_power; // 系统累计发电总功率,单位:W
//故障信息
uint16_t fc_fault_level_1; // 一级故障位
uint16_t fc_fault_level_2; // 二级故障位
uint16_t fc_fault_level_3; // 三级故障位
uint16_t fc_fault_level_4; // 四级故障位
//燃料容量
float hydrogen_capacity; // 储氢罐剩余容量百分比,单位:%
float liquid_oxygen_capacity; // 液氧罐剩余容量百分比,单位:%
//温度压力参数
float palladium_temp; // 钯膜最高温度,单位:℃
float main_pipe_pressure; // 主水路压力,单位:0.01kPa
float aux_pipe_pressure; // 辅水路压力,单位:0.01kPa
//舱室环境参数
float cabin_pressure1; // 舱室1压力,单位:0.01kPa
float cabin_pressure2; // 舱室2压力,单位:0.01kPa
float cabin_temp1; // 舱室1温度,单位:0.01℃
float cabin_temp2; // 舱室2温度,单位:0.01℃
float cabin_humidity1; // 舱室1湿度,单位:0.01%RH
float cabin_humidity2; // 舱室2湿度,单位:0.01%RH
//火焰探测器
uint8_t flame_detector1; // 火焰探测器1状态:00H-无效, 01H-报警, 02H-故障
uint8_t flame_detector2; // 火焰探测器2状态:00H-无效, 01H-报警, 02H-故障
//气体浓度
float h2_concentration1; // 舱室H2浓度1,单位:0.01% LEL
float h2_concentration2; // 舱室H2浓度2,单位:0.01% LEL
float h2_concentration3; // 舱室H2浓度3,单位:0.01% LEL
float o2_concentration1; // 舱室O2浓度1,单位:0.01% LEL
float o2_concentration2; // 舱室O2浓度2,单位:0.01% LEL
float ch3oh_concentration1; // 舱室甲醇气体浓度1,单位:0.01% LEL
float ch3oh_concentration2; // 舱室甲醇气体浓度2,单位:0.01% LEL
//保留字段
float reserved1[10]; // 保留字段
float cabin_ox_concentration; // 仪表舱内氧气浓度,单位:0.1%
float cabin_temperature; // 仪表舱内温度,单位:0.1℃
float cabin_humidity; // 仪表舱内湿度,单位:0.1%RH
float cabin_pressure; // 仪表舱内大气压,单位:0.2kPa
//动力舱参数
float power_cabin_ox_concentration; // 动力舱内氧气浓度,单位:0.1%
float power_cabin_temperature; // 动力舱内温度,单位:0.1℃
float power_cabin_humidity; // 动力舱内湿度,单位:0.1%RH
float power_cabin_pressure; // 动力舱内大气压,单位:0.2kPa
uint8_t reserved2[2]; // 保留字段
//电池报警标志
uint8_t dyn_alarm_flag[6]; // 动力锂电池报警标志
uint8_t ins_alarm_flag[6]; // 仪表锂电池报警标志
//继电器状态
uint8_t ins_relay_status1; // 仪表电池继电器状态
uint8_t ins_relay_status2; // 仪表电池预充继电器和负极继电器状态
uint8_t dyn_relay_status1; // 动力电池正极与充电继电器状态
uint8_t dyn_relay_status2; // 动力电池预充与负极继电器状态
//仪表电池继电器状态
uint8_t ins_pos_relay_status; // 仪表电池正极继电器状态 (X0H:无效 X1H:接通 X2H:断开)
uint8_t ins_charge_relay_status; // 仪表电池充电继电器状态 (0XH:无效 1XH:接通 2XH:断开)
uint8_t ins_precharge_relay_status; // 仪表电池预充继电器状态 (X0H:无效 X1H:接通 X2H:断开)
uint8_t ins_neg_relay_status; // 仪表电池负极继电器状态 (0XH:无效 1XH:接通 2XH:断开)
//动力电池继电器状态
uint8_t dyn_pos_relay_status; // 动力电池正极继电器状态 (X0H:无效 X1H:接通 X2H:断开)
uint8_t dyn_charge_relay_status; // 动力电池充电继电器状态 (0XH:无效 1XH:接通 2XH:断开)
uint8_t dyn_precharge_relay_status; // 动力电池预充继电器状态 (X0H:无效 X1H:接通 X2H:断开)
uint8_t dyn_neg_relay_status; // 动力电池负极继电器状态 (0XH:无效 1XH:接通 2XH:断开)
//电池功率参数
float ins_max_discharge_power; // 仪表电池最大允许放电功率,单位:0.05kW
float dyn_max_discharge_power; // 动力电池最大允许放电功率,单位:0.05kW
//电池SOC
int ins_soc; // 仪表锂电池荷电状态SOC,范围:0~100
int dyn_soc; // 动力锂电池荷电状态SOC,范围:0~100
//电池能量
float ins_total_energy; // 仪表电池总能量,单位:0.1kWh
float dyn_total_energy; // 动力电池总能量,单位:0.1kWh
//电池输入功率
float ins_power_input; // 仪表电池输入功率,单位:0.1kW
float dyn_power_input; // 动力电池输入功率,单位:0.1kW
//电池充放电状态
uint8_t ins_charge_status; // 仪表电池充放电状态:00H-无效,10H-充电,20H-放电
uint8_t dyn_charge_status; // 动力电池充放电状态:00H-无效,10H-充电,20H-放电
//电池电压电流
float ins_voltage_link; // 仪表电池LINK端电压,单位:0.01V
float ins_voltage_pack; // 仪表电池PACK端电压,单位:0.01V
float ins_current; // 仪表电池电流,单位:0.01A
float ins_resistance_pos; // 仪表电池正极绝缘电阻,单位:kΩ
float ins_resistance_neg; // 仪表电池负极绝缘电阻,单位:kΩ
float dyn_voltage_link; // 动力电池LINK端电压,单位:0.01V
float dyn_voltage_pack; // 动力电池PACK端电压,单位:0.01V
float dyn_current; // 动力电池电流,单位:0.05A
float dyn_resistance_pos; // 动力电池正极绝缘电阻,单位:kΩ
float dyn_resistance_neg; // 动力电池负极绝缘电阻,单位:kΩ
//紧急状态
uint8_t ins_emergency_status; // 仪表电池紧急状态
uint8_t dyn_emergency_status; // 动力电池紧急状态
//保留字段
uint8_t reserved3[2]; // 保留字段
float ins_soc_threshold1; // 仪表电池1 SOC门限
float ins_soc_threshold2; // 仪表电池2 SOC门限
float ins_soc_threshold3; // 仪表电池3 SOC门限
float dyn_soc_threshold1; // 动力电池1 SOC门限
float dyn_soc_threshold2; // 动力电池2 SOC门限
float dyn_soc_threshold3; // 动力电池3 SOC门限
float ins_power_limit1; // 仪表电池1功率限制值
float ins_power_limit2; // 仪表电池2功率限制值
float dyn_power_limit1; // 动力电池1功率限制值
float dyn_power_limit2; // 动力电池2功率限制值
//设备在线状态
uint32_t device_online_flag1; // 设备在线状态标志1
uint32_t device_online_flag2; // 设备在线状态标志2
//其他锂电池状态
uint8_t dyn_charge_level; // 动力电池充电状态:01H-1级(不限), 02H-2级(限功率), 03H-3级(关闭)
uint8_t dyn_water_leak_status; // 动力漏水状态:0XH-正常, 1XH-异常漏水
uint8_t ins_water_leak_dcdc_status; // 仪表漏水状态与DCDC状态:低4位-漏水状态(0XH正常,1XH异常),高4位-DCDC状态(X0H正常,X1H故障)
uint8_t reserved4;
unsigned char water_leak_status_from_insbat; // 仪表漏水状态
unsigned char water_leak_status_from_dynbat; // 动力漏水状态
unsigned char dcdc_status_from_insbat; // 仪表DCDC状态
//保留字段
// uint32_t reserved4; // 保留字段
uint32_t heartbeat; // 主机心跳计数器
//锂电池故障字段
unsigned char powfaultCode;
unsigned char insfaultCode;
//应急电池
double emergency_battery1_voltage; // 应急电池1总电压 [V]
double emergency_battery1_current; // 应急电池1总电流 [A]
double emergency_battery1_max_temp; // 应急电池1最高温度 [°C]
uint16_t emergency_battery1_fault_word; // 应急电池1故障字
double emergency_battery2_voltage; // 应急电池2总电压 [V]
double emergency_battery2_current; // 应急电池2总电流 [A]
double emergency_battery2_max_temp; // 应急电池2最高温度 [°C]
uint16_t emergency_battery2_fault_word; // 应急电池2故障字
// MOOSD 状态
bool moosd_status;
//配电系统状态
//DC/DC状态字
struct DcdcStatus
{
// DC/DC5故障字低
union {
unsigned char lowFaultWord;
struct {
bool overTemperatureShutdown : 1; // Bit0: DC/DC模块过温关机
bool outputOverCurrent : 1; // Bit1: 输出过流
bool outputOverVoltage : 1; // Bit2: 输出过压
bool outputUnderVoltage : 1; // Bit3: 输出欠压
bool inputOverVoltage : 1; // Bit4: 输入过压
bool inputUnderVoltage : 1; // Bit5: 输入欠压
bool outputShortCircuit : 1; // Bit6: 输出短路保护
bool internalFault : 1; // Bit7: 内部故障
};
};
// DC/DC5故障字高
union {
unsigned char highFaultWord;
struct {
bool communicationFault : 1; // Bit0: 通讯故障报警
bool workingStatus : 1; // Bit1: 工作状态(1:启动, 0:关闭)
bool coolingPump1Fault : 1; // Bit2: 冷却泵1故障
bool coolingPump2Fault : 1; // Bit3: 冷却泵2故障
bool coolingWaterLeak : 1; // Bit4: 冷却水泄露
bool coolingPump1Running : 1; // Bit5: 冷却泵1运行状态
bool coolingPump2Running : 1; // Bit6: 冷却泵2运行状态
bool reserved : 1; // Bit7: 保留位
};
};
// 构造函数,初始化所有状态为正常
DcdcStatus() : lowFaultWord(0x00), highFaultWord(0x00) {}
} m_dcdcStatus;
//动力母线状态
struct POWER_BUS_STATUS
{
// 5: 燃料电池断路器 0 断开 1 闭合 2 故障
unsigned char fuelCellCircuitBreaker;
// 6: 动力锂电池断路器 0 断开 1 闭合 2 故障
unsigned char powerLithiumBatteryCircuitBreaker;
// 7: 推进电机断路器 0 断开 1 闭合 2 故障
unsigned char propulsionMotorCircuitBreaker;
// 8: 锂电池组仪表断路器 0 断开 1 闭合 2 故障
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
// 9: DC/DC5模块断路器 0 断开 1 闭合 2 故障
unsigned char dcDc5ModuleCircuitBreaker;
// 10: 艏部高压配电箱断路器 0 断开 1 闭合 2 故障
unsigned char bowHighVoltageDistributionBoxCircuitBreaker;
// 11: 艉部FT装置4/5断路器 0 断开 1 闭合 2 故障
unsigned char sternFTDevice45CircuitBreaker;
// 12: 艉舵开关1断路器 0 断开 1 闭合 2 故障
unsigned char sternRudderSwitch1CircuitBreaker;
// 13: 艉舵开关2断路器 0 断开 1 闭合 2 故障
unsigned char sternRudderSwitch2CircuitBreaker;
// 14: FB预留断路器 0 断开 1 闭合 2 故障
unsigned char fbReservedCircuitBreaker;
// 15: TYZ预留断路器 0 断开 1 闭合 2 故障
unsigned char tyzReservedCircuitBreaker;
// 16: 预留断路器 0 断开 1 闭合 2 故障
unsigned char reservedCircuitBreaker;
// 17: DC/DC5模块状态 0 未运行;1 运行;2 DC/DC模块过温关机;3 输出过流;4 输出过压;5 输出欠压;6 输入过压;7 输入欠压;8 输出短路保护;9 内部故障
unsigned char dcDcModuleStatus;
// 18:冷却系统状态 0 未运行 1 运行 2 冷却泵1故障 3 冷却泵2故障 4 冷却水泄露
unsigned char coolingSystemStatus;
// 19: 动力母排绝缘状态 0 正常 1 绝缘低
unsigned char powerBusInsulationStatus;
// 20: A汇流排绝缘状态 0 正常 1 绝缘低
unsigned char aBusInsulationStatus;
// 21: 仪表电源状态 0 正常 1 故障
unsigned char meterPowerLossSignal;
// 22: 应急电源状态 0 正常 1 故障
unsigned char emergencyPowerLossSignal;
// 22: dc/dc温度
float dcDcTemperature;
// 23: 动力汇流排电压
float powerBusVoltage;
// 24: DC/DC5模块电流
float dcDc5ModuleCurrent;
// 25: 动力汇流排电流
float powerBusCurrent;
// 26: A汇流排电压
float busbarAVoltage;
// 27: 推进电机控制箱电流
float propulsionMotorControlBoxCurrent;
// 28: A汇流排电流
float busbarACurrent;
// 29: 锂电池组(仪表)电流
float lithiumBatteryGroupMeterCurrent;
// 30: 艏部高压配电箱电流
float bowHighVoltageDistributionBoxCurrent;
// 31: 艉部FT装置4/5电流
float sternFTDevice45Current;
// 32: TYZ预留开关电流
float tyzReservedSwitchCurrent;
// 33: 艉舵开关1电流
float sternRudderSwitch1Current;
// 34: 预留电流
float reservedCurrent1; // 改为 reservedCurrent1 以避免重名
// 35: 艉舵开关2电流
float sternRudderSwitch2Current;
// 36: 预留电流2
float reservedCurrent2; // 改为 reservedCurrent2 以避免重名
// 37: FB预留电流
float fbReservedSwitchCurrent;
// 38: 预留电流3
float reservedCurrent3; // 改为 reservedCurrent3 以避免重名
// 39: 冷却水压力
float coolWaterPressure;
}power_bus_status;
struct POWER_A_BUS_STATUS
{
//动力汇流排状态
//5. 艏部FT装置1/2/3断路器 0 断开 1 闭合 2 故障
unsigned char bowFTDevice123CircuitBreaker;
//6. 启闭机构断路器 0 断开 1 闭合 2 故障
unsigned char actuatorCircuitBreaker;
//7. 桅杆舵机控制箱断路器 0 断开 1 闭合 2 故障
unsigned char mastSteeringGearControlBoxCircuitBreaker;
//8. XCZ断路器 0 断开 1 闭合 2 故障
unsigned char xczCircuitBreaker;
//9. 艏舵控制箱断路器 0 断开 1 闭合 2 故障
unsigned char bowRudderControlBoxCircuitBreaker;
//10. 敞水盖启动电缸断路器 0 断开 1 闭合 2 故障
unsigned char openWaterCoverStartCylinderCircuitBreaker;
//11. 仪表电源失电信号 0 正常 1 故障
unsigned char instrumentPowerFailureSignal;
//12. 应急电源失电信号 0 正常 1 故障
unsigned char emergencyPowerFailureSignal;
//13. 浸水报警 0 无 1 有
unsigned char waterIngressionAlarm;
//14. 汇流排B电压
float busbarBVoltage;
//15. 汇流排B电流
float busbarBCurrent;
//16. 艏部FT装置1/2/3电流
float bowFTDevice123Current;
//17. 启闭机构电流
float actuatorCurrent;
//18. 桅杆舵机控制箱电流
float mastSteeringGearControlBoxCurrent;
//19. XCZ电流
float xczCurrent;
//20. 艏舵控制箱电流
float bowRudderControlBoxCurrent;
//21. 敞水盖启动电缸电流
float openWaterCoverStartCylinderCurrent;
} power_a_bus_status;
//仪表主母线状态
struct INSTRUMENT_MAIN_BUS_STATUS
{
//5. 锂电池组(仪表)断路器 0 断开 1 闭合 2 故障
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
//6. 艏部低压配电箱断路器 0 断开 1 闭合 2 故障
unsigned char bowLowVoltageDistributionBoxCircuitBreaker;
//7. UNIT4仪表DC48V断路器 0 断开 1 闭合 2 故障
unsigned char unit4InstrumentDC48VCircuitBreaker;
//8. DC-C1直流配电板断路器 0 断开 1 闭合 2 故障
unsigned char dcC1DCDistributionPanelCircuitBreaker;
//9. 预留断路器1 0 断开 1 闭合 2 故障
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
//10. 预留断路器2 0 断开 1 闭合 2 故障
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
//11. 应急锂电池组2断路器 0 断开 1 闭合 2 故障
unsigned char emergencyLithiumBatteryGroup2CircuitBreaker;
//12. 仪表电源失电信号 0 正常 1 故障
unsigned char instrumentPowerFailureSignal;
//13. 应急电源失电信号 0 正常 1 故障
unsigned char emergencyPowerFailureSignal;
//14. 仪表汇流排绝缘低 0 正常 1 绝缘低
unsigned char instrumentBusbarInsulationLow;
//15. 仪表母排电压
float instrumentBusbarVoltage;
//16. 艏部低压配电箱电流
float bowLowVoltageDistributionBoxCurrent;
//17. DC-C1(直流配电板1)仪表DC48V电流
float dcC1InstrumentDC48VCurrent;
//18. 预留电流
float reservedCurrent1; // 为了区分,添加了数字后缀
//19. 应急锂电池组2电流
float emergencyLithiumBatteryGroup2Current;
//20. 锂电池组(仪表)电流
float lithiumBatteryGroupInstrumentCurrent;
//21. UNIT4仪表DC48V电流
float unit4InstrumentDC48VCurrent;
//22. Ushort 预留电流
float reservedCurrent2; // 为了区分,添加了数字后缀
//23. 应急2汇流排电压
float emergency2BusbarVoltage;
//24. 复合能源管控系统应急DC48V电流
float compositeEnergyManagementSystemEmergencyDC48VCurrent;
//25. 燃料电池安全系统应急DC48V电流
float fuelCellSecuritySystemEmergencyDC48VCurrent;
//26. PLC控制电源电流
float plcControlPowerCurrent;
} instrument_main_bus_status;
//仪表汇流排状态
struct INSTRUMENT_BUS_STATUS
{
//5. UNIT1断路器 0 断开 1 闭合 2 故障
unsigned char unit1CircuitBreaker;
//6. UNIT2断路器 0 断开 1 闭合 2 故障
unsigned char unit2CircuitBreaker;
//7. UNIT3断路器 0 断开 1 闭合 2 故障
unsigned char unit3CircuitBreaker;
//8. UNIT5断路器 0 断开 1 闭合 2 故障
unsigned char unit5CircuitBreaker;
//9. 艏部PZ装置断路器 0 断开 1 闭合 2 故障
unsigned char bowPZDeviceCircuitBreaker;
//10. 预留断路器1 0 断开 1 闭合 2 故障
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
//11. 预留断路器2 0 断开 1 闭合 2 故障
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
//12. 应急锂电池组1断路器 0 断开 1 闭合 2 故障
unsigned char emergencyLithiumBatteryGroup1CircuitBreaker;
//13. 仪表电源失电信号 0 正常 1 故障
unsigned char powerFailureSignal;
//14. 应急电源失电信号 0 正常 1 故障
unsigned char emergencyPowerFailureSignal;
//15. 浸水报警 0 无 1 有
unsigned char waterIngressionAlarm;
//16. 仪表母排电压
float instrumentBusbarVoltage;
//17. 仪表母排电流
float instrumentBusbarCurrent;
//18. UNIT1电流
float unit1Current;
//19. UNIT2电流
float unit2Current;
//20. UNIT3电流
float unit3Current;
//21. UNIT5电流
float unit5Current;
//22. 艏部PZ装置电流
float bowPZDeviceCurrent;
//23. 应急锂电池组1电流
float emergencyLithiumBatteryGroup1Current;
//24. 应急1汇流排电压
float emergency1BusbarVoltage;
} instrument_bus_status;
struct COMMON_STATUS
{
//超时状态
bool isTimeout;
//最后更新时间
double lastUpdateTime;
};
struct DeviceCommonStatus
{
COMMON_STATUS ccu_status;
COMMON_STATUS dis_hv_c1;
COMMON_STATUS dis_hv_c2;
COMMON_STATUS dis_lv_c1;
COMMON_STATUS dis_lv_c2;
} device_common_status;
struct DeviceOnlineStatus
{
//在线状态
//0x00: 未上线
//0x01: 在线
//0x02: 上线后掉线
uint8_t ins_online_state; //仪表锂电在线标志位
uint8_t dyn_online_state; //动力锂电在线标志位
uint8_t fuel_online_state; //燃电锂电在线标志位
uint8_t high_voltage_online_state; //高压配电板在线标志位
uint8_t low_voltage_online_state; //低压配电板在线标志位
uint8_t composite_online_state; //复合管控主机在线标志位
uint8_t composite_backup_online_state; //复合管控备机在线标志位
} device_online_status;
enum LeakageStatus {
LEAKAGE_BOW_EMERGENCY = 0, // 艏部应急漏水 (0x01)
LEAKAGE_BOW_HIGH_VOLTAGE, // 艏高压漏水 (0x02)
LEAKAGE_BOW_LOW_VOLTAGE, // 艏低压漏水 (0x04)
LEAKAGE_FUEL_CELL, // 燃电舱漏水 (0x08)
LEAKAGE_LI_BATTERY, // 锂电池舱漏水 (0x10)
LEAKAGE_STERN_EMERGENCY, // 艉应急漏水 (0x20)
LEAKAGE_FUEL_CELL_CABIN, // 燃料电池舱漏水 (0x40)
LEAKAGE_BOW_EMERGENCY2 // 艏部应急漏水2 (0x80)
};
unsigned char leakageCode = 0;
bool leakStatus[8] = {false};
unsigned char generateLeakageCode() {
unsigned char code = 0;
if(leakStatus[LEAKAGE_BOW_EMERGENCY]) code |= 0x01;
if(leakStatus[LEAKAGE_BOW_HIGH_VOLTAGE]) code |= 0x02;
if(leakStatus[LEAKAGE_BOW_LOW_VOLTAGE]) code |= 0x04;
if(leakStatus[LEAKAGE_FUEL_CELL]) code |= 0x08;
if(leakStatus[LEAKAGE_LI_BATTERY]) code |= 0x10;
if(leakStatus[LEAKAGE_STERN_EMERGENCY]) code |= 0x20;
if(leakStatus[LEAKAGE_FUEL_CELL_CABIN]) code |= 0x40;
if(leakStatus[LEAKAGE_BOW_EMERGENCY2]) code |= 0x80;
return code;
}
public:
SystemData(){
//初始化变量全部为0
memset(this, 0, sizeof(SystemData));
disSysFaultCode.clear();
sysFaultCodes.clear();
};
~SystemData(){};
void updateCommonStatus(double time_out=10){
//更新时间
double currentTime = MOOSTime();
//判断是否超时
device_common_status.ccu_status.isTimeout = abs(currentTime - device_common_status.ccu_status.lastUpdateTime) > time_out;
device_common_status.dis_hv_c1.isTimeout = abs(currentTime - device_common_status.dis_hv_c1.lastUpdateTime) > time_out;
device_common_status.dis_hv_c2.isTimeout = abs(currentTime - device_common_status.dis_hv_c2.lastUpdateTime) > time_out;
device_common_status.dis_lv_c1.isTimeout = abs(currentTime - device_common_status.dis_lv_c1.lastUpdateTime) > time_out;
device_common_status.dis_lv_c2.isTimeout = abs(currentTime - device_common_status.dis_lv_c2.lastUpdateTime) > time_out;
};
void updateSystemData(ccuState data){
fc_mode = data.fc_mode;
fc_status = data.fc_status;
fc_fault_level = data.fc_fault_level;
//功率和时间参数
output_power_limit = data.output_power_limit;
total_generation_time = data.total_generation_time * 0.1;
total_generation_power = data.total_generation_power;
//故障信息
#ifdef DEBUG
fc_fault_level_1 = data.fault_level_1;
fc_fault_level_2 = data.fault_level_2;
fc_fault_level_3 = data.fault_level_3;
fc_fault_level_4 = data.fault_level_4;
#endif
//燃料容量
hydrogen_capacity = static_cast<int>(data.hydrogen_capacity);
liquid_oxygen_capacity = static_cast<int>(data.liquid_oxygen_capacity);
//温度压力参数
palladium_temp = data.palladium_temp;
main_pipe_pressure = data.main_pipe_pressure * 0.01;
aux_pipe_pressure = data.aux_pipe_pressure * 0.01;
//舱室环境参数
cabin_pressure1 = data.cabin_pressure1 * 0.01;
cabin_pressure2 = data.cabin_pressure2 * 0.01;
cabin_temp1 = data.cabin_temp1 * 0.01;
cabin_temp2 = data.cabin_temp2 * 0.01;
cabin_humidity1 = data.cabin_humidity1 * 0.01;
cabin_humidity2 = data.cabin_humidity2 * 0.01;
//火焰探测器
flame_detector1 = data.flame_detector1;
flame_detector2 = data.flame_detector2;
//气体浓度
h2_concentration1 = data.h2_concentration1 * 0.01;
h2_concentration2 = data.h2_concentration2 * 0.01;
h2_concentration3 = data.h2_concentration3 * 0.01;
o2_concentration1 = data.o2_concentration1 * 0.01;
o2_concentration2 = data.o2_concentration2 * 0.01;
ch3oh_concentration1 = data.ch3oh_concentration1 * 0.01;
ch3oh_concentration2 = data.ch3oh_concentration2 * 0.01;
//保留字段
for(int i=0; i<10; i++) {
reserved1[i] = data.reserved1[i];
}
//仪表舱参数
cabin_ox_concentration = data.cabin_ox_concentration * 0.1;
cabin_temperature = static_cast<int16_t>(data.cabin_temperature) * 0.1;
cabin_humidity = data.cabin_humidity * 0.1;
cabin_pressure = data.cabin_pressure * 0.2;
//动力舱参数
power_cabin_ox_concentration = data.power_cabin_ox_concentration * 0.1;
power_cabin_temperature = static_cast<int16_t>(data.power_cabin_temperature) * 0.1;
power_cabin_humidity = data.power_cabin_humidity * 0.1;
power_cabin_pressure = data.power_cabin_pressure * 0.2;
//电池报警标志
for(int i=0; i<6; i++) {
dyn_alarm_flag[i] = data.dyn_alarm_flag[i];
ins_alarm_flag[i] = data.ins_alarm_flag[i];
}
//继电器状态
ins_relay_status1 = data.ins_relay_status1;
ins_relay_status2 = data.ins_relay_status2;
dyn_relay_status1 = data.dyn_relay_status1;
dyn_relay_status2 = data.dyn_relay_status2;
//继电器状态
ins_pos_relay_status = (data.ins_relay_status1 ) & 0x0F; // 取高4位作为正极继电器状态
ins_charge_relay_status = ( data.ins_relay_status1 >> 4)& 0x0F; // 取低4位作为充电继电器状态
ins_precharge_relay_status = (data.ins_relay_status2 ) & 0x0F; // 取高4位作为预充继电器状态
ins_neg_relay_status = (data.ins_relay_status2 >> 4) & 0x0F; // 取低4位作为负极继电器状态
dyn_pos_relay_status = (data.dyn_relay_status1 ) & 0x0F; // 取高4位作为正极继电器状态
dyn_charge_relay_status = (data.dyn_relay_status1 >> 4) & 0x0F; // 取低4位作为充电继电器状态
dyn_precharge_relay_status = (data.dyn_relay_status2) & 0x0F; // 取高4位作为预充继电器状态
dyn_neg_relay_status = (data.dyn_relay_status2 >> 4) & 0x0F; // 取低4位作为负极继电器状态
//电池功率参数
ins_max_discharge_power = data.ins_max_discharge_power * 0.05;
dyn_max_discharge_power = data.dyn_max_discharge_power * 0.05;
//电池SOC
ins_soc = static_cast<int>(data.ins_soc);
dyn_soc = static_cast<int>(data.dyn_soc);
//电池能量
ins_total_energy = data.ins_total_energy * 0.1;
dyn_total_energy = data.dyn_total_energy * 0.1;
//电池输入功率
ins_power_input = data.ins_power_input ;
dyn_power_input = data.dyn_power_input ;
//电池充放电状态
ins_charge_status = data.ins_charge_status;
dyn_charge_status = data.dyn_charge_status;
//电池电压电流
ins_voltage_link = data.ins_voltage_link * 0.1;
ins_voltage_pack = data.ins_voltage_pack * 0.1;
ins_current = static_cast<int16_t>(data.ins_current) * 0.05;
ins_resistance_pos = data.ins_resistance_pos;
ins_resistance_neg = data.ins_resistance_neg;
dyn_voltage_link = data.dyn_voltage_link * 0.1;
dyn_voltage_pack = data.dyn_voltage_pack * 0.1;
dyn_current = static_cast<int16_t>(data.dyn_current) * 0.05;
dyn_resistance_pos = data.dyn_resistance_pos;
dyn_resistance_neg = data.dyn_resistance_neg;
//紧急状态
ins_emergency_status = data.ins_emergency_status;
dyn_emergency_status = data.dyn_emergency_status;
//保留字段
for(int i=0; i<2; i++) {
reserved2[i] = data.reserved2[i];
}
//SOC门限值
ins_soc_threshold1 = data.ins_soc_threshold1;
ins_soc_threshold2 = data.ins_soc_threshold2;
ins_soc_threshold3 = data.ins_soc_threshold3;
//功率限制值
ins_power_limit1 = data.ins_power_limit1;
ins_power_limit2 = data.ins_power_limit2;
//设备在线状态
device_online_flag1 = data.device_online_flag1;
device_online_flag2 = data.device_online_flag2;
//更新设备在线状态
device_online_status.ins_online_state = (data.device_online_flag1 >> 0) & 0xFF; // byte0:仪表锂电在线标志位
device_online_status.dyn_online_state = (data.device_online_flag1 >> 8) & 0xFF; // byte1:动力锂电在线标志位
device_online_status.fuel_online_state = (data.device_online_flag1 >> 16) & 0xFF; // byte2:燃电锂电在线标志位
device_online_status.high_voltage_online_state = (data.device_online_flag1 >> 24) & 0xFF; // byte3:高压配电板在线标志位
device_online_status.low_voltage_online_state = (data.device_online_flag2 >> 0) & 0xFF; // byte0:低压配电板在线标志位
device_online_status.composite_online_state = (data.device_online_flag2 >> 8) & 0xFF; // byte1:复合管控主机在线标志位
device_online_status.composite_backup_online_state = (data.device_online_flag2 >> 16) & 0xFF; // byte2:复合管控备机在线标志位
// 更新锂电池其他状态
dyn_water_leak_status = data.dyn_water_leak_status;
ins_water_leak_dcdc_status = data.ins_water_leak_dcdc_status;
dyn_charge_level = data.dyn_charge_level; //01H:1级(不限)02H:2级(限功率)03H:3级(关闭)
water_leak_status_from_insbat = ( data.ins_water_leak_dcdc_status >> 4) & 0x0F; // 00 正常,01 异常漏水
water_leak_status_from_dynbat = (data.dyn_water_leak_status >> 4) & 0x0F; // 00 正常,01 异常漏水
dcdc_status_from_insbat = (data.ins_water_leak_dcdc_status) & 0x0F; // 00 正常,01 故障
//更新漏水状态
if(water_leak_status_from_insbat == 0x01)
{
leakStatus[LEAKAGE_LI_BATTERY] = true;
}
else
{
leakStatus[LEAKAGE_LI_BATTERY] = false;
}
if(water_leak_status_from_dynbat == 0x01)
{
leakStatus[LEAKAGE_LI_BATTERY] = true;
}
else
{
leakStatus[LEAKAGE_LI_BATTERY] = false;
}
//应急电池
emergency_battery1_voltage = data.emergency_battery1_voltage * 0.1;
emergency_battery1_current = data.emergency_battery1_current * 0.05;
emergency_battery1_max_temp = data.emergency_battery1_max_temp * 0.1;
emergency_battery1_fault_word = data.emergency_battery1_fault_word;
emergency_battery2_voltage = data.emergency_battery2_voltage * 0.1;
emergency_battery2_current = data.emergency_battery2_current * 0.05;
emergency_battery2_max_temp = data.emergency_battery2_max_temp * 0.1;
emergency_battery2_fault_word = data.emergency_battery2_fault_word;
//心跳计数器
heartbeat = data.heartbeat;
}
std::set<unsigned int> disSysFaultCode;
mutable std::mutex faultCodeMutex;
void updateBreakerFault(unsigned char& breakerStatus, unsigned char rawStatus, unsigned int faultCode)
{
std::lock_guard<std::mutex> lock(faultCodeMutex);
unsigned char newStatus = rawStatus == 0x55 ? 1 : (rawStatus == 0xAA ? 0 : 2);
breakerStatus = newStatus; // 保证状态更新也是原子的
if(newStatus == 2) {
disSysFaultCode.insert(faultCode);
} else {
disSysFaultCode.erase(faultCode);
}
}
void updateBreakerFault(unsigned char& breakerStatus, unsigned char rawStatus)
{
std::lock_guard<std::mutex> lock(faultCodeMutex);
unsigned char newStatus = rawStatus == 0x55 ? 1 : (rawStatus == 0xAA ? 0 : 2);
breakerStatus = newStatus; // 保证状态更新也是原子的
}
void updateSystemData(disHighVolBusState data){
updateBreakerFault(power_bus_status.fuelCellCircuitBreaker, data.fuelCellCircuitBreaker, 1);
updateBreakerFault(power_bus_status.powerLithiumBatteryCircuitBreaker, data.powerLithiumBatteryCircuitBreaker, 2);
updateBreakerFault(power_bus_status.propulsionMotorCircuitBreaker, data.propulsionMotorCircuitBreaker, 3);
updateBreakerFault(power_bus_status.lithiumBatteryGroupInstrumentCircuitBreaker, data.lithiumBatteryGroupInstrumentCircuitBreaker, 4);
updateBreakerFault(power_bus_status.dcDc5ModuleCircuitBreaker, data.dcDc5ModuleCircuitBreaker, 5);
updateBreakerFault(power_bus_status.bowHighVoltageDistributionBoxCircuitBreaker, data.bowHighVoltageDistributionBoxCircuitBreaker, 6);
updateBreakerFault(power_bus_status.sternFTDevice45CircuitBreaker, data.sternFTDevice45CircuitBreaker, 7);
updateBreakerFault(power_bus_status.sternRudderSwitch1CircuitBreaker, data.sternRudderSwitch1CircuitBreaker, 8);
updateBreakerFault(power_bus_status.sternRudderSwitch2CircuitBreaker, data.sternRudderSwitch2CircuitBreaker, 9);
updateBreakerFault(power_bus_status.fbReservedCircuitBreaker, data.fbReservedCircuitBreaker);
updateBreakerFault(power_bus_status.tyzReservedCircuitBreaker, data.tyzReservedCircuitBreaker);
updateBreakerFault(power_bus_status.reservedCircuitBreaker, data.reservedCircuitBreaker);
//模块状态
power_bus_status.dcDcModuleStatus = data.dcDcFaultWord1;
power_bus_status.coolingSystemStatus = data.dcDcFaultWord2;
m_dcdcStatus.lowFaultWord = data.dcDcFaultWord1;
m_dcdcStatus.highFaultWord = data.dcDcFaultWord2;
//绝缘状态
power_bus_status.powerBusInsulationStatus = data.powerBusInsulationStatus == 0x55 ? 0 : 1;
// if(power_bus_status.powerBusInsulationStatus == 1) disSysFaultCode.insert(34); else disSysFaultCode.erase(34);
power_bus_status.aBusInsulationStatus = data.aBusInsulationStatus == 0x55 ? 0 : 1;
// if(power_bus_status.aBusInsulationStatus == 1) disSysFaultCode.insert(35); else disSysFaultCode.erase(35);
//电源状态
power_bus_status.meterPowerLossSignal = data.meterPowerLossSignal == 0x55 ? 0 : 1;
// if(power_bus_status.meterPowerLossSignal == 1) disSysFaultCode.insert(36); else disSysFaultCode.erase(36);
power_bus_status.emergencyPowerLossSignal = data.emergencyPowerLossSignal == 0x55 ? 0 : 1;
// if(power_bus_status.emergencyPowerLossSignal == 1) disSysFaultCode.insert(37); else disSysFaultCode.erase(37);
{
std::lock_guard<std::mutex> lock(faultCodeMutex);
if(power_bus_status.emergencyPowerLossSignal == 1) disSysFaultCode.insert(37); else disSysFaultCode.erase(37);
if(power_bus_status.meterPowerLossSignal == 1) disSysFaultCode.insert(36); else disSysFaultCode.erase(36);
if(power_bus_status.aBusInsulationStatus == 1) disSysFaultCode.insert(35); else disSysFaultCode.erase(35);
if(power_bus_status.powerBusInsulationStatus == 1) disSysFaultCode.insert(34); else disSysFaultCode.erase(34);
}
//温度
power_bus_status.dcDcTemperature = data.dcDcTemperature-40;
//电压电流参数
power_bus_status.powerBusVoltage = data.powerBusVoltage * 0.1;
power_bus_status.dcDc5ModuleCurrent = data.dcDc5ModuleCurrent * 0.1;
power_bus_status.powerBusCurrent = data.powerBusCurrent * 0.1;
power_bus_status.busbarAVoltage = data.busbarAVoltage * 0.1;
power_bus_status.propulsionMotorControlBoxCurrent = data.propulsionMotorControlBoxCurrent * 0.1;
power_bus_status.busbarACurrent = data.busbarACurrent * 0.1;
power_bus_status.lithiumBatteryGroupMeterCurrent = data.lithiumBatteryGroupMeterCurrent * 0.1;
power_bus_status.bowHighVoltageDistributionBoxCurrent = data.bowHighVoltageDistributionBoxCurrent * 0.1;
power_bus_status.sternFTDevice45Current = data.sternFTDevice45Current * 0.1;
power_bus_status.tyzReservedSwitchCurrent = data.tyzReservedSwitchCurrent * 0.1;
power_bus_status.sternRudderSwitch1Current = data.sternRudderSwitch1Current * 0.1;
power_bus_status.reservedCurrent1 = data.reservedCurrent1 * 0.1;
power_bus_status.sternRudderSwitch2Current = data.sternRudderSwitch2Current * 0.1;
power_bus_status.reservedCurrent2 = data.reservedCurrent2 * 0.1;
power_bus_status.fbReservedSwitchCurrent = data.fbReservedSwitchCurrent * 0.1;
power_bus_status.reservedCurrent3 = data.reservedCurrent3 * 0.1;
//冷却水压力
power_bus_status.coolWaterPressure = data.coolWaterPressure * 0.1;
};
void updateSystemData(disHighAVolBusState data){
//断路器状态 (0x55 1 0xAA 0 0x5A 2)
updateBreakerFault(power_a_bus_status.bowFTDevice123CircuitBreaker, data.bowFTDevice123CircuitBreaker, 13);
updateBreakerFault(power_a_bus_status.actuatorCircuitBreaker, data.actuatorCircuitBreaker, 14);
updateBreakerFault(power_a_bus_status.mastSteeringGearControlBoxCircuitBreaker, data.mastSteeringGearControlBoxCircuitBreaker, 15);
updateBreakerFault(power_a_bus_status.xczCircuitBreaker, data.xczCircuitBreaker, 16);
updateBreakerFault(power_a_bus_status.bowRudderControlBoxCircuitBreaker, data.bowRudderControlBoxCircuitBreaker, 17);
updateBreakerFault(power_a_bus_status.openWaterCoverStartCylinderCircuitBreaker, data.openWaterCoverStartCylinderCircuitBreaker, 18);
//电源状态
power_a_bus_status.instrumentPowerFailureSignal = data.instrumentPowerFailureSignal == 0x55 ? 0 : 1;
// if(power_a_bus_status.instrumentPowerFailureSignal == 1) disSysFaultCode.insert(38); else disSysFaultCode.erase(38);
power_a_bus_status.emergencyPowerFailureSignal = data.emergencyPowerFailureSignal == 0x55 ? 0 : 1;
// if(power_a_bus_status.emergencyPowerFailureSignal == 1) disSysFaultCode.insert(39); else disSysFaultCode.erase(39);
{
std::lock_guard<std::mutex> lock(faultCodeMutex);
if(power_a_bus_status.emergencyPowerFailureSignal == 1) disSysFaultCode.insert(39); else disSysFaultCode.erase(39);
if(power_a_bus_status.instrumentPowerFailureSignal == 1) disSysFaultCode.insert(38); else disSysFaultCode.erase(38);
}
//浸水报警
power_a_bus_status.waterIngressionAlarm = data.waterIngressionAlarm == 0x55 ? 0 : 1;
//更新漏水状态
if(power_a_bus_status.waterIngressionAlarm == 1)
{
leakStatus[LEAKAGE_BOW_HIGH_VOLTAGE] = true;
}
else
{
leakStatus[LEAKAGE_BOW_HIGH_VOLTAGE] = false;
}
//电压电流参数
power_a_bus_status.busbarBVoltage = data.busbarBVoltage * 0.1;
power_a_bus_status.busbarBCurrent = data.busbarBCurrent * 0.1;
power_a_bus_status.bowFTDevice123Current = data.bowFTDevice123Current * 0.1;
power_a_bus_status.actuatorCurrent = data.actuatorCurrent * 0.1;
power_a_bus_status.mastSteeringGearControlBoxCurrent = data.mastSteeringGearControlBoxCurrent * 0.1;
power_a_bus_status.xczCurrent = data.xczCurrent * 0.1;
power_a_bus_status.bowRudderControlBoxCurrent = data.bowRudderControlBoxCurrent * 0.1;
power_a_bus_status.openWaterCoverStartCylinderCurrent = data.openWaterCoverStartCylinderCurrent * 0.1;
};
void updateSystemData(disLowMainBusState data){
//断路器状态 (0x55 1 0xAA 0 0x5A 2)
updateBreakerFault(instrument_main_bus_status.lithiumBatteryGroupInstrumentCircuitBreaker, data.lithiumBatteryGroupInstrumentCircuitBreaker, 19);
updateBreakerFault(instrument_main_bus_status.bowLowVoltageDistributionBoxCircuitBreaker,data.bowLowVoltageDistributionBoxCircuitBreaker, 20);
updateBreakerFault(instrument_main_bus_status.unit4InstrumentDC48VCircuitBreaker,data.unit4InstrumentDC48VCircuitBreaker, 21);
updateBreakerFault(instrument_main_bus_status.dcC1DCDistributionPanelCircuitBreaker, data.dcC1DCDistributionPanelCircuitBreaker, 22);
updateBreakerFault(instrument_main_bus_status.reservedCircuitBreaker1, data.reservedCircuitBreaker1);
updateBreakerFault(instrument_main_bus_status.reservedCircuitBreaker2, data.reservedCircuitBreaker2);
updateBreakerFault(instrument_main_bus_status.emergencyLithiumBatteryGroup2CircuitBreaker, data.emergencyLithiumBatteryGroup2CircuitBreaker, 25);
//电源状态
instrument_main_bus_status.instrumentPowerFailureSignal = data.instrumentPowerFailureSignal == 0x55 ? 0 : 1;
// if(instrument_main_bus_status.instrumentPowerFailureSignal == 1) disSysFaultCode.insert(40); else disSysFaultCode.erase(41);
instrument_main_bus_status.emergencyPowerFailureSignal = data.emergencyPowerFailureSignal == 0x55 ? 0 : 1;
// if(instrument_main_bus_status.emergencyPowerFailureSignal == 1) disSysFaultCode.insert(41); else disSysFaultCode.erase(42);
//绝缘状态
instrument_main_bus_status.instrumentBusbarInsulationLow = data.instrumentBusbarInsulationLow == 0x55 ? 0 : 1;
// if(instrument_main_bus_status.instrumentBusbarInsulationLow == 1) disSysFaultCode.insert(42); else disSysFaultCode.erase(43);
{
std::lock_guard<std::mutex> lock(faultCodeMutex);
if(instrument_main_bus_status.instrumentPowerFailureSignal == 1) disSysFaultCode.insert(41); else disSysFaultCode.erase(41);
if(instrument_main_bus_status.emergencyPowerFailureSignal == 1) disSysFaultCode.insert(42); else disSysFaultCode.erase(42);
if(instrument_main_bus_status.instrumentBusbarInsulationLow == 1) disSysFaultCode.insert(43); else disSysFaultCode.erase(43);
}
//电压电流参数
instrument_main_bus_status.instrumentBusbarVoltage = data.instrumentBusbarVoltage * 0.1;
instrument_main_bus_status.bowLowVoltageDistributionBoxCurrent = data.bowLowVoltageDistributionBoxCurrent * 0.1;
instrument_main_bus_status.dcC1InstrumentDC48VCurrent = data.dcC1InstrumentDC48VCurrent * 0.1;
instrument_main_bus_status.reservedCurrent1 = data.reservedCurrent1 * 0.1;
instrument_main_bus_status.emergencyLithiumBatteryGroup2Current = data.emergencyLithiumBatteryGroup2Current * 0.1;
instrument_main_bus_status.lithiumBatteryGroupInstrumentCurrent = data.lithiumBatteryGroupInstrumentCurrent * 0.1;
instrument_main_bus_status.unit4InstrumentDC48VCurrent = data.unit4InstrumentDC48VCurrent * 0.1;
instrument_main_bus_status.reservedCurrent2 = data.reservedCurrent2 * 0.1;
instrument_main_bus_status.emergency2BusbarVoltage = data.emergency2BusbarVoltage * 0.1;
instrument_main_bus_status.compositeEnergyManagementSystemEmergencyDC48VCurrent = data.compositeEnergyManagementSystemEmergencyDC48VCurrent * 0.1;
instrument_main_bus_status.fuelCellSecuritySystemEmergencyDC48VCurrent = data.fuelCellSecuritySystemEmergencyDC48VCurrent * 0.1;
instrument_main_bus_status.plcControlPowerCurrent = data.plcControlPowerCurrent * 0.1;
}
void updateSystemData(disLowBusState data){
//断路器状态 (0x55 1 0xAA 0 0x5A 2)
updateBreakerFault(instrument_bus_status.unit1CircuitBreaker, data.unit1CircuitBreaker, 26);
updateBreakerFault(instrument_bus_status.unit2CircuitBreaker, data.unit2CircuitBreaker, 27);
updateBreakerFault(instrument_bus_status.unit3CircuitBreaker, data.unit3CircuitBreaker, 28);
updateBreakerFault(instrument_bus_status.unit5CircuitBreaker, data.unit5CircuitBreaker, 29);
updateBreakerFault(instrument_bus_status.bowPZDeviceCircuitBreaker, data.bowPZDeviceCircuitBreaker);
updateBreakerFault(instrument_bus_status.reservedCircuitBreaker1, data.reservedCircuitBreaker1);
updateBreakerFault(instrument_bus_status.reservedCircuitBreaker2, data.reservedCircuitBreaker2);
updateBreakerFault(instrument_bus_status.emergencyLithiumBatteryGroup1CircuitBreaker, data.emergencyLithiumBatteryGroup1CircuitBreaker, 33);
//电源状态
instrument_bus_status.powerFailureSignal = data.powerFailureSignal == 0x55 ? 0 : 1;
// if(instrument_bus_status.powerFailureSignal == 1) disSysFaultCode.insert(44); else disSysFaultCode.erase(44);
instrument_bus_status.emergencyPowerFailureSignal = data.emergencyPowerFailureSignal == 0x55 ? 0 : 1;
// if(instrument_bus_status.emergencyPowerFailureSignal == 1) disSysFaultCode.insert(45); else disSysFaultCode.erase(45);
{
std::lock_guard<std::mutex> lock(faultCodeMutex);
if(instrument_bus_status.emergencyPowerFailureSignal == 1) disSysFaultCode.insert(45); else disSysFaultCode.erase(45);
if(instrument_bus_status.powerFailureSignal == 1) disSysFaultCode.insert(44); else disSysFaultCode.erase(44);
}
//浸水报警
instrument_bus_status.waterIngressionAlarm = data.waterIngressionAlarm == 0x55 ? 0 : 1;
//更新漏水状态
if(instrument_bus_status.waterIngressionAlarm == 1)
{
leakStatus[LEAKAGE_BOW_LOW_VOLTAGE] = true;
}
else
{
leakStatus[LEAKAGE_BOW_LOW_VOLTAGE] = false;
}
//电压电流参数
instrument_bus_status.instrumentBusbarVoltage = data.instrumentBusbarVoltage * 0.1;
instrument_bus_status.instrumentBusbarCurrent = data.instrumentBusbarCurrent * 0.1;
instrument_bus_status.unit1Current = data.unit1Current * 0.1;
instrument_bus_status.unit2Current = data.unit2Current * 0.1;
instrument_bus_status.unit3Current = data.unit3Current * 0.1;
instrument_bus_status.unit5Current = data.unit5Current * 0.1;
instrument_bus_status.bowPZDeviceCurrent = data.bowPZDeviceCurrent * 0.1;
instrument_bus_status.emergencyLithiumBatteryGroup1Current = data.emergencyLithiumBatteryGroup1Current * 0.1;
instrument_bus_status.emergency1BusbarVoltage = data.emergency1BusbarVoltage * 0.1;
}
};
#endif
+139
View File
@@ -0,0 +1,139 @@
#ifndef CCUUDPMSG__H
#define CCUUDPMSG__H
#include "../pmSysvariable.h"
#define CCU_UDPMSG_START1 0x20
#define CCU_UDPMSG_START2 0x20
#define DIS_MSG_HEAD1 0x40
#define DIS_MSG_HEAD2 0x40
#define CCU_CMD_ID 0x0040
#define CCU_SET_PARM_ID 0x0041
#define CCU_STATE_FB_ID 0x0051
#define CCU_SET_PARM_FB_ID 0x0040
#define DIS_HVBUS_FB_ID 0x0005
#define DIS_HVBUSA_FB_ID 0x0006
#define DIS_HVBUSB_FB_ID 0x0007
#define DIS_LVBUS_FB_ID 0x0008
#define DIS_HVBUS_CMD_ID 0x0001
#define DIS_HVBUSA_CMD_ID 0x0002
#define DIS_HVBUSB_CMD_ID 0x0003
#define DIS_LVBUS_CMD_ID 0x0004
#define DIS_BREAKER_ON 0x55
#define DIS_BREAKER_OFF 0xAA
#define DIS_FAULTOFF 0x5A
typedef unsigned int Checksum;
typedef unsigned char cChecksum;
#pragma pack (1)
typedef struct {
unsigned char start1;
unsigned char start2;
unsigned short id;
unsigned short length;
} m_header;
typedef struct {
unsigned short year;
unsigned char month;
unsigned char day;
unsigned char hour;
unsigned char minute;
unsigned char second;
unsigned char milliseconds; //每10毫秒
} m_date;
// 复合管控器操作指令
typedef struct {
m_header header;
m_date date;
ccuColCmd cmd;
Checksum checkCode;
} msg_CcuColCmdMsg;
// 复合管控器参数设定指令
typedef struct {
m_header header;
ccuSetParmCmd cmd;
Checksum checkCode;
} msg_CcuSetParmMsg;
// 配电指令
typedef struct
{
m_header header;
disHighVolBusCmd data;
cChecksum checkCode;
}msg_disHVBCmd;
typedef struct
{
m_header header;
disHighAVolBusCmd data;
cChecksum checkCode;
}msg_disHVBACmd;
typedef struct msg_disHVBBCmd
{
m_header header;
disHighBVolBusCmd data;
cChecksum checkCode;
}msg_disLVMBCmd;
typedef struct
{
m_header header;
disLowBusCmd data;
cChecksum checkCode;
}msg_disLVBCmd;
// 复合管控参数设定反馈指令
typedef struct {
m_header header;
unsigned char flag;
unsigned char failureCode;
Checksum checkCode;
} msg_CcuSetParmFbMsg;
// 复合管控状态反馈
typedef struct {
m_header header;
ccuState data;
Checksum checkCode;
} msg_CcuStateFbMsg;
//高压母线配电反馈
typedef struct {
m_header header;
disHighVolBusState data;
cChecksum checkCode;
} msg_disHighVolBusFbMsg;
// 高压母线A配电反馈
typedef struct {
m_header header;
disHighAVolBusState data;
cChecksum checkCode;
} msg_disHighAVolBusFbMsg;
// 仪表母线配电反馈
typedef struct {
m_header header;
disLowMainBusState data;
cChecksum checkCode;
} msg_disLowMainBusFbMsg;
//仪表汇流排配电反馈
typedef struct {
m_header header;
disLowBusState data;
cChecksum checkCode;
} msg_disLowBusFbMsg;
#pragma pack ()
#endif
@@ -51,7 +51,8 @@ bool udpComm::getMsgId(char *m,unsigned short &id)
return true;
}
else
sError.push_back("Msg Header errar");
// sError.push_back("Msg Header errar");
// LOG_F(ERROR, "Msg Header errar start1: %d, start2: %d", h.start1, h.start2);
return false;
}
bool udpComm::getMsgFromBuff(char *m, msg_CcuStateFbMsg &s) {
@@ -92,6 +93,7 @@ bool udpComm::getMsgFromBuff(char *m, msg_disHighVolBusFbMsg &s)
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disHighVolBusFbMsg), sizeof(cChecksum)) & 0xFF;
if (sum != p->checkCode) {
sError.push_back("DisSys HVBus Msg Check error");
LOG_F(ERROR, "DisSys HVBus Msg Check error sum: %d, source checkCode: %d", sum, p->checkCode);
return false;
}
s = *p;
@@ -107,19 +109,21 @@ bool udpComm::getMsgFromBuff(char *m, msg_disHighAVolBusFbMsg &s)
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disHighAVolBusFbMsg), sizeof(cChecksum)) & 0xFF;
if (sum!= p->checkCode) {
sError.push_back("DisSys HVABus Msg Check error");
LOG_F(ERROR, "DisSys HVABus Msg Check error sum: %d, source checkCode: %d", sum, p->checkCode);
return false;
}
s = *p;
return true;
}
bool udpComm::getMsgFromBuff(char *m, msg_disHighBVolBusFbMsg &s)
bool udpComm::getMsgFromBuff(char *m, msg_disLowMainBusFbMsg &s)
{
cChecksum sum;
msg_disHighBVolBusFbMsg *p;
p = reinterpret_cast<msg_disHighBVolBusFbMsg *>(m);
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disHighBVolBusFbMsg), sizeof(cChecksum)) & 0xFF;
msg_disLowMainBusFbMsg *p;
p = reinterpret_cast<msg_disLowMainBusFbMsg *>(m);
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disLowMainBusFbMsg), sizeof(cChecksum)) & 0xFF;
if (sum!= p->checkCode) {
sError.push_back("DisSys HVBBus Msg Check error");
LOG_F(ERROR, "DisSys HVBBus Msg Check error sum: %d, source checkCode: %d", sum, p->checkCode);
return false;
}
s = *p;
@@ -134,6 +138,7 @@ bool udpComm::getMsgFromBuff(char *m, msg_disLowBusFbMsg &s)
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disLowBusFbMsg), sizeof(cChecksum)) & 0xFF;
if (sum!= p->checkCode) {
sError.push_back("DisSys LVBus Msg Check error");
LOG_F(ERROR, "DisSys LVBus Msg Check error sum: %d, source checkCode: %d", sum, p->checkCode);
return false;
}
s = *p;
@@ -144,7 +149,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
{
if(m==NULL)
{
sError.push_back("pushMsgToQueue faile,Msg is NULL");
// sError.push_back("pushMsgToQueue faile,Msg is NULL");
LOG_F(ERROR, "pushMsgToQueue faile,Msg is NULL m: %p", m);
return false;
}
@@ -155,7 +161,9 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
memcpy(header,Buff,sizeof(m_header));
if(!getMsgId(header,id))
{
sError.push_back("pushMsgToQueue faile,Msg ID error");
// sError.push_back("pushMsgToQueue faile,Msg ID error");
// LOG_F(INFO, "pushMsgToQueue faile,Msg ID error header: %p", header);
delete []header;
return false;
}
delete []header;
@@ -174,7 +182,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
else
{
sError.push_back("pushMsgToQueue faile,CcuState buffer is full");
// sError.push_back("pushMsgToQueue faile,CcuState buffer is full");
LOG_F(INFO, "pushMsgToQueue faile,CcuState buffer is full");
return false;
}
}
@@ -196,7 +205,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
else
{
sError.push_back("pushMsgToQueue faile,CcuSetParm buffer is full");
// sError.push_back("pushMsgToQueue faile,CcuSetParm buffer is full");
LOG_F(INFO, "pushMsgToQueue faile,CcuSetParm buffer is full");
return false;
}
}
@@ -218,7 +228,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
else
{
sError.push_back("pushMsgToQueue faile,DisSysHVBus buffer is full");
// sError.push_back("pushMsgToQueue faile,DisSysHVBus buffer is full");
LOG_F(INFO, "pushMsgToQueue faile,DisSysHVBus buffer is full");
return false;
}
}
@@ -240,7 +251,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
else
{
sError.push_back("pushMsgToQueue faile,DisSysHVABus buffer is full");
// sError.push_back("pushMsgToQueue faile,DisSysHVABus buffer is full");
LOG_F(INFO, "pushMsgToQueue faile,DisSysHVABus buffer is full");
return false;
}
}
@@ -252,7 +264,7 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
case DIS_HVBUSB_FB_ID: //DIS_HVBUSB_FB 0x0007
{
msg_disHighBVolBusFbMsg s;
msg_disLowMainBusFbMsg s;
if(getMsgFromBuff((char *)Buff,s))
{
if(m_qReceiveDisHighBVolBusBuffer.size()<QUENUE_SIZE)
@@ -262,7 +274,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
else
{
sError.push_back("pushMsgToQueue faile,DisSysHVBBus buffer is full");
// sError.push_back("pushMsgToQueue faile,DisSysHVBBus buffer is full");
LOG_F(INFO, "pushMsgToQueue faile,DisSysHVBBus buffer is full");
return false;
}
}
@@ -284,7 +297,8 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
}
else
{
sError.push_back("pushMsgToQueue faile,DisSysLVBus buffer is full");
// sError.push_back("pushMsgToQueue faile,DisSysLVBus buffer is full");
LOG_F(INFO, "pushMsgToQueue faile,DisSysLVBus buffer is full");
return false;
}
}
@@ -301,98 +315,127 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
bool udpComm::clearMsgQueue()
{
while(!m_qReceiveCcuStateBuffer.empty())
m_qReceiveCcuStateBuffer.pop();
{
std::lock_guard<std::mutex> lock(m_mutexCcuState);
while(!m_qReceiveCcuStateBuffer.empty())
m_qReceiveCcuStateBuffer.pop();
}
while(!m_qReceiveCcuSetParmBuffer.empty())
m_qReceiveCcuSetParmBuffer.pop();
{
std::lock_guard<std::mutex> lock(m_mutexCcuSetParm);
while(!m_qReceiveCcuSetParmBuffer.empty())
m_qReceiveCcuSetParmBuffer.pop();
}
while(!m_qReceiveDisHighVolBusBuffer.empty())
m_qReceiveDisHighVolBusBuffer.pop();
{
std::lock_guard<std::mutex> lock(m_mutexDisHighVolBus);
while(!m_qReceiveDisHighVolBusBuffer.empty())
m_qReceiveDisHighVolBusBuffer.pop();
}
while(!m_qReceiveDisHighAVolBusBuffer.empty())
m_qReceiveDisHighAVolBusBuffer.pop();
{
std::lock_guard<std::mutex> lock(m_mutexDisHighAVolBus);
while(!m_qReceiveDisHighAVolBusBuffer.empty())
m_qReceiveDisHighAVolBusBuffer.pop();
}
while(!m_qReceiveDisHighBVolBusBuffer.empty())
m_qReceiveDisHighBVolBusBuffer.pop();
while(!m_qReceiveDisLowBusBuffer.empty())
m_qReceiveDisLowBusBuffer.pop();
return true;
{
std::lock_guard<std::mutex> lock(m_mutexDisHighBVolBus);
while(!m_qReceiveDisHighBVolBusBuffer.empty())
m_qReceiveDisHighBVolBusBuffer.pop();
}
{
std::lock_guard<std::mutex> lock(m_mutexDisLowBus);
while(!m_qReceiveDisLowBusBuffer.empty())
m_qReceiveDisLowBusBuffer.pop();
}
return true;
}
bool udpComm::popMsgFormQueue(double &time,msg_CcuStateFbMsg &m)
{
if(m_qReceiveCcuStateBuffer.empty())
return false;
time = m_qReceiveCcuStateBuffer.front().first;
m = m_qReceiveCcuStateBuffer.front().second;
m_qReceiveCcuStateBuffer.pop();
return true;
std::lock_guard<std::mutex> lock(m_mutexCcuState);
if(m_qReceiveCcuStateBuffer.empty())
return false;
time = m_qReceiveCcuStateBuffer.front().first;
m = m_qReceiveCcuStateBuffer.front().second;
m_qReceiveCcuStateBuffer.pop();
return true;
}
bool udpComm::popMsgFormQueue(double &time,msg_CcuSetParmFbMsg &m)
{
if(m_qReceiveCcuSetParmBuffer.empty())
return false;
time = m_qReceiveCcuSetParmBuffer.front().first;
m = m_qReceiveCcuSetParmBuffer.front().second;
m_qReceiveCcuSetParmBuffer.pop();
return true;
std::lock_guard<std::mutex> lock(m_mutexCcuSetParm);
if(m_qReceiveCcuSetParmBuffer.empty())
return false;
time = m_qReceiveCcuSetParmBuffer.front().first;
m = m_qReceiveCcuSetParmBuffer.front().second;
m_qReceiveCcuSetParmBuffer.pop();
return true;
}
bool udpComm::popMsgFormQueue(double &time,msg_disHighVolBusFbMsg &m)
{
if(m_qReceiveDisHighVolBusBuffer.empty())
return false;
time = m_qReceiveDisHighVolBusBuffer.front().first;
m = m_qReceiveDisHighVolBusBuffer.front().second;
m_qReceiveDisHighVolBusBuffer.pop();
return true;
std::lock_guard<std::mutex> lock(m_mutexDisHighVolBus);
if(m_qReceiveDisHighVolBusBuffer.empty())
return false;
time = m_qReceiveDisHighVolBusBuffer.front().first;
m = m_qReceiveDisHighVolBusBuffer.front().second;
m_qReceiveDisHighVolBusBuffer.pop();
return true;
}
bool udpComm::popMsgFormQueue(double &time,msg_disHighAVolBusFbMsg &m)
{
if(m_qReceiveDisHighAVolBusBuffer.empty())
return false;
time = m_qReceiveDisHighAVolBusBuffer.front().first;
m = m_qReceiveDisHighAVolBusBuffer.front().second;
m_qReceiveDisHighAVolBusBuffer.pop();
return true;
std::lock_guard<std::mutex> lock(m_mutexDisHighAVolBus);
if(m_qReceiveDisHighAVolBusBuffer.empty())
return false;
time = m_qReceiveDisHighAVolBusBuffer.front().first;
m = m_qReceiveDisHighAVolBusBuffer.front().second;
m_qReceiveDisHighAVolBusBuffer.pop();
return true;
}
bool udpComm::popMsgFormQueue(double &time,msg_disHighBVolBusFbMsg &m)
bool udpComm::popMsgFormQueue(double &time,msg_disLowMainBusFbMsg &m)
{
if(m_qReceiveDisHighBVolBusBuffer.empty())
return false;
time = m_qReceiveDisHighBVolBusBuffer.front().first;
m = m_qReceiveDisHighBVolBusBuffer.front().second;
m_qReceiveDisHighBVolBusBuffer.pop();
return true;
std::lock_guard<std::mutex> lock(m_mutexDisHighBVolBus);
if(m_qReceiveDisHighBVolBusBuffer.empty())
return false;
time = m_qReceiveDisHighBVolBusBuffer.front().first;
m = m_qReceiveDisHighBVolBusBuffer.front().second;
m_qReceiveDisHighBVolBusBuffer.pop();
return true;
}
bool udpComm::popMsgFormQueue(double &time,msg_disLowBusFbMsg &m)
{
if(m_qReceiveDisLowBusBuffer.empty())
return false;
time = m_qReceiveDisLowBusBuffer.front().first;
m = m_qReceiveDisLowBusBuffer.front().second;
m_qReceiveDisLowBusBuffer.pop();
return true;
std::lock_guard<std::mutex> lock(m_mutexDisLowBus);
if(m_qReceiveDisLowBusBuffer.empty())
return false;
time = m_qReceiveDisLowBusBuffer.front().first;
m = m_qReceiveDisLowBusBuffer.front().second;
m_qReceiveDisLowBusBuffer.pop();
return true;
}
bool udpComm::sendDisSysCmd(const disHighVolBusCmd cmd)
{
unsigned char* msgBuf;
Checksum cc;
cChecksum cc;
msg_disHVBCmd* msg = new msg_disHVBCmd;
msg->header.id = DIS_HVBUS_CMD_ID;
msg->header.start1 = DIS_MSG_HEAD1;
msg->header.start2 = DIS_MSG_HEAD2;
msg->header.length = sizeof(disHighVolBusCmd);
//TODO : 阈字节长度固定了,后续会修改
msg->header.length = 18;
// msg->header.length = sizeof(disHighVolBusCmd);
msg->data = cmd;
msgBuf = reinterpret_cast<unsigned char *>(msg);
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBCmd));
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
// std::cout << (int)sizeof(msg_disHVBCmd) << endl;
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBCmd),sizeof(cChecksum));
msg->checkCode = cc;
try
{
sendMsg(msgBuf,sizeof(msg_disHVBCmd));
@@ -408,16 +451,18 @@ bool udpComm::sendDisSysCmd(const disHighVolBusCmd cmd)
bool udpComm::sendDisSysCmd(const disHighAVolBusCmd cmd)
{
unsigned char* msgBuf;
Checksum cc;
cChecksum cc;
msg_disHVBACmd* msg = new msg_disHVBACmd;
msg->header.id = DIS_HVBUSA_CMD_ID;
msg->header.start1 = DIS_MSG_HEAD1;
msg->header.start2 = DIS_MSG_HEAD2;
msg->header.length = sizeof(disHighAVolBusCmd);
//TODO : 阈字节长度固定了,后续会修改
msg->header.length = 6;
// msg->header.length = sizeof(disHighAVolBusCmd);
msg->data = cmd;
msgBuf = reinterpret_cast<unsigned char *>(msg);
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBACmd));
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBACmd),sizeof(cChecksum));
msg->checkCode = cc;
try
{
sendMsg(msgBuf,sizeof(msg_disHVBACmd));
@@ -433,16 +478,18 @@ bool udpComm::sendDisSysCmd(const disHighAVolBusCmd cmd)
bool udpComm::sendDisSysCmd(const disHighBVolBusCmd cmd)
{
unsigned char* msgBuf;
Checksum cc;
cChecksum cc;
msg_disHVBBCmd* msg = new msg_disHVBBCmd;
msg->header.id = DIS_HVBUSB_CMD_ID;
msg->header.start1 = DIS_MSG_HEAD1;
msg->header.start2 = DIS_MSG_HEAD2;
msg->header.length = sizeof(disHighBVolBusCmd);
//TODO : 阈字节长度固定了,后续会修改
msg->header.length = 8;
// msg->header.length = sizeof(disHighBVolBusCmd);
msg->data = cmd;
msgBuf = reinterpret_cast<unsigned char *>(msg);
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBBCmd));
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBBCmd),sizeof(cChecksum));
msg->checkCode = cc;
try
{
// cout << "=========" <<(int)sizeof(msg_disHVBBCmd) << endl;
@@ -459,16 +506,20 @@ bool udpComm::sendDisSysCmd(const disHighBVolBusCmd cmd)
bool udpComm::sendDisSysCmd(const disLowBusCmd cmd)
{
unsigned char* msgBuf;
Checksum cc;
cChecksum cc;
msg_disLVBCmd* msg = new msg_disLVBCmd;
msg->header.id = DIS_LVBUS_CMD_ID;
msg->header.start1 = DIS_MSG_HEAD1;
msg->header.start2 = DIS_MSG_HEAD2;
msg->header.length = sizeof(disLowBusCmd);
//TODO : 阈字节长度固定了,后续会修改
msg->header.length = 8;
// msg->header.length = sizeof(disLowBusCmd);
msg->data = cmd;
msgBuf = reinterpret_cast<unsigned char *>(msg);
cc = calculateChecksum(msgBuf,sizeof(msg_disLVBCmd));
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
cc = calculateChecksum(msgBuf,sizeof(msg_disLVBCmd),sizeof(cChecksum));
// msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
msg->checkCode = cc;
cout << "cc======disLowBusCmd=============================" << (int) msg->checkCode << endl;
try
{
sendMsg(msgBuf,sizeof(msg_disLVBCmd));
@@ -485,32 +536,39 @@ bool udpComm::sendCcuColCmd(const ccuColCmd cmd)
{
unsigned char* msgBuf;
Checksum cc;
msg_CcuColCmdMsg* msg = new msg_CcuColCmdMsg;
msg_CcuColCmdMsg* msg = new msg_CcuColCmdMsg();
memset(msg, 0, sizeof(msg_CcuColCmdMsg)); // 初始化所有字段为0
msg->header.id = CCU_CMD_ID;
msg->header.start1 = CCU_UDPMSG_START1;
msg->header.start2 = CCU_UDPMSG_START2;
msg->header.length = sizeof(ccuColCmd);
getDate(msg->date.year,msg->date.month,msg->date.day,msg->date.hour,msg->date.minute,msg->date.second,msg->date.milliseconds);
// 确保日期获取成功
if(!getDate(msg->date.year,msg->date.month,msg->date.day,
msg->date.hour,msg->date.minute,msg->date.second,msg->date.milliseconds)) {
LOG_F(ERROR, "Failed to get current date/time");
delete msg;
return false;
}
msg->cmd = cmd;
msgBuf = reinterpret_cast<unsigned char *>(msg);
cc = calculateChecksum(msgBuf,sizeof(msg_CcuColCmdMsg));
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
try
{
if(udpScoket == nullptr) {
throw std::runtime_error("UDP socket not initialized");
bool sendResult = false;
try {
sendResult = sendMsg(msgBuf,sizeof(msg_CcuColCmdMsg));
if (!sendResult) {
LOG_F(ERROR, "Failed to send CCU command");
}
if(ccuHost.empty() || ccuPort <= 0 || ccuPort > 65535) {
throw std::runtime_error("Invalid CCU address: " + ccuHost + ":" + std::to_string(ccuPort));
}
sendMsg(msgBuf,sizeof(msg_CcuColCmdMsg));
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
} catch (const std::exception& e) {
LOG_F(ERROR, "Exception in sendCcuColCmd: %s", e.what());
}
delete msg;
return true;
return sendResult;
}
bool udpComm::sendCcuSetParmCmd(const ccuSetParmCmd cmd)
{
@@ -566,4 +624,4 @@ bool udpComm::getDate(unsigned short &year, unsigned char &month, unsigned char
milliseconds = static_cast<unsigned char>(ms);
return true;
}
}
@@ -10,10 +10,11 @@
#include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h"
#include "MOOS/libMOOS/Comms/XPCUdpSocket.h"
#include <ctime>
#include <mutex>
#include <chrono>
#include <iostream>
#include <utility> // for std::pair
#include <utility>
#include "../logc/loguru.hpp"
using namespace std;
#define QUENUE_SIZE 100
@@ -32,14 +33,14 @@ public:
bool getMsgFromBuff(char *m, msg_CcuSetParmFbMsg &s);
bool getMsgFromBuff(char *m, msg_disHighVolBusFbMsg &s);
bool getMsgFromBuff(char *m, msg_disHighAVolBusFbMsg &s);
bool getMsgFromBuff(char *m, msg_disHighBVolBusFbMsg &s);
bool getMsgFromBuff(char *m, msg_disLowMainBusFbMsg &s);
bool getMsgFromBuff(char *m, msg_disLowBusFbMsg &s);
bool popMsgFormQueue(double &time,msg_CcuStateFbMsg &m);
bool popMsgFormQueue(double &time,msg_CcuSetParmFbMsg &m);
bool popMsgFormQueue(double &time,msg_disHighVolBusFbMsg &m);
bool popMsgFormQueue(double &time,msg_disHighAVolBusFbMsg &m);
bool popMsgFormQueue(double &time,msg_disHighBVolBusFbMsg &m);
bool popMsgFormQueue(double &time,msg_disLowMainBusFbMsg &m);
bool popMsgFormQueue(double &time,msg_disLowBusFbMsg &m);
bool sendCcuColCmd(const ccuColCmd cmd);
@@ -49,10 +50,31 @@ public:
bool sendDisSysCmd(const disHighAVolBusCmd cmd);
bool sendDisSysCmd(const disHighBVolBusCmd cmd);
bool sendDisSysCmd(const disLowBusCmd cmd);
bool sendMsg(const unsigned char* msg,unsigned int size){
// cout << "sendMsgTo" << ccuHost << ":" << ccuPort << endl;
udpScoket->iSendMessageTo((void*) msg, size, ccuPort, ccuHost);
return true;
bool sendMsg(const unsigned char* msg, unsigned int size) {
if (!udpScoket) {
LOG_F(ERROR, "UDP socket is null in sendMsg");
return false;
}
if (!msg || size == 0) {
LOG_F(ERROR, "Invalid message parameters in sendMsg");
return false;
}
if (ccuHost.empty() || ccuPort <= 0) {
LOG_F(ERROR, "Invalid CCU address: %s:%d", ccuHost.c_str(), ccuPort);
return false;
}
try {
udpScoket->iSendMessageTo((void*)msg, size, ccuPort, ccuHost);
return true;
} catch (const XPCException& e) {
LOG_F(ERROR, "XPCException in sendMsg");
} catch (const std::exception& e) {
LOG_F(ERROR, "Exception in sendMsg: %s", e.what());
} catch (...) {
LOG_F(ERROR, "Unknown exception in sendMsg");
}
return false;
}
bool getMsgId(char *m,unsigned short &id);
@@ -63,12 +85,19 @@ public:
std::vector<std::string> sError;
std::mutex m_mutexCcuState;
std::mutex m_mutexCcuSetParm;
std::mutex m_mutexDisHighVolBus;
std::mutex m_mutexDisHighAVolBus;
std::mutex m_mutexDisHighBVolBus;
std::mutex m_mutexDisLowBus;
// std::queue<msgWithTime> m_qReceiveCcuStateBuffer;
std::queue<std::pair<double,msg_CcuStateFbMsg>> m_qReceiveCcuStateBuffer;
std::queue<std::pair<double,msg_CcuSetParmFbMsg>> m_qReceiveCcuSetParmBuffer;
std::queue<std::pair<double,msg_disHighVolBusFbMsg>> m_qReceiveDisHighVolBusBuffer;
std::queue<std::pair<double,msg_disHighAVolBusFbMsg>> m_qReceiveDisHighAVolBusBuffer;
std::queue<std::pair<double,msg_disHighBVolBusFbMsg>> m_qReceiveDisHighBVolBusBuffer;
std::queue<std::pair<double,msg_disLowMainBusFbMsg>> m_qReceiveDisHighBVolBusBuffer;
std::queue<std::pair<double,msg_disLowBusFbMsg>> m_qReceiveDisLowBusBuffer;
private:
@@ -0,0 +1,60 @@
/* json 格式 XC阵控制软件→复合能源管控系统
{
"xcLowVoltageAdd_int32 " : XX //命令类型:“无命令”0,“申请仪表上电”1,“申请仪表断电”2;类型:int
"xcHighVoltageAdd_int32 " : XX, //命令类型:“无命令”0,“申请高压上电”1,“申请高压断电”2;类型:int
}
*/
#ifndef UDETECT_XCVOLTAGE_CMD_H
#define UDETECT_XCVOLTAGE_CMD_H
#include "../logc/loguru.hpp"
#include "json/json.h"
#include <string>
#include <memory>
class uDetect_xcVoltage_cmd
{
private:
/* data */
public:
uDetect_xcVoltage_cmd(){};
~uDetect_xcVoltage_cmd(){};
int xcLowVoltageAdd_int32;
int xcHighVoltageAdd_int32;
static std::string key;
std::string toJsonString()
{
Json::Value j;
j["xcLowVoltageAdd_int32"] = xcLowVoltageAdd_int32;
j["xcHighVoltageAdd_int32"] = xcHighVoltageAdd_int32;
Json::StreamWriterBuilder builder;
builder.settings_["indentation"] = "";
return Json::writeString(builder, j);
}
bool fromJsonString(std::string jsonString)
{
Json::CharReaderBuilder readerBuilder;
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
Json::Value j;
std::string errors;
LOG_F(INFO, "jsonString: %s", jsonString.c_str());
bool parsingSuccessful = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &j, &errors);
if (!parsingSuccessful) {
LOG_F(ERROR, "Failed to parse JSON: %s", errors.c_str());
return false;
}
if (j.isMember("xcLowVoltageAdd_int32") && j.isMember("xcHighVoltageAdd_int32")) {
xcLowVoltageAdd_int32 = j["xcLowVoltageAdd_int32"].asInt();
xcHighVoltageAdd_int32 = j["xcHighVoltageAdd_int32"].asInt();
return true;
}
LOG_F(ERROR, "JSON does not contain required fields");
return false;
}
};
#endif
@@ -0,0 +1,56 @@
/* json 格式 XC阵控制软件→复合能源管控系统
{
"zdpVoltageAdd_int32 " : XX //命令类型:“无命令”0,“申请仪表上电”1,“申请仪表断电”2;类型:int
}
*/
#ifndef UDETECT_ZDPVOLTAGE_CMD_H
#define UDETECT_ZDPVOLTAGE_CMD_H
#include "../logc/loguru.hpp"
#include "json/json.h"
#include <string>
#include <memory>
class uDetect_zdpVoltage_cmd
{
private:
/* data */
public:
uDetect_zdpVoltage_cmd(){};
~uDetect_zdpVoltage_cmd(){};
int zdpVoltageAdd_int32;
static std::string key;
std::string toJsonString()
{
Json::Value j;
j["zdpVoltageAdd_int32"] = zdpVoltageAdd_int32;
Json::StreamWriterBuilder builder;
builder.settings_["indentation"] = "";
return Json::writeString(builder, j);
}
bool fromJsonString(std::string jsonString)
{
Json::CharReaderBuilder readerBuilder;
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
Json::Value j;
std::string errors;
LOG_F(INFO, "jsonString: %s", jsonString.c_str());
bool parsingSuccessful = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &j, &errors);
if (!parsingSuccessful) {
LOG_F(ERROR, "Failed to parse JSON: %s", errors.c_str());
return false;
}
if (j.isMember("zdpVoltageAdd_int32")) {
zdpVoltageAdd_int32 = j["zdpVoltageAdd_int32"].asInt();
return true;
}
LOG_F(ERROR, "JSON does not contain required fields");
return false;
}
};
#endif
@@ -0,0 +1,52 @@
//决策消息
#ifndef UDEVICE_DEPTH_ST_H
#define UDEVICE_DEPTH_ST_H
#include <string>
#include "../logc/loguru.hpp"
#define DB_TO_PM_DEEPTH "uDevice_depth_st"
class uDevice_depthMsg
{
private:
public:
std::string key = "uDevice_depth_st";
uDevice_depthMsg(/* args */){};
~uDevice_depthMsg(){};
int getDepth(const std::string& msgkey, const std::string& msg){
if (msgkey != DB_TO_PM_DEEPTH)
{
LOG_F(WARNING, "消息类型错误 %s", msgkey.c_str());
return 0;
}
int deepth;
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(msg);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
std::cerr << "JSON解析失败: " << errs << std::endl;
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
return -1;
}
// 检查并读取深度数组
if (root.isMember("value_array_int32") && root["value_array_int32"].isArray()) {
const Json::Value& array = root["value_array_int32"];
if (array.size() >= 3) {
// 计算三个深度值的平均值
deepth = (array[0].asInt() + array[1].asInt() + array[2].asInt()) / 3;
} else {
LOG_F(WARNING, "深度数组元素不足3个");
return -1;
}
} else {
LOG_F(WARNING, "缺少或类型不匹配: value_array_int32");
return -1;
}
return deepth;
}
};
#endif
@@ -0,0 +1,531 @@
#ifndef UDEVICE_SECDISTSTATE_H
#define UDEVICE_SECDISTSTATE_H
#include <string>
#include <json/json.h>
#include "../driver.h"
#include "../logc/loguru.hpp"
#include <cstring>
class uDevice_secdistStateMsg
{
private:
/* data */
public:
uDevice_secdistStateMsg(){};
~uDevice_secdistStateMsg(){};
std::string key_fb = "uDevice_secdistState_st";
std::string key_cmd = "uPower_secdistState_cmd";
struct DeviceSecdistState
{
// UNIT1
u_int8_t bowCover1;
u_int8_t bowCover2;
u_int8_t bowCover3;
u_int8_t bowCover4;
u_int8_t bowCover5;
u_int8_t bowCover6;
u_int8_t singleBeamSonar1;
u_int8_t singleBeamSonar2;
u_int8_t singleBeamSonar3;
u_int8_t singleBeamSonar4;
u_int8_t singleBeamSonar5;
u_int8_t singleBeamSonar6;
u_int8_t forwardSonar;
u_int8_t depth3;
u_int8_t soundVeloc;
u_int8_t bowRudderServo;
u_int8_t bowRudderDeploy;
u_int8_t ctd1;
u_int8_t waterInject;
// UNIT2
u_int8_t sideSonar;
u_int8_t bowWaterInet1;
u_int8_t bowWaterInet2;
u_int8_t bowWaterInet3;
u_int8_t bowWaterInet4;
u_int8_t bowWaterInet5;
u_int8_t bowWaterInet6;
u_int8_t bowWaterInet7;
u_int8_t bowWaterInet8;
u_int8_t launchControler;
u_int8_t electSensor;
u_int8_t lowFreqSonar;
// UNIT3
u_int8_t buoyancyAdjust1;
u_int8_t buoyancyAdjust2;
u_int8_t buoyancyAdjust3;
u_int8_t USBL;
u_int8_t depth1;
u_int8_t commDev;
u_int8_t mastLiftingServo;
u_int8_t DVL;
u_int8_t ADCP;
u_int8_t inOutLetWater1;
u_int8_t inOutLetWater2;
// UNIT4
u_int8_t singleBeamSonar7;
u_int8_t singleBeamSonar8;
u_int8_t buoyage;
u_int8_t bowThrow;
u_int8_t depth2;
u_int8_t thruster;
u_int8_t dragSonar;
u_int8_t haulingMachine;
u_int8_t buoyancyAdjust4;
u_int8_t buoyancyAdjust5;
u_int8_t sternRudderServo1;
u_int8_t sternRudderServo2;
u_int8_t sternRudderServo3;
u_int8_t sternRudderServo4;
u_int8_t ctd2;
u_int8_t commDevStern;
u_int8_t inOutLetWater3;
// UNIT5
u_int8_t secINS;
u_int8_t photoSensor;
u_int8_t sternThrow;
u_int8_t mainINS;
} deviceSecdistState;
bool parseSecdistStateFromJson(DeviceSecdistState &state, const std::string &strJson){
Json::Value root;
Json::CharReaderBuilder readerBuilder;
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
std::string errors;
if(!reader->parse(strJson.c_str(), strJson.c_str() + strJson.length(), &root, &errors)){
LOG_F(ERROR, "Failed to parse JSON: %s", errors.c_str());
return false;
}
auto checkField = [&root](const std::string& field) -> bool {
if(!root.isMember(field) || !root[field].isUInt()) {
// std::cerr << "Missing or invalid field: " << field << std::endl;
// LOG_F(ERROR, "Missing or invalid field: %s", field.c_str());
return false;
}
return true;
};
bool ok = true;
// UNIT1
if(!checkField("bowCover1_uint8")) ok=false; state.bowCover1 = root["bowCover1_uint8"].asUInt();
if(!checkField("bowCover2_uint8")) ok=false; state.bowCover2 = root["bowCover2_uint8"].asUInt();
if(!checkField("bowCover3_uint8")) ok=false; state.bowCover3 = root["bowCover3_uint8"].asUInt();
if(!checkField("bowCover4_uint8")) ok=false; state.bowCover4 = root["bowCover4_uint8"].asUInt();
if(!checkField("bowCover5_uint8")) ok=false; state.bowCover5 = root["bowCover5_uint8"].asUInt();
if(!checkField("bowCover6_uint8")) ok=false; state.bowCover6 = root["bowCover6_uint8"].asUInt();
if(!checkField("singleBeamSonar1_uint8")) ok=false; state.singleBeamSonar1 = root["singleBeamSonar1_uint8"].asUInt();
if(!checkField("singleBeamSonar2_uint8")) ok=false; state.singleBeamSonar2 = root["singleBeamSonar2_uint8"].asUInt();
if(!checkField("singleBeamSonar3_uint8")) ok=false; state.singleBeamSonar3 = root["singleBeamSonar3_uint8"].asUInt();
if(!checkField("singleBeamSonar4_uint8")) ok=false; state.singleBeamSonar4 = root["singleBeamSonar4_uint8"].asUInt();
if(!checkField("singleBeamSonar5_uint8")) ok=false; state.singleBeamSonar5 = root["singleBeamSonar5_uint8"].asUInt();
if(!checkField("singleBeamSonar6_uint8")) ok=false; state.singleBeamSonar6 = root["singleBeamSonar6_uint8"].asUInt();
if(!checkField("forwardSonar_uint8")) ok=false; state.forwardSonar = root["forwardSonar_uint8"].asUInt();
if(!checkField("depth3_uint8")) ok=false; state.depth3 = root["depth3_uint8"].asUInt();
if(!checkField("soundVeloc_uint8")) ok=false; state.soundVeloc = root["soundVeloc_uint8"].asUInt();
if(!checkField("bowRudderServo_uint8")) ok=false; state.bowRudderServo = root["bowRudderServo_uint8"].asUInt();
if(!checkField("bowRudderDeploy_uint8")) ok=false; state.bowRudderDeploy = root["bowRudderDeploy_uint8"].asUInt();
if(!checkField("ctd1_uint8")) ok=false; state.ctd1 = root["ctd1_uint8"].asUInt();
if(!checkField("waterInject_uint8")) ok=false; state.waterInject = root["waterInject_uint8"].asUInt();
// UNIT2
if(!checkField("sideSonar_uint8")) ok=false; state.sideSonar = root["sideSonar_uint8"].asUInt();
if(!checkField("bowWaterInet1_uint8")) ok=false; state.bowWaterInet1 = root["bowWaterInet1_uint8"].asUInt();
if(!checkField("bowWaterInet2_uint8")) ok=false; state.bowWaterInet2 = root["bowWaterInet2_uint8"].asUInt();
if(!checkField("bowWaterInet3_uint8")) ok=false; state.bowWaterInet3 = root["bowWaterInet3_uint8"].asUInt();
if(!checkField("bowWaterInet4_uint8")) ok=false; state.bowWaterInet4 = root["bowWaterInet4_uint8"].asUInt();
if(!checkField("bowWaterInet5_uint8")) ok=false; state.bowWaterInet5 = root["bowWaterInet5_uint8"].asUInt();
if(!checkField("bowWaterInet6_uint8")) ok=false; state.bowWaterInet6 = root["bowWaterInet6_uint8"].asUInt();
if(!checkField("bowWaterInet7_uint8")) ok=false; state.bowWaterInet7 = root["bowWaterInet7_uint8"].asUInt();
if(!checkField("bowWaterInet8_uint8")) ok=false; state.bowWaterInet8 = root["bowWaterInet8_uint8"].asUInt();
if(!checkField("launchControler_uint8")) ok=false; state.launchControler = root["launchControler_uint8"].asUInt();
if(!checkField("electSensor_uint8")) ok=false; state.electSensor = root["electSensor_uint8"].asUInt();
if(!checkField("lowFreqSonar_uint8")) ok=false; state.lowFreqSonar = root["lowFreqSonar_uint8"].asUInt();
// UNIT3
if(!checkField("buoyancyAdjust1_uint8")) ok=false; state.buoyancyAdjust1 = root["buoyancyAdjust1_uint8"].asUInt();
if(!checkField("buoyancyAdjust2_uint8")) ok=false; state.buoyancyAdjust2 = root["buoyancyAdjust2_uint8"].asUInt();
if(!checkField("buoyancyAdjust3_uint8")) ok=false; state.buoyancyAdjust3 = root["buoyancyAdjust3_uint8"].asUInt();
if(!checkField("USBL_uint8")) ok=false; state.USBL = root["USBL_uint8"].asUInt();
if(!checkField("depth1_uint8")) ok=false; state.depth1 = root["depth1_uint8"].asUInt();
if(!checkField("commDev_uint8")) ok=false; state.commDev = root["commDev_uint8"].asUInt();
if(!checkField("mastLiftingServo_uint8")) ok=false; state.mastLiftingServo = root["mastLiftingServo_uint8"].asUInt();
if(!checkField("DVL_uint8")) ok=false; state.DVL = root["DVL_uint8"].asUInt();
if(!checkField("ADCP_uint8")) ok=false; state.ADCP = root["ADCP_uint8"].asUInt();
if(!checkField("inOutLetWater1_uint8")) ok=false; state.inOutLetWater1 = root["inOutLetWater1_uint8"].asUInt();
if(!checkField("inOutLetWater2_uint8")) ok=false; state.inOutLetWater2 = root["inOutLetWater2_uint8"].asUInt();
// UNIT4
if(!checkField("singleBeamSonar7_uint8")) ok=false; state.singleBeamSonar7 = root["singleBeamSonar7_uint8"].asUInt();
if(!checkField("singleBeamSonar8_uint8")) ok=false; state.singleBeamSonar8 = root["singleBeamSonar8_uint8"].asUInt();
if(!checkField("buoyage_uint8")) ok=false; state.buoyage = root["buoyage_uint8"].asUInt();
if(!checkField("bowThrow_uint8")) ok=false; state.bowThrow = root["bowThrow_uint8"].asUInt();
if(!checkField("depth2_uint8")) ok=false; state.depth2 = root["depth2_uint8"].asUInt();
if(!checkField("thruster_uint8")) ok=false; state.thruster = root["thruster_uint8"].asUInt();
if(!checkField("dragSonar_uint8")) ok=false; state.dragSonar = root["dragSonar_uint8"].asUInt();
if(!checkField("haulingMachine_uint8")) ok=false; state.haulingMachine = root["haulingMachine_uint8"].asUInt();
if(!checkField("buoyancyAdjust4_uint8")) ok=false; state.buoyancyAdjust4 = root["buoyancyAdjust4_uint8"].asUInt();
if(!checkField("buoyancyAdjust5_uint8")) ok=false; state.buoyancyAdjust5 = root["buoyancyAdjust5_uint8"].asUInt();
if(!checkField("sternRudderServo1_uint8")) ok=false; state.sternRudderServo1 = root["sternRudderServo1_uint8"].asUInt();
if(!checkField("sternRudderServo2_uint8")) ok=false; state.sternRudderServo2 = root["sternRudderServo2_uint8"].asUInt();
if(!checkField("sternRudderServo3_uint8")) ok=false; state.sternRudderServo3 = root["sternRudderServo3_uint8"].asUInt();
if(!checkField("sternRudderServo4_uint8")) ok=false; state.sternRudderServo4 = root["sternRudderServo4_uint8"].asUInt();
if(!checkField("ctd2_uint8")) ok=false; state.ctd2 = root["ctd2_uint8"].asUInt();
if(!checkField("commDevStern_uint8")) ok=false; state.commDevStern = root["commDevStern_uint8"].asUInt();
if(!checkField("inOutLetWater3_uint8")) ok=false; state.inOutLetWater3 = root["inOutLetWater3_uint8"].asUInt();
// UNIT5
if(!checkField("secINS_uint8")) ok=false; state.secINS = root["secINS_uint8"].asUInt();
if(!checkField("photoSensor_uint8")) ok=false; state.photoSensor = root["photoSensor_uint8"].asUInt();
if(!checkField("sternThrow_uint8")) ok=false; state.sternThrow = root["sternThrow_uint8"].asUInt();
if(!checkField("mainINS_uint8")) ok=false; state.mainINS = root["mainINS_uint8"].asUInt();
//不检查字段缺失
ok = true;
return ok;
};
std::string buildSecdistStateToJson(DeviceSecdistState &state){
Json::Value root;
// UNIT1
root["bowCover1_uint8"] = state.bowCover1;
root["bowCover2_uint8"] = state.bowCover2;
root["bowCover3_uint8"] = state.bowCover3;
root["bowCover4_uint8"] = state.bowCover4;
root["bowCover5_uint8"] = state.bowCover5;
root["bowCover6_uint8"] = state.bowCover6;
root["singleBeamSonar1_uint8"] = state.singleBeamSonar1;
root["singleBeamSonar2_uint8"] = state.singleBeamSonar2;
root["singleBeamSonar3_uint8"] = state.singleBeamSonar3;
root["singleBeamSonar4_uint8"] = state.singleBeamSonar4;
root["singleBeamSonar5_uint8"] = state.singleBeamSonar5;
root["singleBeamSonar6_uint8"] = state.singleBeamSonar6;
root["forwardSonar_uint8"] = state.forwardSonar;
root["depth3_uint8"] = state.depth3;
root["soundVeloc_uint8"] = state.soundVeloc;
root["bowRudderServo_uint8"] = state.bowRudderServo;
root["bowRudderDeploy_uint8"] = state.bowRudderDeploy;
root["ctd1_uint8"] = state.ctd1;
root["waterInject_uint8"] = state.waterInject;
// UNIT2
root["sideSonar_uint8"] = state.sideSonar;
root["bowWaterInet1_uint8"] = state.bowWaterInet1;
root["bowWaterInet2_uint8"] = state.bowWaterInet2;
root["bowWaterInet3_uint8"] = state.bowWaterInet3;
root["bowWaterInet4_uint8"] = state.bowWaterInet4;
root["bowWaterInet5_uint8"] = state.bowWaterInet5;
root["bowWaterInet6_uint8"] = state.bowWaterInet6;
root["bowWaterInet7_uint8"] = state.bowWaterInet7;
root["bowWaterInet8_uint8"] = state.bowWaterInet8;
root["launchControler_uint8"] = state.launchControler;
root["electSensor_uint8"] = state.electSensor;
root["lowFreqSonar_uint8"] = state.lowFreqSonar;
// UNIT3
root["buoyancyAdjust1_uint8"] = state.buoyancyAdjust1;
root["buoyancyAdjust2_uint8"] = state.buoyancyAdjust2;
root["buoyancyAdjust3_uint8"] = state.buoyancyAdjust3;
root["USBL_uint8"] = state.USBL;
root["depth1_uint8"] = state.depth1;
root["commDev_uint8"] = state.commDev;
root["mastLiftingServo_uint8"] = state.mastLiftingServo;
root["DVL_uint8"] = state.DVL;
root["ADCP_uint8"] = state.ADCP;
root["inOutLetWater1_uint8"] = state.inOutLetWater1;
root["inOutLetWater2_uint8"] = state.inOutLetWater2;
// UNIT4
root["singleBeamSonar7_uint8"] = state.singleBeamSonar7;
root["singleBeamSonar8_uint8"] = state.singleBeamSonar8;
root["buoyage_uint8"] = state.buoyage;
root["bowThrow_uint8"] = state.bowThrow;
root["depth2_uint8"] = state.depth2;
root["thruster_uint8"] = state.thruster;
root["dragSonar_uint8"] = state.dragSonar;
root["haulingMachine_uint8"] = state.haulingMachine;
root["buoyancyAdjust4_uint8"] = state.buoyancyAdjust4;
root["buoyancyAdjust5_uint8"] = state.buoyancyAdjust5;
root["sternRudderServo1_uint8"] = state.sternRudderServo1;
root["sternRudderServo2_uint8"] = state.sternRudderServo2;
root["sternRudderServo3_uint8"] = state.sternRudderServo3;
root["sternRudderServo4_uint8"] = state.sternRudderServo4;
root["ctd2_uint8"] = state.ctd2;
root["commDevStern_uint8"] = state.commDevStern;
root["inOutLetWater3_uint8"] = state.inOutLetWater3;
// UNIT5
root["secINS_uint8"] = state.secINS;
root["photoSensor_uint8"] = state.photoSensor;
root["sternThrow_uint8"] = state.sternThrow;
root["mainINS_uint8"] = state.mainINS;
Json::StreamWriterBuilder writerBuilder;
writerBuilder.settings_["indentation"] = ""; // 紧凑格式,无缩进
return Json::writeString(writerBuilder, root);
};
bool converFromDriverTable(DeviceSecdistState &state,const DriverTable &driver){
// UNIT1
state.bowCover1 = driver.bowCover1;
state.bowCover2 = driver.bowCover2;
state.bowCover3 = driver.bowCover3;
state.bowCover4 = driver.bowCover4;
state.bowCover5 = driver.bowCover5;
state.bowCover6 = driver.bowCover6;
state.singleBeamSonar1 = driver.singleBeamSonar1;
state.singleBeamSonar2 = driver.singleBeamSonar2;
state.singleBeamSonar3 = driver.singleBeamSonar3;
state.singleBeamSonar4 = driver.singleBeamSonar4;
state.singleBeamSonar5 = driver.singleBeamSonar5;
state.singleBeamSonar6 = driver.singleBeamSonar6;
state.forwardSonar = driver.forwardSonar;
state.depth3 = driver.depth3;
state.soundVeloc = driver.soundVeloc;
state.bowRudderServo = driver.bowRudderServo1;
state.bowRudderDeploy = driver.bowRudderDeploy;
state.ctd1 = driver.ctd1;
state.waterInject = driver.waterInject;
// UNIT2
state.sideSonar = driver.sideSonar;
state.bowWaterInet1 = driver.bowWaterInet1;
state.bowWaterInet2 = driver.bowWaterInet2;
state.bowWaterInet3 = driver.bowWaterInet3;
state.bowWaterInet4 = driver.bowWaterInet4;
state.bowWaterInet5 = driver.bowWaterInet5;
state.bowWaterInet6 = driver.bowWaterInet6;
state.bowWaterInet7 = driver.bowWaterInet7;
state.bowWaterInet8 = driver.bowWaterInet8;
state.launchControler = driver.launchControler;
state.electSensor = driver.electSensor;
state.lowFreqSonar = driver.lowFreqSonar;
// UNIT3
state.buoyancyAdjust1 = driver.buoyancyAdjust1;
state.buoyancyAdjust2 = driver.buoyancyAdjust2;
state.buoyancyAdjust3 = driver.buoyancyAdjust3;
state.USBL = driver.USBL;
state.depth1 = driver.depth1;
state.commDev = driver.commMast;
state.mastLiftingServo = driver.mastLiftingServo;
state.DVL = driver.DVL;
state.ADCP = driver.DVL; // Assuming ADCP is same as DVL
//出入水传感器1、2共用一个继电器
state.inOutLetWater1 = driver.inputWaterSensor1;
state.inOutLetWater2 = driver.inputWaterSensor1;
// state.inOutLetWater2 = driver.inputWaterSensor2;
// UNIT4
state.singleBeamSonar7 = driver.singleBeamSonar7;
state.singleBeamSonar8 = driver.singleBeamSonar8;
state.buoyage = driver.buoyage;
state.bowThrow = driver.bowThrow;
state.depth2 = driver.depth2;
state.thruster = driver.thruster;
state.haulingMachine = 2; // No corresponding field in DriverTable
state.buoyancyAdjust4 = driver.buoyancyAdjust4;
state.buoyancyAdjust5 = driver.buoyancyAdjust5;
state.sternRudderServo1 = driver.sternRudderServo1;
state.sternRudderServo2 = driver.sternRudderServo2;
state.sternRudderServo3 = driver.sternRudderServo3;
state.sternRudderServo4 = driver.sternRudderServo4;
state.ctd2 = driver.ctd2;
state.commDevStern = 2; // No corresponding field in DriverTable
state.inOutLetWater3 = driver.inputWaterSensor3;
// UNIT5
state.secINS = driver.ins;
state.photoSensor = driver.photoSensor;
state.sternThrow = driver.sternThrow;
state.mainINS = driver.ins;
// 未映射字段
// driver.overDeep1
// driver.overDeep2
// driver.ntp
state.dragSonar = 2; // Assuming dragSonar is same as lowFreqSonar
return true;
};
bool converToDriverTable(const DeviceSecdistState &state, DriverTable &driver){
// UNIT1
driver.bowCover1 = state.bowCover1;
driver.bowCover2 = state.bowCover2;
driver.bowCover3 = state.bowCover3;
driver.bowCover4 = state.bowCover4;
driver.bowCover5 = state.bowCover5;
driver.bowCover6 = state.bowCover6;
driver.singleBeamSonar1 = state.singleBeamSonar1;
driver.singleBeamSonar2 = state.singleBeamSonar2;
driver.singleBeamSonar3 = state.singleBeamSonar3;
driver.singleBeamSonar4 = state.singleBeamSonar4;
driver.singleBeamSonar5 = state.singleBeamSonar5;
driver.singleBeamSonar6 = state.singleBeamSonar6;
driver.forwardSonar = state.forwardSonar;
driver.depth3 = state.depth3;
driver.soundVeloc = state.soundVeloc;
driver.bowRudderServo1 = state.bowRudderServo;
driver.bowRudderServo2 = state.bowRudderServo;
driver.bowRudderDeploy = state.bowRudderDeploy;
driver.ctd1 = state.ctd1;
driver.waterInject = state.waterInject;
// UNIT2
driver.sideSonar = state.sideSonar;
driver.bowWaterInet1 = state.bowWaterInet1;
driver.bowWaterInet2 = state.bowWaterInet2;
driver.bowWaterInet3 = state.bowWaterInet3;
driver.bowWaterInet4 = state.bowWaterInet4;
driver.bowWaterInet5 = state.bowWaterInet5;
driver.bowWaterInet6 = state.bowWaterInet6;
driver.bowWaterInet7 = state.bowWaterInet7;
driver.bowWaterInet8 = state.bowWaterInet8;
driver.launchControler = state.launchControler;
driver.electSensor = state.electSensor;
driver.lowFreqSonar = state.lowFreqSonar;
// UNIT3
driver.buoyancyAdjust1 = state.buoyancyAdjust1;
driver.buoyancyAdjust2 = state.buoyancyAdjust2;
driver.buoyancyAdjust3 = state.buoyancyAdjust3;
driver.USBL = state.USBL;
driver.depth1 = state.depth1;
driver.commMast = state.commDev;
driver.ntp = 1;
driver.mastLiftingServo = state.mastLiftingServo;
driver.DVL = state.DVL;
driver.inputWaterSensor1 = state.inOutLetWater1;
driver.inputWaterSensor2 = state.inOutLetWater2;
driver.overDeep1 = (state.depth1 == 1) ? 1 : 0;
driver.overDeep2 = (state.depth2 == 1 || state.depth3 == 1) ? 1 : 0;
// UNIT4
driver.singleBeamSonar7 = state.singleBeamSonar7;
driver.singleBeamSonar8 = state.singleBeamSonar8;
driver.buoyage = state.buoyage;
driver.bowThrow = state.bowThrow;
driver.depth2 = state.depth2;
driver.thruster = state.thruster;
driver.buoyancyAdjust4 = state.buoyancyAdjust4;
driver.buoyancyAdjust5 = state.buoyancyAdjust5;
driver.sternRudderServo1 = state.sternRudderServo1;
driver.sternRudderServo2 = state.sternRudderServo2;
driver.sternRudderServo3 = state.sternRudderServo3;
driver.sternRudderServo4 = state.sternRudderServo4;
driver.ctd2 = state.ctd2;
driver.inputWaterSensor3 = state.inOutLetWater3;
// UNIT5
driver.ins = state.secINS | state.mainINS;
driver.photoSensor = state.photoSensor;
driver.sternThrow = state.sternThrow;
return true;
}
std::string buildMsg(DriverTable &driver){
DeviceSecdistState s;
converFromDriverTable(s,driver);
// std::cout << (int)s.depth1 << std::endl;
// std::cout << buildSecdistStateToJson(s) << std::endl;
return buildSecdistStateToJson(s);
};
bool parseMsg(const std::string &strJson,DriverTable &driver){
DeviceSecdistState s;
if(!parseSecdistStateFromJson(s,strJson)){
LOG_F(WARNING, "parseSecdistStateFromJson failed");
return false;
}
converToDriverTable(s,driver);
return true;
};
std::string buildMsg(DriverTable driver, DriverTable driver_state){
DeviceSecdistState s;
DriverTable driverCopy = driver;
for (size_t i = 0; i < sizeof(DriverTable); ++i) {
unsigned char* driverCopyPtr = reinterpret_cast<unsigned char*>(&driverCopy) + i;
unsigned char* statePtr = reinterpret_cast<unsigned char*>(&driver_state) + i;
if (*driverCopyPtr == *statePtr) {
*driverCopyPtr = 2;
}
}
converFromDriverTable(s, driverCopy);
// std::cout << (int)s.depth1 << std::endl;
// std::cout << buildSecdistStateToJson(s) << std::endl;
return buildSecdistStateToJson(s);
};
std::string buildMsg(DriverTable driver, DriverTable driver_state, unsigned int nCheck){
static size_t callCount = 0; // 静态变量,记录函数调用次数
DeviceSecdistState s;
DriverTable driverCopy = driver;
if (nCheck > 0 && callCount % nCheck == 0)
{
for (size_t i = 0; i < sizeof(DriverTable); ++i) {
unsigned char* driverCopyPtr = reinterpret_cast<unsigned char*>(&driverCopy) + i;
unsigned char* statePtr = reinterpret_cast<unsigned char*>(&driver_state) + i;
if (*driverCopyPtr == *statePtr) {
*driverCopyPtr = 2;
}
}
}
else {
memset(&driverCopy, 2, sizeof(DriverTable));
}
callCount ++;
converFromDriverTable(s, driverCopy);
// std::cout << (int)s.depth1 << std::endl;
// std::cout << buildSecdistStateToJson(s) << std::endl;
return buildSecdistStateToJson(s);
};
static DriverTable fault_state;
std::string buildMsg(DriverTable driver, DriverTable driver_state, DriverTable &driver_fault_state){
static size_t f_callCount = 0; // 静态变量,记录函数调用次数
unsigned int nCheck = 10;
DeviceSecdistState s;
DriverTable driverCopy = driver;
for (size_t i = 0; i < sizeof(DriverTable); ++i)
{
unsigned char* driverCopyPtr = reinterpret_cast<unsigned char*>(&driverCopy) + i;
unsigned char* statePtr = reinterpret_cast<unsigned char*>(&driver_state) + i;
unsigned char* faultStatePtr = reinterpret_cast<unsigned char*>(&driver_fault_state) + i;
unsigned char* faultState = reinterpret_cast<unsigned char*>(&fault_state) + i;
if (*driverCopyPtr == *statePtr)
{
*driverCopyPtr = 2;
*faultStatePtr = 0;
*faultState = 0;
}
else
{
*faultState = *faultState + 1;
if(*faultState >= 5)
{
//只有开启失败才计入故障
if(*driverCopyPtr == 1)
*faultStatePtr = 1;
*faultState = 5;
}
}
}
f_callCount ++;
converFromDriverTable(s, driverCopy);
return buildSecdistStateToJson(s);
};
};
#endif
@@ -0,0 +1,124 @@
/*
{
"rpm int16": "xxx", // 实际转速,类型:int16_t
"voltage_uint16": "xxx", // 电压,类型:uint16_t,单位 V
"current_uint16": "xxx", // 电流,类型:uint16_t,单位 A
"ctrlTemp_uint16": "xxx", // 控制器温度,类型:uint16_t,单位 °C
"motorTemp_uint16": "xxx", // 电机温度,类型:uint16_t,单位 °C
"motorTorque_uint16": "xxx", // 电机扭矩,类型:uint16_t,单位 N・m
"maxTorque_uint16": "xxx", // 电机最大扭矩,类型:uint16_t,单位 N・m,电机使能时该字段非零,无使能地址报警,含使能整标标识字,00 无故障,按位常量零
"error_int64": "xxx" // 见表 [1],类型:int64_t
}
*/
#ifndef UDEVICE_THRUSTER_ST_H
#define UDEVICE_THRUSTER_ST_H
#include "../logc/loguru.hpp"
#include "json/json.h"
#include <string>
#include <memory>
#include <sstream>
class uDevice_thruster_st
{
private:
/* data */
public:
uDevice_thruster_st(){};
~uDevice_thruster_st(){};
int16_t rpm_int16;
uint16_t voltage_uint16;
uint16_t current_uint16;
uint16_t ctrlTemp_uint16;
uint16_t motorTemp_uint16;
uint16_t motorTorque_uint16;
uint16_t maxTorque_uint16;
int64_t error_int64;
static std::string key;
std::string toJsonString()
{
Json::Value j;
j["rpm_int16"] = rpm_int16;
j["voltage_uint16"] = voltage_uint16;
j["current_uint16"] = current_uint16;
j["ctrlTemp_uint16"] = ctrlTemp_uint16;
j["motorTemp_uint16"] = motorTemp_uint16;
j["motorTorque_uint16"] = motorTorque_uint16;
j["maxTorque_uint16"] = maxTorque_uint16;
j["error_int64"] = static_cast<Json::Int64>(error_int64);
Json::StreamWriterBuilder builder;
builder.settings_["indentation"] = "";
return Json::writeString(builder, j);
}
bool fromJsonString(std::string jsonString)
{
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(jsonString);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
return false;
}
// 提取rpm_int16
if (root.isMember("rpm_int16") && root["rpm_int16"].isInt()) {
rpm_int16 = root["rpm_int16"].asInt();
// LOG_F(INFO, "rpm_int16: %d", rpm_int16);
}
// 提取voltage_uint16
if (root.isMember("voltage_uint16") && root["voltage_uint16"].isUInt()) {
voltage_uint16 = root["voltage_uint16"].asUInt();
// LOG_F(INFO, "voltage_uint16: %u", voltage_uint16);
}
// 提取current_uint16
if (root.isMember("current_uint16") && root["current_uint16"].isUInt()) {
current_uint16 = root["current_uint16"].asUInt();
// LOG_F(INFO, "current_uint16: %u", current_uint16);
}
// 提取ctrlTemp_uint16
if (root.isMember("ctrlTemp_uint16") && root["ctrlTemp_uint16"].isUInt()) {
ctrlTemp_uint16 = root["ctrlTemp_uint16"].asUInt();
// LOG_F(INFO, "ctrlTemp_uint16: %u", ctrlTemp_uint16);
}
// 提取motorTemp_uint16
if (root.isMember("motorTemp_uint16") && root["motorTemp_uint16"].isUInt()) {
motorTemp_uint16 = root["motorTemp_uint16"].asUInt();
// LOG_F(INFO, "motorTemp_uint16: %u", motorTemp_uint16);
}
// 提取motorTorque_uint16
if (root.isMember("motorTorque_uint16") && root["motorTorque_uint16"].isUInt()) {
motorTorque_uint16 = root["motorTorque_uint16"].asUInt();
// LOG_F(INFO, "motorTorque_uint16: %u", motorTorque_uint16);
}
// 提取maxTorque_uint16
if (root.isMember("maxTorque_uint16") && root["maxTorque_uint16"].isUInt()) {
maxTorque_uint16 = root["maxTorque_uint16"].asUInt();
// LOG_F(INFO, "maxTorque_uint16: %u", maxTorque_uint16);
}
// 提取error_int64
if (root.isMember("error_int64") && root["error_int64"].isInt64()) {
error_int64 = root["error_int64"].asInt64();
// LOG_F(INFO, "error_int64: %lld", error_int64);
}
// LOG_F(INFO, "jsonString: %s", jsonString.c_str());
return true;
}
};
#endif
@@ -0,0 +1,43 @@
#ifndef UEXTERNCOMM_SETDEVICESWITCH_CMD_H
#define UEXTERNCOMM_SETDEVICESWITCH_CMD_H
#include <string>
class uExternComm_setDeviceSwitchMsg
{
private:
/* data */
public:
std::string key = "uExternComm_setDeviceSwitch_cmd";
uExternComm_setDeviceSwitchMsg(/* args */){};
~uExternComm_setDeviceSwitchMsg(){};
DeviceSwitchCmd getSetDevSwitch(const std::string& key, const std::string& msg)
{
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
DeviceSwitchCmd cmd{};
// 解析JSON字符串
std::istringstream stream(msg);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
cmd.id = -1;
}
// 检查并读取设备开关状态
if (root.isMember("id_uint8") && root["id_uint8"].isUInt()) {
cmd.id = root["id_uint8"].asUInt();
} else {
cmd.id = -1;
LOG_F(WARNING, "缺少或类型不匹配: id_uint8");
}
if (root.isMember("cmd_uint8") && root["cmd_uint8"].isUInt()) {
cmd.cmd = root["cmd_uint8"].asUInt();
} else {
LOG_F(WARNING, "缺少或类型不匹配: state_bool");
}
return cmd;
};
};
#endif
@@ -0,0 +1,43 @@
#ifndef UEXTERCOMM_SETOPCONDITION_CMD_H
#define UEXTERCOMM_SETOPCONDITION_CMD_H
#include <string>
#include "../logc/loguru.hpp"
#include "json/json.h"
//外部通信消息
#define DB_TO_PM_SETOPCONDITION "uExternComm_setOpCondition_cmd"
class uExternComm_setOpConditionMsg
{
private:
/* data */
public:
std::string key = "uExternComm_setOpCondition_cmd";
uExternComm_setOpConditionMsg(/* args */){};
~uExternComm_setOpConditionMsg(){};
int getSetOpCondition(const std::string& key, const std::string& msg)
{
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(msg);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
return -1;
}
// 检查并读取操作条件
if (root.isMember("state_uint8") && root["state_uint8"].isUInt()) {
return root["state_uint8"].asUInt();
LOG_F(INFO, "上位机指令:opCondition: %d", root["state_uint8"].asUInt());
} else {
LOG_F(WARNING, "缺少或类型不匹配: opCondition");
return -1;
}
}
};
#endif
@@ -0,0 +1,46 @@
#ifndef UEXTERCOMM_SETOPMODE_CMD_H
#define UEXTERCOMM_SETOPMODE_CMD_H
#include <string>
#include "../logc/loguru.hpp"
//外部通信消息
#define DB_TO_PM_SETOPMODE "uExternComm_setOpMode_cmd"
class uExternComm_setOpModeMsg
{
private:
/* data */
public:
std::string key = "uExternComm_setOpMode_cmd";
uExternComm_setOpModeMsg(/* args */){};
~uExternComm_setOpModeMsg(){};
int getSetOpMode(const std::string& msgkey, const std::string& msg){
if (msgkey!= key)
{
LOG_F(WARNING, "消息类型错误 %s", msgkey.c_str());
return 0;
}
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(msg);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
return -1;
}
// 检查并读取操作模式
if (root.isMember("state_uint8") && root["state_uint8"].isUInt()) {
return root["state_uint8"].asUInt();
} else {
LOG_F(WARNING, "缺少或类型不匹配: opMode");
return -1;
}
};
};
#endif
@@ -0,0 +1,39 @@
#ifndef UEXTERNCONM_SETPMSYS_H
#define UEXTERNCONM_SETPMSYS_H
#include <string>
#include "../logc/loguru.hpp"
#define DB_TO_PM_SETPMSYS "uExternComm_setPowerSystem_cmd"
class uExternComm_setPowerSystemMsg
{
private:
public:
std::string key = "uExternComm_setPowerSystem_cmd";
uExternComm_setPowerSystemMsg(/* args */){};
~uExternComm_setPowerSystemMsg(){};
int getSetPMSys(const std::string& key, const std::string& msg)
{
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(msg);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
std::cerr << "JSON解析失败: " << errs << std::endl;
return -1;
}
// 检查并读取电源系统设置
if (root.isMember("powerCmd_uint8") && root["powerCmd_uint8"].isUInt()) {
return root["powerCmd_uint8"].asUInt();
} else {
LOG_F(WARNING, "缺少或类型不匹配: powerCmd_uint8");
return -1;
}
}
};
#endif
@@ -0,0 +1,70 @@
/*
{
"rpm_int16": "xx", // 期望转速;单位:rpm;类型 int16_t
"enable_int16": "xx" // 使能指令,1 - 使能,0 - 去使能。类型 int16_t
}
*/
#ifndef UEXTERNCOMM_SETTHRUSTSPEED_CMD_H
#define UEXTERNCOMM_SETTHRUSTSPEED_CMD_H
#include "../logc/loguru.hpp"
#include "json/json.h"
#include <string>
#include <memory>
#include <sstream>
class uExternComm_setThrustSpeed_cmd
{
private:
/* data */
public:
uExternComm_setThrustSpeed_cmd(){};
~uExternComm_setThrustSpeed_cmd(){};
int16_t rpm_int16;
int16_t enable_int16;
static std::string key;
std::string toJsonString()
{
Json::Value j;
j["rpm_int16"] = rpm_int16;
j["enable_int16"] = enable_int16;
Json::StreamWriterBuilder builder;
builder.settings_["indentation"] = "";
return Json::writeString(builder, j);
}
bool fromJsonString(std::string jsonString)
{
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(jsonString);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
return false;
}
// 提取rpm_int16
if (root.isMember("rpm_int16") && root["rpm_int16"].isInt()) {
rpm_int16 = root["rpm_int16"].asInt();
// LOG_F(INFO, "rpm_int16: %d", rpm_int16);
}
// 提取enable_int16
if (root.isMember("enable_int16") && root["enable_int16"].isInt()) {
enable_int16 = root["enable_int16"].asInt();
// LOG_F(INFO, "enable_int16: %d", enable_int16);
}
// LOG_F(INFO, "jsonString: %s", jsonString.c_str());
return true;
}
};
#endif
@@ -0,0 +1,35 @@
#ifndef UPLAN_PLANSTOP_CMD_H
#define UPLAN_PLANSTOP_CMD_H
#include <string>
#include "../logc/loguru.hpp"
#define DB_TO_PM_TASKSTOP "uPlan_planStop_st"
class uPlan_planStopMsg
{
private:
/* data */
public:
std::string key = "uPlan_planStop_st";
uPlan_planStopMsg(/* args */){};
~uPlan_planStopMsg(){};
bool getTaskStop(const std::string& key, const std::string& msg) {
Json::Value root;
Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
// 解析JSON字符串
std::istringstream stream(msg);
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
LOG_F(WARNING, "JSON解析失败: %s", errs.c_str());
return false;
}
// 检查op_int32字段
if (root.isMember("op_int32") && root["op_int32"].isInt()) {
return root["op_int32"].asInt() == 1;
}
return false;
};
};
#endif

Some files were not shown because too many files have changed in this diff Show More