Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a870071490 | ||
|
|
b653f17b03 | ||
|
|
785a47ff99 | ||
|
|
bac5f5291e | ||
|
|
35e5d5230e | ||
|
|
b5a746c2ef | ||
|
|
7ef9ec5ac0 | ||
|
|
c47660fcb1 | ||
|
|
ebf1701335 | ||
|
|
002df307d7 | ||
|
|
8677811dac | ||
|
|
c51eb7073a | ||
|
|
811fbf2924 | ||
|
|
341630f547 | ||
|
|
16cffa296a | ||
|
|
0fbe95bc45 | ||
|
|
1e295aeeb3 | ||
|
|
9cc3140651 | ||
|
|
02d54a585a | ||
|
|
115ee57b14 | ||
|
|
4ee5cbfb86 | ||
|
|
d89a1936ee | ||
|
|
75575f935c | ||
|
|
5b9934c6f2 | ||
|
|
14f7890d77 | ||
|
|
7dac85505b | ||
|
|
a179789b3f | ||
|
|
2599050c1f | ||
|
|
1aa46629a7 | ||
|
|
59202d20aa | ||
|
|
845360c46b | ||
|
|
df8a23fd46 | ||
|
|
6d00ecfbf2 | ||
|
|
25b4e0d688 | ||
|
|
734226a33a | ||
|
|
f83f737a79 | ||
|
|
ed0d7f7fe0 | ||
|
|
59faa14afb | ||
|
|
e072f2b9d4 | ||
|
|
6f5de4b614 | ||
|
|
c824caa27e | ||
|
|
0d5ffb31ce | ||
|
|
57dd677271 | ||
|
|
d2961cf005 | ||
|
|
d9d715326a | ||
|
|
ec595ac1dc | ||
|
|
6374e60b91 | ||
|
|
abd91d0e88 | ||
|
|
eb2877f03f | ||
|
|
4693ce2619 | ||
|
|
590662d7a5 | ||
|
|
e2bfa98754 | ||
|
|
dfd13848ef | ||
|
|
985b667200 |
+242
@@ -0,0 +1,242 @@
|
|||||||
|
# ---> C++
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# ---> Python
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# ---> MATLAB
|
||||||
|
# Windows default autosave extension
|
||||||
|
*.asv
|
||||||
|
|
||||||
|
# OSX / *nix default autosave extension
|
||||||
|
*.m~
|
||||||
|
|
||||||
|
# Compiled MEX binaries (all platforms)
|
||||||
|
*.mex*
|
||||||
|
|
||||||
|
# Packaged app and toolbox files
|
||||||
|
*.mlappinstall
|
||||||
|
*.mltbx
|
||||||
|
|
||||||
|
# Generated helpsearch folders
|
||||||
|
helpsearch*/
|
||||||
|
|
||||||
|
# Simulink code generation folders
|
||||||
|
slprj/
|
||||||
|
sccprj/
|
||||||
|
|
||||||
|
# Matlab code generation folders
|
||||||
|
codegen/
|
||||||
|
|
||||||
|
# Simulink autosave extension
|
||||||
|
*.autosave
|
||||||
|
|
||||||
|
# Simulink cache files
|
||||||
|
*.slxc
|
||||||
|
|
||||||
|
# Octave session info
|
||||||
|
octave-workspace
|
||||||
|
|
||||||
|
# ---> CMake
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
|
||||||
Vendored
+85
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"list": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"queue": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"coroutine": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"source_location": "cpp",
|
||||||
|
"future": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"typeindex": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"*.ipp": "cpp"
|
||||||
|
},
|
||||||
|
"C_Cpp.errorSquiggles": "disabled",
|
||||||
|
"marscode.chatLanguage": "cn",
|
||||||
|
"marscode.codeCompletionPro": {
|
||||||
|
"enableCodeCompletionPro": true
|
||||||
|
},
|
||||||
|
"marscode.enableInlineCommand": true
|
||||||
|
}
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
#=======================================================================
|
||||||
|
# FILE: moos-ivp-extend/CMakeLists.txt
|
||||||
|
# DATE: 2012/07/24
|
||||||
|
# INFO: Top-level CMakeLists.txt file for the moos-ivp-extend project
|
||||||
|
# NAME: Maintained by Mike Benjamin - Original setup by Christian Convey
|
||||||
|
# Chris Gagner, and tips borrowed from Dave Billin
|
||||||
|
#=======================================================================
|
||||||
|
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||||
|
PROJECT( IVP_EXTEND )
|
||||||
|
|
||||||
|
set (CMAKE_CXX_STANDARD 11)
|
||||||
|
set (MOOSIVP_SOURCE_TREE_BASE "/home/zjk/project/lib/moos-ivp")
|
||||||
|
|
||||||
|
#=======================================================================
|
||||||
|
# Set the output directories for the binary and library files
|
||||||
|
#=======================================================================
|
||||||
|
|
||||||
|
GET_FILENAME_COMPONENT(IVP_EXTEND_BIN_DIR "${CMAKE_SOURCE_DIR}/bin" ABSOLUTE )
|
||||||
|
GET_FILENAME_COMPONENT(IVP_EXTEND_LIB_DIR "${CMAKE_SOURCE_DIR}/lib" ABSOLUTE )
|
||||||
|
|
||||||
|
SET( LIBRARY_OUTPUT_PATH "${IVP_EXTEND_LIB_DIR}" CACHE PATH "" )
|
||||||
|
SET( ARCHIVE_OUTPUT_DIRECTORY "${IVP_EXTEND_LIB_DIR}" CACHE PATH "" )
|
||||||
|
SET( LIBRARY_OUTPUT_DIRECTORY "${IVP_EXTEND_LIB_DIR}" CACHE PATH "" )
|
||||||
|
|
||||||
|
SET( EXECUTABLE_OUTPUT_PATH "${IVP_EXTEND_BIN_DIR}" CACHE PATH "" )
|
||||||
|
SET( RUNTIME_OUTPUT_DIRECTORY "${IVP_EXTEND_BIN_DIR}" CACHE PATH "" )
|
||||||
|
|
||||||
|
#=======================================================================
|
||||||
|
# Find MOOS
|
||||||
|
#=======================================================================
|
||||||
|
find_package(MOOS 10.0)
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
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_* )
|
||||||
|
INCLUDE_DIRECTORIES(${IVP_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
FILE(GLOB IVP_LIBRARY_DIRS ${MOOSIVP_SOURCE_TREE_BASE}/lib )
|
||||||
|
LINK_DIRECTORIES(${IVP_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# Specify Compiler Flags
|
||||||
|
#======================================================================
|
||||||
|
IF( ${WIN32} )
|
||||||
|
#---------------------------------------------
|
||||||
|
# Windows Compiler Flags
|
||||||
|
#---------------------------------------------
|
||||||
|
IF(MSVC)
|
||||||
|
# Flags for Microsoft Visual Studio
|
||||||
|
SET( WALL_ON OFF CACHE BOOL
|
||||||
|
"tell me about all compiler warnings (-Wall) ")
|
||||||
|
IF(WALL_ON)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||||
|
ENDIF(WALL_ON)
|
||||||
|
ELSE(MSVC)
|
||||||
|
# Other Windows compilers go here
|
||||||
|
ENDIF(MSVC)
|
||||||
|
|
||||||
|
ELSE( ${WIN32} )
|
||||||
|
#---------------------------------------------
|
||||||
|
# Linux and Apple Compiler Flags
|
||||||
|
#---------------------------------------------
|
||||||
|
# Force -fPIC because gcc complains when we don't use it with x86_64 code.
|
||||||
|
# Note sure why: -fPIC should only be needed for shared objects, and
|
||||||
|
# AFAIK, CMake gets that right when building shared objects. -CJC
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -g -Wdeprecated-declarations")
|
||||||
|
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
# Flags for the GNU C++ Compiler
|
||||||
|
SET( WALL_ON OFF CACHE BOOL
|
||||||
|
"tell me about all compiler warnings (-Wall) ")
|
||||||
|
IF(WALL_ON)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" -C++11)
|
||||||
|
ENDIF( WALL_ON)
|
||||||
|
ELSE(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
|
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
|
ENDIF( ${WIN32} )
|
||||||
|
|
||||||
|
#=======================================================================
|
||||||
|
# Add Subdirectories
|
||||||
|
#=======================================================================
|
||||||
|
ADD_SUBDIRECTORY( src )
|
||||||
|
# ADD_SUBDIRECTORY( test )
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
@startuml PowerManagerFsm状态图
|
||||||
|
[*] --> InitState
|
||||||
|
|
||||||
|
state InitState {
|
||||||
|
[*] --> 等待复合管控消息
|
||||||
|
等待复合管控消息 --> 等待关键断路器闭合: 连接成功
|
||||||
|
等待复合管控消息 --> FaultState: 超时(10秒)
|
||||||
|
等待关键断路器闭合 --> StandbyState: 关键断路器闭合
|
||||||
|
等待关键断路器闭合 --> FaultState: 系统错误
|
||||||
|
}
|
||||||
|
|
||||||
|
state StandbyState {
|
||||||
|
[*] --> 待机
|
||||||
|
待机 --> FaultState: 检测到错误
|
||||||
|
待机 --> 处理电源命令: 收到命令
|
||||||
|
处理电源命令 --> 待机: 完成处理
|
||||||
|
}
|
||||||
|
|
||||||
|
state FaultState {
|
||||||
|
[*] --> 故障处理
|
||||||
|
}
|
||||||
|
|
||||||
|
InitState --> FaultState : FaultEvent(faultCode=1/2)
|
||||||
|
StandbyState --> FaultState : FaultEvent(faultCode)
|
||||||
|
InitState --> StandbyState : StandbyEvent
|
||||||
|
@enduml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ProcessConfig = pPowerManger
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,379 @@
|
|||||||
|
let currentDbPath = '/home/zjk/project/H100/H100PowerManger/data/power_data.db';
|
||||||
|
|
||||||
|
// 数据库下载功能
|
||||||
|
function downloadDatabase() {
|
||||||
|
const downloadBtn = document.getElementById('download-db');
|
||||||
|
const progressBar = document.getElementById('download-progress');
|
||||||
|
|
||||||
|
downloadBtn.disabled = true;
|
||||||
|
progressBar.style.display = 'block';
|
||||||
|
progressBar.value = 0;
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', '/api/download-db', true);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
|
||||||
|
xhr.onprogress = function(event) {
|
||||||
|
if (event.lengthComputable) {
|
||||||
|
const percentComplete = (event.loaded / event.total) * 100;
|
||||||
|
progressBar.value = percentComplete;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (this.status === 200) {
|
||||||
|
const blob = this.response;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = 'power_data.db';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
progressBar.value = 100;
|
||||||
|
setTimeout(() => {
|
||||||
|
progressBar.style.display = 'none';
|
||||||
|
downloadBtn.disabled = false;
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
throw new Error('下载失败:' + this.statusText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function() {
|
||||||
|
console.error('下载数据库失败:', this.statusText);
|
||||||
|
alert('下载数据库失败:' + this.statusText);
|
||||||
|
progressBar.style.display = 'none';
|
||||||
|
downloadBtn.disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('download-db').addEventListener('click', downloadDatabase);
|
||||||
|
|
||||||
|
// WebSocket连接
|
||||||
|
let ws = null;
|
||||||
|
let reconnectAttempts = 0;
|
||||||
|
const maxReconnectAttempts = 5;
|
||||||
|
const reconnectDelay = 5000;
|
||||||
|
|
||||||
|
// 初始化WebSocket连接
|
||||||
|
function initWebSocket() {
|
||||||
|
ws = new WebSocket('ws://' + window.location.host + '/ws/state');
|
||||||
|
|
||||||
|
ws.onopen = () => {
|
||||||
|
console.log('WebSocket连接已建立');
|
||||||
|
reconnectAttempts = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onmessage = (event) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
updateUI(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = () => {
|
||||||
|
console.log('WebSocket连接已关闭');
|
||||||
|
if (reconnectAttempts < maxReconnectAttempts) {
|
||||||
|
setTimeout(() => {
|
||||||
|
reconnectAttempts++;
|
||||||
|
console.log(`尝试重新连接 (${reconnectAttempts}/${maxReconnectAttempts})`);
|
||||||
|
initWebSocket();
|
||||||
|
}, reconnectDelay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onerror = (error) => {
|
||||||
|
console.error('WebSocket错误:', error);
|
||||||
|
ws.close();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新UI
|
||||||
|
function updateUI(data) {
|
||||||
|
// 更新数据库状态
|
||||||
|
if (data.db_status) {
|
||||||
|
const dbStatus = document.getElementById('db-status');
|
||||||
|
const dbSizeElement = 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}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dbSizeElement && data.db_status.size) {
|
||||||
|
const sizeInMB = (data.db_status.size / 1024 / 1024).toFixed(2);
|
||||||
|
dbSizeElement.textContent = `${sizeInMB} MB`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新MOOS数据库状态
|
||||||
|
if (data.moos_db_status) {
|
||||||
|
const 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>`;
|
||||||
|
} else {
|
||||||
|
moosDbStatus.className = 'db-status disconnected';
|
||||||
|
moosDbStatus.innerHTML = `<i class="fas fa-database"></i><span>MOOS数据库连接失败</span>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态机面板
|
||||||
|
document.getElementById('state-time').textContent = data.state.time;
|
||||||
|
document.getElementById('state-id').textContent = data.state.state_id;
|
||||||
|
document.getElementById('state-name').textContent = data.state.state_name;
|
||||||
|
document.getElementById('state-event').textContent = data.state.event;
|
||||||
|
document.getElementById('state-event-id').textContent = data.state.event_id;
|
||||||
|
document.getElementById('state-fault-code').textContent = data.state.fault_code;
|
||||||
|
document.getElementById('state-note').textContent = data.state.note;
|
||||||
|
|
||||||
|
// 更新DIS系统状态
|
||||||
|
// document.getElementById('dis-sys-state').textContent = JSON.stringify(data.status.disSys, null, 2);
|
||||||
|
|
||||||
|
// 更新CCU状态
|
||||||
|
// document.getElementById('ccu-state').textContent = JSON.stringify(data.status.ccuState, null, 2);
|
||||||
|
|
||||||
|
// 更新进程消息面板
|
||||||
|
console.log('Received WebSocket message:', data);
|
||||||
|
if (data && data.processes && data.processes.list) {
|
||||||
|
console.log('Updating processes:', data.processes);
|
||||||
|
updateProcesses(data.processes);
|
||||||
|
} else {
|
||||||
|
console.warn('Invalid processes data received:', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新运行日志
|
||||||
|
document.getElementById('log-data').textContent = data.status.logs.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// MOOS通知功能
|
||||||
|
function sendMoosNotify() {
|
||||||
|
const varValue = document.getElementById('moos-var').value.trim();
|
||||||
|
const keyValue = document.getElementById('moos-key').value.trim();
|
||||||
|
|
||||||
|
if (!varValue || !keyValue) {
|
||||||
|
alert('请填写Var和Key值');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
var: varValue,
|
||||||
|
key: keyValue
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch('/api/moos-notify', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert('发送成功');
|
||||||
|
} else {
|
||||||
|
alert('发送失败: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('发送请求失败');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('moos-send-btn').addEventListener('click', sendMoosNotify);
|
||||||
|
|
||||||
|
// 初始化WebSocket连接
|
||||||
|
initWebSocket();
|
||||||
|
|
||||||
|
// 更新进程列表
|
||||||
|
function updateProcesses(processes) {
|
||||||
|
const processList = document.getElementById('process-list');
|
||||||
|
processList.innerHTML = ''; // 清空现有内容
|
||||||
|
|
||||||
|
const totalCount = document.getElementById('process-count');
|
||||||
|
totalCount.textContent = processes.count;
|
||||||
|
|
||||||
|
// 创建消息详情弹窗
|
||||||
|
const modal = document.createElement('div');
|
||||||
|
modal.id = 'message-modal';
|
||||||
|
modal.className = 'modal';
|
||||||
|
modal.innerHTML = `
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close-modal">×</span>
|
||||||
|
<h3>消息详情</h3>
|
||||||
|
<div class="message-details">
|
||||||
|
<div class="detail-row">
|
||||||
|
<label>消息名称:</label>
|
||||||
|
<span id="message-name"></span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-row">
|
||||||
|
<label>消息类型:</label>
|
||||||
|
<span id="message-type"></span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-row">
|
||||||
|
<label>最后更新时间:</label>
|
||||||
|
<span id="message-timestamp"></span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-row">
|
||||||
|
<label>消息内容:</label>
|
||||||
|
<pre id="message-content"></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
|
||||||
|
// 添加弹窗关闭事件
|
||||||
|
modal.querySelector('.close-modal').addEventListener('click', () => {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
processes.list.forEach(process => {
|
||||||
|
const processElement = document.createElement('div');
|
||||||
|
processElement.className = 'process-card';
|
||||||
|
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.className = 'process-header';
|
||||||
|
header.innerHTML = `
|
||||||
|
<span class="process-name">${process.name}</span>
|
||||||
|
<span class="topic-count">订阅:${process.subscribed.length} 发布:${process.published.length}</span>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const body = document.createElement('div');
|
||||||
|
body.className = 'process-body';
|
||||||
|
body.innerHTML = `
|
||||||
|
<div class="topic-group">
|
||||||
|
<h4>订阅主题</h4>
|
||||||
|
<ul class="subscribed-list">${process.subscribed.map(t => `<li class="message-item" data-type="subscribed">${t}</li>`).join('')}</ul>
|
||||||
|
</div>
|
||||||
|
<div class="topic-group">
|
||||||
|
<h4>发布主题</h4>
|
||||||
|
<ul class="published-list">${process.published.map(t => `<li class="message-item" data-type="published">${t}</li>`).join('')}</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
body.querySelectorAll('.message-item').forEach(item => {
|
||||||
|
let timeoutId;
|
||||||
|
item.addEventListener('mouseenter', function(event) {
|
||||||
|
timeoutId = setTimeout(async () => {
|
||||||
|
const spinner = createSpinner(event.clientX, event.clientY);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const messageName = item.textContent; // 新增获取消息名称
|
||||||
|
const messageType = item.dataset.type; // 新增获取消息类型
|
||||||
|
const response = await fetch(`/api/message-details?name=${encodeURIComponent(messageName)}&type=${messageType}`);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
// 根据C++的CVar结构映射字段
|
||||||
|
document.getElementById('message-name').textContent = data.name || 'N/A';
|
||||||
|
document.getElementById('message-type').textContent = data.type || '未知类型';
|
||||||
|
document.getElementById('message-timestamp').textContent = new Date(data.time * 1000).toLocaleString(); // 时间戳转换
|
||||||
|
document.getElementById('message-content').textContent = JSON.stringify({
|
||||||
|
value: data.value,
|
||||||
|
source: data.source
|
||||||
|
}, null, 2);
|
||||||
|
modal.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
showErrorTooltip(event, `获取失败: ${data.message || '未知错误'}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showErrorTooltip(event, '网络连接异常,请检查后重试');
|
||||||
|
console.error('获取消息详情失败:', error);
|
||||||
|
} finally {
|
||||||
|
spinner.remove();
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
item.addEventListener('mouseleave', () => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
modal.style.display = 'none';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
processElement.appendChild(header);
|
||||||
|
processElement.appendChild(body);
|
||||||
|
processList.appendChild(processElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染单个进程信息
|
||||||
|
function renderProcess(process) {
|
||||||
|
const template = document.getElementById('process-template');
|
||||||
|
const clone = document.importNode(template.content, true);
|
||||||
|
|
||||||
|
const processEntry = clone.querySelector('.process-entry');
|
||||||
|
processEntry.querySelector('.process-name').textContent = process.name;
|
||||||
|
|
||||||
|
const subscribedList = processEntry.querySelector('.subscribed-list');
|
||||||
|
process.subscribed.forEach(topic => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.textContent = topic;
|
||||||
|
subscribedList.appendChild(li);
|
||||||
|
});
|
||||||
|
|
||||||
|
const publishedList = processEntry.querySelector('.published-list');
|
||||||
|
process.published.forEach(topic => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.textContent = topic;
|
||||||
|
publishedList.appendChild(li);
|
||||||
|
});
|
||||||
|
|
||||||
|
return processEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空进程列表
|
||||||
|
function clearProcessList() {
|
||||||
|
const processLog = document.getElementById('log-data');
|
||||||
|
while (processLog.firstChild && processLog.firstChild.tagName !== 'TEMPLATE') {
|
||||||
|
processLog.removeChild(processLog.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增工具函数
|
||||||
|
function createSpinner(x, y) {
|
||||||
|
const spinner = document.createElement('div');
|
||||||
|
spinner.className = 'loading-spinner';
|
||||||
|
spinner.style = `
|
||||||
|
position: fixed;
|
||||||
|
left: ${x + 15}px;
|
||||||
|
top: ${y + 15}px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border: 3px solid rgba(97, 218, 251, 0.3);
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top-color: #61dafb;
|
||||||
|
animation: spin 1s ease-in-out infinite;
|
||||||
|
z-index: 1000;
|
||||||
|
`;
|
||||||
|
document.body.appendChild(spinner);
|
||||||
|
return spinner;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showErrorTooltip(event, message) {
|
||||||
|
const tooltip = document.createElement('div');
|
||||||
|
tooltip.className = 'error-tooltip';
|
||||||
|
tooltip.innerHTML = `
|
||||||
|
<i class="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;
|
||||||
|
background: rgba(255, 87, 87, 0.9);
|
||||||
|
color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
z-index: 1000;
|
||||||
|
animation: fadeIn 0.3s ease;
|
||||||
|
`;
|
||||||
|
document.body.appendChild(tooltip);
|
||||||
|
setTimeout(() => tooltip.remove(), 3000);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>电源管理</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||||
|
<link rel="stylesheet" href="/static/style.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="db-status-panel">
|
||||||
|
<div class="status-columns">
|
||||||
|
<div class="status-column">
|
||||||
|
<h3>MOOSDB</h3>
|
||||||
|
<div class="db-status" id="moos-db-status">
|
||||||
|
<i class="fas fa-database"></i>
|
||||||
|
<span>正在连接MOOSDB...</span>
|
||||||
|
</div>
|
||||||
|
<div class="moos-notify-panel">
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="moos-var">Var:</label>
|
||||||
|
<input type="text" id="moos-var" placeholder="输入Var值">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="moos-key">Key:</label>
|
||||||
|
<input type="text" id="moos-key" placeholder="输入Key值">
|
||||||
|
</div>
|
||||||
|
<button id="moos-send-btn">发送</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-column">
|
||||||
|
<h3>本地数据库</h3>
|
||||||
|
<div class="db-status" id="db-status">
|
||||||
|
<i class="fas fa-database"></i>
|
||||||
|
<span>正在连接数据库:</span>
|
||||||
|
</div>
|
||||||
|
<div class="db-size" id="db-size">
|
||||||
|
<i class="fas fa-database"></i>
|
||||||
|
<span>本地数据库大小:</span>
|
||||||
|
<span class="size-value">0.00 MB</span>
|
||||||
|
</div>
|
||||||
|
<div class="db-download">
|
||||||
|
<button id="download-db">
|
||||||
|
<i class="fas fa-download"></i>
|
||||||
|
下载数据库
|
||||||
|
</button>
|
||||||
|
<progress id="download-progress" value="0" max="100" style="display: none;"></progress>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-panel">
|
||||||
|
<button id="mode-switch">
|
||||||
|
<i class="fas fa-exchange-alt"></i>
|
||||||
|
系统模式切换
|
||||||
|
</button>
|
||||||
|
<button id="condition-switch">
|
||||||
|
<i class="fas fa-cogs"></i>
|
||||||
|
系统工况切换
|
||||||
|
</button>
|
||||||
|
<button id="system-reset">
|
||||||
|
<i class="fas fa-redo"></i>
|
||||||
|
系统复位操作
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel log-panel">
|
||||||
|
<h2>进程消息 <span class="badge" id="process-count">0</span></h2>
|
||||||
|
<div id="process-list" class="process-container"></div>
|
||||||
|
<pre id="log-data" class="process-log">
|
||||||
|
<template id="process-template">
|
||||||
|
<div class="process-entry">
|
||||||
|
<div class="process-name"></div>
|
||||||
|
<div class="message-list">
|
||||||
|
<div class="message-type">订阅的消息</div>
|
||||||
|
<ul class="subscribed-list"></ul>
|
||||||
|
<div class="message-type">发布的消息</div>
|
||||||
|
<ul class="published-list"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel state-machine-panel">
|
||||||
|
<h2>状态机状态</h2>
|
||||||
|
<div class="state-info">
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-clock"></i> 更新时间:</span>
|
||||||
|
<span class="state-value" id="state-time">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-hashtag"></i> 状态ID:</span>
|
||||||
|
<span class="state-value" id="state-id">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-tag"></i> 状态名称:</span>
|
||||||
|
<span class="state-value" id="state-name">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-bolt"></i> 事件:</span>
|
||||||
|
<span class="state-value" id="state-event">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-barcode"></i> 事件ID:</span>
|
||||||
|
<span class="state-value" id="state-event-id">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-exclamation-triangle"></i> 故障代码:</span>
|
||||||
|
<span class="state-value" id="state-fault-code">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
<div class="state-row">
|
||||||
|
<span class="state-label"><i class="fas fa-sticky-note"></i> 备注:</span>
|
||||||
|
<span class="state-value" id="state-note">正在加载...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel dis-sys-panel">
|
||||||
|
<h2>DIS系统状态</h2>
|
||||||
|
<pre id="dis-sys-state">正在加载...</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel ccu-state-panel">
|
||||||
|
<h2>CCU状态</h2>
|
||||||
|
<pre id="ccu-state">正在加载...</pre>
|
||||||
|
</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;">
|
||||||
|
<div class="message-detail-header">
|
||||||
|
<div class="message-detail-title">消息详情</div>
|
||||||
|
<div class="message-detail-close" id="message-detail-close">×</div>
|
||||||
|
</div>
|
||||||
|
<div class="message-detail-content">
|
||||||
|
<div class="message-detail-item">
|
||||||
|
<div class="message-detail-label">消息名称</div>
|
||||||
|
<div class="message-detail-value" id="message-name"></div>
|
||||||
|
</div>
|
||||||
|
<div class="message-detail-item">
|
||||||
|
<div class="message-detail-label">消息类型</div>
|
||||||
|
<div class="message-detail-value" id="message-type"></div>
|
||||||
|
</div>
|
||||||
|
<div class="message-detail-item">
|
||||||
|
<div class="message-detail-label">消息内容</div>
|
||||||
|
<div class="message-detail-value" id="message-content"></div>
|
||||||
|
</div>
|
||||||
|
<div class="message-detail-item">
|
||||||
|
<div class="message-detail-label">时间戳</div>
|
||||||
|
<div class="message-detail-value" id="message-timestamp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="message-detail-item">
|
||||||
|
<div class="message-detail-label">来源</div>
|
||||||
|
<div class="message-detail-value" id="message-source"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/static/script.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
INVOCATION_ABS_DIR=`pwd`
|
||||||
|
BUILD_TYPE="None"
|
||||||
|
CMD_LINE_ARGS=""
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
# Part 1: Check for and handle command-line arguments
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
for ARGI; do
|
||||||
|
if [ "${ARGI}" = "--help" -o "${ARGI}" = "-h" ] ; then
|
||||||
|
printf "%s [SWITCHES] \n" $0
|
||||||
|
printf "Switches: \n"
|
||||||
|
printf " --help, -h \n"
|
||||||
|
printf " --debug, -d \n"
|
||||||
|
printf " --release, -r \n"
|
||||||
|
printf "Notes: \n"
|
||||||
|
printf " (1) All other command line args will be passed as args \n"
|
||||||
|
printf " to \"make\" when it is eventually invoked. \n"
|
||||||
|
printf " (2) For example -k will continue making when/if a failure \n"
|
||||||
|
printf " is encountered in building one of the subdirectories. \n"
|
||||||
|
printf " (3) For example -j2 will utilize a 2nd core in the build \n"
|
||||||
|
printf " if your machine has two cores. -j4 etc for quad core. \n"
|
||||||
|
exit 0;
|
||||||
|
elif [ "${ARGI}" = "--debug" -o "${ARGI}" = "-d" ] ; then
|
||||||
|
BUILD_TYPE="Debug"
|
||||||
|
elif [ "${ARGI}" = "--release" -o "${ARGI}" = "-r" ] ; then
|
||||||
|
BUILD_TYPE="Release"
|
||||||
|
else
|
||||||
|
CMD_LINE_ARGS=$CMD_LINE_ARGS" "$ARGI
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
# Part 2: Invoke the call to make in the build directory
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ../
|
||||||
|
|
||||||
|
make ${CMD_LINE_ARGS}
|
||||||
|
cd ${INVOCATION_ABS_DIR}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
rm -rf build/*
|
||||||
|
rm -rf lib/*
|
||||||
|
rm -rf bin/p*
|
||||||
|
rm -f .DS_Store
|
||||||
|
rm -f missions/*/.LastOpenedMOOSLogDirectory
|
||||||
|
|
||||||
|
find . -name '.DS_Store' -print -exec rm -rfv {} \;
|
||||||
|
find . -name '*~' -print -exec rm -rfv {} \;
|
||||||
|
find . -name '#*' -print -exec rm -rfv {} \;
|
||||||
|
find . -name '*.moos++' -print -exec rm -rfv {} \;
|
||||||
|
|
||||||
|
find . -name 'MOOSLog*' -print -exec rm -rfv {} \;
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"value_array_uint16" :[2,1,3]
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"HVolABusBreaker_unit16": 0,
|
||||||
|
"HVolBBusBreaker_unit16": 79,
|
||||||
|
"HVolBusBreaker_uint16": 58,
|
||||||
|
"LVolBusBreaker_uint16": 159,
|
||||||
|
"faultCode_array":
|
||||||
|
[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"currentMod_uint8": 0,
|
||||||
|
"falutLevel_uint8": 0,
|
||||||
|
"faultCode_array":
|
||||||
|
[
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"powerState_uint8": 0,
|
||||||
|
"soc_uint32": 0,
|
||||||
|
"sustainableTime_uint32": 0,
|
||||||
|
"workCondition_uint8": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"powerCMD":0,
|
||||||
|
"modCMD":0,
|
||||||
|
"workCMD":0
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"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": "故障代码"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,637 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
{
|
||||||
|
"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)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
{
|
||||||
|
"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)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
{
|
||||||
|
"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)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
# PowerManager系统架构优化设计方案
|
||||||
|
|
||||||
|
## 1. 总体架构
|
||||||
|
```mermaid
|
||||||
|
classDiagram
|
||||||
|
class PowerManagerCore {
|
||||||
|
+startup()
|
||||||
|
+shutdown()
|
||||||
|
+getSystemState()
|
||||||
|
}
|
||||||
|
|
||||||
|
class StateMachineService {
|
||||||
|
+triggerEvent()
|
||||||
|
+getCurrentState()
|
||||||
|
+addStateListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
class CommunicationMediator {
|
||||||
|
+registerHandler()
|
||||||
|
+sendMessage()
|
||||||
|
+addMessageListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerManagerCore --> StateMachineService
|
||||||
|
PowerManagerCore --> CommunicationMediator
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 状态机重构方案
|
||||||
|
|
||||||
|
### 2.1 状态设计模式
|
||||||
|
```cpp
|
||||||
|
class IPowerState {
|
||||||
|
public:
|
||||||
|
virtual void onEntry(PowerContext&) = 0;
|
||||||
|
virtual void handleEvent(PowerContext&, const Event&) = 0;
|
||||||
|
virtual void onExit(PowerContext&) = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 状态转换规则
|
||||||
|
```yaml
|
||||||
|
# states_config.yaml
|
||||||
|
transitions:
|
||||||
|
- from: STANDBY
|
||||||
|
event: START_CMD
|
||||||
|
to: OPERATING
|
||||||
|
- from: OPERATING
|
||||||
|
event: STOP_CMD
|
||||||
|
to: STANDBY
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 通信中介者设计
|
||||||
|
|
||||||
|
### 3.1 核心架构
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant Upper as 上位机
|
||||||
|
participant Mediator as 通信中介者
|
||||||
|
participant Lower as 下位机
|
||||||
|
|
||||||
|
Upper->>Mediator: 控制命令(JSON)
|
||||||
|
Mediator->>Lower: 设备指令(ProtocolBuffer)
|
||||||
|
Lower->>Mediator: 状态更新
|
||||||
|
Mediator->>Upper: 系统报告
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 关键实现
|
||||||
|
```cpp
|
||||||
|
class CommunicationMediator {
|
||||||
|
// 线程安全消息队列
|
||||||
|
moodycamel::ConcurrentQueue<Message> queue;
|
||||||
|
|
||||||
|
// 消息处理线程
|
||||||
|
void processMessages() {
|
||||||
|
while (running) {
|
||||||
|
Message msg;
|
||||||
|
if (queue.try_dequeue(msg)) {
|
||||||
|
handlers[msg.type]->handle(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 数据库服务设计
|
||||||
|
|
||||||
|
### 4.1 日志策略模式
|
||||||
|
```cpp
|
||||||
|
class ILogStrategy {
|
||||||
|
public:
|
||||||
|
virtual bool log(const SystemLog& log) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SQLiteLogStrategy : public ILogStrategy {
|
||||||
|
// SQLite实现...
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileLogStrategy : public ILogStrategy {
|
||||||
|
// 文件系统实现...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. 实施计划
|
||||||
|
|
||||||
|
### 5.1 阶段划分
|
||||||
|
```mermaid
|
||||||
|
gantt
|
||||||
|
title 重构实施甘特图
|
||||||
|
section 核心框架
|
||||||
|
接口定义 :2025-04-08, 3d
|
||||||
|
基础实现 :2025-04-11, 5d
|
||||||
|
|
||||||
|
section 模块重构
|
||||||
|
状态机 :2025-04-16, 5d
|
||||||
|
通信模块 :2025-04-21, 5d
|
||||||
|
|
||||||
|
section 测试验证
|
||||||
|
单元测试 :2025-04-26, 3d
|
||||||
|
集成测试 :2025-04-29, 5d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. 性能指标
|
||||||
|
|
||||||
|
| 模块 | 当前QPS | 目标QPS | 优化手段 |
|
||||||
|
|----------------|---------|---------|-----------------------|
|
||||||
|
| 状态机处理 | 100 | 500 | 无锁状态转换 |
|
||||||
|
| 消息处理 | 200 | 1000 | 批量处理+线程池 |
|
||||||
|
| 数据库写入 | 50 | 300 | 异步写入+批量提交 |
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<testsuites name="H100PowerManger" tests="5" failures="0" time="1741">
|
|
||||||
<testsuite name="H100PowerManger CI" tests="5" failures="0" time="1741">
|
|
||||||
<testcase name="build_aarch64" classname="ci.build" time="1725">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
<testcase name="SQLiteTest" classname="ci.unit" time="0">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
<testcase name="PowerMangerTests" classname="ci.unit" time="1">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
<testcase name="SmokeTest_MOOSDB_pPowerManger" classname="ci.smoke" time="9">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
<testcase name="IntegrationTest_UDP_To_SQLite" classname="ci.integration" time="6">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
To Run this mission, make sure that the following two bin
|
||||||
|
directories are in your path:
|
||||||
|
|
||||||
|
moos-ivp/ivp/bin/
|
||||||
|
moos-ivp-extend/bin/
|
||||||
|
|
||||||
|
Then launch the mission by:
|
||||||
|
|
||||||
|
pAntler alder.moos
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//-------- FILE: alder.bhv -------------
|
||||||
|
|
||||||
|
initialize DEPLOY = false
|
||||||
|
initialize RETURN = false
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
Behavior = BHV_SimpleWaypoint
|
||||||
|
{
|
||||||
|
name = waypt_to_point
|
||||||
|
pwt = 100
|
||||||
|
condition = RETURN = false
|
||||||
|
condition = DEPLOY = true
|
||||||
|
endflag = RETURN = true
|
||||||
|
|
||||||
|
speed = 2.0 // meters per second
|
||||||
|
radius = 8.0
|
||||||
|
ptx = 100
|
||||||
|
pty = -50
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
Behavior = BHV_Waypoint
|
||||||
|
{
|
||||||
|
name = waypt_return
|
||||||
|
pwt = 100
|
||||||
|
condition = (RETURN = true)
|
||||||
|
condition = (DEPLOY = true)
|
||||||
|
|
||||||
|
speed = 2.0
|
||||||
|
radius = 8.0
|
||||||
|
point = 0,0
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
// Level 2 Configuration file: M. Benjamin
|
||||||
|
|
||||||
|
ServerHost = localhost
|
||||||
|
ServerPort = 9000
|
||||||
|
Simulator = true
|
||||||
|
|
||||||
|
Community = alder
|
||||||
|
|
||||||
|
MOOSTimeWarp = 1
|
||||||
|
|
||||||
|
LatOrigin = 43.825300
|
||||||
|
LongOrigin = -70.330400
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// Antler configuration block
|
||||||
|
ProcessConfig = ANTLER
|
||||||
|
{
|
||||||
|
MSBetweenLaunches = 200
|
||||||
|
|
||||||
|
Run = MOOSDB @ NewConsole = false
|
||||||
|
Run = uSimMarine @ NewConsole = false
|
||||||
|
Run = pNodeReporter @ NewConsole = false
|
||||||
|
Run = pMarinePID @ NewConsole = false
|
||||||
|
Run = pMarineViewer @ NewConsole = false
|
||||||
|
Run = uProcessWatch @ NewConsole = false
|
||||||
|
Run = pHelmIvP @ NewConsole = false
|
||||||
|
Run = pOdometry @ NewConsole = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// uSimMarine config block
|
||||||
|
|
||||||
|
ProcessConfig = uSimMarine
|
||||||
|
{
|
||||||
|
AppTick = 10
|
||||||
|
CommsTick = 10
|
||||||
|
|
||||||
|
START_X = 0
|
||||||
|
START_Y = 0
|
||||||
|
START_SPEED = 0
|
||||||
|
START_HEADING = 180
|
||||||
|
|
||||||
|
PREFIX = NAV
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// uProcessWatch config block
|
||||||
|
|
||||||
|
ProcessConfig = uProcessWatch
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
|
||||||
|
term_report_interval = 0.8
|
||||||
|
|
||||||
|
summary_wait = 5
|
||||||
|
|
||||||
|
nowatch = uXMS*
|
||||||
|
nowatch = uPokeDB*
|
||||||
|
nowatch = uTermCommand*
|
||||||
|
watch_all = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// pHelmIvP config block
|
||||||
|
|
||||||
|
ProcessConfig = pHelmIvP
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
|
||||||
|
Behaviors = alder.bhv
|
||||||
|
Verbose = quiet
|
||||||
|
Domain = course:0:359:360
|
||||||
|
Domain = speed:0:4:21
|
||||||
|
|
||||||
|
IVP_BEHAVIOR_DIR = ../../lib
|
||||||
|
//IVP_BEHAVIOR_DIR = /Users/mikerb/Research/moos-ivp-extend/trunk/lib
|
||||||
|
|
||||||
|
ok_skew = any
|
||||||
|
start_in_drive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// pMarinePID config block
|
||||||
|
|
||||||
|
ProcessConfig = pMarinePID
|
||||||
|
{
|
||||||
|
AppTick = 20
|
||||||
|
CommsTick = 20
|
||||||
|
|
||||||
|
VERBOSE = true
|
||||||
|
DEPTH_CONTROL = false
|
||||||
|
|
||||||
|
// Yaw PID controller
|
||||||
|
YAW_PID_KP = 0.5
|
||||||
|
YAW_PID_KD = 0.0
|
||||||
|
YAW_PID_KI = 0.0
|
||||||
|
YAW_PID_INTEGRAL_LIMIT = 0.07
|
||||||
|
|
||||||
|
// Speed PID controller
|
||||||
|
SPEED_PID_KP = 1.0
|
||||||
|
SPEED_PID_KD = 0.0
|
||||||
|
SPEED_PID_KI = 0.0
|
||||||
|
SPEED_PID_INTEGRAL_LIMIT = 0.07
|
||||||
|
|
||||||
|
//MAXIMUMS
|
||||||
|
MAXRUDDER = 100
|
||||||
|
MAXTHRUST = 100
|
||||||
|
|
||||||
|
// A non-zero SPEED_FACTOR overrides use of SPEED_PID
|
||||||
|
// Will set DESIRED_THRUST = DESIRED_SPEED * SPEED_FACTOR
|
||||||
|
SPEED_FACTOR = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// pMarineViewer config block
|
||||||
|
|
||||||
|
ProcessConfig = pMarineViewer
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
|
||||||
|
TIFF_FILE = forrest19.tif
|
||||||
|
set_pan_x = -90
|
||||||
|
set_pan_y = -280
|
||||||
|
zoom = 0.65
|
||||||
|
vehicle_shape_scale = 1.5
|
||||||
|
hash_delta = 50
|
||||||
|
hash_shade = 0.4
|
||||||
|
hash_viewable = true
|
||||||
|
|
||||||
|
scope = ODOMETRY_DIST
|
||||||
|
|
||||||
|
// Appcast configuration
|
||||||
|
appcast_height = 75
|
||||||
|
appcast_width = 30
|
||||||
|
appcast_viewable = true
|
||||||
|
appcast_color_scheme = indigo
|
||||||
|
nodes_font_size = medium
|
||||||
|
procs_font_size = medium
|
||||||
|
appcast_font_size = small
|
||||||
|
|
||||||
|
BUTTON_ONE = DEPLOY # DEPLOY=true
|
||||||
|
BUTTON_ONE = MOOS_MANUAL_OVERIDE=false # RETURN=false
|
||||||
|
BUTTON_TWO = RETURN # RETURN=true
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// pNodeReporter config block
|
||||||
|
|
||||||
|
ProcessConfig = pNodeReporter
|
||||||
|
{
|
||||||
|
AppTick = 2
|
||||||
|
CommsTick = 2
|
||||||
|
VESSEL_TYPE = KAYAK
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//-------- FILE: alder.bhv -------------
|
||||||
|
|
||||||
|
initialize DEPLOY = false
|
||||||
|
initialize RETURN = false
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
Behavior = BHV_SimpleWaypoint
|
||||||
|
{
|
||||||
|
name = waypt_to_point
|
||||||
|
pwt = 100
|
||||||
|
condition = RETURN = false
|
||||||
|
condition = DEPLOY = true
|
||||||
|
endflag = RETURN = true
|
||||||
|
|
||||||
|
speed = 2.0 // meters per second
|
||||||
|
radius = 8.0
|
||||||
|
ptx = 100
|
||||||
|
pty = -50
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
Behavior = BHV_SimpleWaypoint
|
||||||
|
{
|
||||||
|
name = waypt_return
|
||||||
|
pwt = 100
|
||||||
|
condition = (RETURN = true)
|
||||||
|
condition = (DEPLOY = true)
|
||||||
|
|
||||||
|
speed = 2.0
|
||||||
|
radius = 8.0
|
||||||
|
ptx = 0
|
||||||
|
pty = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------
|
||||||
|
Behavior = BHV_HSLine
|
||||||
|
{
|
||||||
|
name = hsline
|
||||||
|
time_on_leg = 20
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ProcessConfig = pPowerManger
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// MOOS file
|
||||||
|
|
||||||
|
ServerHost = localhost
|
||||||
|
ServerPort = 9000
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// Antler configuration block
|
||||||
|
ProcessConfig = ANTLER
|
||||||
|
{
|
||||||
|
MSBetweenLaunches = 200
|
||||||
|
|
||||||
|
Run = MOOSDB @ NewConsole = false
|
||||||
|
Run = pXRelay @ NewConsole = true ~ pXRelay_APPLES
|
||||||
|
Run = pXRelay @ NewConsole = true ~ pXRelay_PEARS
|
||||||
|
Run = uXMS @ NewConsole = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// First pXRelay configuration block
|
||||||
|
|
||||||
|
ProcessConfig = pXRelay_APPLES
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
|
||||||
|
OUTGOING_VAR = APPLES
|
||||||
|
INCOMING_VAR = PEARS
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// Second pXRelay configuration block
|
||||||
|
|
||||||
|
ProcessConfig = pXRelay_PEARS
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
|
||||||
|
OUTGOING_VAR = PEARS
|
||||||
|
INCOMING_VAR = APPLES
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// uXMS configuration block
|
||||||
|
|
||||||
|
ProcessConfig = uXMS
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
|
||||||
|
VAR = PEARS, PEARS_ITER_HZ, PEARS_POST_HZ
|
||||||
|
VAR = APPLES, APPLES_ITER_HZ, APPLES_POST_HZ
|
||||||
|
}
|
||||||
|
|
||||||
Executable
+401
@@ -0,0 +1,401 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -d "$2$1" ]; then
|
||||||
|
echo "$2$1 already exists... quitting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$1" ] ; then
|
||||||
|
echo "GenMOOSApp: usage: $0 [app-name] [prefix]"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$2" ] ; then
|
||||||
|
echo "GenMOOSApp: usage: $0 [app-name] [prefix]"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
#if [ -z "$3" ] ; then
|
||||||
|
# $3="YOUR-NAME-HERE"
|
||||||
|
#fi
|
||||||
|
|
||||||
|
mkdir $2$1
|
||||||
|
cd $2$1
|
||||||
|
|
||||||
|
cat > CMakeLists.txt <<EOF
|
||||||
|
#--------------------------------------------------------
|
||||||
|
# The CMakeLists.txt for: $2$1
|
||||||
|
# Author(s): $3
|
||||||
|
#--------------------------------------------------------
|
||||||
|
|
||||||
|
SET(SRC
|
||||||
|
${1}.cpp
|
||||||
|
${1}_Info.cpp
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE($2$1 \${SRC})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES($2$1
|
||||||
|
\${MOOS_LIBRARIES}
|
||||||
|
mbutil
|
||||||
|
m
|
||||||
|
pthread)
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > ${1}.h <<EOF
|
||||||
|
/************************************************************/
|
||||||
|
/* NAME: $3 */
|
||||||
|
/* ORGN: MIT */
|
||||||
|
/* FILE: ${1}.h */
|
||||||
|
/* DATE: */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
#ifndef ${1}_HEADER
|
||||||
|
#define ${1}_HEADER
|
||||||
|
|
||||||
|
#include "MOOS/libMOOS/MOOSLib.h"
|
||||||
|
|
||||||
|
class ${1} : public CMOOSApp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
${1}();
|
||||||
|
~${1}();
|
||||||
|
|
||||||
|
protected: // Standard MOOSApp functions to overload
|
||||||
|
bool OnNewMail(MOOSMSG_LIST &NewMail);
|
||||||
|
bool Iterate();
|
||||||
|
bool OnConnectToServer();
|
||||||
|
bool OnStartUp();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void RegisterVariables();
|
||||||
|
|
||||||
|
private: // Configuration variables
|
||||||
|
|
||||||
|
private: // State variables
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > main.cpp <<EOF
|
||||||
|
/************************************************************/
|
||||||
|
/* NAME: $3 */
|
||||||
|
/* ORGN: MIT */
|
||||||
|
/* FILE: main.cpp */
|
||||||
|
/* DATE: */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "MBUtils.h"
|
||||||
|
#include "ColorParse.h"
|
||||||
|
#include "${1}.h"
|
||||||
|
#include "${1}_Info.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
cout << termColor("green");
|
||||||
|
cout << "${2}${1} launching as " << run_command << endl;
|
||||||
|
cout << termColor() << endl;
|
||||||
|
|
||||||
|
${1} ${1};
|
||||||
|
|
||||||
|
${1}.Run(run_command.c_str(), mission_file.c_str());
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > $2${1}.moos <<EOF
|
||||||
|
//------------------------------------------------
|
||||||
|
// ${2}${1} config block
|
||||||
|
|
||||||
|
ProcessConfig = ${2}${1}
|
||||||
|
{
|
||||||
|
AppTick = 4
|
||||||
|
CommsTick = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > ${1}.cpp <<EOF
|
||||||
|
/************************************************************/
|
||||||
|
/* NAME: $3 */
|
||||||
|
/* ORGN: MIT */
|
||||||
|
/* FILE: ${1}.cpp */
|
||||||
|
/* DATE: */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include "MBUtils.h"
|
||||||
|
#include "${1}.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Constructor
|
||||||
|
|
||||||
|
${1}::${1}()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
${1}::~${1}()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Procedure: OnNewMail
|
||||||
|
|
||||||
|
bool ${1}::OnNewMail(MOOSMSG_LIST &NewMail)
|
||||||
|
{
|
||||||
|
MOOSMSG_LIST::iterator p;
|
||||||
|
|
||||||
|
for(p=NewMail.begin(); p!=NewMail.end(); p++) {
|
||||||
|
CMOOSMsg &msg = *p;
|
||||||
|
|
||||||
|
#if 0 // Keep these around just for template
|
||||||
|
string key = msg.GetKey();
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Procedure: OnConnectToServer
|
||||||
|
|
||||||
|
bool ${1}::OnConnectToServer()
|
||||||
|
{
|
||||||
|
RegisterVariables();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Procedure: Iterate()
|
||||||
|
// happens AppTick times per second
|
||||||
|
|
||||||
|
bool ${1}::Iterate()
|
||||||
|
{
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Procedure: OnStartUp()
|
||||||
|
// happens before connection is open
|
||||||
|
|
||||||
|
bool ${1}::OnStartUp()
|
||||||
|
{
|
||||||
|
list<string> sParams;
|
||||||
|
m_MissionReader.EnableVerbatimQuoting(false);
|
||||||
|
if(m_MissionReader.GetConfiguration(GetAppName(), sParams)) {
|
||||||
|
list<string>::iterator p;
|
||||||
|
for(p=sParams.begin(); p!=sParams.end(); p++) {
|
||||||
|
string line = *p;
|
||||||
|
string param = tolower(biteStringX(line, '='));
|
||||||
|
string value = line;
|
||||||
|
|
||||||
|
if(param == "foo") {
|
||||||
|
//handled
|
||||||
|
}
|
||||||
|
else if(param == "bar") {
|
||||||
|
//handled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterVariables();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Procedure: RegisterVariables
|
||||||
|
|
||||||
|
void ${1}::RegisterVariables()
|
||||||
|
{
|
||||||
|
// Register("FOOBAR", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
cat > ${1}_Info.h <<EOF
|
||||||
|
/****************************************************************/
|
||||||
|
/* NAME: ${3} */
|
||||||
|
/* ORGN: MIT Cambridge MA */
|
||||||
|
/* FILE: ${1}_Info.h */
|
||||||
|
/* DATE: Dec 29th 1963 */
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
#ifndef ${1}_INFO_HEADER
|
||||||
|
#define ${1}_INFO_HEADER
|
||||||
|
|
||||||
|
void showSynopsis();
|
||||||
|
void showHelpAndExit();
|
||||||
|
void showExampleConfigAndExit();
|
||||||
|
void showInterfaceAndExit();
|
||||||
|
void showReleaseInfoAndExit();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
cat > ${1}_Info.cpp <<EOF
|
||||||
|
/****************************************************************/
|
||||||
|
/* NAME: ${3} */
|
||||||
|
/* ORGN: MIT Cambridge MA */
|
||||||
|
/* FILE: ${1}_Info.cpp */
|
||||||
|
/* DATE: Dec 29th 1963 */
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include "${1}_Info.h"
|
||||||
|
#include "ColorParse.h"
|
||||||
|
#include "ReleaseInfo.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Procedure: showSynopsis
|
||||||
|
|
||||||
|
void showSynopsis()
|
||||||
|
{
|
||||||
|
blk("SYNOPSIS: ");
|
||||||
|
blk("------------------------------------ ");
|
||||||
|
blk(" The ${2}${1} application is used for ");
|
||||||
|
blk(" ");
|
||||||
|
blk(" ");
|
||||||
|
blk(" ");
|
||||||
|
blk(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Procedure: showHelpAndExit
|
||||||
|
|
||||||
|
void showHelpAndExit()
|
||||||
|
{
|
||||||
|
blk(" ");
|
||||||
|
blu("=============================================================== ");
|
||||||
|
blu("Usage: ${2}${1} file.moos [OPTIONS] ");
|
||||||
|
blu("=============================================================== ");
|
||||||
|
blk(" ");
|
||||||
|
showSynopsis();
|
||||||
|
blk(" ");
|
||||||
|
blk("Options: ");
|
||||||
|
mag(" --alias","=<ProcessName> ");
|
||||||
|
blk(" Launch ${2}${1} with the given process name ");
|
||||||
|
blk(" rather than ${2}${1}. ");
|
||||||
|
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 ${2}${1}. ");
|
||||||
|
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("${2}${1} Example MOOS Configuration ");
|
||||||
|
blu("=============================================================== ");
|
||||||
|
blk(" ");
|
||||||
|
blk("ProcessConfig = ${2}${1} ");
|
||||||
|
blk("{ ");
|
||||||
|
blk(" AppTick = 4 ");
|
||||||
|
blk(" CommsTick = 4 ");
|
||||||
|
blk(" ");
|
||||||
|
blk("} ");
|
||||||
|
blk(" ");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Procedure: showInterfaceAndExit
|
||||||
|
|
||||||
|
void showInterfaceAndExit()
|
||||||
|
{
|
||||||
|
blk(" ");
|
||||||
|
blu("=============================================================== ");
|
||||||
|
blu("${2}${1} 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("${2}${1}", "gpl");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
echo "$2${1} generated"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
This directory may contain developer utility scripts.
|
||||||
|
|
||||||
|
The MyGenMOOSApp script is similar to that found in the moos-ivp/trunk/scripts/
|
||||||
|
directory. Users are encouraged to tailor this one to their own needs.
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
##############################################################################
|
||||||
|
# FILE: moos-ivp-extend/src/CMakeLists.txt
|
||||||
|
# DATE: 2010/09/07
|
||||||
|
# 2020/05/09 minor mods
|
||||||
|
# DESCRIPTION: CMakeLists.txt file for the moos-ivp-extend source directory
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
#============================================================================
|
||||||
|
# Add the libraries in the current directory to the include path
|
||||||
|
#============================================================================
|
||||||
|
FILE(GLOB LOCAL_LIBRARY_DIRS ./lib_*)
|
||||||
|
INCLUDE_DIRECTORIES(${LOCAL_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
#============================================================================
|
||||||
|
# List the subdirectories to build...
|
||||||
|
#============================================================================
|
||||||
|
ADD_SUBDIRECTORY(pPowerManger)
|
||||||
|
ADD_SUBDIRECTORY(appPowerMangerWebUI)
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# END of CMakeLists.txt
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#--------------------------------------------------------
|
||||||
|
# The CMakeLists.txt for: appPowerMangerWebUI
|
||||||
|
# Author(s):
|
||||||
|
#--------------------------------------------------------
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# 设置 vcpkg 工具链文件路径
|
||||||
|
set(CMAKE_TOOLCHAIN_FILE "/home/zjk/project/lib/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
|
||||||
|
|
||||||
|
# 查找Boost库
|
||||||
|
find_package(Boost REQUIRED COMPONENTS system thread)
|
||||||
|
|
||||||
|
#find crow库
|
||||||
|
find_package(Crow CONFIG REQUIRED)
|
||||||
|
# Find SQLite3 package
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
|
||||||
|
SET(SRC
|
||||||
|
main.cpp
|
||||||
|
DBImage.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(appPowerMangerWebUI ${SRC})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(appPowerMangerWebUI
|
||||||
|
${MOOS_LIBRARIES}
|
||||||
|
mbutil
|
||||||
|
m
|
||||||
|
pthread
|
||||||
|
Crow::Crow
|
||||||
|
asio::asio
|
||||||
|
jsoncpp
|
||||||
|
SQLiteDB
|
||||||
|
sqlite3
|
||||||
|
Boost::system
|
||||||
|
Boost::thread)
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// MOOS - Mission Oriented Operating Suite
|
||||||
|
//
|
||||||
|
// A suit of Applications and Libraries for Mobile Robotics Research
|
||||||
|
// Copyright (C) 2001-2005 Massachusetts Institute of Technology and
|
||||||
|
// Oxford University.
|
||||||
|
//
|
||||||
|
// This software was written by Paul Newman at MIT 2001-2002 and Oxford
|
||||||
|
// University 2003-2005. email: pnewman@robots.ox.ac.uk.
|
||||||
|
//
|
||||||
|
// This file is part of a MOOS Utility Component.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
// 02111-1307, USA.
|
||||||
|
//
|
||||||
|
////////////////////////// END_GPL //////////////////////////////////
|
||||||
|
// DBImage.cpp: implementation of the CDBImage class.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "DBImage.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Construction/Destruction
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool CDBImage::Set(MOOSMSG_LIST & InMail)
|
||||||
|
{
|
||||||
|
MOOSMSG_LIST::iterator p;
|
||||||
|
|
||||||
|
|
||||||
|
m_Lock.Lock();
|
||||||
|
//MOOSTrace("Rx'd %d \n",InMail.size());
|
||||||
|
|
||||||
|
for(p = InMail.begin();p!=InMail.end();p++)
|
||||||
|
{
|
||||||
|
CMOOSMsg & rMsg= *p;
|
||||||
|
//MOOSTrace("Rx'd %s \n",rMsg.m_sKey.c_str());
|
||||||
|
|
||||||
|
if(!m_Mask.empty() && m_Mask.find(rMsg.GetSource())!=m_Mask.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rMsg.IsDataType(MOOS_NOT_SET) && !m_bShowPending)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nNdx = GetIndex(rMsg.m_sKey);
|
||||||
|
if(nNdx<0)
|
||||||
|
{
|
||||||
|
m_IndexMap[rMsg.m_sKey] = m_DBData.size();
|
||||||
|
m_DBData.push_back(CVar(rMsg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool bChanging = !( rMsg.GetTime()==m_DBData[nNdx].GetTimeVal());
|
||||||
|
m_DBData[nNdx]= CVar(rMsg);
|
||||||
|
m_DBData[nNdx].Changed(bChanging);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_Lock.UnLock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int CDBImage::GetIndex(const std::string & sName)
|
||||||
|
{
|
||||||
|
std::map<std::string,int>::iterator q = m_IndexMap.find(sName);
|
||||||
|
|
||||||
|
if(q!=m_IndexMap.end())
|
||||||
|
{
|
||||||
|
int n = q->second;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDBImage:: HasChanged(int n)
|
||||||
|
{
|
||||||
|
if(n >= static_cast<int> (m_DBData.size()) || n<0)
|
||||||
|
return false;
|
||||||
|
return m_DBData[n].IsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDBImage::Get(CVar & rVar, int n)
|
||||||
|
{
|
||||||
|
m_Lock.Lock();
|
||||||
|
|
||||||
|
if(n>=static_cast<int> (m_DBData.size()) || n<0)
|
||||||
|
{
|
||||||
|
m_Lock.UnLock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rVar = m_DBData[n];
|
||||||
|
|
||||||
|
m_Lock.UnLock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDBImage::SetProcInfo(MOOSMSG_LIST & InMail)
|
||||||
|
{
|
||||||
|
m_Lock.Lock();
|
||||||
|
// TODO: Add your control notification handler code here
|
||||||
|
m_nClients = InMail.size();
|
||||||
|
m_Processes.clear();
|
||||||
|
MOOSMSG_LIST::iterator p;
|
||||||
|
for(p=InMail.begin();p!=InMail.end();p++)
|
||||||
|
{
|
||||||
|
|
||||||
|
CMOOSMsg & rMsg = *p;
|
||||||
|
std::string sTmp = rMsg.m_sVal;
|
||||||
|
std::string sWho = MOOSChomp(sTmp,":");
|
||||||
|
|
||||||
|
if(m_Processes.find(sWho)==m_Processes.end())
|
||||||
|
{
|
||||||
|
ProcInfo Info;
|
||||||
|
m_Processes[sWho] = Info;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sSubscribed,sPublished;
|
||||||
|
sSubscribed = MOOSChomp(sTmp,"PUBLISHED=");
|
||||||
|
sPublished = sTmp;
|
||||||
|
MOOSChomp(sSubscribed,"SUBSCRIBED=");
|
||||||
|
|
||||||
|
while(!sSubscribed.empty())
|
||||||
|
{
|
||||||
|
sTmp = MOOSChomp(sSubscribed,",");
|
||||||
|
if(!sTmp.empty())
|
||||||
|
{
|
||||||
|
m_Processes[sWho].m_Subscribed.push_front(sTmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!sPublished.empty())
|
||||||
|
{
|
||||||
|
sTmp = MOOSChomp(sPublished,",");
|
||||||
|
if(!sTmp.empty())
|
||||||
|
{
|
||||||
|
m_Processes[sWho].m_Published.push_front(sTmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_Lock.UnLock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDBImage::GetProcInfo(const std::string & sWhat,STRING_LIST & sSubs,STRING_LIST & sPubs)
|
||||||
|
{
|
||||||
|
bool bRes = false;
|
||||||
|
m_Lock.Lock();
|
||||||
|
PROC_INFO_MAP::iterator q = m_Processes.find(sWhat);
|
||||||
|
if(q!=m_Processes.end())
|
||||||
|
{
|
||||||
|
sSubs = q->second.m_Subscribed;
|
||||||
|
sPubs = q->second.m_Published;
|
||||||
|
bRes = true;
|
||||||
|
}
|
||||||
|
m_Lock.UnLock();
|
||||||
|
return bRes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDBImage::GetProcesses(STRING_LIST & sProcs)
|
||||||
|
{
|
||||||
|
m_Lock.Lock();
|
||||||
|
|
||||||
|
sProcs.clear();
|
||||||
|
|
||||||
|
PROC_INFO_MAP::iterator q;
|
||||||
|
for(q=m_Processes.begin();q!=m_Processes.end();q++)
|
||||||
|
{
|
||||||
|
sProcs.push_back(q->first.c_str());
|
||||||
|
}
|
||||||
|
m_Lock.UnLock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDBImage::SetMask(std::set<std::string> Mask)
|
||||||
|
{
|
||||||
|
m_Mask = Mask;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDBImage::Clear()
|
||||||
|
{
|
||||||
|
m_Lock.Lock();
|
||||||
|
m_DBData.clear();
|
||||||
|
m_IndexMap.clear();
|
||||||
|
m_Lock.UnLock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// MOOS - Mission Oriented Operating Suite
|
||||||
|
//
|
||||||
|
// A suit of Applications and Libraries for Mobile Robotics Research
|
||||||
|
// Copyright (C) 2001-2005 Massachusetts Institute of Technology and
|
||||||
|
// Oxford University.
|
||||||
|
//
|
||||||
|
// This software was written by Paul Newman at MIT 2001-2002 and Oxford
|
||||||
|
// University 2003-2005. email: pnewman@robots.ox.ac.uk.
|
||||||
|
//
|
||||||
|
// This file is part of a MOOS Utility Component.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
// 02111-1307, USA.
|
||||||
|
//
|
||||||
|
////////////////////////// END_GPL //////////////////////////////////
|
||||||
|
// DBImage.h: interface for the CDBImage class.
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning(disable : 4786)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(AFX_DBIMAGE_H__E4F9EC4D_7049_4EC8_86BA_0AF21BBCA23C__INCLUDED_)
|
||||||
|
|
||||||
|
#define AFX_DBIMAGE_H__E4F9EC4D_7049_4EC8_86BA_0AF21BBCA23C__INCLUDED_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif // _MSC_VER > 1000
|
||||||
|
|
||||||
|
#include "MOOS/libMOOS/MOOSLib.h"
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
class CDBImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Clear();
|
||||||
|
|
||||||
|
CDBImage()
|
||||||
|
{
|
||||||
|
m_bShowPending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProcInfo
|
||||||
|
{
|
||||||
|
std::string m_sName;
|
||||||
|
STRING_LIST m_Published;
|
||||||
|
STRING_LIST m_Subscribed;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string,ProcInfo> PROC_INFO_MAP;
|
||||||
|
|
||||||
|
class CVar
|
||||||
|
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CVar()
|
||||||
|
{
|
||||||
|
m_dfTime = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVar(CMOOSMsg & rMsg)
|
||||||
|
{
|
||||||
|
m_dfTime = rMsg.m_dfTime;
|
||||||
|
switch(rMsg.m_cDataType)
|
||||||
|
{
|
||||||
|
case MOOS_STRING:
|
||||||
|
m_eType = STR;
|
||||||
|
break;
|
||||||
|
case MOOS_DOUBLE:
|
||||||
|
m_eType = DBL;
|
||||||
|
break;
|
||||||
|
case MOOS_BINARY_STRING:
|
||||||
|
m_eType = BIN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_eType = UNKNOWN;
|
||||||
|
}
|
||||||
|
m_sStr = rMsg.GetAsString();
|
||||||
|
m_sCommunity = rMsg.m_sOriginatingCommunity;
|
||||||
|
m_sName = rMsg.m_sKey;
|
||||||
|
m_sFreq = MOOSFormat("%.1f",rMsg.m_dfVal2);
|
||||||
|
m_sSource = rMsg.m_sSrc;
|
||||||
|
m_bChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetTime(){return MOOSFormat("%.3f",m_dfTime);};
|
||||||
|
double GetTimeVal(){return m_dfTime;};
|
||||||
|
std::string GetValue(){return m_eType==UNKNOWN?"":m_sStr;};
|
||||||
|
std::string GetCommunity(){return m_sCommunity;};
|
||||||
|
std::string GetName(){return m_sName;};
|
||||||
|
std::string GetFrequency(){return m_sFreq;};
|
||||||
|
std::string GetSource(){return m_sSource;};
|
||||||
|
bool IsChanged(){return m_bChanged;};
|
||||||
|
void Changed(bool b){m_bChanged = b;};
|
||||||
|
std::string GetType()
|
||||||
|
{
|
||||||
|
switch(m_eType)
|
||||||
|
{
|
||||||
|
case STR:
|
||||||
|
return "$";
|
||||||
|
case DBL:
|
||||||
|
return "D";
|
||||||
|
case BIN:
|
||||||
|
return "B";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double m_dfTime;
|
||||||
|
std::string m_sStr;
|
||||||
|
enum Type{ STR,DBL,BIN,UNKNOWN};
|
||||||
|
Type m_eType;
|
||||||
|
std::string m_sCommunity;
|
||||||
|
std::string m_sSrc;
|
||||||
|
std::string m_sName;
|
||||||
|
std::string m_sFreq;
|
||||||
|
std::string m_sSource;
|
||||||
|
bool m_bChanged;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Set(MOOSMSG_LIST & InMail);
|
||||||
|
bool Get(CVar & rVar, int n);
|
||||||
|
bool HasChanged(int n);
|
||||||
|
bool SetProcInfo(MOOSMSG_LIST & InMail) ;
|
||||||
|
bool GetProcesses(STRING_LIST & sProcs);
|
||||||
|
int GetNumVariables(){return m_DBData.size();}
|
||||||
|
bool GetProcInfo(const std::string & sWhat,STRING_LIST & sSubs,STRING_LIST & sPubs);
|
||||||
|
bool SetMask(std::set<std::string> Mask);
|
||||||
|
bool ShowPending(bool b){m_bShowPending = b;return true;};
|
||||||
|
protected:
|
||||||
|
int GetIndex(const std::string & sName);
|
||||||
|
std::vector<CVar> m_DBData;
|
||||||
|
std::map<std::string,int> m_IndexMap;
|
||||||
|
std::set<std::string> m_Mask;
|
||||||
|
|
||||||
|
bool m_bShowPending ;
|
||||||
|
int m_nClients;
|
||||||
|
int m_nVariables;
|
||||||
|
PROC_INFO_MAP m_Processes;
|
||||||
|
CMOOSLock m_Lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !defined(AFX_DBIMAGE_H__E4F9EC4D_7049_4EC8_86BA_0AF21BBCA23C__INCLUDED_)
|
||||||
|
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
#include <string>
|
||||||
|
#include "crow.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include "json/json.h"
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
#include "../pPowerManger/SQLiteDB.h"
|
||||||
|
#include "../pPowerManger/pmSysvariable.h"
|
||||||
|
#include <MOOS/libMOOS/Comms/MOOSAsyncCommClient.h>
|
||||||
|
#include "DBImage.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// 定义全局变量
|
||||||
|
ccuState ccustate;
|
||||||
|
StateData stateData;
|
||||||
|
mutex wsMutex;
|
||||||
|
vector<crow::websocket::connection*> wsConnections;
|
||||||
|
shared_ptr<SQLiteDB> db;
|
||||||
|
shared_ptr<MOOS::MOOSAsyncCommClient> moosClient;
|
||||||
|
shared_ptr<CDBImage> dbImage;
|
||||||
|
|
||||||
|
bool bContinue = true;
|
||||||
|
|
||||||
|
// WebSocket消息处理
|
||||||
|
void sendStateUpdate() {
|
||||||
|
crow::json::wvalue msg;
|
||||||
|
string time;
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lock(wsMutex);
|
||||||
|
db->getStateData(stateData, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 基本状态信息
|
||||||
|
msg["state"] = {
|
||||||
|
{"time", time},
|
||||||
|
{"state_id", stateData.state_id},
|
||||||
|
{"state_name", stateData.state_name},
|
||||||
|
{"event", stateData.event},
|
||||||
|
{"event_id", stateData.event_id},
|
||||||
|
{"fault_code", stateData.fault_code},
|
||||||
|
{"note", stateData.note}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数据库状态信息
|
||||||
|
msg["db_status"] = {
|
||||||
|
{"connected", db->isDatabaseConnected("/home/zjk/project/H100/H100PowerManger/data", "power_data.db")},
|
||||||
|
{"database", db->getDBPatch()},
|
||||||
|
{"size", db->getDatabaseSize()}
|
||||||
|
};
|
||||||
|
|
||||||
|
// MOOS数据库状态信息
|
||||||
|
msg["moos_db_status"] = {
|
||||||
|
{"connected", moosClient->IsConnected()},
|
||||||
|
{"host", "localhost"},
|
||||||
|
{"port", 9000}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 进程详细信息
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lock(wsMutex);
|
||||||
|
STRING_LIST processes;
|
||||||
|
dbImage->GetProcesses(processes);
|
||||||
|
|
||||||
|
crow::json::wvalue::list processList;
|
||||||
|
for(const auto& proc : processes) {
|
||||||
|
STRING_LIST subs, pubs;
|
||||||
|
if(dbImage->GetProcInfo(proc, subs, pubs)) {
|
||||||
|
crow::json::wvalue processInfo;
|
||||||
|
processInfo["name"] = proc;
|
||||||
|
std::vector<std::string> subs_vec(subs.begin(), subs.end());
|
||||||
|
std::vector<std::string> pubs_vec(pubs.begin(), pubs.end());
|
||||||
|
processInfo["subscribed"] = subs_vec;
|
||||||
|
processInfo["published"] = pubs_vec;
|
||||||
|
processList.push_back(std::move(processInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg["processes"] = {
|
||||||
|
{"count", processes.size()},
|
||||||
|
{"list", std::move(processList)}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据库变量信息
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lock(wsMutex);
|
||||||
|
int varCount = dbImage->GetNumVariables();
|
||||||
|
crow::json::wvalue::list varList;
|
||||||
|
|
||||||
|
// 遍历所有变量
|
||||||
|
for(int i = 0; i < varCount; i++) {
|
||||||
|
CDBImage::CVar var;
|
||||||
|
if(dbImage->Get(var, i)) {
|
||||||
|
varList.push_back({
|
||||||
|
{"name", var.GetName()},
|
||||||
|
{"value", var.GetValue()},
|
||||||
|
{"time", var.GetTime()},
|
||||||
|
{"type", var.GetType()},
|
||||||
|
{"source", var.GetSource()}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg["variables"] = {
|
||||||
|
{"count", varCount},
|
||||||
|
{"data", std::move(varList)} // 包含所有变量的数组
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送WebSocket消息
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lock(wsMutex);
|
||||||
|
for(auto conn : wsConnections) {
|
||||||
|
conn->send_text(msg.dump());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅MOOS变量
|
||||||
|
bool FetchLoop(MOOS::MOOSAsyncCommClient* comms, CDBImage* m_DBImage)
|
||||||
|
{
|
||||||
|
int nCounts = 0;
|
||||||
|
while(true) // 外部需要控制循环退出条件
|
||||||
|
{
|
||||||
|
if(comms->IsConnected())
|
||||||
|
{
|
||||||
|
// 每5次循环获取一次进程摘要
|
||||||
|
if(nCounts++ % 5 == 0)
|
||||||
|
{
|
||||||
|
MOOSMSG_LIST procMail;
|
||||||
|
if(comms->ServerRequest("PROC_SUMMARY", procMail))
|
||||||
|
{
|
||||||
|
m_DBImage->SetProcInfo(procMail);
|
||||||
|
|
||||||
|
// 打印进程信息
|
||||||
|
// STRING_LIST processes;
|
||||||
|
// m_DBImage->GetProcesses(processes);
|
||||||
|
// std::cout << "Active processes: " << processes.size() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每次循环都获取数据库摘要
|
||||||
|
MOOSMSG_LIST dbMail;
|
||||||
|
if(comms->ServerRequest("ALL", dbMail))
|
||||||
|
{
|
||||||
|
m_DBImage->Set(dbMail);
|
||||||
|
|
||||||
|
// 打印数据库变量信息
|
||||||
|
int varCount = m_DBImage->GetNumVariables();
|
||||||
|
// std::cout << "Database variables: " << varCount << std::endl;
|
||||||
|
|
||||||
|
// 打印最近更新的变量
|
||||||
|
if(varCount > 0) {
|
||||||
|
CDBImage::CVar lastVar;
|
||||||
|
if(m_DBImage->Get(lastVar, varCount-1)) {
|
||||||
|
// std::cout << "Last updated variable: "
|
||||||
|
// << lastVar.GetName() << " = "
|
||||||
|
// << lastVar.GetValue() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保持大约4Hz的频率
|
||||||
|
MOOSPause(250);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
crow::SimpleApp app;
|
||||||
|
db = make_shared<SQLiteDB>("/home/zjk/project/H100/H100PowerManger/data/power_data.db");
|
||||||
|
moosClient = make_shared<MOOS::MOOSAsyncCommClient>();
|
||||||
|
dbImage = make_shared<CDBImage>();
|
||||||
|
moosClient->Run("localhost", 9000, "appPowerMangerWebUI");
|
||||||
|
|
||||||
|
// WebSocket路由
|
||||||
|
CROW_WEBSOCKET_ROUTE(app, "/ws/state")
|
||||||
|
.onopen([&](crow::websocket::connection& conn){
|
||||||
|
lock_guard<mutex> lock(wsMutex);
|
||||||
|
wsConnections.push_back(&conn);
|
||||||
|
cout << "New WebSocket connection" << endl;
|
||||||
|
})
|
||||||
|
.onclose([&](crow::websocket::connection& conn, const string& /*reason*/, uint16_t /*code*/){
|
||||||
|
lock_guard<mutex> lock(wsMutex);
|
||||||
|
wsConnections.erase(
|
||||||
|
remove(wsConnections.begin(), wsConnections.end(), &conn),
|
||||||
|
wsConnections.end());
|
||||||
|
cout << "WebSocket connection closed" << endl;
|
||||||
|
})
|
||||||
|
.onmessage([&](crow::websocket::connection& conn, const string& data, bool is_binary){
|
||||||
|
cout << "Received WebSocket message: " << data << endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 状态更新定时器
|
||||||
|
thread([](){
|
||||||
|
while(true) {
|
||||||
|
sendStateUpdate();
|
||||||
|
this_thread::sleep_for(chrono::seconds(1));
|
||||||
|
}
|
||||||
|
}).detach();
|
||||||
|
|
||||||
|
//MOOS数据库更新定时器
|
||||||
|
std::thread fetchThread([&](){
|
||||||
|
while(bContinue) {
|
||||||
|
FetchLoop(moosClient.get(), dbImage.get());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 绑定主页路由
|
||||||
|
CROW_ROUTE(app, "/")([]() {
|
||||||
|
auto page = crow::mustache::load_text("index.html");
|
||||||
|
return page;
|
||||||
|
});
|
||||||
|
|
||||||
|
// MOOS通知API
|
||||||
|
CROW_ROUTE(app, "/api/moos-notify")
|
||||||
|
.methods("POST"_method)
|
||||||
|
([](const crow::request& req) {
|
||||||
|
auto json = crow::json::load(req.body);
|
||||||
|
if (!json) {
|
||||||
|
return crow::response(400, "Invalid JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
string var = json["var"].s();
|
||||||
|
string key = json["key"].s();
|
||||||
|
|
||||||
|
if (var.empty() || key.empty()) {
|
||||||
|
return crow::response(400, "Var and Key are required");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
moosClient->Notify(var, key);
|
||||||
|
return crow::response(200, "{\"success\":true}");
|
||||||
|
} catch (const exception& e) {
|
||||||
|
return crow::response(500,
|
||||||
|
crow::json::wvalue{{"success", false}, {"message", e.what()}}.dump());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 下载数据库API
|
||||||
|
CROW_ROUTE(app, "/api/download-db")
|
||||||
|
([]() {
|
||||||
|
const std::string dbPath = "/home/zjk/project/H100/H100PowerManger/data/power_data.db";
|
||||||
|
const size_t chunkSize = 4096; // 4KB chunks
|
||||||
|
|
||||||
|
std::ifstream file(dbPath, std::ios::binary | std::ios::ate);
|
||||||
|
if (!file) {
|
||||||
|
return crow::response(404, "Database file not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件大小
|
||||||
|
std::streamsize fileSize = file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
if (fileSize == 0) {
|
||||||
|
return crow::response(500, "Database file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建响应
|
||||||
|
crow::response res;
|
||||||
|
res.code = 200;
|
||||||
|
res.set_header("Content-Type", "application/octet-stream");
|
||||||
|
res.set_header("Content-Disposition", "attachment; filename=power_data.db");
|
||||||
|
res.set_header("Content-Length", std::to_string(fileSize));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 分块读取和写入文件
|
||||||
|
auto buffer = std::make_unique<char[]>(chunkSize);
|
||||||
|
size_t totalSent = 0;
|
||||||
|
|
||||||
|
while (totalSent < fileSize) {
|
||||||
|
size_t remaining = fileSize - totalSent;
|
||||||
|
size_t readSize = std::min(remaining, chunkSize);
|
||||||
|
|
||||||
|
file.read(buffer.get(), readSize);
|
||||||
|
if (file.gcount() <= 0) break;
|
||||||
|
|
||||||
|
res.write(std::string(buffer.get(), file.gcount()));
|
||||||
|
totalSent += file.gcount();
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return res;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
file.close();
|
||||||
|
return crow::response(500, std::string("Download failed: ") + e.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 启动服务器
|
||||||
|
app.port(18080)
|
||||||
|
.multithreaded()
|
||||||
|
.concurrency(16)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#--------------------------------------------------------
|
||||||
|
# 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})
|
||||||
|
|
||||||
|
# Find SQLite3 package
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
|
||||||
|
SET(SRC
|
||||||
|
PowerManagerFsm.cpp
|
||||||
|
PowerManger.cpp
|
||||||
|
PowerManger_Info.cpp
|
||||||
|
udpComm.cpp
|
||||||
|
main.cpp
|
||||||
|
SQLiteDB.cpp
|
||||||
|
driver.cpp
|
||||||
|
LowerCommManager.cpp
|
||||||
|
UpperCommManager.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(pPowerManger ${SRC})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(pPowerManger
|
||||||
|
${MOOS_LIBRARIES}
|
||||||
|
apputil
|
||||||
|
mbutil
|
||||||
|
m
|
||||||
|
pthread
|
||||||
|
jsoncpp
|
||||||
|
${SYSTEM_LIBS}
|
||||||
|
SQLiteDB
|
||||||
|
sqlite3)
|
||||||
|
|
||||||
|
# Add SQLiteDB static library
|
||||||
|
SET(UDPCOMM_SRC
|
||||||
|
udpComm.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(SQLITEDB_SRC
|
||||||
|
SQLiteDB.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(FSMLIB_SRC
|
||||||
|
PowerManagerFsm.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})
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
#include "LowerCommManager.h"
|
||||||
|
#include "PowerManger.h"
|
||||||
|
#include "driver.h"
|
||||||
|
#include "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 << "PORT = " << m_port << std::endl;
|
||||||
|
std::cout << "CCUHOST = " << m_udpComm->ccuHost << std::endl;
|
||||||
|
std::cout << "CCUPORT = " << m_udpComm->ccuPort << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
LowerCommManager::~LowerCommManager(){
|
||||||
|
try {
|
||||||
|
stopListenThread();
|
||||||
|
if (m_udpComm) {
|
||||||
|
delete m_udpComm;
|
||||||
|
m_udpComm = nullptr;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
cerr << "Error during cleanup" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool LowerCommManager::initUdpComm(){
|
||||||
|
//设置UDP监听端口
|
||||||
|
if(m_udpComm->udpScoket)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_udpComm->udpScoket->vBindSocket();
|
||||||
|
cout<<MOOS::ConsoleColours::green()<< "UDP set succeed!"<< MOOS::ConsoleColours::reset() << endl;
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
cout<<MOOS::ConsoleColours::red()<< "UDP set Fild!"<< MOOS::ConsoleColours::reset() << endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout<<MOOS::ConsoleColours::red()<< "UDP set Fild!"<< MOOS::ConsoleColours::reset() << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void LowerCommManager::processPeriodicTasks() {
|
||||||
|
sendCcuCommand(m_pm->m_CcuColCmd);
|
||||||
|
sendDisSysCommand(m_pm->m_targetDisBreakerState);
|
||||||
|
m_udpComm->clearMsgQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
m_udpComm->sendDisSysCmd(a);
|
||||||
|
//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);
|
||||||
|
//c. 高压汇流排B断路器
|
||||||
|
disHighBVolBusCmd c;
|
||||||
|
c.lithiumBatteryGroupInstrumentCircuitBreaker = getBreakerOption(cmd.bus3Breaker.lithiumBatteryGroupInstrumentCircuitBreaker);
|
||||||
|
c.bowLowVoltageDistributionBoxCircuitBreaker = getBreakerOption(cmd.bus3Breaker.bowLowVoltageDistributionBoxCircuitBreaker);
|
||||||
|
c.unit4InstrumentDC48VCircuitBreaker = getBreakerOption(cmd.bus3Breaker.unit4InstrumentDC48VCircuitBreaker);
|
||||||
|
c.dcC1DCDistributionPanelCircuitBreaker = getBreakerOption(cmd.bus3Breaker.dcC1DCDistributionPanelCircuitBreaker);
|
||||||
|
c.reservedCircuitBreaker1 = getBreakerOption(cmd.bus3Breaker.reservedCircuitBreaker1);
|
||||||
|
c.reservedCircuitBreaker2 = getBreakerOption(cmd.bus3Breaker.reservedCircuitBreaker2);
|
||||||
|
c.emergencyLithiumBatteryGroup2CircuitBreaker = getBreakerOption(cmd.bus3Breaker.emergencyLithiumBatteryGroup2CircuitBreaker);
|
||||||
|
m_udpComm->sendDisSysCmd(c);
|
||||||
|
//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->insertDisSysCmd(a);
|
||||||
|
m_pm->m_db->insertDisSysCmd(b);
|
||||||
|
m_pm->m_db->insertDisSysCmd(c);
|
||||||
|
m_pm->m_db->insertDisSysCmd(d);
|
||||||
|
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_db->insertCcuData(m_CcuCurrentState.data); //写入数据库
|
||||||
|
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_db->insertDisHighVolBusData(m_disHighVolBusCurrentState.data); //写入数据库
|
||||||
|
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_db->insertDisHighAVolBusData(m_disHighAVolBusCurrentState.data); //写入数据库
|
||||||
|
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_db->insertDisHighBVolBusData(m_disHighBVolBusCurrentState.data); //写入数据库
|
||||||
|
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_db->insertDisLowBusData(m_disLowBusState.data); //写入数据库
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:根据心跳检查连接状态
|
||||||
|
bool LowerCommManager::checkConnection()
|
||||||
|
{
|
||||||
|
m_pm->connectState =5;
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
#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 "ccuUdpMsg.h"
|
||||||
|
#include "pmSysvariable.h"
|
||||||
|
#include <queue>
|
||||||
|
#include <map>
|
||||||
|
#include <functional>
|
||||||
|
#include <atomic>
|
||||||
|
#include <vector>
|
||||||
|
#include "udpComm.h"
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// TODO:实现连接检查功能
|
||||||
|
bool checkConnection();
|
||||||
|
|
||||||
|
// 更新设备状态
|
||||||
|
bool updatePoweSystemStates();
|
||||||
|
|
||||||
|
// 发送CCU控制命令
|
||||||
|
bool sendCcuCommand(const ccuColCmd cmd);
|
||||||
|
bool sendDisSysCommand(const disSysBreakerList& cmd);
|
||||||
|
|
||||||
|
// 获取通信状态
|
||||||
|
int getConnectionState() const { return m_connectState; }
|
||||||
|
|
||||||
|
// 启动/停止监听线程
|
||||||
|
void startListenThread();
|
||||||
|
void stopListenThread();
|
||||||
|
|
||||||
|
//转换函数
|
||||||
|
char getBreakerOption(char cmd);
|
||||||
|
|
||||||
|
// 配电和CCU的反馈状态
|
||||||
|
msg_CcuStateFbMsg m_CcuCurrentState;
|
||||||
|
msg_disHighVolBusFbMsg m_disHighVolBusCurrentState;
|
||||||
|
msg_disHighAVolBusFbMsg m_disHighAVolBusCurrentState;
|
||||||
|
msg_disHighBVolBusFbMsg 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
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#include "PowerManagerFsm.hpp"
|
||||||
|
#include "PowerManger.h"
|
||||||
|
#include <string>
|
||||||
|
#include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h"
|
||||||
|
|
||||||
|
// 定义静态成员
|
||||||
|
PowerManger* PowerManagerFsm::pm = nullptr;
|
||||||
|
|
||||||
|
// InitState实现
|
||||||
|
void InitState::entry() {
|
||||||
|
PowerManagerFsm::entry();
|
||||||
|
std::cout << "初始化配电指令" << std::endl;
|
||||||
|
pm->initControlCmd();
|
||||||
|
// PowerManagerFsm::pm->printState("InitState", "进入初始化状态");
|
||||||
|
transit<StandbyState>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// StandbyState实现
|
||||||
|
void StandbyState::entry() {
|
||||||
|
PowerManagerFsm::entry();
|
||||||
|
pm->m_driver.getSTANDBYTable(&pm->m_subDisSysCmd);
|
||||||
|
pm->m_CcuColCmd.fcuCmd = FcuCommand::Stop;
|
||||||
|
pm->m_CcuColCmd.powerBatCmd = BatteryCommand::Stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandbyState::react(StandbyEvent const &) {
|
||||||
|
transit<StandbyState>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StandbyState::handlePowerCommands() {
|
||||||
|
switch (PowerManagerFsm::pm->m_msCmd.powerCMD) {
|
||||||
|
case 0: PowerManagerFsm::pm->m_pmEvent = "收到上位机控制指令:关机"; break;
|
||||||
|
case 1: handlePowerOn(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandbyState::handlePowerOn() {
|
||||||
|
PowerManagerFsm::pm->m_pmEvent = "动力电上电";
|
||||||
|
PowerManagerFsm::pm->m_CcuColCmd.powerBatCmd = 0x10;
|
||||||
|
if(PowerManagerFsm::pm->m_pmCurrentState.ccustate.fcuState == 0x04)
|
||||||
|
PowerManagerFsm::pm->m_CcuColCmd.fcuCmd = 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FaultState实现
|
||||||
|
void FaultState::entry() {
|
||||||
|
PowerManagerFsm::entry();
|
||||||
|
PowerManagerFsm::pm->printState("FaultState", "进入故障状态");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaultState::react(FaultEvent const & e) {
|
||||||
|
switch (e.faultCode) {
|
||||||
|
case 1:
|
||||||
|
PowerManagerFsm::pm->m_pmEvent = "复合管控连接超时";
|
||||||
|
PowerManagerFsm::pm->printState("FaultState", "通信故障");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
PowerManagerFsm::pm->m_pmEvent = "能源系统故障";
|
||||||
|
PowerManagerFsm::pm->printState("FaultState", "能源故障");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置初始状态
|
||||||
|
FSM_INITIAL_STATE(PowerManagerFsm, InitState);
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
#ifndef POWER_MANAGER_FSM_HPP
|
||||||
|
#define POWER_MANAGER_FSM_HPP
|
||||||
|
#include "tinyfsm.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <chrono> // 新增头文件
|
||||||
|
#include <iomanip> // 新增头文件
|
||||||
|
#include <ctime> // 新增头文件,用于localtime函数
|
||||||
|
#include <cxxabi.h> // 新增头文件,用于demangle功能
|
||||||
|
#include "pmSysvariable.h"
|
||||||
|
#include "driver.h"
|
||||||
|
// 前向声明
|
||||||
|
class PowerManger;
|
||||||
|
|
||||||
|
enum class PowerSystemState {
|
||||||
|
INIT,
|
||||||
|
STANDBY,
|
||||||
|
FAULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
//==================状态切换事件=============================
|
||||||
|
struct InitEvent : tinyfsm::Event { };
|
||||||
|
struct StandbyEvent : tinyfsm::Event { };
|
||||||
|
struct FaultEvent : tinyfsm::Event {
|
||||||
|
unsigned int faultCode;
|
||||||
|
FaultEvent(unsigned int code) : faultCode(code) {}
|
||||||
|
};
|
||||||
|
//==================状态流程事件============================
|
||||||
|
struct MasterCommandEvent : tinyfsm::Event {};
|
||||||
|
struct TaskStart : tinyfsm::Event { };
|
||||||
|
struct DeviceCmd : tinyfsm::Event { };
|
||||||
|
|
||||||
|
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(FaultEvent const &) {};
|
||||||
|
virtual void react(MasterCommandEvent const &) {};
|
||||||
|
virtual void react(TaskStart const &) {};
|
||||||
|
virtual void react(DeviceCmd const &) {};
|
||||||
|
|
||||||
|
// 状态机生命周期方法
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class InitState : public PowerManagerFsm {
|
||||||
|
public:
|
||||||
|
void entry() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StandbyState : public PowerManagerFsm {
|
||||||
|
public:
|
||||||
|
void entry() override;
|
||||||
|
void react(StandbyEvent const &) override;
|
||||||
|
// void react(MasterCommandEvent const &) override;
|
||||||
|
// void react(DeviceCmd const &) override;
|
||||||
|
private:
|
||||||
|
void handlePowerCommands();
|
||||||
|
void handlePowerOn();
|
||||||
|
};
|
||||||
|
|
||||||
|
class FaultState : public PowerManagerFsm {
|
||||||
|
public:
|
||||||
|
void entry() override;
|
||||||
|
void react(FaultEvent const &);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // POWER_MANAGER_FSM_HPP
|
||||||
@@ -0,0 +1,343 @@
|
|||||||
|
/************************************************************/
|
||||||
|
/* NAME: */
|
||||||
|
/* ORGN: MIT, Cambridge MA */
|
||||||
|
/* FILE: PowerManger.cpp */
|
||||||
|
/* DATE: December 29th, 1963 */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include "MBUtils.h"
|
||||||
|
#include "ACTable.h"
|
||||||
|
#include "PowerManger.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
bool _FsmCB(void * pParam)
|
||||||
|
{
|
||||||
|
PowerManger* pMe = (PowerManger* )pParam;
|
||||||
|
return pMe->FsmLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Constructor()
|
||||||
|
|
||||||
|
PowerManger::PowerManger()
|
||||||
|
{
|
||||||
|
workCondition = 0;
|
||||||
|
currentMod = 0;
|
||||||
|
powerState = 0;
|
||||||
|
falutLevel = 0;
|
||||||
|
soc = 0;
|
||||||
|
sustainableTime = 0;
|
||||||
|
m_faultNum = 0;
|
||||||
|
m_ticker = 0;
|
||||||
|
faultCode.push_back(0);
|
||||||
|
|
||||||
|
m_pmCurrentState = {};
|
||||||
|
m_currentDisBreakerState = {};
|
||||||
|
m_targetDisBreakerState = {};
|
||||||
|
m_currentDriverState = {};
|
||||||
|
m_MSDriverCmd = {};
|
||||||
|
m_subDisSysCmd = {};
|
||||||
|
m_subDisSysState = {};
|
||||||
|
//初始化控制指令
|
||||||
|
initControlCmd();
|
||||||
|
|
||||||
|
//初始化数据库
|
||||||
|
string dbPath = "/home/zjk/project/H100/H100PowerManger/data/power_data.db";
|
||||||
|
m_db = new SQLiteDB(dbPath);
|
||||||
|
m_db->createPowerDataTables();
|
||||||
|
m_db->createStateTables();
|
||||||
|
m_db->createDisCcuSysTables();
|
||||||
|
m_db->createDriversTables(VAR_TO_STR(m_currentDriverState));
|
||||||
|
m_db->createDriversTables(VAR_TO_STR(m_subDisSysState));
|
||||||
|
m_db->createDriversTables(VAR_TO_STR(m_subDisSysCmd));
|
||||||
|
m_db->createDriversTables(VAR_TO_STR(m_MSDriverCmd));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
PowerManger::~PowerManger()
|
||||||
|
{
|
||||||
|
delete m_db;
|
||||||
|
delete m_lowerCommManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// 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();
|
||||||
|
//处理上位机发送的控制指令
|
||||||
|
if(!m_upperCommManager->processUpperMsg(key,strJson))
|
||||||
|
{
|
||||||
|
cout << "processUpperMsg failed" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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")
|
||||||
|
cout << "great!";
|
||||||
|
|
||||||
|
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();
|
||||||
|
// 打印当前状态
|
||||||
|
// cout << " Current State : " << (int)PowerManagerFsm::current_state_ptr->getCurrentState();
|
||||||
|
if (m_ticker++ % 5 == 0)
|
||||||
|
{
|
||||||
|
m_CcuColCmd.heartbeat++;
|
||||||
|
m_lowerCommManager->processPeriodicTasks();
|
||||||
|
m_upperCommManager->processPeriodicTasks();
|
||||||
|
writeDataToDB();
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
//初始化UDP通信
|
||||||
|
m_lowerCommManager = new LowerCommManager(this,IPORT,CCUPORT,CCUHOST);
|
||||||
|
m_lowerCommManager->initUdpComm();
|
||||||
|
m_lowerCommManager->startListenThread();
|
||||||
|
|
||||||
|
//初始化上位机通信
|
||||||
|
m_upperCommManager = new UpperCommManager(this);
|
||||||
|
|
||||||
|
// 初始化状态机
|
||||||
|
PowerManagerFsm::init(this);
|
||||||
|
PowerManagerFsm::start();
|
||||||
|
InitEvent initEvent;
|
||||||
|
PowerManagerFsm::dispatch(initEvent);
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// Procedure: registerVariables()
|
||||||
|
|
||||||
|
void PowerManger::registerVariables()
|
||||||
|
{
|
||||||
|
AppCastingMOOSApp::RegisterVariables();
|
||||||
|
Register(DB_TO_PM_MSCMD, 0);
|
||||||
|
Register(DB_TO_PM_EQUIPMENTCMD, 0);
|
||||||
|
Register(DB_TO_PM_SUBDISSTATE, 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()
|
||||||
|
{
|
||||||
|
//状态机循环
|
||||||
|
// while (!m_FsmThread.IsQuitRequested())
|
||||||
|
// {
|
||||||
|
// // // 检查故障并触发事件
|
||||||
|
// // if(int error = checkError()) {
|
||||||
|
// // m_fsm.triggerFaultEvent(error);
|
||||||
|
// // } else {
|
||||||
|
// // // 自动状态转换由状态机内部处理
|
||||||
|
// // MOOSPause(1000);
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// //延时1s
|
||||||
|
// usleep(1000000);
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PowerManger::writeDataToDB()
|
||||||
|
{
|
||||||
|
//写入设备状态
|
||||||
|
if(!m_db->insertDriverTables(m_currentDriverState,VAR_TO_STR(m_currentDriverState)))
|
||||||
|
return false;
|
||||||
|
if(!m_db->insertDriverTables(m_subDisSysState,VAR_TO_STR(m_subDisSysState)))
|
||||||
|
return false;
|
||||||
|
if(!m_db->insertDriverTables(m_subDisSysCmd,VAR_TO_STR(m_subDisSysCmd)))
|
||||||
|
return false;
|
||||||
|
if(!m_db->insertDriverTables(m_MSDriverCmd,VAR_TO_STR(m_MSDriverCmd)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int PowerManger::checkError()
|
||||||
|
{
|
||||||
|
//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;
|
||||||
|
//2.检查断路器状态
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerManger::printState(const std::string& stateName, const std::string& desp){
|
||||||
|
cout << MOOS::ConsoleColours::Yellow() << "STATE " << stateName << " " << MOOS::ConsoleColours::reset();
|
||||||
|
cout << MOOS::ConsoleColours::Blue() << " -> " << MOOS::ConsoleColours::reset();
|
||||||
|
// 检查desp是否有“故障”
|
||||||
|
if (desp.find("故障") != string::npos) {
|
||||||
|
cout << MOOS::ConsoleColours::Red() << desp << MOOS::ConsoleColours::reset() << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cout << MOOS::ConsoleColours::Green() << desp << MOOS::ConsoleColours::reset() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==============================系统操作函数====================
|
||||||
|
bool PowerManger::shutdown()
|
||||||
|
{
|
||||||
|
m_CcuColCmd.masterState = 0xFF; //关机
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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.workCondition = 0x00; //默认无效
|
||||||
|
m_CcuColCmd.fcuCmd = 0x00; //无效指令
|
||||||
|
m_CcuColCmd.fcuPowerEfficiency = 15; //默认为15kw
|
||||||
|
m_CcuColCmd.fcuInsEfficiency = 00; //预留指令,无效
|
||||||
|
m_CcuColCmd.insBatCmd = 0x00; //无效指令
|
||||||
|
m_CcuColCmd.powerBatCmd = 0x00; //无效指令
|
||||||
|
m_CcuColCmd.powerBatEfficiency = 230; //默认为最大
|
||||||
|
m_CcuColCmd.heartbeat = 0;
|
||||||
|
m_CcuColCmd.masterState = 0xAA;//主站状态,运行中
|
||||||
|
//================初始化上位机指令=========================
|
||||||
|
m_msCmd.modCMD = 99;
|
||||||
|
m_msCmd.powerCMD = 99;
|
||||||
|
m_msCmd.workCMD = 99;
|
||||||
|
//================初始化设备驱动指令========================
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* @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 "MOOS/libMOOS/Thirdparty/AppCasting/AppCastingMOOSApp.h"
|
||||||
|
#include "MOOS/libMOOS/Utils/MOOSThread.h"
|
||||||
|
// #include "MOOS/libMOOS/Comms/XPCUdpSocket.h"
|
||||||
|
#include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h"
|
||||||
|
#include "MOOS/libMOOS/Utils/ConsoleColours.h"
|
||||||
|
#include "ccuUdpMsg.h"
|
||||||
|
#include "json/json.h"
|
||||||
|
#include "udpComm.h"
|
||||||
|
#include "pmSysvariable.h"
|
||||||
|
#include "PowerManagerFsm.hpp"
|
||||||
|
#include "SQLiteDB.h"
|
||||||
|
#include "driver.h"
|
||||||
|
#include "LowerCommManager.h"
|
||||||
|
#include "UpperCommManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define IPORT 5000
|
||||||
|
#define CCUPORT 5001
|
||||||
|
#define CCUHOST "127.0.0.1"
|
||||||
|
#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();}
|
||||||
|
//数据库
|
||||||
|
SQLiteDB* m_db;
|
||||||
|
bool writeDataToDB();
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
/* |<------------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;
|
||||||
|
|
||||||
|
int m_depth;
|
||||||
|
int m_missionCode;
|
||||||
|
//===========================STATE=========================================
|
||||||
|
unsigned char workCondition;
|
||||||
|
unsigned char currentMod;
|
||||||
|
unsigned char powerState;
|
||||||
|
unsigned char falutLevel;
|
||||||
|
vector<unsigned int> faultCode;
|
||||||
|
unsigned int soc;
|
||||||
|
unsigned int sustainableTime;
|
||||||
|
unsigned int m_faultNum;
|
||||||
|
Driver m_driver; //设备表处理
|
||||||
|
std::string m_pmEvent; // 状态机事件描述
|
||||||
|
//===========================CONFIG========================================
|
||||||
|
long m_lPort;
|
||||||
|
unsigned int m_nReceiveBufferSizeKB;
|
||||||
|
unsigned int m_nSendBufferSizeKB;
|
||||||
|
double m_current_time;
|
||||||
|
unsigned int m_ticker;
|
||||||
|
int connectState;
|
||||||
|
|
||||||
|
//=============================过程函数======================================
|
||||||
|
void initControlCmd();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// CMOOSThread m_FsmThread;
|
||||||
|
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;
|
||||||
|
|
||||||
|
//==================================================================================
|
||||||
|
int checkError();
|
||||||
|
bool shutdown();
|
||||||
|
bool powerOn();
|
||||||
|
bool powerOff();
|
||||||
|
|
||||||
|
bool sendNotification(const std::string& key, const std::string& value) {
|
||||||
|
return Notify(key, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
|||||||
|
#ifndef SQLITEDB_H
|
||||||
|
#define SQLITEDB_H
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "json/json.h"
|
||||||
|
#include "ccuUdpMsg.h"
|
||||||
|
#include "pmSysvariable.h"
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
struct PowerData {
|
||||||
|
double voltage;
|
||||||
|
double current;
|
||||||
|
double power;
|
||||||
|
double temperature;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StateData {
|
||||||
|
int state_id;
|
||||||
|
std::string state_name;
|
||||||
|
std::string event;
|
||||||
|
int event_id;
|
||||||
|
int fault_code;
|
||||||
|
std::string note;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SQLiteDB {
|
||||||
|
public:
|
||||||
|
SQLiteDB(const std::string& dbPath);
|
||||||
|
~SQLiteDB();
|
||||||
|
|
||||||
|
// 模板函数声明
|
||||||
|
template<typename T>
|
||||||
|
bool executeInsert(const char* sql, const T& data);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool bindParameters(sqlite3_stmt* stmt, const T& data);
|
||||||
|
// 数据库操作函数
|
||||||
|
bool createPowerDataTables();
|
||||||
|
bool createStateTables();
|
||||||
|
bool createDisCcuSysTables();
|
||||||
|
bool createDriversTables(string tableName);
|
||||||
|
|
||||||
|
bool clearPowerData();
|
||||||
|
bool clearStateData();
|
||||||
|
|
||||||
|
// 插入数据函数
|
||||||
|
bool insertPowerData(const PowerData& powerData);
|
||||||
|
bool insertStateData(StateData stateData,bool filter=true);
|
||||||
|
|
||||||
|
|
||||||
|
bool insertCcuData(ccuState s);
|
||||||
|
bool insertDisHighVolBusData(disHighVolBusState s);
|
||||||
|
bool insertDisHighAVolBusData(disHighAVolBusState s);
|
||||||
|
bool insertDisHighBVolBusData(disHighBVolBusState s);
|
||||||
|
bool insertDisLowBusData(disLowBusState s);
|
||||||
|
|
||||||
|
bool insertCcuSysCmd(ccuColCmd cmd);
|
||||||
|
bool insertDisSysCmd(disHighVolBusCmd cmd);
|
||||||
|
bool insertDisSysCmd(disHighAVolBusCmd cmd);
|
||||||
|
bool insertDisSysCmd(disHighBVolBusCmd cmd);
|
||||||
|
bool insertDisSysCmd(disLowBusCmd cmd);
|
||||||
|
|
||||||
|
bool insertDriverTables(DriverTable driverTable,string tableName);
|
||||||
|
|
||||||
|
bool insertDisCcuData(pmState s,bool filter=true);//由于信息同步原因,暂时不使用该函数
|
||||||
|
|
||||||
|
// 获取最新的状态数据
|
||||||
|
bool getStateData(StateData &stateData);
|
||||||
|
bool getStateData(StateData &stateData,string &time);
|
||||||
|
|
||||||
|
// 使用函数
|
||||||
|
bool isDatabaseConnected(const std::string& path, const std::string& dbName);
|
||||||
|
std::vector<PowerData> getPowerData(int limit = 100);
|
||||||
|
|
||||||
|
// 获取数据库状态函数
|
||||||
|
string getDBPatch();
|
||||||
|
|
||||||
|
// 获取数据库大小
|
||||||
|
long getDatabaseSize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
sqlite3* m_db;
|
||||||
|
string m_dbPath;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQLITEDB_H
|
||||||
@@ -0,0 +1,586 @@
|
|||||||
|
#include "UpperCommManager.h"
|
||||||
|
#include "PowerManger.h"
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
UpperCommManager::UpperCommManager(PowerManger* pm) : m_pm(pm) {}
|
||||||
|
|
||||||
|
bool UpperCommManager::processUpperMsg(const string& key, const string& strJson) {
|
||||||
|
if(key == DB_TO_PM_MSCMD) {
|
||||||
|
m_pm->m_msCmd = getMasterControlCmd(key, strJson);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(key == DB_TO_PM_EQUIPMENTCMD) {
|
||||||
|
m_pm->m_MSDriverCmd = getEquipmentCmd(key, strJson);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(key == DB_TO_PM_SUBDISSTATE) {
|
||||||
|
m_pm->m_subDisSysState = getSubDisState(key, strJson);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(key == DB_TO_PM_DEEPTH) {
|
||||||
|
m_pm->m_depth = getDeepth(key, strJson);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::cout << "Unknown key: " << key << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MSControlCmd UpperCommManager::getMasterControlCmd(const std::string& key, const std::string& msg)
|
||||||
|
{
|
||||||
|
MSControlCmd cmd;
|
||||||
|
if (parseControlCmdFromJson(cmd, msg)) {
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << MOOS::ConsoleColours::Red << "parse control cmd error:" << msg
|
||||||
|
<< MOOS::ConsoleColours::reset << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DriverTable UpperCommManager::getEquipmentCmd(const std::string& key, const std::string& msg)
|
||||||
|
{
|
||||||
|
DriverTable cmd;
|
||||||
|
if (m_pm->m_driver.loadDriverTableFromJson(msg, cmd) < 0) {
|
||||||
|
cout << MOOS::ConsoleColours::Red << "get equipment cmd error:" << msg
|
||||||
|
<< MOOS::ConsoleColours::reset << endl;
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DriverTable UpperCommManager::getSubDisState(const std::string& key, const std::string& msg)
|
||||||
|
{
|
||||||
|
DriverTable state;
|
||||||
|
if (m_pm->m_driver.loadDriverTableFromJson(msg, state) < 0) {
|
||||||
|
cout << MOOS::ConsoleColours::Red << "get sub dis state error:" << msg
|
||||||
|
<< MOOS::ConsoleColours::reset << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int UpperCommManager::getDeepth(const std::string& key, const std::string& msg){
|
||||||
|
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;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查并读取深度数组
|
||||||
|
if (root.isMember("value_array_uint16") && root["value_array_uint16"].isArray()) {
|
||||||
|
const Json::Value& array = root["value_array_uint16"];
|
||||||
|
if (array.size() >= 3) {
|
||||||
|
// 计算三个深度值的平均值
|
||||||
|
deepth = (array[0].asInt() + array[1].asInt() + array[2].asInt()) / 3;
|
||||||
|
} else {
|
||||||
|
std::cerr << "深度数组元素不足3个" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "JSON格式错误" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string UpperCommManager::getCurrentEquState(DriverTable& driver)
|
||||||
|
{
|
||||||
|
return m_pm->m_driver.saveDriverTableToJson(&driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string UpperCommManager::getSubDisCmd(DriverTable& driver)
|
||||||
|
{
|
||||||
|
return m_pm->m_driver.saveDriverTableToJson(&driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpperCommManager::processPeriodicTasks() {
|
||||||
|
buildSystemReport();
|
||||||
|
std::string strJson;
|
||||||
|
strJson = getCurrentEquState(m_pm->m_currentDriverState);
|
||||||
|
m_pm->sendNotification(PM_TO_DB_EQUIPMENTSTATE, strJson);
|
||||||
|
strJson = getSubDisCmd(m_pm->m_subDisSysCmd);
|
||||||
|
m_pm->sendNotification(PM_TO_DB_SUBDISCMD, strJson);
|
||||||
|
}
|
||||||
|
bool UpperCommManager::parseControlCmdFromJson(MSControlCmd &cmd, const std::string &strJson)
|
||||||
|
{
|
||||||
|
Json::CharReaderBuilder builder;
|
||||||
|
Json::Value root;
|
||||||
|
std::string errs;
|
||||||
|
|
||||||
|
// 解析JSON字符串
|
||||||
|
std::istringstream s(strJson);
|
||||||
|
if (!Json::parseFromStream(builder, s, &root, &errs))
|
||||||
|
{
|
||||||
|
std::cerr << "JSON解析失败: " << errs << std::endl;
|
||||||
|
return false; // 解析失败
|
||||||
|
}
|
||||||
|
if (root.isMember("powerCMD") && root["powerCMD"].isUInt())
|
||||||
|
{
|
||||||
|
cmd.powerCMD = root["powerCMD"].asUInt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "缺少或类型不匹配: powerCMD" << std::endl;
|
||||||
|
return false; // 缺少或类型不匹配
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.isMember("modCMD") && root["modCMD"].isUInt())
|
||||||
|
{
|
||||||
|
cmd.modCMD = root["modCMD"].asUInt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "缺少或类型不匹配: modCMD" << std::endl;
|
||||||
|
return false; // 缺少或类型不匹配
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.isMember("workCMD") && root["workCMD"].isUInt())
|
||||||
|
{
|
||||||
|
cmd.workCMD = root["workCMD"].asUInt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "缺少或类型不匹配: workCMD" << std::endl;
|
||||||
|
return false; // 缺少或类型不匹配
|
||||||
|
}
|
||||||
|
return true; // 成功
|
||||||
|
}
|
||||||
|
void UpperCommManager::buildSystemReport() {
|
||||||
|
string suffix;
|
||||||
|
Json::Value pms;
|
||||||
|
Json::Value fcs;
|
||||||
|
Json::Value lbs;
|
||||||
|
Json::Value dis;
|
||||||
|
// 构建能源系统报告
|
||||||
|
//1.构建系统状态报告
|
||||||
|
suffix = getTypeName(typeid(m_pm->workCondition).name());
|
||||||
|
pms[VAR_TO_STR(workCondition)+suffix] = m_pm->workCondition;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->currentMod).name());
|
||||||
|
pms[VAR_TO_STR(currentMod)+suffix] = m_pm->currentMod;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->powerState).name());
|
||||||
|
pms[VAR_TO_STR(powerState)+suffix] = m_pm->powerState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->falutLevel).name());
|
||||||
|
pms[VAR_TO_STR(falutLevel)+suffix] = m_pm->falutLevel;
|
||||||
|
|
||||||
|
Json::Value faultCode_array;
|
||||||
|
for(auto val : m_pm->faultCode)
|
||||||
|
{
|
||||||
|
faultCode_array.append(val);
|
||||||
|
}
|
||||||
|
pms[VAR_TO_STR(faultCode_array)] = faultCode_array;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->soc).name());
|
||||||
|
pms[VAR_TO_STR(soc)+suffix] = m_pm->soc;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->sustainableTime).name());
|
||||||
|
pms[VAR_TO_STR(sustainableTime)+suffix] = m_pm->sustainableTime;
|
||||||
|
|
||||||
|
//2.构建燃料电池状态报告
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuState).name());
|
||||||
|
fcs[VAR_TO_STR(fcuState)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuFaultLeve).name());
|
||||||
|
fcs[VAR_TO_STR(fcuFaultLeve)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuFaultLeve;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerLimit).name());
|
||||||
|
fcs[VAR_TO_STR(powLimit)+suffix] = m_pm->m_pmCurrentState.ccustate.powerLimit;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.totalPowerGeneration).name());
|
||||||
|
fcs[VAR_TO_STR(powerGen)+suffix] = m_pm->m_pmCurrentState.ccustate.totalPowerGeneration;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.ch4o).name());
|
||||||
|
fcs[VAR_TO_STR(ch4o)+suffix] = m_pm->m_pmCurrentState.ccustate.ch4o;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.o2).name());
|
||||||
|
fcs[VAR_TO_STR(o2)+suffix] = m_pm->m_pmCurrentState.ccustate.o2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuVoltage).name());
|
||||||
|
fcs[VAR_TO_STR(fcuVol)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuVoltage;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuCurrent).name());
|
||||||
|
fcs[VAR_TO_STR(fcuCur)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuCurrent;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.o2Level).name());
|
||||||
|
fcs[VAR_TO_STR(o2Level)+suffix] = m_pm->m_pmCurrentState.ccustate.o2Level;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.exchangerTemperature).name());
|
||||||
|
fcs[VAR_TO_STR(excTemp)+suffix] = m_pm->m_pmCurrentState.ccustate.exchangerTemperature;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuOutPower).name());
|
||||||
|
fcs[VAR_TO_STR(fcuOutPower)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuOutPower;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuOutIns).name());
|
||||||
|
fcs[VAR_TO_STR(fcuOutIns)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuOutIns;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuVoltageIns).name());
|
||||||
|
fcs[VAR_TO_STR(fcuVolIns)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuVoltageIns;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuVoltagePower).name());
|
||||||
|
fcs[VAR_TO_STR(fcuVolPower)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuVoltagePower;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuCurrentIns).name());
|
||||||
|
fcs[VAR_TO_STR(fcuCurIns)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuCurrentIns;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuCurrentPower).name());
|
||||||
|
fcs[VAR_TO_STR(fcuCurPower)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuCurrentPower;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.h2Concentration1).name());
|
||||||
|
fcs[VAR_TO_STR(h2Concent1)+suffix] = m_pm->m_pmCurrentState.ccustate.h2Concentration1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.h2Concentration2).name());
|
||||||
|
fcs[VAR_TO_STR(h2Concent2)+suffix] = m_pm->m_pmCurrentState.ccustate.h2Concentration2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.o2Concentration1).name());
|
||||||
|
fcs[VAR_TO_STR(o2Concent1)+suffix] = m_pm->m_pmCurrentState.ccustate.o2Concentration1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.o2Concentration2).name());
|
||||||
|
fcs[VAR_TO_STR(o2Concent2)+suffix] = m_pm->m_pmCurrentState.ccustate.o2Concentration2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.ch4oConcentration1).name());
|
||||||
|
fcs[VAR_TO_STR(ch4oConcent1)+suffix] = m_pm->m_pmCurrentState.ccustate.ch4oConcentration1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.ch4oConcentration2).name());
|
||||||
|
fcs[VAR_TO_STR(ch4oConcent2)+suffix] = m_pm->m_pmCurrentState.ccustate.ch4oConcentration2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.backpressure1).name());
|
||||||
|
fcs[VAR_TO_STR(backpressure1)+suffix] = m_pm->m_pmCurrentState.ccustate.backpressure1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.backpressure2).name());
|
||||||
|
fcs[VAR_TO_STR(backpressure2)+suffix] = m_pm->m_pmCurrentState.ccustate.backpressure2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.flameDetection).name());
|
||||||
|
fcs[VAR_TO_STR(flameDet)+suffix] = m_pm->m_pmCurrentState.ccustate.flameDetection;
|
||||||
|
|
||||||
|
unsigned short faultCode1;
|
||||||
|
unsigned short faultCode2;
|
||||||
|
unsigned short faultCode3;
|
||||||
|
faultCode1 = (m_pm->m_pmCurrentState.ccustate.fcuGZ_1H << 8) | m_pm->m_pmCurrentState.ccustate.fcuGZ_1L;
|
||||||
|
faultCode2 = (m_pm->m_pmCurrentState.ccustate.fcuGZ_2H << 8) | m_pm->m_pmCurrentState.ccustate.fcuGZ_2L;
|
||||||
|
faultCode3 = (m_pm->m_pmCurrentState.ccustate.fcuGZ_3H << 8) | m_pm->m_pmCurrentState.ccustate.fcuGZ_3L;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(faultCode1).name());
|
||||||
|
fcs[VAR_TO_STR(faultCode1)+suffix] = faultCode1;
|
||||||
|
suffix = getTypeName(typeid(faultCode2).name());
|
||||||
|
fcs[VAR_TO_STR(faultCode2)+suffix] = faultCode2;
|
||||||
|
suffix = getTypeName(typeid(faultCode3).name());
|
||||||
|
fcs[VAR_TO_STR(faultCode3)+suffix] = faultCode3;
|
||||||
|
|
||||||
|
//4.构建动力锂电池状态报告
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insPosRelayState).name());
|
||||||
|
lbs[VAR_TO_STR(insPosRelayState)+suffix] = m_pm->m_pmCurrentState.ccustate.insPosRelayState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insNegRelayState).name());
|
||||||
|
lbs[VAR_TO_STR(insNegRelayState)+suffix] = m_pm->m_pmCurrentState.ccustate.insNegRelayState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerPosRelayState).name());
|
||||||
|
lbs[VAR_TO_STR(powPosRelayState)+suffix] = m_pm->m_pmCurrentState.ccustate.powerPosRelayState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerNegRelayState).name());
|
||||||
|
lbs[VAR_TO_STR(powNegRelayState)+suffix] = m_pm->m_pmCurrentState.ccustate.powerNegRelayState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insBatLimit).name());
|
||||||
|
lbs[VAR_TO_STR(insBatLimit)+suffix] = m_pm->m_pmCurrentState.ccustate.insBatLimit;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerBatLimit).name());
|
||||||
|
lbs[VAR_TO_STR(powerBatLimit)+suffix] = m_pm->m_pmCurrentState.ccustate.powerBatLimit;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insBatSoc).name());
|
||||||
|
lbs[VAR_TO_STR(insBatSoc)+suffix] = m_pm->m_pmCurrentState.ccustate.insBatSoc;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerBatSoc).name());
|
||||||
|
lbs[VAR_TO_STR(powBatSoc)+suffix] = m_pm->m_pmCurrentState.ccustate.powerBatSoc;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insBatTotalElectricity).name());
|
||||||
|
lbs[VAR_TO_STR(insBatTotalElect)+suffix] = m_pm->m_pmCurrentState.ccustate.insBatTotalElectricity;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerBatTotalElectricity).name());
|
||||||
|
lbs[VAR_TO_STR(powBatTotalElect)+suffix] = m_pm->m_pmCurrentState.ccustate.powerBatTotalElectricity;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insBatCurrentElectricity).name());
|
||||||
|
lbs[VAR_TO_STR(insBatCurElect)+suffix] = m_pm->m_pmCurrentState.ccustate.insBatCurrentElectricity;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerBatCurrentElectricity).name());
|
||||||
|
lbs[VAR_TO_STR(powBatCurElect)+suffix] = m_pm->m_pmCurrentState.ccustate.powerBatCurrentElectricity;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insChargeState).name());
|
||||||
|
lbs[VAR_TO_STR(insChargeState)+suffix] = m_pm->m_pmCurrentState.ccustate.insChargeState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerChargeState).name());
|
||||||
|
lbs[VAR_TO_STR(powChargeState)+suffix] = m_pm->m_pmCurrentState.ccustate.powerChargeState;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insLinkVoltage).name());
|
||||||
|
lbs[VAR_TO_STR(insLinkVol)+suffix] = m_pm->m_pmCurrentState.ccustate.insLinkVoltage;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insPackVoltage).name());
|
||||||
|
lbs[VAR_TO_STR(insPackVol)+suffix] = m_pm->m_pmCurrentState.ccustate.insPackVoltage;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insCurrent).name());
|
||||||
|
lbs[VAR_TO_STR(insCurrent)+suffix] = m_pm->m_pmCurrentState.ccustate.insCurrent;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insPosInsulationResistance).name());
|
||||||
|
lbs[VAR_TO_STR(insPosRes)+suffix] = m_pm->m_pmCurrentState.ccustate.insPosInsulationResistance;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insNegInsulationResistance).name());
|
||||||
|
lbs[VAR_TO_STR(insNegRes)+suffix] = m_pm->m_pmCurrentState.ccustate.insNegInsulationResistance;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerLinkVoltage).name());
|
||||||
|
lbs[VAR_TO_STR(powLinkVol)+suffix] = m_pm->m_pmCurrentState.ccustate.powerLinkVoltage;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerPackVoltage).name());
|
||||||
|
lbs[VAR_TO_STR(powerPackVol)+suffix] = m_pm->m_pmCurrentState.ccustate.powerPackVoltage;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerCurrent).name());
|
||||||
|
lbs[VAR_TO_STR(powCur)+suffix] = m_pm->m_pmCurrentState.ccustate.powerCurrent;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerPosInsulationResistance).name());
|
||||||
|
lbs[VAR_TO_STR(powPosRes)+suffix] = m_pm->m_pmCurrentState.ccustate.powerPosInsulationResistance;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerNegInsulationResistance).name());
|
||||||
|
lbs[VAR_TO_STR(powNegRes)+suffix] = m_pm->m_pmCurrentState.ccustate.powerNegInsulationResistance;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insCurrentSocHold1).name());
|
||||||
|
lbs[VAR_TO_STR(insCurSocHold1)+suffix] = m_pm->m_pmCurrentState.ccustate.insCurrentSocHold1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insCurrentSocHold2).name());
|
||||||
|
lbs[VAR_TO_STR(insCurSocHold2)+suffix] = m_pm->m_pmCurrentState.ccustate.insCurrentSocHold2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insCurrentSocHold3).name());
|
||||||
|
lbs[VAR_TO_STR(insCurSocHold3)+suffix] = m_pm->m_pmCurrentState.ccustate.insCurrentSocHold3;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuCurrentToInsLimit1).name());
|
||||||
|
lbs[VAR_TO_STR(fcuCurToInsLimit1)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuCurrentToInsLimit1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.fcuCurrentToinsLimit2).name());
|
||||||
|
lbs[VAR_TO_STR(fcuCurToinsLimit2)+suffix] = m_pm->m_pmCurrentState.ccustate.fcuCurrentToinsLimit2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerCurrentSocHold1).name());
|
||||||
|
lbs[VAR_TO_STR(powCurSocHold1)+suffix] = m_pm->m_pmCurrentState.ccustate.powerCurrentSocHold1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerCurrentSocHold2).name());
|
||||||
|
lbs[VAR_TO_STR(powCurSocHold2)+suffix] = m_pm->m_pmCurrentState.ccustate.powerCurrentSocHold2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerCurrentSocHold3).name());
|
||||||
|
lbs[VAR_TO_STR(powCurSocHold3)+suffix] = m_pm->m_pmCurrentState.ccustate.powerCurrentSocHold3;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerCurrentToInsLimit1).name());
|
||||||
|
lbs[VAR_TO_STR(powCurToInsLimit1)+suffix] = m_pm->m_pmCurrentState.ccustate.powerCurrentToInsLimit1;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerCurrentToinsLimit2).name());
|
||||||
|
lbs[VAR_TO_STR(powCurToinsLimit2)+suffix] = m_pm->m_pmCurrentState.ccustate.powerCurrentToinsLimit2;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.insAlarmIdentificationWord).name());
|
||||||
|
lbs[VAR_TO_STR(insfaultCode)+suffix] = m_pm->m_pmCurrentState.ccustate.insAlarmIdentificationWord;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.ccustate.powerAlarmIdentificationWord).name());
|
||||||
|
lbs[VAR_TO_STR(powfaultCode)+suffix] = m_pm->m_pmCurrentState.ccustate.powerAlarmIdentificationWord;
|
||||||
|
|
||||||
|
//5.构建配电系统状态报告
|
||||||
|
disBus1Breaker* pdis1=new disBus1Breaker;
|
||||||
|
disBus2Breaker* pdis2=new disBus2Breaker;
|
||||||
|
disBus3Breaker* pdis3=new disBus3Breaker;
|
||||||
|
disBus4Breaker* pdis4=new disBus4Breaker;
|
||||||
|
|
||||||
|
*pdis1 = m_pm->m_currentDisBreakerState.bus1Breaker;
|
||||||
|
*pdis2 = m_pm->m_currentDisBreakerState.bus2Breaker;
|
||||||
|
*pdis3 = m_pm->m_currentDisBreakerState.bus3Breaker;
|
||||||
|
*pdis4 = m_pm->m_currentDisBreakerState.bus4Breaker;
|
||||||
|
|
||||||
|
dis["HVolBusBreaker_uint16"] = *(unsigned short*)pdis1;
|
||||||
|
dis["HVolABusBreaker_unit16"] = *(unsigned short*)pdis2;
|
||||||
|
dis["HVolBBusBreaker_unit16"] = *(unsigned short*)pdis3;
|
||||||
|
dis["LVolBusBreaker_uint16"] = *(unsigned short*)pdis4;
|
||||||
|
|
||||||
|
//TODO: 构建配电系统故障码
|
||||||
|
Json::Value faultCodeDis_array;
|
||||||
|
for(auto val : m_pm->faultCode)
|
||||||
|
{
|
||||||
|
faultCodeDis_array.append(val);
|
||||||
|
}
|
||||||
|
dis[VAR_TO_STR(faultCode_array)] = faultCodeDis_array;
|
||||||
|
|
||||||
|
|
||||||
|
Json::Value currentBusState;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.powerBusVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBpowerBusVol)+suffix] = m_pm->m_pmCurrentState.bus1State.powerBusVoltage;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.dcDc5ModuleCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBdcDc5Cur)+suffix] = m_pm->m_pmCurrentState.bus1State.dcDc5ModuleCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.powerBusCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBpowerBusCur)+suffix] = m_pm->m_pmCurrentState.bus1State.powerBusCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.busbarAVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBbusAVol)+suffix] = m_pm->m_pmCurrentState.bus1State.busbarAVoltage;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.propulsionMotorControlBoxCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBmotorCur)+suffix] = m_pm->m_pmCurrentState.bus1State.propulsionMotorControlBoxCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.busbarACurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBbusACur)+suffix] = m_pm->m_pmCurrentState.bus1State.busbarACurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.lithiumBatteryGroupMeterCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBbatGroupCur)+suffix] = m_pm->m_pmCurrentState.bus1State.lithiumBatteryGroupMeterCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.bowHighVoltageDistributionBoxCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBbowHVolDisBoxCur)+suffix] = m_pm->m_pmCurrentState.bus1State.bowHighVoltageDistributionBoxCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.sternFTDevice45Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBFTDev45Cur)+suffix] = m_pm->m_pmCurrentState.bus1State.sternFTDevice45Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.tyzReservedSwitchCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBtyzCur)+suffix] = m_pm->m_pmCurrentState.bus1State.tyzReservedSwitchCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.sternRudderSwitch1Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBsternRud1Cur)+suffix] = m_pm->m_pmCurrentState.bus1State.sternRudderSwitch1Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.reservedCurrent1).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBreservedCur1)+suffix] = m_pm->m_pmCurrentState.bus1State.reservedCurrent1;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.sternRudderSwitch2Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBsternRud2Cur)+suffix] = m_pm->m_pmCurrentState.bus1State.sternRudderSwitch2Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.reservedCurrent2).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBreservedCur2)+suffix] = m_pm->m_pmCurrentState.bus1State.reservedCurrent2;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.fbReservedSwitchCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBfbCur)+suffix] = m_pm->m_pmCurrentState.bus1State.fbReservedSwitchCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus1State.reservedCurrent3).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBreservedCur3)+suffix] = m_pm->m_pmCurrentState.bus1State.reservedCurrent3;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.busbarBVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABbusBVol)+suffix] = m_pm->m_pmCurrentState.bus2State.busbarBVoltage;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.busbarBCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABbusBCur)+suffix] = m_pm->m_pmCurrentState.bus2State.busbarBCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.bowFTDevice123Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABFTDev123Cur)+suffix] = m_pm->m_pmCurrentState.bus2State.bowFTDevice123Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.actuatorCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABactCur)+suffix] = m_pm->m_pmCurrentState.bus2State.actuatorCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.mastSteeringGearControlBoxCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABmastSteGeaCur)+suffix] = m_pm->m_pmCurrentState.bus2State.mastSteeringGearControlBoxCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.xczCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABxczCur)+suffix] = m_pm->m_pmCurrentState.bus2State.xczCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.bowRudderControlBoxCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABbowRudCur)+suffix] = m_pm->m_pmCurrentState.bus2State.bowRudderControlBoxCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus2State.openWaterCoverStartCylinderCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVABopenWaterCur)+suffix] = m_pm->m_pmCurrentState.bus2State.openWaterCoverStartCylinderCurrent;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.instrumentBusbarVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBinsBusVol)+suffix] = m_pm->m_pmCurrentState.bus3State.instrumentBusbarVoltage;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.bowLowVoltageDistributionBoxCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBbowLowVolDisBoxCur)+suffix] = m_pm->m_pmCurrentState.bus3State.bowLowVoltageDistributionBoxCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.dcC1InstrumentDC48VCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBdcC1InsCur)+suffix] = m_pm->m_pmCurrentState.bus3State.dcC1InstrumentDC48VCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.reservedCurrent1).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBreservedCur1)+suffix] = m_pm->m_pmCurrentState.bus3State.reservedCurrent1;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.emergencyLithiumBatteryGroup2Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBemerBatCur)+suffix] = m_pm->m_pmCurrentState.bus3State.emergencyLithiumBatteryGroup2Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.lithiumBatteryGroupInstrumentCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBbatInsCur)+suffix] = m_pm->m_pmCurrentState.bus3State.lithiumBatteryGroupInstrumentCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.unit4InstrumentDC48VCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBunit4Cur)+suffix] = m_pm->m_pmCurrentState.bus3State.unit4InstrumentDC48VCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.reservedCurrent2).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBreservedCur2)+suffix] = m_pm->m_pmCurrentState.bus3State.reservedCurrent2;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.emergency2BusbarVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBemer2BusVol)+suffix] = m_pm->m_pmCurrentState.bus3State.emergency2BusbarVoltage;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.compositeEnergyManagementSystemEmergencyDC48VCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBCCUCur)+suffix] = m_pm->m_pmCurrentState.bus3State.compositeEnergyManagementSystemEmergencyDC48VCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.fuelCellSecuritySystemEmergencyDC48VCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBFCSSecurSysCur)+suffix] = m_pm->m_pmCurrentState.bus3State.fuelCellSecuritySystemEmergencyDC48VCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus3State.plcControlPowerCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(HVBBplcCur)+suffix] = m_pm->m_pmCurrentState.bus3State.plcControlPowerCurrent;
|
||||||
|
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.instrumentBusbarVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBinsBusVol)+suffix] = m_pm->m_pmCurrentState.bus4State.instrumentBusbarVoltage;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.instrumentBusbarCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBinsBusCur)+suffix] = m_pm->m_pmCurrentState.bus4State.instrumentBusbarCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.unit1Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBunit1Cur)+suffix] = m_pm->m_pmCurrentState.bus4State.unit1Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.unit2Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBunit2Cur)+suffix] = m_pm->m_pmCurrentState.bus4State.unit2Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.unit3Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBunit3Cur)+suffix] = m_pm->m_pmCurrentState.bus4State.unit3Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.unit5Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBunit5Cur)+suffix] = m_pm->m_pmCurrentState.bus4State.unit5Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.bowPZDeviceCurrent).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBbowPZDevCur)+suffix] = m_pm->m_pmCurrentState.bus4State.bowPZDeviceCurrent;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.emergencyLithiumBatteryGroup1Current).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBemerBatCur)+suffix] = m_pm->m_pmCurrentState.bus4State.emergencyLithiumBatteryGroup1Current;
|
||||||
|
suffix = getTypeName(typeid(m_pm->m_pmCurrentState.bus4State.emergency1BusbarVoltage).name());
|
||||||
|
currentBusState[VAR_TO_STR(LVBBemerBusVol)+suffix] = m_pm->m_pmCurrentState.bus4State.emergency1BusbarVoltage;
|
||||||
|
|
||||||
|
// dis["currentBusState"] = currentBusState;
|
||||||
|
|
||||||
|
// pms[VAR_TO_STR(fcs_obj)] = fcs;
|
||||||
|
// pms[VAR_TO_STR(lbs_obj)] = lbs;
|
||||||
|
// pms[VAR_TO_STR(dis_obj)] = dis;
|
||||||
|
|
||||||
|
m_pm->sendNotification(PM_TO_DB_STATE, pms.toStyledString());
|
||||||
|
m_pm->sendNotification(PM_TO_DB_FCSSTATE, fcs.toStyledString());
|
||||||
|
m_pm->sendNotification(PM_TO_DB_LIBATSTATE, lbs.toStyledString());
|
||||||
|
m_pm->sendNotification(PM_TO_DB_DISSTATE, dis.toStyledString());
|
||||||
|
m_pm->sendNotification(PM_TO_DB_CURRENTSTATE, currentBusState.toStyledString());
|
||||||
|
|
||||||
|
// 使用StreamWriterBuilder来设置保持插入顺序
|
||||||
|
Json::StreamWriterBuilder builder;
|
||||||
|
builder["indentation"] = " "; // 设置不缩进,保持紧凑格式
|
||||||
|
builder["enableYAMLCompatibility"] = true; // 保持插入顺序
|
||||||
|
|
||||||
|
// 将Json::Value对象转换为字符串
|
||||||
|
string pathFile = "/home/zjk/project/H100/H100PowerManger/data/msg/";
|
||||||
|
string jsonStr = Json::writeString(builder, pms);
|
||||||
|
|
||||||
|
saveStringToJsonFile(jsonStr, pathFile+PM_TO_DB_STATE+".json");
|
||||||
|
|
||||||
|
jsonStr = Json::writeString(builder, fcs);
|
||||||
|
saveStringToJsonFile(jsonStr, pathFile+PM_TO_DB_FCSSTATE+".json");
|
||||||
|
|
||||||
|
jsonStr = Json::writeString(builder, lbs);
|
||||||
|
saveStringToJsonFile(jsonStr, pathFile+PM_TO_DB_LIBATSTATE+".json");
|
||||||
|
|
||||||
|
jsonStr = Json::writeString(builder, dis);
|
||||||
|
saveStringToJsonFile(jsonStr, pathFile+PM_TO_DB_DISSTATE + ".json");
|
||||||
|
|
||||||
|
jsonStr = Json::writeString(builder, currentBusState);
|
||||||
|
saveStringToJsonFile(jsonStr, pathFile+PM_TO_DB_CURRENTSTATE + ".json");
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
}
|
||||||
|
bool UpperCommManager::saveStringToJsonFile(const string &strJson, const string &filePath)
|
||||||
|
{
|
||||||
|
std::ofstream file(filePath, std::ios::trunc);
|
||||||
|
if (file.is_open()) {
|
||||||
|
file << strJson;
|
||||||
|
file.close();
|
||||||
|
// std::cout << "字符串已成功保存到文件中。" << std::endl;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
std::cerr << "无法打开文件!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string UpperCommManager::getTypeName(const string typeName)
|
||||||
|
{
|
||||||
|
// 映射类型名称到指定的字符串
|
||||||
|
if (typeName == "i" || typeName == "c") {
|
||||||
|
return "_int8";
|
||||||
|
} else if (typeName == "h" || typeName == "C") {
|
||||||
|
return "_uint8";
|
||||||
|
} else if (typeName == "s" || typeName == "S") {
|
||||||
|
return "_int16";
|
||||||
|
} else if (typeName == "t" || typeName == "T") {
|
||||||
|
return "_uint16";
|
||||||
|
} else if (typeName == "i" || typeName == "I") {
|
||||||
|
return "_int32";
|
||||||
|
} else if (typeName == "j" || typeName == "J") {
|
||||||
|
return "_uint32";
|
||||||
|
} else if (typeName == "x" || typeName == "X") {
|
||||||
|
return "_int64";
|
||||||
|
} else if (typeName == "f" || typeName == "F") {
|
||||||
|
return "_fp32";
|
||||||
|
} else if (typeName == "d" || typeName == "D") {
|
||||||
|
return "_fp64";
|
||||||
|
} else if (typeName == "b" || typeName == "B") {
|
||||||
|
return "_bool";
|
||||||
|
} else if (typeName == "NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE") {
|
||||||
|
return "_str";
|
||||||
|
} else if (typeName == "St6vector" || typeName == "St5deque" || typeName == "St4list" || typeName == "St4pair") {
|
||||||
|
return "_array";
|
||||||
|
} else {
|
||||||
|
// 默认情况
|
||||||
|
return "_obj";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#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>
|
||||||
|
using namespace std;
|
||||||
|
#define VAR_TO_STR(var) #var
|
||||||
|
//能源管理反馈的消息
|
||||||
|
#define PM_TO_DB_STATE "uPower_pmState_st"
|
||||||
|
#define PM_TO_DB_CURRENTSTATE "uPower_currentState_st"
|
||||||
|
#define PM_TO_DB_DISSTATE "uPower_disSysState_st"
|
||||||
|
#define PM_TO_DB_LIBATSTATE "uPower_liBatState_st"
|
||||||
|
#define PM_TO_DB_FCSSTATE "uPower_fcsState_st"
|
||||||
|
|
||||||
|
#define PM_TO_DB_SUBDISCMD "uPower_secdistState_cmd"
|
||||||
|
#define PM_TO_DB_EQUIPMENTSTATE "uPower_equState_fb"
|
||||||
|
|
||||||
|
//控制消息
|
||||||
|
#define DB_TO_PM_MSCMD "uPower_sysState_cmd"
|
||||||
|
#define DB_TO_PM_EQUIPMENTCMD "uPower_equState_cmd"
|
||||||
|
#define DB_TO_PM_SUBDISSTATE "uDevice_secdistState_st"
|
||||||
|
|
||||||
|
//决策消息
|
||||||
|
#define DB_TO_PM_DEEPTH "uDevice_depth_st"
|
||||||
|
#define DB_TO_PM_MISSION "uPlan_taskStart_cmd"
|
||||||
|
|
||||||
|
class PowerManger; // 前向声明
|
||||||
|
|
||||||
|
class UpperCommManager {
|
||||||
|
public:
|
||||||
|
UpperCommManager(PowerManger* powerManager);
|
||||||
|
~UpperCommManager();
|
||||||
|
|
||||||
|
// 周期调用
|
||||||
|
void processPeriodicTasks();
|
||||||
|
|
||||||
|
// 处理上位机消息
|
||||||
|
bool processUpperMsg(const std::string& key, const std::string& msg);
|
||||||
|
|
||||||
|
// 生成系统报告
|
||||||
|
void buildSystemReport();
|
||||||
|
|
||||||
|
// 消息处理函数
|
||||||
|
const MSControlCmd getMasterControlCmd(const std::string& key, const std::string& msg);
|
||||||
|
const DriverTable getEquipmentCmd(const std::string& key, const std::string& msg);
|
||||||
|
const DriverTable getSubDisState(const std::string& key, const std::string& msg);
|
||||||
|
const int getDeepth(const std::string& key, const std::string& msg);
|
||||||
|
|
||||||
|
|
||||||
|
const std::string getCurrentEquState(DriverTable& driver);
|
||||||
|
const std::string getSubDisCmd(DriverTable& driver);
|
||||||
|
// 其他公共函数
|
||||||
|
string getTypeName(const string typeName);
|
||||||
|
bool saveStringToJsonFile(const string &strJson, const string &filePath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PowerManger* m_pm;
|
||||||
|
MSControlCmd m_msCmd;
|
||||||
|
Driver m_driver;
|
||||||
|
|
||||||
|
// 从JSON解析控制命令
|
||||||
|
bool parseControlCmdFromJson(MSControlCmd &cmd, const std::string &strJson);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UPPER_COMM_MANAGER_H
|
||||||
@@ -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 0x0050
|
||||||
|
#define CCU_SET_PARM_ID 0x0051
|
||||||
|
#define CCU_STATE_FB_ID 0x0041
|
||||||
|
#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
|
||||||
|
{
|
||||||
|
m_header header;
|
||||||
|
disHighBVolBusCmd data;
|
||||||
|
cChecksum checkCode;
|
||||||
|
}msg_disHVBBCmd;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 高压母线B配电反馈
|
||||||
|
typedef struct {
|
||||||
|
m_header header;
|
||||||
|
disHighBVolBusState data;
|
||||||
|
cChecksum checkCode;
|
||||||
|
} msg_disHighBVolBusFbMsg;
|
||||||
|
|
||||||
|
//仪表汇流排配电反馈
|
||||||
|
typedef struct {
|
||||||
|
m_header header;
|
||||||
|
disLowBusState data;
|
||||||
|
cChecksum checkCode;
|
||||||
|
} msg_disLowBusFbMsg;
|
||||||
|
|
||||||
|
#pragma pack ()
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,146 @@
|
|||||||
|
#ifndef DRIVER_H
|
||||||
|
#define DRIVER_H
|
||||||
|
#include "json/json.h"
|
||||||
|
#include "iostream"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
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 bowWaterlnet1;
|
||||||
|
unsigned char bowWaterlnet2;
|
||||||
|
unsigned char bowWaterlnet3;
|
||||||
|
unsigned char bowWaterlnet4;
|
||||||
|
unsigned char bowWaterlnet5;
|
||||||
|
unsigned char bowWaterlnet6;
|
||||||
|
unsigned char bowWaterlnet7;
|
||||||
|
unsigned char bowWaterlnet8;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DriverState
|
||||||
|
{
|
||||||
|
POWER_OFF, // 断电
|
||||||
|
FULL_POWER_ON, // 全电
|
||||||
|
INSTRUMENT_POWER_ON, // 仪表电上电
|
||||||
|
MOTIVE_POWER_ON, // 动力电上电
|
||||||
|
};
|
||||||
|
|
||||||
|
enum workCondition
|
||||||
|
{
|
||||||
|
STANDBY, // 待机工况
|
||||||
|
SHORE_BASED_READY, // 岸基备航
|
||||||
|
WATER_BASED_READY, // 水中备航
|
||||||
|
CRUISE_MODE, // 巡航模式
|
||||||
|
HIGH_SPEED_MODE, // 高速模式
|
||||||
|
ASCEND_DESCEND, // 上浮下潜
|
||||||
|
BUOYANCY_ADJUST, // 浮调模式
|
||||||
|
UNDERWATER_RECON, // 水下侦查
|
||||||
|
SURFACE_RECON, // 水面侦查
|
||||||
|
DJ_MODE, // DJ模式
|
||||||
|
DEBUG_MODE // 调试模式
|
||||||
|
};
|
||||||
|
|
||||||
|
class Driver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Driver();
|
||||||
|
~Driver();
|
||||||
|
void setDebug(bool debug);
|
||||||
|
|
||||||
|
public:
|
||||||
|
DriverTable* currentDriverTable;
|
||||||
|
DriverTable* nextDriverTable;
|
||||||
|
|
||||||
|
int getDriverTable(workCondition condition, DriverTable* driverTable);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int SafeReadUInt(const Json::Value& root, const std::string& key, unsigned char& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool debug;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DRIVER_H
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/************************************************************/
|
||||||
|
/* 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"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
cout << termColor("green");
|
||||||
|
cout << "pPowerManger launching as " << run_command << endl;
|
||||||
|
cout << termColor() << endl;
|
||||||
|
|
||||||
|
PowerManger PowerManger;
|
||||||
|
|
||||||
|
PowerManger.Run(run_command.c_str(), mission_file.c_str());
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,413 @@
|
|||||||
|
#ifndef PMSYSVARIABLE_H
|
||||||
|
#define PMSYSVARIABLE_H
|
||||||
|
|
||||||
|
//宏定义
|
||||||
|
|
||||||
|
|
||||||
|
#define BREAK_OFF 0xAA
|
||||||
|
#define BREAK_ON 0x55
|
||||||
|
#define BREAK_FALSE 0x5A
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//消息结构体变量定义
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct ccuState
|
||||||
|
{
|
||||||
|
unsigned char currentWorkCondition;
|
||||||
|
unsigned char fcuState;
|
||||||
|
unsigned char fcuFaultLeve;
|
||||||
|
float powerLimit;
|
||||||
|
float totalPowerGeneration;
|
||||||
|
float ch4o;
|
||||||
|
float o2;
|
||||||
|
float fcuVoltage;
|
||||||
|
float fcuCurrent;
|
||||||
|
float o2Level;
|
||||||
|
float placeholder1;
|
||||||
|
float exchangerTemperature;
|
||||||
|
float fcuOutPower;
|
||||||
|
float fcuOutIns;
|
||||||
|
float fcuVoltageIns;
|
||||||
|
float fcuVoltagePower;
|
||||||
|
float fcuCurrentIns;
|
||||||
|
float fcuCurrentPower;
|
||||||
|
float h2Concentration1;
|
||||||
|
float h2Concentration2;
|
||||||
|
float o2Concentration1;
|
||||||
|
float o2Concentration2;
|
||||||
|
float ch4oConcentration1;
|
||||||
|
float ch4oConcentration2;
|
||||||
|
float backpressure1;
|
||||||
|
float backpressure2;
|
||||||
|
unsigned char flameDetection;
|
||||||
|
unsigned char fcuGZ_1L;
|
||||||
|
unsigned char fcuGZ_1H;
|
||||||
|
unsigned char fcuGZ_2L;
|
||||||
|
unsigned char fcuGZ_2H;
|
||||||
|
unsigned char fcuGZ_3L;
|
||||||
|
unsigned char fcuGZ_3H;
|
||||||
|
unsigned char insPosRelayState;
|
||||||
|
unsigned char insNegRelayState;
|
||||||
|
unsigned char powerPosRelayState;
|
||||||
|
unsigned char powerNegRelayState;
|
||||||
|
unsigned short insBatLimit;
|
||||||
|
unsigned short powerBatLimit;
|
||||||
|
unsigned char insBatSoc;
|
||||||
|
unsigned char powerBatSoc;
|
||||||
|
unsigned short insBatTotalElectricity;
|
||||||
|
unsigned short powerBatTotalElectricity;
|
||||||
|
unsigned short insBatCurrentElectricity;
|
||||||
|
unsigned short powerBatCurrentElectricity;
|
||||||
|
unsigned char insChargeState;
|
||||||
|
unsigned char powerChargeState;
|
||||||
|
unsigned short insLinkVoltage;
|
||||||
|
unsigned short insPackVoltage;
|
||||||
|
unsigned short insCurrent;
|
||||||
|
unsigned short insPosInsulationResistance;
|
||||||
|
unsigned short insNegInsulationResistance;
|
||||||
|
unsigned short powerLinkVoltage;
|
||||||
|
unsigned short powerPackVoltage;
|
||||||
|
unsigned short powerCurrent;
|
||||||
|
unsigned short powerPosInsulationResistance;
|
||||||
|
unsigned short powerNegInsulationResistance;
|
||||||
|
unsigned char insEmergencyStatusWord;
|
||||||
|
unsigned char powerEmergencyStatusWord;
|
||||||
|
unsigned char insAlarmIdentificationWord;
|
||||||
|
unsigned char powerAlarmIdentificationWord;
|
||||||
|
unsigned char insCurrentSocHold1;
|
||||||
|
unsigned char insCurrentSocHold2;
|
||||||
|
unsigned char insCurrentSocHold3;
|
||||||
|
unsigned char fcuCurrentToInsLimit1;
|
||||||
|
unsigned char fcuCurrentToinsLimit2;
|
||||||
|
unsigned char powerCurrentSocHold1;
|
||||||
|
unsigned char powerCurrentSocHold2;
|
||||||
|
unsigned char powerCurrentSocHold3;
|
||||||
|
unsigned char powerCurrentToInsLimit1;
|
||||||
|
unsigned char powerCurrentToinsLimit2;
|
||||||
|
float placeholder2;
|
||||||
|
float placeholder3;
|
||||||
|
float placeholder4;
|
||||||
|
float placeholder5;
|
||||||
|
} 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 workCondition;
|
||||||
|
unsigned char fcuCmd;
|
||||||
|
unsigned char fcuPowerEfficiency;
|
||||||
|
unsigned char fcuInsEfficiency;
|
||||||
|
unsigned char insBatCmd;
|
||||||
|
unsigned char powerBatCmd;
|
||||||
|
unsigned char powerBatEfficiency;
|
||||||
|
unsigned char heartbeat;
|
||||||
|
unsigned char masterState;
|
||||||
|
}ccuColCmd;
|
||||||
|
|
||||||
|
typedef struct disHighVolBusState
|
||||||
|
{
|
||||||
|
unsigned char fuelCellCircuitBreaker;
|
||||||
|
unsigned char powerLithiumBatteryCircuitBreaker;
|
||||||
|
unsigned char propulsionMotorCircuitBreaker;
|
||||||
|
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
|
||||||
|
unsigned char dcDc5ModuleCircuitBreaker;
|
||||||
|
unsigned char bowHighVoltageDistributionBoxCircuitBreaker;
|
||||||
|
unsigned char sternFTDevice45CircuitBreaker;
|
||||||
|
unsigned char sternRudderSwitch1CircuitBreaker;
|
||||||
|
unsigned char sternRudderSwitch2CircuitBreaker;
|
||||||
|
unsigned char fbReservedCircuitBreaker;
|
||||||
|
unsigned char tyzReservedCircuitBreaker;
|
||||||
|
unsigned char reservedCircuitBreaker;
|
||||||
|
unsigned char busInsulationLow;
|
||||||
|
unsigned char busAInsulationHigh;
|
||||||
|
unsigned char lostPower;
|
||||||
|
unsigned char lostEmerPower;
|
||||||
|
unsigned short powerBusVoltage;
|
||||||
|
unsigned short dcDc5ModuleCurrent;
|
||||||
|
unsigned short powerBusCurrent;
|
||||||
|
unsigned short busbarAVoltage;
|
||||||
|
unsigned short propulsionMotorControlBoxCurrent;
|
||||||
|
unsigned short busbarACurrent;
|
||||||
|
unsigned short lithiumBatteryGroupMeterCurrent;
|
||||||
|
unsigned short bowHighVoltageDistributionBoxCurrent;
|
||||||
|
unsigned short sternFTDevice45Current;
|
||||||
|
unsigned short tyzReservedSwitchCurrent;
|
||||||
|
unsigned short sternRudderSwitch1Current;
|
||||||
|
unsigned short reservedCurrent1; // 改为 reservedCurrent1 以避免重名
|
||||||
|
unsigned short sternRudderSwitch2Current;
|
||||||
|
unsigned short reservedCurrent2; // 改为 reservedCurrent2 以避免重名
|
||||||
|
unsigned short fbReservedSwitchCurrent;
|
||||||
|
unsigned short reservedCurrent3; // 改为 reservedCurrent3 以避免重名
|
||||||
|
}disHighVolBusState;
|
||||||
|
|
||||||
|
typedef struct disHighAVolBusState
|
||||||
|
{
|
||||||
|
unsigned char bowFTDevice123CircuitBreaker;
|
||||||
|
unsigned char actuatorCircuitBreaker;
|
||||||
|
unsigned char mastSteeringGearControlBoxCircuitBreaker;
|
||||||
|
unsigned char xczCircuitBreaker;
|
||||||
|
unsigned char bowRudderControlBoxCircuitBreaker;
|
||||||
|
unsigned char openWaterCoverStartCylinderCircuitBreaker;
|
||||||
|
unsigned char instrumentPowerFailureSignal;
|
||||||
|
unsigned char emergencyPowerFailureSignal;
|
||||||
|
unsigned char waterIngressionAlarm;
|
||||||
|
unsigned short busbarBVoltage;
|
||||||
|
unsigned short busbarBCurrent;
|
||||||
|
unsigned short bowFTDevice123Current;
|
||||||
|
unsigned short actuatorCurrent;
|
||||||
|
unsigned short mastSteeringGearControlBoxCurrent;
|
||||||
|
unsigned short xczCurrent;
|
||||||
|
unsigned short bowRudderControlBoxCurrent;
|
||||||
|
unsigned short openWaterCoverStartCylinderCurrent;
|
||||||
|
}disHighAVolBusState;
|
||||||
|
|
||||||
|
typedef struct disHighBVolBusState
|
||||||
|
{
|
||||||
|
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
|
||||||
|
unsigned char bowLowVoltageDistributionBoxCircuitBreaker;
|
||||||
|
unsigned char unit4InstrumentDC48VCircuitBreaker;
|
||||||
|
unsigned char dcC1DCDistributionPanelCircuitBreaker;
|
||||||
|
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
|
||||||
|
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
|
||||||
|
unsigned char emergencyLithiumBatteryGroup2CircuitBreaker;
|
||||||
|
unsigned char instrumentPowerFailureSignal;
|
||||||
|
unsigned char emergencyPowerFailureSignal;
|
||||||
|
unsigned char instrumentBusbarInsulationLow;
|
||||||
|
unsigned short instrumentBusbarVoltage;
|
||||||
|
unsigned short bowLowVoltageDistributionBoxCurrent;
|
||||||
|
unsigned short dcC1InstrumentDC48VCurrent;
|
||||||
|
unsigned short reservedCurrent1; // 为了区分,添加了数字后缀
|
||||||
|
unsigned short emergencyLithiumBatteryGroup2Current;
|
||||||
|
unsigned short lithiumBatteryGroupInstrumentCurrent;
|
||||||
|
unsigned short unit4InstrumentDC48VCurrent;
|
||||||
|
unsigned short reservedCurrent2; // 为了区分,添加了数字后缀
|
||||||
|
unsigned short emergency2BusbarVoltage;
|
||||||
|
unsigned short compositeEnergyManagementSystemEmergencyDC48VCurrent;
|
||||||
|
unsigned short fuelCellSecuritySystemEmergencyDC48VCurrent;
|
||||||
|
unsigned short plcControlPowerCurrent;
|
||||||
|
}disHighBVolBusState;
|
||||||
|
|
||||||
|
typedef struct disLowBusState
|
||||||
|
{
|
||||||
|
unsigned char unit1CircuitBreaker;
|
||||||
|
unsigned char unit2CircuitBreaker;
|
||||||
|
unsigned char unit3CircuitBreaker;
|
||||||
|
unsigned char unit5CircuitBreaker;
|
||||||
|
unsigned char bowPZDeviceCircuitBreaker;
|
||||||
|
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
|
||||||
|
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
|
||||||
|
unsigned char emergencyLithiumBatteryGroup1CircuitBreaker;
|
||||||
|
unsigned char powerFailureSignal;
|
||||||
|
unsigned char waterIngressionAlarm;
|
||||||
|
unsigned short instrumentBusbarVoltage;
|
||||||
|
unsigned short instrumentBusbarCurrent;
|
||||||
|
unsigned short unit1Current;
|
||||||
|
unsigned short unit2Current;
|
||||||
|
unsigned short unit3Current;
|
||||||
|
unsigned short unit5Current;
|
||||||
|
unsigned short bowPZDeviceCurrent;
|
||||||
|
unsigned short emergencyLithiumBatteryGroup1Current;
|
||||||
|
unsigned short emergency1BusbarVoltage;
|
||||||
|
}disLowBusState;
|
||||||
|
|
||||||
|
typedef struct disHighVolBusCmd
|
||||||
|
{
|
||||||
|
unsigned char fuelCellCircuitBreaker;
|
||||||
|
unsigned char powerLithiumBatteryCircuitBreaker;
|
||||||
|
unsigned char propulsionMotorCircuitBreaker;
|
||||||
|
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
|
||||||
|
unsigned char dcDc5ModuleCircuitBreaker;
|
||||||
|
unsigned char bowHighVoltageDistributionBoxCircuitBreaker;
|
||||||
|
unsigned char sternFTDevice45CircuitBreaker;
|
||||||
|
unsigned char sternRudderSwitch1CircuitBreaker;
|
||||||
|
unsigned char sternRudderSwitch2CircuitBreaker;
|
||||||
|
unsigned char fbReservedCircuitBreaker;
|
||||||
|
unsigned char tyzReservedCircuitBreaker;
|
||||||
|
unsigned char reservedCircuitBreaker;
|
||||||
|
unsigned char dcdc5Module;
|
||||||
|
unsigned char inputWater;
|
||||||
|
unsigned char outputWater;
|
||||||
|
}disHighVolBusCmd;
|
||||||
|
|
||||||
|
typedef struct disHighAVolBusCmd
|
||||||
|
{
|
||||||
|
unsigned char bowFTDevice123CircuitBreaker;
|
||||||
|
unsigned char actuatorCircuitBreaker;
|
||||||
|
unsigned char mastSteeringGearControlBoxCircuitBreaker;
|
||||||
|
unsigned char xczCircuitBreaker;
|
||||||
|
unsigned char bowRudderControlBoxCircuitBreaker;
|
||||||
|
unsigned char openWaterCoverStartCylinderCircuitBreaker;
|
||||||
|
}disHighAVolBusCmd;
|
||||||
|
|
||||||
|
typedef struct disHighBVolBusCmd
|
||||||
|
{
|
||||||
|
unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
|
||||||
|
unsigned char bowLowVoltageDistributionBoxCircuitBreaker;
|
||||||
|
unsigned char unit4InstrumentDC48VCircuitBreaker;
|
||||||
|
unsigned char dcC1DCDistributionPanelCircuitBreaker;
|
||||||
|
unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
|
||||||
|
unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
|
||||||
|
unsigned char emergencyLithiumBatteryGroup2CircuitBreaker;
|
||||||
|
}disHighBVolBusCmd;
|
||||||
|
|
||||||
|
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;
|
||||||
|
disHighBVolBusState 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 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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* TinyFSM - Tiny Finite State Machine Processor
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012-2022 Axel Burri
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
* Version: 0.3.3
|
||||||
|
*
|
||||||
|
* API documentation: see "../doc/50-API.md"
|
||||||
|
*
|
||||||
|
* The official TinyFSM website is located at:
|
||||||
|
* https://digint.ch/tinyfsm/
|
||||||
|
*
|
||||||
|
* Author:
|
||||||
|
* Axel Burri <axel@tty0.ch>
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TINYFSM_HPP_INCLUDED
|
||||||
|
#define TINYFSM_HPP_INCLUDED
|
||||||
|
|
||||||
|
#ifndef TINYFSM_NOSTDLIB
|
||||||
|
#include <type_traits>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #include <iostream>
|
||||||
|
// #define DBG(str) do { std::cerr << str << std::endl; } while( false )
|
||||||
|
// DBG("*** dbg_example *** " << __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
namespace tinyfsm
|
||||||
|
{
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct Event { };
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef TINYFSM_NOSTDLIB
|
||||||
|
// remove dependency on standard library (silent fail!).
|
||||||
|
// useful in conjunction with -nostdlib option, e.g. if your compiler
|
||||||
|
// does not provide a standard library.
|
||||||
|
// NOTE: this silently disables all static_assert() calls below!
|
||||||
|
template<typename F, typename S>
|
||||||
|
struct is_same_fsm { static constexpr bool value = true; };
|
||||||
|
#else
|
||||||
|
// check if both fsm and state class share same fsmtype
|
||||||
|
template<typename F, typename S>
|
||||||
|
struct is_same_fsm : std::is_same< typename F::fsmtype, typename S::fsmtype > { };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename S>
|
||||||
|
struct _state_instance
|
||||||
|
{
|
||||||
|
using value_type = S;
|
||||||
|
using type = _state_instance<S>;
|
||||||
|
static S value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename S>
|
||||||
|
typename _state_instance<S>::value_type _state_instance<S>::value;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
class Fsm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
using fsmtype = Fsm<F>;
|
||||||
|
using state_ptr_t = F *;
|
||||||
|
|
||||||
|
static state_ptr_t current_state_ptr;
|
||||||
|
|
||||||
|
// public, leaving ability to access state instance (e.g. on reset)
|
||||||
|
template<typename S>
|
||||||
|
static constexpr S & state(void) {
|
||||||
|
static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
|
||||||
|
return _state_instance<S>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename S>
|
||||||
|
static constexpr bool is_in_state(void) {
|
||||||
|
static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
|
||||||
|
return current_state_ptr == &_state_instance<S>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// state machine functions
|
||||||
|
public:
|
||||||
|
|
||||||
|
// explicitely specialized in FSM_INITIAL_STATE macro
|
||||||
|
static void set_initial_state();
|
||||||
|
|
||||||
|
static void reset() { };
|
||||||
|
|
||||||
|
static void enter() {
|
||||||
|
current_state_ptr->entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start() {
|
||||||
|
set_initial_state();
|
||||||
|
enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
static void dispatch(E const & event) {
|
||||||
|
current_state_ptr->react(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// state transition functions
|
||||||
|
protected:
|
||||||
|
|
||||||
|
template<typename S>
|
||||||
|
void transit(void) {
|
||||||
|
static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
|
||||||
|
current_state_ptr->exit();
|
||||||
|
current_state_ptr = &_state_instance<S>::value;
|
||||||
|
current_state_ptr->entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename S, typename ActionFunction>
|
||||||
|
void transit(ActionFunction action_function) {
|
||||||
|
static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
|
||||||
|
current_state_ptr->exit();
|
||||||
|
// NOTE: do not send events in action_function definisions.
|
||||||
|
action_function();
|
||||||
|
current_state_ptr = &_state_instance<S>::value;
|
||||||
|
current_state_ptr->entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename S, typename ActionFunction, typename ConditionFunction>
|
||||||
|
void transit(ActionFunction action_function, ConditionFunction condition_function) {
|
||||||
|
if(condition_function()) {
|
||||||
|
transit<S>(action_function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
typename Fsm<F>::state_ptr_t Fsm<F>::current_state_ptr;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename... FF>
|
||||||
|
struct FsmList;
|
||||||
|
|
||||||
|
template<> struct FsmList<> {
|
||||||
|
static void set_initial_state() { }
|
||||||
|
static void reset() { }
|
||||||
|
static void enter() { }
|
||||||
|
template<typename E>
|
||||||
|
static void dispatch(E const &) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F, typename... FF>
|
||||||
|
struct FsmList<F, FF...>
|
||||||
|
{
|
||||||
|
using fsmtype = Fsm<F>;
|
||||||
|
|
||||||
|
static void set_initial_state() {
|
||||||
|
fsmtype::set_initial_state();
|
||||||
|
FsmList<FF...>::set_initial_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset() {
|
||||||
|
F::reset();
|
||||||
|
FsmList<FF...>::reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enter() {
|
||||||
|
fsmtype::enter();
|
||||||
|
FsmList<FF...>::enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start() {
|
||||||
|
set_initial_state();
|
||||||
|
enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
static void dispatch(E const & event) {
|
||||||
|
fsmtype::template dispatch<E>(event);
|
||||||
|
FsmList<FF...>::template dispatch<E>(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename... SS> struct StateList;
|
||||||
|
template<> struct StateList<> {
|
||||||
|
static void reset() { }
|
||||||
|
};
|
||||||
|
template<typename S, typename... SS>
|
||||||
|
struct StateList<S, SS...>
|
||||||
|
{
|
||||||
|
static void reset() {
|
||||||
|
_state_instance<S>::value = S();
|
||||||
|
StateList<SS...>::reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
struct MooreMachine : tinyfsm::Fsm<F>
|
||||||
|
{
|
||||||
|
virtual void entry(void) { }; /* entry actions in some states */
|
||||||
|
void exit(void) { }; /* no exit actions */
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
struct MealyMachine : tinyfsm::Fsm<F>
|
||||||
|
{
|
||||||
|
// input actions are modeled in react():
|
||||||
|
// - conditional dependent of event type or payload
|
||||||
|
// - transit<>(ActionFunction)
|
||||||
|
void entry(void) { }; /* no entry actions */
|
||||||
|
void exit(void) { }; /* no exit actions */
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace tinyfsm */
|
||||||
|
|
||||||
|
|
||||||
|
#define FSM_INITIAL_STATE(_FSM, _STATE) \
|
||||||
|
namespace tinyfsm { \
|
||||||
|
template<> void Fsm< _FSM >::set_initial_state(void) { \
|
||||||
|
current_state_ptr = &_state_instance< _STATE >::value; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TINYFSM_HPP_INCLUDED */
|
||||||
@@ -0,0 +1,569 @@
|
|||||||
|
#include "udpComm.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
udpComm::udpComm()
|
||||||
|
{
|
||||||
|
udpScoket = nullptr;
|
||||||
|
ccuHost = "";
|
||||||
|
ccuPort = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
udpComm::~udpComm() {
|
||||||
|
if (udpScoket) {
|
||||||
|
delete udpScoket;
|
||||||
|
udpScoket = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Checksum udpComm::calculateChecksum(const unsigned char* data, int size)
|
||||||
|
{
|
||||||
|
Checksum checksum = 0;
|
||||||
|
int size_data = size - sizeof(Checksum);
|
||||||
|
for (int i = 0; i < size_data; i++) {
|
||||||
|
checksum += data[i];
|
||||||
|
}
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
Checksum udpComm::calculateChecksum(const unsigned char* data, int dataSize, int checkSize)
|
||||||
|
{
|
||||||
|
Checksum checksum = 0;
|
||||||
|
int size_data = dataSize - checkSize;
|
||||||
|
for (int i = 0; i < size_data; i++) {
|
||||||
|
checksum += data[i];
|
||||||
|
}
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
bool udpComm::getMsgId(char *m,unsigned short &id)
|
||||||
|
{
|
||||||
|
m_header h;
|
||||||
|
h = *reinterpret_cast<m_header *>(m);
|
||||||
|
// 判断消息是否有效
|
||||||
|
if (h.start1== DIS_MSG_HEAD1 && h.start2==DIS_MSG_HEAD2)
|
||||||
|
{
|
||||||
|
id = h.id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (h.start1==CCU_UDPMSG_START1 && h.start2==CCU_UDPMSG_START2)
|
||||||
|
{
|
||||||
|
id = h.id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sError.push_back("Msg Header errar");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool udpComm::getMsgFromBuff(char *m, msg_CcuStateFbMsg &s) {
|
||||||
|
Checksum sum;
|
||||||
|
msg_CcuStateFbMsg *p;
|
||||||
|
p = reinterpret_cast<msg_CcuStateFbMsg *>(m);
|
||||||
|
sum = calculateChecksum((unsigned char*)m, sizeof(msg_CcuStateFbMsg));
|
||||||
|
|
||||||
|
if (sum != p->checkCode) {
|
||||||
|
sError.push_back("CcuStat Msg Check error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s = *p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::getMsgFromBuff(char *m, msg_CcuSetParmFbMsg &s)
|
||||||
|
{
|
||||||
|
Checksum sum;
|
||||||
|
msg_CcuSetParmFbMsg *p;
|
||||||
|
p = reinterpret_cast<msg_CcuSetParmFbMsg *>(m);
|
||||||
|
sum = calculateChecksum((unsigned char*)m, sizeof(msg_CcuSetParmFbMsg));
|
||||||
|
|
||||||
|
if (sum!= p->checkCode) {
|
||||||
|
sError.push_back("CcuSetParm Msg Check error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = *p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::getMsgFromBuff(char *m, msg_disHighVolBusFbMsg &s)
|
||||||
|
{
|
||||||
|
cChecksum sum;
|
||||||
|
msg_disHighVolBusFbMsg *p;
|
||||||
|
p = reinterpret_cast<msg_disHighVolBusFbMsg *>(m);
|
||||||
|
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disHighVolBusFbMsg), sizeof(cChecksum)) & 0xFF;
|
||||||
|
if (sum != p->checkCode) {
|
||||||
|
sError.push_back("DisSys HVBus Msg Check error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s = *p;
|
||||||
|
// cout << s.data.busbarAVoltage << endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::getMsgFromBuff(char *m, msg_disHighAVolBusFbMsg &s)
|
||||||
|
{
|
||||||
|
cChecksum sum;
|
||||||
|
msg_disHighAVolBusFbMsg *p;
|
||||||
|
p = reinterpret_cast<msg_disHighAVolBusFbMsg *>(m);
|
||||||
|
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disHighAVolBusFbMsg), sizeof(cChecksum)) & 0xFF;
|
||||||
|
if (sum!= p->checkCode) {
|
||||||
|
sError.push_back("DisSys HVABus Msg Check error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s = *p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool udpComm::getMsgFromBuff(char *m, msg_disHighBVolBusFbMsg &s)
|
||||||
|
{
|
||||||
|
cChecksum sum;
|
||||||
|
msg_disHighBVolBusFbMsg *p;
|
||||||
|
p = reinterpret_cast<msg_disHighBVolBusFbMsg *>(m);
|
||||||
|
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disHighBVolBusFbMsg), sizeof(cChecksum)) & 0xFF;
|
||||||
|
if (sum!= p->checkCode) {
|
||||||
|
sError.push_back("DisSys HVBBus Msg Check error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s = *p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::getMsgFromBuff(char *m, msg_disLowBusFbMsg &s)
|
||||||
|
{
|
||||||
|
cChecksum sum;
|
||||||
|
msg_disLowBusFbMsg *p;
|
||||||
|
p = reinterpret_cast<msg_disLowBusFbMsg *>(m);
|
||||||
|
sum = calculateChecksum((unsigned char*)m, sizeof(msg_disLowBusFbMsg), sizeof(cChecksum)) & 0xFF;
|
||||||
|
if (sum!= p->checkCode) {
|
||||||
|
sError.push_back("DisSys LVBus Msg Check error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s = *p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||||
|
{
|
||||||
|
if(m==NULL)
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,Msg is NULL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* Buff = m;
|
||||||
|
//消息头鉴定
|
||||||
|
char *header = new char[sizeof(m_header)];
|
||||||
|
unsigned short id;
|
||||||
|
memcpy(header,Buff,sizeof(m_header));
|
||||||
|
if(!getMsgId(header,id))
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,Msg ID error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delete []header;
|
||||||
|
//输入消息
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case CCU_STATE_FB_ID: //CCU_STATE_FB 0x0051
|
||||||
|
{
|
||||||
|
msg_CcuStateFbMsg s;
|
||||||
|
if(getMsgFromBuff((char *)Buff,s))
|
||||||
|
{
|
||||||
|
if(m_qReceiveCcuStateBuffer.size()<QUENUE_SIZE)
|
||||||
|
{
|
||||||
|
double time = MOOSTime();
|
||||||
|
m_qReceiveCcuStateBuffer.push(std::make_pair(time, s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,CcuState buffer is full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CCU_SET_PARM_FB_ID: //CCU_SET_PARM_FB 0x0040
|
||||||
|
{
|
||||||
|
msg_CcuSetParmFbMsg s;
|
||||||
|
if(getMsgFromBuff((char *)Buff,s))
|
||||||
|
{
|
||||||
|
if(m_qReceiveCcuSetParmBuffer.size()<QUENUE_SIZE)
|
||||||
|
{
|
||||||
|
double time = MOOSTime();
|
||||||
|
m_qReceiveCcuSetParmBuffer.push(std::make_pair(time, s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,CcuSetParm buffer is full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIS_HVBUS_FB_ID: //DIS_HVBUS_FB 0x0020
|
||||||
|
{
|
||||||
|
msg_disHighVolBusFbMsg s;
|
||||||
|
if(getMsgFromBuff((char *)Buff,s))
|
||||||
|
{
|
||||||
|
if(m_qReceiveDisHighVolBusBuffer.size()<QUENUE_SIZE)
|
||||||
|
{
|
||||||
|
double time = MOOSTime();
|
||||||
|
m_qReceiveDisHighVolBusBuffer.push(std::make_pair(time, s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,DisSysHVBus buffer is full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIS_HVBUSA_FB_ID: //DIS_HVBUSA_FB 0x0006
|
||||||
|
{
|
||||||
|
msg_disHighAVolBusFbMsg s;
|
||||||
|
if(getMsgFromBuff((char *)Buff,s))
|
||||||
|
{
|
||||||
|
if(m_qReceiveDisHighAVolBusBuffer.size()<QUENUE_SIZE)
|
||||||
|
{
|
||||||
|
double time = MOOSTime();
|
||||||
|
m_qReceiveDisHighAVolBusBuffer.push(std::make_pair(time, s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,DisSysHVABus buffer is full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIS_HVBUSB_FB_ID: //DIS_HVBUSB_FB 0x0007
|
||||||
|
{
|
||||||
|
msg_disHighBVolBusFbMsg s;
|
||||||
|
if(getMsgFromBuff((char *)Buff,s))
|
||||||
|
{
|
||||||
|
if(m_qReceiveDisHighBVolBusBuffer.size()<QUENUE_SIZE)
|
||||||
|
{
|
||||||
|
double time = MOOSTime();
|
||||||
|
m_qReceiveDisHighBVolBusBuffer.push(std::make_pair(time, s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,DisSysHVBBus buffer is full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIS_LVBUS_FB_ID: //DIS_LVBUS_FB 0x0008
|
||||||
|
{
|
||||||
|
msg_disLowBusFbMsg s;
|
||||||
|
if(getMsgFromBuff((char *)Buff,s))
|
||||||
|
{
|
||||||
|
if(m_qReceiveDisLowBusBuffer.size()<QUENUE_SIZE)
|
||||||
|
{
|
||||||
|
double time = MOOSTime();
|
||||||
|
m_qReceiveDisLowBusBuffer.push(std::make_pair(time, s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sError.push_back("pushMsgToQueue faile,DisSysLVBus buffer is full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::clearMsgQueue()
|
||||||
|
{
|
||||||
|
while(!m_qReceiveCcuStateBuffer.empty())
|
||||||
|
m_qReceiveCcuStateBuffer.pop();
|
||||||
|
|
||||||
|
while(!m_qReceiveCcuSetParmBuffer.empty())
|
||||||
|
m_qReceiveCcuSetParmBuffer.pop();
|
||||||
|
|
||||||
|
while(!m_qReceiveDisHighVolBusBuffer.empty())
|
||||||
|
m_qReceiveDisHighVolBusBuffer.pop();
|
||||||
|
|
||||||
|
while(!m_qReceiveDisHighAVolBusBuffer.empty())
|
||||||
|
m_qReceiveDisHighAVolBusBuffer.pop();
|
||||||
|
|
||||||
|
while(!m_qReceiveDisHighBVolBusBuffer.empty())
|
||||||
|
m_qReceiveDisHighBVolBusBuffer.pop();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
bool udpComm::popMsgFormQueue(double &time,msg_disHighBVolBusFbMsg &m)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool udpComm::sendDisSysCmd(const disHighVolBusCmd cmd)
|
||||||
|
{
|
||||||
|
unsigned char* msgBuf;
|
||||||
|
Checksum 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);
|
||||||
|
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;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sendMsg(msgBuf,sizeof(msg_disHVBCmd));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
delete msg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::sendDisSysCmd(const disHighAVolBusCmd cmd)
|
||||||
|
{
|
||||||
|
unsigned char* msgBuf;
|
||||||
|
Checksum 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);
|
||||||
|
msg->data = cmd;
|
||||||
|
msgBuf = reinterpret_cast<unsigned char *>(msg);
|
||||||
|
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBACmd));
|
||||||
|
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sendMsg(msgBuf,sizeof(msg_disHVBACmd));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
delete msg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::sendDisSysCmd(const disHighBVolBusCmd cmd)
|
||||||
|
{
|
||||||
|
unsigned char* msgBuf;
|
||||||
|
Checksum 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);
|
||||||
|
msg->data = cmd;
|
||||||
|
msgBuf = reinterpret_cast<unsigned char *>(msg);
|
||||||
|
cc = calculateChecksum(msgBuf,sizeof(msg_disHVBBCmd));
|
||||||
|
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// cout << "=========" <<(int)sizeof(msg_disHVBBCmd) << endl;
|
||||||
|
sendMsg(msgBuf,sizeof(msg_disHVBBCmd));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
delete msg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::sendDisSysCmd(const disLowBusCmd cmd)
|
||||||
|
{
|
||||||
|
unsigned char* msgBuf;
|
||||||
|
Checksum 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);
|
||||||
|
msg->data = cmd;
|
||||||
|
msgBuf = reinterpret_cast<unsigned char *>(msg);
|
||||||
|
cc = calculateChecksum(msgBuf,sizeof(msg_disLVBCmd));
|
||||||
|
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sendMsg(msgBuf,sizeof(msg_disLVBCmd));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
delete msg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::sendCcuColCmd(const ccuColCmd cmd)
|
||||||
|
{
|
||||||
|
unsigned char* msgBuf;
|
||||||
|
Checksum cc;
|
||||||
|
msg_CcuColCmdMsg* msg = new msg_CcuColCmdMsg;
|
||||||
|
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);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
delete msg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool udpComm::sendCcuSetParmCmd(const ccuSetParmCmd cmd)
|
||||||
|
{
|
||||||
|
unsigned char* msgBuf;
|
||||||
|
Checksum cc;
|
||||||
|
msg_CcuSetParmMsg* msg = new msg_CcuSetParmMsg;
|
||||||
|
msg->header.id = CCU_SET_PARM_ID;
|
||||||
|
msg->header.start1 = CCU_UDPMSG_START1;
|
||||||
|
msg->header.start2 = CCU_UDPMSG_START2;
|
||||||
|
msg->header.length = sizeof(ccuSetParmCmd);
|
||||||
|
msg->cmd = cmd;
|
||||||
|
msgBuf = reinterpret_cast<unsigned char *>(msg);
|
||||||
|
cc = calculateChecksum(msgBuf,sizeof(msg_CcuSetParmMsg));
|
||||||
|
msg->checkCode = static_cast<cChecksum>(cc & 0xFF);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sendMsg(msgBuf,sizeof(msg_CcuSetParmMsg));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
delete msg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool udpComm::getDate(unsigned short &year, unsigned char &month, unsigned char &day, unsigned char &hour, unsigned char &minute, unsigned char &second, unsigned char &milliseconds) {
|
||||||
|
// 获取当前时间
|
||||||
|
std::time_t now = std::time(nullptr);
|
||||||
|
if (now == -1) {
|
||||||
|
return false; // 获取时间失败
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为本地时间
|
||||||
|
std::tm *localTime = std::localtime(&now);
|
||||||
|
if (!localTime) {
|
||||||
|
return false; // 转换失败
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取年、月、日、时、分、秒
|
||||||
|
year = localTime->tm_year + 1900; // tm_year 是从 1900 年开始的
|
||||||
|
month = localTime->tm_mon + 1; // tm_mon 是从 0 开始的,0 对应 1 月
|
||||||
|
day = localTime->tm_mday;
|
||||||
|
hour = localTime->tm_hour;
|
||||||
|
minute = localTime->tm_min;
|
||||||
|
second = localTime->tm_sec;
|
||||||
|
|
||||||
|
// 获取毫秒,使用 std::chrono
|
||||||
|
auto now_ms = std::chrono::system_clock::now();
|
||||||
|
auto duration = now_ms.time_since_epoch();
|
||||||
|
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; // 取毫秒部分
|
||||||
|
ms = ms/10;
|
||||||
|
milliseconds = static_cast<unsigned char>(ms);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef UDPCOMM__H
|
||||||
|
#define UDPCOMM__H
|
||||||
|
#define UNIX
|
||||||
|
|
||||||
|
#include "ccuUdpMsg.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h"
|
||||||
|
#include "MOOS/libMOOS/Comms/XPCUdpSocket.h"
|
||||||
|
#include <ctime>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <utility> // for std::pair
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
#define QUENUE_SIZE 100
|
||||||
|
|
||||||
|
class udpComm {
|
||||||
|
public:
|
||||||
|
udpComm();
|
||||||
|
~udpComm();
|
||||||
|
XPCUdpSocket *udpScoket;
|
||||||
|
string ccuHost;
|
||||||
|
long int ccuPort;
|
||||||
|
|
||||||
|
bool pushMsgToQueue(unsigned char *m);
|
||||||
|
bool clearMsgQueue();
|
||||||
|
|
||||||
|
bool getMsgFromBuff(char *m, msg_CcuStateFbMsg &s);
|
||||||
|
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_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_disLowBusFbMsg &m);
|
||||||
|
|
||||||
|
bool sendCcuColCmd(const ccuColCmd cmd);
|
||||||
|
bool sendCcuSetParmCmd(const ccuSetParmCmd cmd);
|
||||||
|
|
||||||
|
bool sendDisSysCmd(const disHighVolBusCmd cmd);
|
||||||
|
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 getMsgId(char *m,unsigned short &id);
|
||||||
|
Checksum calculateChecksum(const unsigned char* data, int size);
|
||||||
|
Checksum calculateChecksum(const unsigned char* data, int dataSize, int checkSize);
|
||||||
|
|
||||||
|
bool getDate(unsigned short &year, unsigned char &month, unsigned char &day, unsigned char &hour, unsigned char &minute, unsigned char &second, unsigned char &milliseconds);
|
||||||
|
|
||||||
|
std::vector<std::string> sError;
|
||||||
|
|
||||||
|
// 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_disLowBusFbMsg>> m_qReceiveDisLowBusBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
msg_CcuColCmdMsg m_ccuColCmd;
|
||||||
|
msg_CcuSetParmMsg m_ccuSetParmCmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
## H100PowerManger CI 测试报告
|
|
||||||
|
|
||||||
**总体结论: ✅ 全部通过**
|
|
||||||
|
|
||||||
| 步骤 | 结果 | 耗时 |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| 构建 (aarch64) | ✅ 通过 | 1725s |
|
|
||||||
| 单元测试 SQLiteTest | ✅ 通过 | 0s |
|
|
||||||
| 单元测试 PowerMangerTests (gtest) | ✅ 通过 | 1s |
|
|
||||||
| 冒烟测试 MOOSDB+pPowerManger | ✅ 通过 | 9s |
|
|
||||||
| 集成测试 UDP反馈→SQLite | ✅ 通过 | 6s |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
- 架构: `aarch64`
|
|
||||||
- Commit: `38c489c`
|
|
||||||
- 时间: 2026-09-02 12:54:52 UTC
|
|
||||||
- 运行: [https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/actions/runs/36](https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/actions/runs/36)
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(SQLiteDBTest)
|
||||||
|
|
||||||
|
# 设置 C++ 标准
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
#############################################SQLiteDBTest####################################################################
|
||||||
|
# 查找 SQLiteDB 项目库
|
||||||
|
find_library(SQLiteDB_LIB NAMES SQLiteDB PATHS /home/zjk/project/H100/H100PowerManger/lib)
|
||||||
|
if(NOT SQLiteDB_LIB)
|
||||||
|
message(FATAL_ERROR "SQLiteDB library not found!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 查找 Catch2 测试框架
|
||||||
|
find_package(Catch2 REQUIRED)
|
||||||
|
|
||||||
|
# 添加测试可执行文件
|
||||||
|
add_executable(SQLiteDBTest SQLiteDBTest.cpp)
|
||||||
|
# 链接库文件(注意顺序:先项目库后系统库)
|
||||||
|
target_link_libraries(SQLiteDBTest
|
||||||
|
${SQLiteDB_LIB} # 项目SQLiteDB库
|
||||||
|
Catch2::Catch2WithMain # 测试框架
|
||||||
|
sqlite3
|
||||||
|
jsoncpp
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################udpCommTest####################################################################
|
||||||
|
# 查找 udpComm 项目库
|
||||||
|
find_library(UDPCOMM_LIB NAMES UDPComm PATHS /home/zjk/project/H100/H100PowerManger/lib)
|
||||||
|
if(NOT UDPCOMM_LIB)
|
||||||
|
message(FATAL_ERROR "udpComm library not found!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 添加 udpComm 测试可执行文件
|
||||||
|
add_executable(udpCommTest udpCommTest.cpp)
|
||||||
|
|
||||||
|
# 链接库文件(注意顺序:先项目库后系统库)
|
||||||
|
target_link_libraries(udpCommTest
|
||||||
|
${UDPCOMM_LIB} # 项目udpComm库
|
||||||
|
${MOOS_LIBRARIES}
|
||||||
|
Catch2::Catch2WithMain # 测试框架
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################PowerMangerTest####################################################################
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#include "catch2/catch.hpp"
|
||||||
|
#include "../src/pPowerManger/SQLiteDB.h"
|
||||||
|
#include "../src/pPowerManger/driver.h"
|
||||||
|
|
||||||
|
TEST_CASE("SQLiteDB Test", "[SQLiteDB]") {
|
||||||
|
SQLiteDB db("test.db");
|
||||||
|
|
||||||
|
SECTION("Create Tables") {
|
||||||
|
REQUIRE(db.createPowerDataTables() == true);
|
||||||
|
// REQUIRE(db.createStateTables() == true);
|
||||||
|
REQUIRE(db.createDisCcuSysTables() == true);
|
||||||
|
REQUIRE(db.createDriversTables("test") == true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test isDatabaseConnected") {
|
||||||
|
REQUIRE(db.isDatabaseConnected("/home/zjk/project/H100/H100PowerManger/bin","test.db") == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test insertPowerData") {
|
||||||
|
PowerData powerData;
|
||||||
|
StateData stateData;
|
||||||
|
stateData.state_id = 1;
|
||||||
|
stateData.state_name = "test";
|
||||||
|
stateData.event = "test";
|
||||||
|
stateData.event_id = 1;
|
||||||
|
stateData.fault_code = 1;
|
||||||
|
stateData.note = "test";
|
||||||
|
REQUIRE(db.insertStateData(stateData) == true);
|
||||||
|
// db.insertPowerData(powerData);
|
||||||
|
|
||||||
|
StateData stateDataForGet;
|
||||||
|
REQUIRE(db.getStateData(stateDataForGet) == true);
|
||||||
|
REQUIRE(stateDataForGet.state_id == 1);
|
||||||
|
REQUIRE(stateDataForGet.state_name == "test");
|
||||||
|
REQUIRE(stateDataForGet.event == "test");
|
||||||
|
REQUIRE(stateDataForGet.event_id == 1);
|
||||||
|
REQUIRE(stateDataForGet.fault_code == 1);
|
||||||
|
REQUIRE(stateDataForGet.note == "test");
|
||||||
|
|
||||||
|
//REQUIRE(db.clearPowerData(stateDataForGet) == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test insertStateData") {
|
||||||
|
|
||||||
|
for(int i = 0; i < 100; i++)
|
||||||
|
{ DriverTable driver;
|
||||||
|
REQUIRE(db.insertDriverTables(driver,"test") == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test GETDATA") {
|
||||||
|
StateData stateData;
|
||||||
|
std::string time;
|
||||||
|
REQUIRE(db.getStateData(stateData,time) == true);
|
||||||
|
REQUIRE(db.getStateData(stateData) == true);
|
||||||
|
REQUIRE(stateData.state_id == 1);
|
||||||
|
REQUIRE(stateData.state_name == "test");
|
||||||
|
cout << "-------------------------------------------------" << time << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from disSys import *
|
||||||
|
from logWin import *
|
||||||
|
from udpComm import *
|
||||||
|
from ccuSys import *
|
||||||
|
|
||||||
|
|
||||||
|
# 创建UDP通信套接字
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
# 目标IP地址和端口号
|
||||||
|
target_ip = 'localhost'
|
||||||
|
target_port = 5001
|
||||||
|
server_address = (target_ip, target_port)
|
||||||
|
sock.bind(server_address)
|
||||||
|
# 要发送的消息
|
||||||
|
# 创建主窗口
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("能源管理系统调试")
|
||||||
|
# 创建消息显示窗口
|
||||||
|
logFrame = tk.LabelFrame(root, text="消息")
|
||||||
|
logFrame.grid(row=0, rowspan=3,column=1, sticky='ns')
|
||||||
|
logwin = logWin(logFrame)
|
||||||
|
logwin.grid(row=0, column=0, sticky='nesw')
|
||||||
|
# 创建配电窗口
|
||||||
|
disSysFrame = tk.LabelFrame(root, text="配电系统")
|
||||||
|
disSysFrame.grid(row=0, column=0, sticky='ne')
|
||||||
|
disSysWin = disSys(disSysFrame)
|
||||||
|
disSysWin.grid(row=0, column=0, sticky='ne')
|
||||||
|
# 创建ccu消息窗口
|
||||||
|
ccuSysFrame = tk.LabelFrame(root, text="ccu消息")
|
||||||
|
ccuSysFrame.grid(row=1, column=0, sticky='swe')
|
||||||
|
ccuSysWin = ccuSys(ccuSysFrame)
|
||||||
|
# ccuSysWin.grid(row=0, column=0, sticky='ne')
|
||||||
|
|
||||||
|
# 创建并启动接收和发送消息的线程
|
||||||
|
thread = threading.Thread(target=receive_messages, args=(sock, logwin, disSysWin))
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
thread2 = threading.Thread(target=send_messages, args=(sock, logwin, disSysWin,ccuSysWin))
|
||||||
|
thread2.daemon = True
|
||||||
|
thread2.start()
|
||||||
|
|
||||||
|
# 运行主循环
|
||||||
|
root.mainloop()
|
||||||
|
# 关闭套接字
|
||||||
|
sock.close()
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font
|
||||||
|
from guiEle import ElementDisplayApp
|
||||||
|
from until import *
|
||||||
|
from guiInput import InputGUI
|
||||||
|
|
||||||
|
# 创建UDP套接字
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
server_address = ('localhost', 5001)
|
||||||
|
sock.bind(server_address)
|
||||||
|
|
||||||
|
# 创建主窗口
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("UDP消息显示")
|
||||||
|
eleplay = ElementDisplayApp(root)
|
||||||
|
inp = InputGUI(root)
|
||||||
|
|
||||||
|
# 创建一个文本框用于显示消息
|
||||||
|
custom_font = font.Font(family="Arial", size=12, weight="normal")
|
||||||
|
text_box = tk.Text(root, height=10, width=50, font=custom_font)
|
||||||
|
# .pack(side='left', fill='y', expand=True)
|
||||||
|
text_box.grid(row=0, column=4, sticky='ne')
|
||||||
|
|
||||||
|
# 创建并启动接收和发送消息的线程
|
||||||
|
thread = threading.Thread(target=receive_messages, args=(sock, text_box,eleplay))
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
thread2 = threading.Thread(target=send_messages, args=(sock, eleplay))
|
||||||
|
thread2.daemon = True
|
||||||
|
thread2.start()
|
||||||
|
|
||||||
|
# 运行主循环
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
# 关闭套接字
|
||||||
|
sock.close()
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import font
|
||||||
|
from udpmsg import *
|
||||||
|
|
||||||
|
class ElementDisplayApp:
|
||||||
|
def __init__(self, root):
|
||||||
|
self.root = root
|
||||||
|
|
||||||
|
self.disHVB = msg_disHighVolBusFbMsg()
|
||||||
|
self.disHVBA = msg_disHighAVolBusFbMsg()
|
||||||
|
self.disHVBB = msg_disHighBVolBusFbMsg()
|
||||||
|
self.disLVB = msg_disLowBusFbMsg()
|
||||||
|
|
||||||
|
# 定义每组的颜色
|
||||||
|
self.colors = ["#FFC0CB", "#ADD8E6", "#90EE90", "#FFD700"]
|
||||||
|
|
||||||
|
# 创建自定义字体
|
||||||
|
self.custom_font = font.Font(family="Arial", size=12, weight='bold')
|
||||||
|
|
||||||
|
# 创建4个Frame来分组显示元素的值
|
||||||
|
self.frames = []
|
||||||
|
for i in range(4):
|
||||||
|
frame = tk.Frame(self.root, bg=self.colors[i], padx=10, pady=10)
|
||||||
|
# frame.pack(padx=10, pady=10, expand=True, fill='both')
|
||||||
|
frame.grid(row=0, column=i, sticky='nsew') # 使用 grid 布局管理器
|
||||||
|
self.frames.append(frame)
|
||||||
|
|
||||||
|
# 定义四个字典来存储元素的值
|
||||||
|
# self.dict1 = {f"元素{i+1}": f"Value {i+1}" for i in range(16)}
|
||||||
|
self.dict1={'燃料电池断路器':'闭合','动力锂电池断路器':'闭合','推进电机断路器':'闭合','仪表锂电池断路器':'闭合','DC/DC5模块断路器':'闭合',
|
||||||
|
'艏部高压配电断路器':'闭合','艏部FT4/5断路器':'闭合','艉舵1/2断路器':'闭合','艉舵3/4断路器':'闭合',
|
||||||
|
'FB预留断路器':'闭合','TYZ预留断路器':'闭合','预留断路器':'闭合'}
|
||||||
|
# self.dict2 = {f"元素{i+17}": f"Value {i+17}" for i in range(16)}
|
||||||
|
self.dict2 = {'艏部FT1-3断路器':'闭合','启闭机构断路器':'闭合','桅杆舵机断路器':'闭合','XCZ断路器':'闭合',
|
||||||
|
'艏舵断路器':'闭合','敞开电缸断路器':'闭合'}
|
||||||
|
# self.dict3 = {f"元素{i+33}": f"Value {i+33}" for i in range(16)}
|
||||||
|
self.dict3 = {'仪表锂电池断路器':'闭合','艏部低压断路器':'闭合','UNIT4断路器':'闭合','DC/DC1断路器':'闭合',
|
||||||
|
'预留断路器1':'闭合', '预留断路器2':'闭合','艉部应急电池开关':'闭合'}
|
||||||
|
# self.dict4 = {f"元素{i+49}": f"Value {i+49}" for i in range(16)}
|
||||||
|
self.dict4 = {'UNIT1断路器':'闭合','UNIT2断路器':'闭合','UNIT3断路器':'闭合','UNIT5断路器':'闭合','艏部抛载断路器':'闭合',
|
||||||
|
'预留断路器1':'闭合','预留断路器2':'断开','艏部应急电池开关':'闭合'}
|
||||||
|
|
||||||
|
# 创建Label来显示每个字典中的元素值,并应用自定义字体
|
||||||
|
self.labels = []
|
||||||
|
for i, dictionary in enumerate([self.dict1, self.dict2, self.dict3, self.dict4]):
|
||||||
|
for j, (key, value) in enumerate(dictionary.items()):
|
||||||
|
# 根据元素的值选择颜色
|
||||||
|
if value == "闭合":
|
||||||
|
color = "green"
|
||||||
|
else:
|
||||||
|
color = "red"
|
||||||
|
label = tk.Label(self.frames[i], text=f"{key}: {value}", fg=color, font=self.custom_font, anchor="w")
|
||||||
|
label.grid(row=j//2, column=j%2, padx=5, pady=5)
|
||||||
|
# self.labels.append(label)
|
||||||
|
|
||||||
|
def update_disp(self):
|
||||||
|
# 更新Label的文本
|
||||||
|
for i, dictionary in enumerate([self.dict1, self.dict2, self.dict3, self.dict4]):
|
||||||
|
for j, (key, value) in enumerate(dictionary.items()):
|
||||||
|
# 根据元素的值选择颜色
|
||||||
|
if value == "闭合":
|
||||||
|
color = "green"
|
||||||
|
else:
|
||||||
|
color = "red"
|
||||||
|
# self.labels[i + j].config(text=f"{key}: {value}", fg=color, font=self.custom_font, anchor="w")
|
||||||
|
label = tk.Label(self.frames[i], text=f"{key}: {value}", fg=color, font=self.custom_font, anchor="w")
|
||||||
|
label.grid(row=j//2, column=j%2, padx=5, pady=5)
|
||||||
|
|
||||||
|
def updata_data(self):
|
||||||
|
if (self.dict1['燃料电池断路器']=='闭合'):
|
||||||
|
self.disHVB.DCB1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.DCB1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['动力锂电池断路器']=='闭合'):
|
||||||
|
self.disHVB.DCB2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.DCB2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['推进电机断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['仪表锂电池断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['DC/DC5模块断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK3 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK3 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艏部高压配电断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK4 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK4 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艏部FT4/5断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK5 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK5 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艉舵1/2断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK6 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK6 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艉舵3/4断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK7 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK7 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['FB预留断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK8 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK8 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['TYZ预留断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK9 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK9 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['预留断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK10 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK10 = 0xAA
|
||||||
|
######################################################
|
||||||
|
if (self.dict2['艏部FT1-3断路器']=='闭合'):
|
||||||
|
self.disHVBA.bowFTDevice123CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.bowFTDevice123CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['启闭机构断路器']=='闭合'):
|
||||||
|
self.disHVBA.actuatorCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.actuatorCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['桅杆舵机断路器']=='闭合'):
|
||||||
|
self.disHVBA.mastSteeringGearControlBoxCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.mastSteeringGearControlBoxCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['XCZ断路器']=='闭合'):
|
||||||
|
self.disHVBA.xczCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.xczCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['艏舵断路器']=='闭合'):
|
||||||
|
self.disHVBA.bowRudderControlBoxCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.bowRudderControlBoxCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['敞开电缸断路器']=='闭合'):
|
||||||
|
self.disHVBA.openWaterCoverStartCylinderCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.openWaterCoverStartCylinderCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
if (self.dict3['仪表锂电池断路器']=='闭合'):
|
||||||
|
self.disHVBB.lithiumBatteryGroupInstrumentCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.lithiumBatteryGroupInstrumentCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['艏部低压断路器']=='闭合'):
|
||||||
|
self.disHVBB.bowLowVoltageDistributionCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.bowLowVoltageDistributionCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['UNIT4断路器']=='闭合'):
|
||||||
|
self.disHVBB.unit4CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.unit4CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['DC/DC1断路器']=='闭合'):
|
||||||
|
self.disHVBB.dcdc1CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.dcdc1CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['预留断路器1']=='闭合'):
|
||||||
|
self.disHVBB.reservedCircuitBreaker1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.reservedCircuitBreaker1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['预留断路器2']=='闭合'):
|
||||||
|
self.disHVBB.reservedCircuitBreaker2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.reservedCircuitBreaker2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['艉部应急电池开关']=='闭合'):
|
||||||
|
self.disHVBB.emergencyLithiumBatteryGroup2CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.emergencyLithiumBatteryGroup2CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
if (self.dict4['UNIT1断路器']=='闭合'):
|
||||||
|
self.disLVB.unit1CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit1CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['UNIT2断路器']=='闭合'):
|
||||||
|
self.disLVB.unit2CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit2CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['UNIT3断路器']=='闭合'):
|
||||||
|
self.disLVB.unit3CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit3CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['UNIT5断路器']=='闭合'):
|
||||||
|
self.disLVB.unit5CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit5CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['预留断路器1']=='闭合'):
|
||||||
|
self.disLVB.reservedCircuitBreaker1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.reservedCircuitBreaker1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['预留断路器2']=='闭合'):
|
||||||
|
self.disLVB.reservedCircuitBreaker2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.reservedCircuitBreaker2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['艏部抛载断路器']=='闭合'):
|
||||||
|
self.disLVB.bowPZDeviceCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.bowPZDeviceCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['艏部应急电池开关']=='闭合'):
|
||||||
|
self.disLVB.emergencyLithiumBatteryGroup1CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.emergencyLithiumBatteryGroup1CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
a = self.disHVB.pack()
|
||||||
|
b = self.disHVBA.pack()
|
||||||
|
c = self.disHVBB.pack()
|
||||||
|
d = self.disLVB.pack()
|
||||||
|
return a,b,c,d
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
app = ElementDisplayApp(root)
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
# # 创建主窗口
|
||||||
|
# root = tk.Tk()
|
||||||
|
|
||||||
|
# # 创建应用实例并在root中显示
|
||||||
|
# app = ElementDisplayApp(root)
|
||||||
|
|
||||||
|
# # 运行主循环
|
||||||
|
# root.mainloop()
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
from udpmsg import msg_CcuStateFbMsg
|
||||||
|
|
||||||
|
class msg_CcuStateFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x40
|
||||||
|
self.start2 = 0x40
|
||||||
|
self.id = 0x0001
|
||||||
|
self.length = 0x0000
|
||||||
|
self.flag = 0x00
|
||||||
|
self.failvreCode = 0x00
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
pass # function body is omitted
|
||||||
|
|
||||||
|
class InputGUI:
|
||||||
|
def __init__(self, master):
|
||||||
|
self.master = master
|
||||||
|
self.printing = False
|
||||||
|
self.msg_instance = msg_CcuStateFbMsg()
|
||||||
|
|
||||||
|
# 创建一个Frame来包含所有的输入框和标签
|
||||||
|
row = 0
|
||||||
|
column = 0
|
||||||
|
|
||||||
|
self.input_frame = tk.Frame(master, bg='lightgray')
|
||||||
|
self.input_frame.grid(row=1, column=0, sticky='nsew')
|
||||||
|
|
||||||
|
self.title_label = tk.Label(self.input_frame, text="复合管控消息交互", font=("Arial", 16, "bold"))
|
||||||
|
self.title_label.grid(row=0, column=0, columnspan=2, pady=(10, 20), sticky="nsew") # 调整标题的上下边距并居中显示
|
||||||
|
|
||||||
|
# 创建输入框和标签
|
||||||
|
self.start1_label = tk.Label(self.input_frame, text="Start1:")
|
||||||
|
self.start1_label.grid(row=1, column=0)
|
||||||
|
self.start1_entry = tk.Entry(self.input_frame)
|
||||||
|
self.start1_entry.grid(row=1, column=1)
|
||||||
|
|
||||||
|
self.start2_label = tk.Label(self.input_frame, text="Start2:")
|
||||||
|
self.start2_label.grid(row=2, column=0)
|
||||||
|
self.start2_entry = tk.Entry(self.input_frame)
|
||||||
|
self.start2_entry.grid(row=2, column=1)
|
||||||
|
|
||||||
|
self.id_label = tk.Label(self.input_frame, text="ID:")
|
||||||
|
self.id_label.grid(row=3, column=0)
|
||||||
|
self.id_entry = tk.Entry(self.input_frame)
|
||||||
|
self.id_entry.grid(row=3, column=1)
|
||||||
|
|
||||||
|
self.length_label = tk.Label(self.input_frame, text="Length:")
|
||||||
|
self.length_label.grid(row=4, column=0)
|
||||||
|
self.length_entry = tk.Entry(self.input_frame)
|
||||||
|
self.length_entry.grid(row=4, column=1)
|
||||||
|
|
||||||
|
self.flag_label = tk.Label(self.input_frame, text="Flag:")
|
||||||
|
self.flag_label.grid(row=5, column=0)
|
||||||
|
self.flag_entry = tk.Entry(self.input_frame)
|
||||||
|
self.flag_entry.grid(row=5, column=1)
|
||||||
|
|
||||||
|
self.failvreCode_label = tk.Label(self.input_frame, text="Failvre Code:")
|
||||||
|
self.failvreCode_label.grid(row=6, column=0)
|
||||||
|
self.failvreCode_entry = tk.Entry(self.input_frame)
|
||||||
|
self.failvreCode_entry.grid(row=6, column=1)
|
||||||
|
|
||||||
|
# 创建更新按钮
|
||||||
|
self.update_button = tk.Button(self.input_frame, text="Update", command=self.update_msg)
|
||||||
|
self.update_button.grid(row=7, column=0, columnspan=2)
|
||||||
|
|
||||||
|
# 创建打印按钮
|
||||||
|
self.print_button = tk.Button(self.input_frame, text="Print", command=self.start_printing)
|
||||||
|
self.print_button.grid(row=8, column=0)
|
||||||
|
|
||||||
|
# 创建停止打印按钮
|
||||||
|
self.stop_button = tk.Button(self.input_frame, text="Stop", command=self.stop_printing, state=tk.DISABLED)
|
||||||
|
self.stop_button.grid(row=8, column=1)
|
||||||
|
|
||||||
|
# 创建显示打印消息数量的标签
|
||||||
|
self.print_count_label = tk.Label(self.input_frame, text="Print Count: 0", font=("Arial", 12))
|
||||||
|
self.print_count_label.grid(row=9, column=0, columnspan=2)
|
||||||
|
# 创建更新按钮
|
||||||
|
self.update_button = tk.Button(self.input_frame, text="Update", command=self.update_msg)
|
||||||
|
self.update_button.grid(row=7, column=0, columnspan=2)
|
||||||
|
|
||||||
|
def update_msg(self):
|
||||||
|
try:
|
||||||
|
self.msg_instance.start1 = int(self.start1_entry.get(), 16)
|
||||||
|
self.msg_instance.start2 = int(self.start2_entry.get(), 16)
|
||||||
|
self.msg_instance.id = int(self.id_entry.get(), 16)
|
||||||
|
self.msg_instance.length = int(self.length_entry.get(), 16)
|
||||||
|
self.msg_instance.flag = int(self.flag_entry.get(), 16)
|
||||||
|
self.msg_instance.failvreCode = int(self.failvreCode_entry.get(), 16)
|
||||||
|
messagebox.showinfo("Success", "msg_CcuStateFbMsg updated successfully!")
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror("Error", "Invalid input. Please enter valid hexadecimal values.")
|
||||||
|
|
||||||
|
def start_printing(self):
|
||||||
|
self.printing = True
|
||||||
|
self.print_count = 0
|
||||||
|
self.print_count_label.config(text="Print Count: 0")
|
||||||
|
self.print_button.config(state=tk.DISABLED)
|
||||||
|
self.stop_button.config(state=tk.NORMAL)
|
||||||
|
self.print_message()
|
||||||
|
|
||||||
|
def stop_printing(self):
|
||||||
|
self.printing = False
|
||||||
|
self.print_button.config(state=tk.NORMAL)
|
||||||
|
self.stop_button.config(state=tk.DISABLED)
|
||||||
|
|
||||||
|
def print_message(self, callback=None):
|
||||||
|
if self.printing:
|
||||||
|
print("Printing message...")
|
||||||
|
self.print_count += 1
|
||||||
|
self.print_count_label.config(text=f"Print Count: {self.print_count}")
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
self.master.after(1000, self.print_message, callback) # 每秒打印一次
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
gui = InputGUI(root)
|
||||||
|
root.mainloop()
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import socket
|
||||||
|
import time
|
||||||
|
import struct
|
||||||
|
from udpmsg import *
|
||||||
|
|
||||||
|
# 目标IP地址和端口
|
||||||
|
target_ip = '127.0.0.1'
|
||||||
|
target_port = 5000
|
||||||
|
|
||||||
|
|
||||||
|
mTest = msg_CcuStateFbMsg()
|
||||||
|
mTest2 = msg_CcuSetParamFbMsg()
|
||||||
|
mTest3 = msg_disHighVolBusFbMsg()
|
||||||
|
|
||||||
|
valid_msg = mTest.pack()
|
||||||
|
valid_msg2 = mTest2.pack()
|
||||||
|
valid_msg3 = mTest3.pack()
|
||||||
|
print(valid_msg)
|
||||||
|
|
||||||
|
|
||||||
|
# 创建UDP套接字
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
server_address = ('localhost', 5001)
|
||||||
|
sock.bind(server_address)
|
||||||
|
|
||||||
|
# 要发送的信息
|
||||||
|
# message = "Hello, this is a test message."
|
||||||
|
message = valid_msg3
|
||||||
|
# 发送信息的次数
|
||||||
|
num_messages = 100
|
||||||
|
|
||||||
|
# 发送信息的时间间隔(秒)
|
||||||
|
interval = 1
|
||||||
|
|
||||||
|
for i in range(num_messages):
|
||||||
|
# 发送信息
|
||||||
|
mTest.fcuState += 1
|
||||||
|
sock.sendto(mTest.pack(), (target_ip, target_port))
|
||||||
|
time.sleep(interval)
|
||||||
|
sock.sendto(msg_CcuSetParamFbMsg().pack(), (target_ip, target_port))
|
||||||
|
time.sleep(interval)
|
||||||
|
mTest3.busbarAVoltage += 1
|
||||||
|
sock.sendto(mTest3.pack(), (target_ip, target_port))
|
||||||
|
time.sleep(interval)
|
||||||
|
sock.sendto(msg_disHighAVolBusFbMsg().pack(), (target_ip, target_port))
|
||||||
|
time.sleep(interval)
|
||||||
|
sock.sendto(msg_disHighBVolBusFbMsg().pack(), (target_ip, target_port))
|
||||||
|
time.sleep(interval)
|
||||||
|
sock.sendto(msg_disLowBusFbMsg().pack(), (target_ip, target_port))
|
||||||
|
# 打印发送的信息和目标地址
|
||||||
|
print(f"Sent message to {target_ip}:{target_port}")
|
||||||
|
# 等待一段时间
|
||||||
|
# sock.sendto(valid_msg2, (target_ip, target_port))
|
||||||
|
time.sleep(interval)
|
||||||
|
|
||||||
|
# 关闭套接字
|
||||||
|
sock.close()
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font
|
||||||
|
from disSys import *
|
||||||
|
from guiEle import ElementDisplayApp
|
||||||
|
from until import *
|
||||||
|
from guiInput import InputGUI
|
||||||
|
|
||||||
|
# 创建UDP套接字
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
server_address = ('localhost', 5001)
|
||||||
|
sock.bind(server_address)
|
||||||
|
|
||||||
|
# 创建主窗口
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("能源管理系统调试")
|
||||||
|
|
||||||
|
disSysWin = disSys(root)
|
||||||
|
disSysWin.grid(row=0, column=0, sticky='ne')
|
||||||
|
|
||||||
|
|
||||||
|
# 创建一个文本框用于显示消息
|
||||||
|
custom_font = font.Font(family="Arial", size=12, weight="normal")
|
||||||
|
text_box = tk.Text(root, height=10, width=50, font=custom_font)
|
||||||
|
text_box.grid(row=6, column=0, sticky='ne')
|
||||||
|
|
||||||
|
# 创建并启动接收和发送消息的线程
|
||||||
|
# thread = threading.Thread(target=receive_messages, args=(sock, text_box,eleplay))
|
||||||
|
# thread.daemon = True
|
||||||
|
# thread.start()
|
||||||
|
|
||||||
|
# thread2 = threading.Thread(target=send_messages, args=(sock, eleplay))
|
||||||
|
# thread2.daemon = True
|
||||||
|
# thread2.start()
|
||||||
|
|
||||||
|
# 运行主循环
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
# 关闭套接字
|
||||||
|
sock.close()
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font
|
||||||
|
from guiEle import ElementDisplayApp
|
||||||
|
import threading
|
||||||
|
|
||||||
|
target_ip = '127.0.0.1'
|
||||||
|
target_port = 5000
|
||||||
|
|
||||||
|
def receive_messages(sock, text_box,eleplay:ElementDisplayApp):
|
||||||
|
while True:
|
||||||
|
current_time = datetime.now()
|
||||||
|
formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
data, address = sock.recvfrom(4096)
|
||||||
|
headBuf = data[:6]
|
||||||
|
header = struct.unpack('<BBHH',headBuf)
|
||||||
|
start1 = data[0]
|
||||||
|
start2 = data[1]
|
||||||
|
msg_id = data[2]
|
||||||
|
msg_len = data[3]
|
||||||
|
if(start1==0x40 and start2==0x40):
|
||||||
|
if(msg_id==0x0001):
|
||||||
|
msg = msg_disHVBCmd()
|
||||||
|
msg.unpack(data)
|
||||||
|
text_box.insert(tk.END, f"{formatted_time}->接收到来自 {address} | 高压母线配电指令:\n")
|
||||||
|
if(msg.fuelCellCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['燃料电池断路器']='闭合'
|
||||||
|
elif(msg.fuelCellCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['燃料电池断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.powerLithiumBatteryCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['动力锂电池断路器']='闭合'
|
||||||
|
elif(msg.powerLithiumBatteryCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['动力锂电池断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.propulsionMotorCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['推进电机断路器']='闭合'
|
||||||
|
elif(msg.propulsionMotorCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['推进电机断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.lithiumBatteryGroupInstrumentCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['仪表锂电池断路器']='闭合'
|
||||||
|
elif(msg.lithiumBatteryGroupInstrumentCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['仪表锂电池断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.dcDc5ModuleCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['DC/DC5模块断路器']='闭合'
|
||||||
|
elif(msg.dcDc5ModuleCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['DC/DC5模块断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.bowHighVoltageDistributionBoxCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['艏部高压配电断路器']='闭合'
|
||||||
|
elif(msg.bowHighVoltageDistributionBoxCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['艏部高压配电断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.sternFTDevice45CircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['艏部FT4/5断路器']='闭合'
|
||||||
|
elif(msg.sternFTDevice45CircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['艏部FT4/5断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.sternRudderSwitch1CircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['艉舵1/2断路器']='闭合'
|
||||||
|
elif(msg.sternRudderSwitch1CircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['艉舵1/2断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.sternRudderSwitch2CircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['艉舵3/4断路器']='闭合'
|
||||||
|
elif(msg.sternRudderSwitch2CircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['艉舵3/4断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.fbReservedCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['FB预留断路器']='闭合'
|
||||||
|
elif(msg.fbReservedCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['FB预留断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.tyzReservedCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['TYZ预留断路器']='闭合'
|
||||||
|
elif(msg.tyzReservedCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['TYZ预留断路器']='断开'
|
||||||
|
|
||||||
|
if(msg.reservedCircuitBreaker==0x55):
|
||||||
|
eleplay.dict1['预留断路器']='闭合'
|
||||||
|
elif(msg.reservedCircuitBreaker==0xAA):
|
||||||
|
eleplay.dict1['预留断路器']='断开'
|
||||||
|
eleplay.update_disp()
|
||||||
|
text_box.see(tk.END)
|
||||||
|
|
||||||
|
|
||||||
|
def send_messages(sock, eleplay:ElementDisplayApp):
|
||||||
|
while True:
|
||||||
|
# 配电消息反馈
|
||||||
|
a,b,c,d = eleplay.updata_data()
|
||||||
|
sock.sendto(a, (target_ip, target_port))
|
||||||
|
sock.sendto(b, (target_ip, target_port))
|
||||||
|
sock.sendto(c, (target_ip, target_port))
|
||||||
|
sock.sendto(d, (target_ip, target_port))
|
||||||
|
|
||||||
|
#TODO复合管控消息反馈
|
||||||
|
|
||||||
|
|
||||||
|
threading.Event().wait(1) # 每隔1秒发送一次消息
|
||||||
@@ -0,0 +1,458 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import threading
|
||||||
|
import random
|
||||||
|
from udpmsg import *
|
||||||
|
from udpmsg import msg_CcuStateFbMsg
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font
|
||||||
|
from tkinter import Frame
|
||||||
|
from tkinter.ttk import *
|
||||||
|
|
||||||
|
class ccuSys(Frame):
|
||||||
|
def __init__(self, root):
|
||||||
|
super().__init__(root)
|
||||||
|
# Initialize CCU state
|
||||||
|
self.ccuState = msg_CcuStateFbMsg()
|
||||||
|
self.col_frames = []
|
||||||
|
self.state_entries = []
|
||||||
|
|
||||||
|
# Timer settings
|
||||||
|
self.update_interval = 1000 # Default update interval in milliseconds
|
||||||
|
|
||||||
|
# Network settings
|
||||||
|
self.udp_ip = "127.0.0.1"
|
||||||
|
self.udp_port = 5005
|
||||||
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
self.sock.settimeout(1.0)
|
||||||
|
|
||||||
|
# Initialize GUI
|
||||||
|
self.master = root
|
||||||
|
self.createWidgets()
|
||||||
|
|
||||||
|
# Start data update thread
|
||||||
|
self.running = True
|
||||||
|
self.update_thread = threading.Thread(target=self._update_thread)
|
||||||
|
self.update_thread.daemon = True
|
||||||
|
self.update_thread.start()
|
||||||
|
|
||||||
|
# Start timer for periodic display update
|
||||||
|
self.update_timer = None
|
||||||
|
self.start_update_timer()
|
||||||
|
|
||||||
|
def createWidgets(self):
|
||||||
|
# Main window configuration
|
||||||
|
# self.master.title("CCU Monitoring System")
|
||||||
|
# self.master.geometry("1200x800")
|
||||||
|
|
||||||
|
# Create status display area
|
||||||
|
self.status_frame = tk.Frame(self.master)
|
||||||
|
self.status_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||||
|
|
||||||
|
# Create status columns
|
||||||
|
self._create_status_column("FCU Status", [
|
||||||
|
"fcuState", "fcuFaultLeve", "powerLimit",
|
||||||
|
"totalPowerGeneration", "fcuVoltage", "fcuCurrent",
|
||||||
|
"fcuOutPower", "fcuOutIns", "fcuGZ_1L", "fcuGZ_1H",
|
||||||
|
"fcuGZ_2L", "fcuGZ_2H", "fcuGZ_3L", "fcuGZ_3H"
|
||||||
|
])
|
||||||
|
|
||||||
|
self._create_status_column("Battery Status", [
|
||||||
|
"insBatSoc", "powerBatSoc", "insBatLimit",
|
||||||
|
"powerBatLimit", "insBatTotalElectricity",
|
||||||
|
"powerBatTotalElectricity", "insCurrent",
|
||||||
|
"powerCurrent"
|
||||||
|
])
|
||||||
|
|
||||||
|
self._create_status_column("Sensor Status", [
|
||||||
|
"h2Concentration1", "h2Concentration2",
|
||||||
|
"o2Concentration1", "o2Concentration2",
|
||||||
|
"ch4oConcentration1", "ch4oConcentration2",
|
||||||
|
"backpressure1", "backpressure2"
|
||||||
|
])
|
||||||
|
|
||||||
|
self._create_status_column("System Status", [
|
||||||
|
"insPosRelayState", "insNegRelayState",
|
||||||
|
"powerPosRelayState", "powerNegRelayState",
|
||||||
|
"flameDetection", "exchangerTemperature",
|
||||||
|
"insEmergencyStatusWord", "powerEmergencyStatusWord"
|
||||||
|
])
|
||||||
|
|
||||||
|
# Create control panel
|
||||||
|
self.control_frame = tk.Frame(self.master)
|
||||||
|
self.control_frame.pack(fill=tk.X, padx=10, pady=5)
|
||||||
|
|
||||||
|
# Add control buttons
|
||||||
|
self.refresh_btn = tk.Button(
|
||||||
|
self.control_frame, text="Refresh", command=self.update_display
|
||||||
|
)
|
||||||
|
self.refresh_btn.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
self.export_btn = tk.Button(
|
||||||
|
self.control_frame, text="Export Data", command=self.export_data
|
||||||
|
)
|
||||||
|
self.export_btn.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# Timer control
|
||||||
|
self.timer_frame = tk.Frame(self.control_frame)
|
||||||
|
self.timer_frame.pack(side=tk.RIGHT, padx=10)
|
||||||
|
|
||||||
|
# Timer interval label
|
||||||
|
tk.Label(self.timer_frame, text="Update Interval (ms):").pack(side=tk.LEFT)
|
||||||
|
|
||||||
|
# Timer interval entry
|
||||||
|
self.interval_entry = tk.Entry(self.timer_frame, width=6)
|
||||||
|
self.interval_entry.insert(0, str(self.update_interval))
|
||||||
|
self.interval_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# Set interval button
|
||||||
|
self.set_interval_btn = tk.Button(
|
||||||
|
self.timer_frame,
|
||||||
|
text="Set",
|
||||||
|
command=self.set_update_interval
|
||||||
|
)
|
||||||
|
self.set_interval_btn.pack(side=tk.LEFT)
|
||||||
|
|
||||||
|
# Status indicator
|
||||||
|
self.status_indicator = tk.Label(
|
||||||
|
self.timer_frame, text="●", fg="green", font=("Arial", 16)
|
||||||
|
)
|
||||||
|
self.status_indicator.pack(side=tk.RIGHT, padx=10)
|
||||||
|
|
||||||
|
# FCU control panel
|
||||||
|
self.fcu_frame = tk.Frame(self.control_frame)
|
||||||
|
self.fcu_frame.pack(side=tk.LEFT, padx=10)
|
||||||
|
|
||||||
|
# FCU state control
|
||||||
|
tk.Label(self.fcu_frame, text="FCU State:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_state_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_state_menu = tk.OptionMenu(
|
||||||
|
self.fcu_frame, self.fcu_state_var,
|
||||||
|
*range(4), command=self.set_fcu_state
|
||||||
|
)
|
||||||
|
self.fcu_state_menu.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# FCU fault level control
|
||||||
|
tk.Label(self.fcu_frame, text="Fault Level:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_fault_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_fault_menu = tk.OptionMenu(
|
||||||
|
self.fcu_frame, self.fcu_fault_var,
|
||||||
|
*range(4), command=self.set_fcu_fault_level
|
||||||
|
)
|
||||||
|
self.fcu_fault_menu.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# FCU GZ control
|
||||||
|
tk.Label(self.fcu_frame, text="GZ 1L:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_gz1l_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_gz1l_entry = tk.Entry(
|
||||||
|
self.fcu_frame, textvariable=self.fcu_gz1l_var, width=5
|
||||||
|
)
|
||||||
|
self.fcu_gz1l_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
self.fcu_gz1l_entry.bind("<Return>", lambda e: self.set_fcu_gz1l())
|
||||||
|
|
||||||
|
tk.Label(self.fcu_frame, text="GZ 1H:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_gz1h_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_gz1h_entry = tk.Entry(
|
||||||
|
self.fcu_frame, textvariable=self.fcu_gz1h_var, width=5
|
||||||
|
)
|
||||||
|
self.fcu_gz1h_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
self.fcu_gz1h_entry.bind("<Return>", lambda e: self.set_fcu_gz1h())
|
||||||
|
|
||||||
|
# Add more GZ controls
|
||||||
|
tk.Label(self.fcu_frame, text="GZ 2L:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_gz2l_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_gz2l_entry = tk.Entry(
|
||||||
|
self.fcu_frame, textvariable=self.fcu_gz2l_var, width=5
|
||||||
|
)
|
||||||
|
self.fcu_gz2l_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
self.fcu_gz2l_entry.bind("<Return>", lambda e: self.set_fcu_gz2l())
|
||||||
|
|
||||||
|
tk.Label(self.fcu_frame, text="GZ 2H:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_gz2h_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_gz2h_entry = tk.Entry(
|
||||||
|
self.fcu_frame, textvariable=self.fcu_gz2h_var, width=5
|
||||||
|
)
|
||||||
|
self.fcu_gz2h_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
self.fcu_gz2h_entry.bind("<Return>", lambda e: self.set_fcu_gz2h())
|
||||||
|
|
||||||
|
tk.Label(self.fcu_frame, text="GZ 3L:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_gz3l_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_gz3l_entry = tk.Entry(
|
||||||
|
self.fcu_frame, textvariable=self.fcu_gz3l_var, width=5
|
||||||
|
)
|
||||||
|
self.fcu_gz3l_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
self.fcu_gz3l_entry.bind("<Return>", lambda e: self.set_fcu_gz3l())
|
||||||
|
|
||||||
|
tk.Label(self.fcu_frame, text="GZ 3H:").pack(side=tk.LEFT)
|
||||||
|
self.fcu_gz3h_var = tk.IntVar(value=0)
|
||||||
|
self.fcu_gz3h_entry = tk.Entry(
|
||||||
|
self.fcu_frame, textvariable=self.fcu_gz3h_var, width=5
|
||||||
|
)
|
||||||
|
self.fcu_gz3h_entry.pack(side=tk.LEFT, padx=5)
|
||||||
|
self.fcu_gz3h_entry.bind("<Return>", lambda e: self.set_fcu_gz3h())
|
||||||
|
|
||||||
|
def _create_status_column(self, title, fields):
|
||||||
|
"""Create a status column with specified fields"""
|
||||||
|
col_frame = tk.LabelFrame(
|
||||||
|
self.status_frame, text=title, bd=2, relief=tk.GROOVE
|
||||||
|
)
|
||||||
|
col_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||||
|
|
||||||
|
for field in fields:
|
||||||
|
field_frame = tk.Frame(col_frame)
|
||||||
|
field_frame.pack(fill=tk.X, padx=5, pady=2)
|
||||||
|
|
||||||
|
# Field name
|
||||||
|
name_label = tk.Label(
|
||||||
|
field_frame, text=field, width=20, anchor=tk.W
|
||||||
|
)
|
||||||
|
name_label.pack(side=tk.LEFT)
|
||||||
|
|
||||||
|
# Value display
|
||||||
|
value_entry = tk.Entry(
|
||||||
|
field_frame, width=15, state='readonly'
|
||||||
|
)
|
||||||
|
value_entry.pack(side=tk.RIGHT, fill=tk.X, expand=True)
|
||||||
|
|
||||||
|
# Store reference for updates
|
||||||
|
self.state_entries.append((field, value_entry))
|
||||||
|
|
||||||
|
def generate_simulated_data(self):
|
||||||
|
"""Generate simulated CCU state data"""
|
||||||
|
self.ccuState.fcuState = self.fcu_state_var.get()
|
||||||
|
self.ccuState.fcuFaultLeve = self.fcu_fault_var.get()
|
||||||
|
self.ccuState.powerLimit = random.randint(0, 100)
|
||||||
|
self.ccuState.totalPowerGeneration = int(random.uniform(0, 1000))
|
||||||
|
self.ccuState.fcuVoltage = int(random.uniform(200, 400))
|
||||||
|
self.ccuState.fcuCurrent = int(random.uniform(0, 100))
|
||||||
|
self.ccuState.fcuOutPower = random.randint(0, 1000)
|
||||||
|
self.ccuState.fcuOutIns = random.randint(0, 100)
|
||||||
|
|
||||||
|
self.ccuState.insBatSoc = random.randint(0, 100)
|
||||||
|
self.ccuState.powerBatSoc = random.randint(0, 100)
|
||||||
|
self.ccuState.insBatLimit = random.randint(0, 100)
|
||||||
|
self.ccuState.powerBatLimit = random.randint(0, 100)
|
||||||
|
self.ccuState.insBatTotalElectricity = random.randint(0, 1000)
|
||||||
|
self.ccuState.powerBatTotalElectricity = random.randint(0, 1000)
|
||||||
|
self.ccuState.insCurrent = random.randint(0, 100)
|
||||||
|
self.ccuState.powerCurrent = random.randint(0, 100)
|
||||||
|
|
||||||
|
self.ccuState.h2Concentration1 = random.randint(0, 100)
|
||||||
|
self.ccuState.h2Concentration2 = random.randint(0, 100)
|
||||||
|
self.ccuState.o2Concentration1 = random.randint(0, 100)
|
||||||
|
self.ccuState.o2Concentration2 = random.randint(0, 100)
|
||||||
|
self.ccuState.ch4oConcentration1 = random.randint(0, 100)
|
||||||
|
self.ccuState.ch4oConcentration2 = random.randint(0, 100)
|
||||||
|
self.ccuState.backpressure1 = random.randint(0, 10)
|
||||||
|
self.ccuState.backpressure2 = random.randint(0, 10)
|
||||||
|
|
||||||
|
self.ccuState.insPosRelayState = random.randint(0, 1)
|
||||||
|
self.ccuState.insNegRelayState = random.randint(0, 1)
|
||||||
|
self.ccuState.powerPosRelayState = random.randint(0, 1)
|
||||||
|
self.ccuState.powerNegRelayState = random.randint(0, 1)
|
||||||
|
self.ccuState.flameDetection = random.randint(0, 1)
|
||||||
|
self.ccuState.exchangerTemperature = random.randint(20, 100)
|
||||||
|
self.ccuState.insEmergencyStatusWord = random.randint(0, 255)
|
||||||
|
self.ccuState.powerEmergencyStatusWord = random.randint(0, 255)
|
||||||
|
|
||||||
|
self.ccuState.fcuGZ_1L=self.fcu_gz1l_var.get()
|
||||||
|
self.ccuState.fcuGZ_1H=self.fcu_gz1h_var.get()
|
||||||
|
self.ccuState.fcuGZ_2L=self.fcu_gz2l_var.get()
|
||||||
|
self.ccuState.fcuGZ_2H=self.fcu_gz2h_var.get()
|
||||||
|
self.ccuState.fcuGZ_3L=self.fcu_gz3l_var.get()
|
||||||
|
self.ccuState.fcuGZ_3H=self.fcu_gz3h_var.get()
|
||||||
|
|
||||||
|
def update_display(self):
|
||||||
|
"""Update all displayed values"""
|
||||||
|
# Generate simulated data if no real data available
|
||||||
|
if not hasattr(self.ccuState, 'fcuState'):
|
||||||
|
self.generate_simulated_data()
|
||||||
|
|
||||||
|
for field, entry in self.state_entries:
|
||||||
|
value = getattr(self.ccuState, field, "N/A")
|
||||||
|
entry.config(state='normal')
|
||||||
|
entry.delete(0, tk.END)
|
||||||
|
entry.insert(0, str(value))
|
||||||
|
entry.config(state='readonly')
|
||||||
|
|
||||||
|
# Update status indicator
|
||||||
|
self._update_status_indicator()
|
||||||
|
|
||||||
|
def _update_status_indicator(self):
|
||||||
|
"""Update the status indicator based on system state"""
|
||||||
|
if self.ccuState.fcuFaultLeve > 0:
|
||||||
|
self.status_indicator.config(fg="red")
|
||||||
|
else:
|
||||||
|
self.status_indicator.config(fg="green")
|
||||||
|
|
||||||
|
def export_data(self):
|
||||||
|
"""Export current status data to file"""
|
||||||
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
filename = f"ccu_status_{timestamp}.log"
|
||||||
|
try:
|
||||||
|
with open(filename, 'w') as f:
|
||||||
|
for field, _ in self.state_entries:
|
||||||
|
value = getattr(self.ccuState, field, "N/A")
|
||||||
|
f.write(f"{field}: {value}\n")
|
||||||
|
print(f"Data exported to {filename}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Export failed: {str(e)}")
|
||||||
|
|
||||||
|
def _update_thread(self):
|
||||||
|
"""Thread for updating CCU state"""
|
||||||
|
while self.running:
|
||||||
|
try:
|
||||||
|
# Receive data from UDP
|
||||||
|
data, _ = self.sock.recvfrom(1024)
|
||||||
|
self.ccuState.unpack(data)
|
||||||
|
|
||||||
|
except socket.timeout:
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Update error: {str(e)}")
|
||||||
|
break
|
||||||
|
|
||||||
|
def set_update_interval(self):
|
||||||
|
"""Set new update interval from GUI input"""
|
||||||
|
try:
|
||||||
|
new_interval = int(self.interval_entry.get())
|
||||||
|
if new_interval < 100:
|
||||||
|
raise ValueError("Interval must be >= 100ms")
|
||||||
|
self.update_interval = new_interval
|
||||||
|
self.stop_update_timer()
|
||||||
|
self.start_update_timer()
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"Invalid interval: {str(e)}")
|
||||||
|
|
||||||
|
def set_fcu_state(self, state):
|
||||||
|
"""Set FCU state and update display"""
|
||||||
|
self.ccuState.fcuState = state
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_fault_level(self, level):
|
||||||
|
"""Set FCU fault level and update display"""
|
||||||
|
self.ccuState.fcuFaultLeve = level
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_gz1l(self, value=None):
|
||||||
|
"""Set FCU GZ 1L and update display"""
|
||||||
|
if value is None:
|
||||||
|
try:
|
||||||
|
value = self.fcu_gz1l_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
tk.messagebox.showwarning("Input Error", "Invalid GZ 1L value")
|
||||||
|
return
|
||||||
|
self.ccuState.fcuGZ_1L = value
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_gz1h(self, value=None):
|
||||||
|
"""Set FCU GZ 1H and update display"""
|
||||||
|
if value is None:
|
||||||
|
try:
|
||||||
|
value = self.fcu_gz1h_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
tk.messagebox.showwarning("Input Error", "Invalid GZ 1H value")
|
||||||
|
return
|
||||||
|
self.ccuState.fcuGZ_1H = value
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_gz2l(self, value=None):
|
||||||
|
"""Set FCU GZ 2L and update display"""
|
||||||
|
if value is None:
|
||||||
|
try:
|
||||||
|
value = self.fcu_gz2l_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
tk.messagebox.showwarning("Input Error", "Invalid GZ 2L value")
|
||||||
|
return
|
||||||
|
self.ccuState.fcuGZ_2L = value
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_gz2h(self, value=None):
|
||||||
|
"""Set FCU GZ 2H and update display"""
|
||||||
|
if value is None:
|
||||||
|
try:
|
||||||
|
value = self.fcu_gz2h_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
tk.messagebox.showwarning("Input Error", "Invalid GZ 2H value")
|
||||||
|
return
|
||||||
|
self.ccuState.fcuGZ_2H = value
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_gz3l(self, value=None):
|
||||||
|
"""Set FCU GZ 3L and update display"""
|
||||||
|
if value is None:
|
||||||
|
try:
|
||||||
|
value = self.fcu_gz3l_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
tk.messagebox.showwarning("Input Error", "Invalid GZ 3L value")
|
||||||
|
return
|
||||||
|
self.ccuState.fcuGZ_3L = value
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def set_fcu_gz3h(self, value=None):
|
||||||
|
"""Set FCU GZ 3H and update display"""
|
||||||
|
if value is None:
|
||||||
|
try:
|
||||||
|
value = self.fcu_gz3h_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
tk.messagebox.showwarning("Input Error", "Invalid GZ 3H value")
|
||||||
|
return
|
||||||
|
self.ccuState.fcuGZ_3H = value
|
||||||
|
self.update_display()
|
||||||
|
|
||||||
|
def start_update_timer(self):
|
||||||
|
"""Start the periodic display update timer"""
|
||||||
|
if not hasattr(self, 'data_update_thread'):
|
||||||
|
self.data_update_running = True
|
||||||
|
self.data_update_thread = threading.Thread(
|
||||||
|
target=self._data_update_loop
|
||||||
|
)
|
||||||
|
self.data_update_thread.daemon = True
|
||||||
|
self.data_update_thread.start()
|
||||||
|
|
||||||
|
self._update_display_loop()
|
||||||
|
|
||||||
|
def _update_display_loop(self):
|
||||||
|
"""Periodically update the display"""
|
||||||
|
self.generate_simulated_data()
|
||||||
|
self.update_display()
|
||||||
|
self.update_timer = self.master.after(
|
||||||
|
self.update_interval,
|
||||||
|
self._update_display_loop
|
||||||
|
)
|
||||||
|
|
||||||
|
def _data_update_loop(self):
|
||||||
|
"""Periodically update data from network"""
|
||||||
|
while self.data_update_running:
|
||||||
|
try:
|
||||||
|
# Receive data from UDP
|
||||||
|
data, _ = self.sock.recvfrom(1024)
|
||||||
|
self.ccuState.unpack(data)
|
||||||
|
time.sleep(self.update_interval / 1000)
|
||||||
|
except socket.timeout:
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Data update error: {str(e)}")
|
||||||
|
break
|
||||||
|
|
||||||
|
def stop_update_timer(self):
|
||||||
|
"""Stop the periodic display update timer"""
|
||||||
|
if self.update_timer:
|
||||||
|
self.master.after_cancel(self.update_timer)
|
||||||
|
self.update_timer = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Clean up resources"""
|
||||||
|
self.running = False
|
||||||
|
self.stop_update_timer()
|
||||||
|
if hasattr(self, 'update_thread'):
|
||||||
|
self.update_thread.join()
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
app = ccuSys(root)
|
||||||
|
app.pack(fill=tk.BOTH, expand=True)
|
||||||
|
root.mainloop()
|
||||||
@@ -0,0 +1,664 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font
|
||||||
|
from tkinter import Frame
|
||||||
|
from tkinter.ttk import *
|
||||||
|
|
||||||
|
class disSys(Frame):
|
||||||
|
def __init__(self,root):
|
||||||
|
super().__init__(root)
|
||||||
|
# 当前接受的消息,用于显示和更新
|
||||||
|
self.disHVB = msg_disHighVolBusFbMsg()
|
||||||
|
self.disHVBA = msg_disHighAVolBusFbMsg()
|
||||||
|
self.disHVBB = msg_disHighBVolBusFbMsg()
|
||||||
|
self.disLVB = msg_disLowBusFbMsg()
|
||||||
|
# 初始化列框架列表
|
||||||
|
self.col_frames = []
|
||||||
|
|
||||||
|
self.createWidgets()
|
||||||
|
self.root = root
|
||||||
|
self.root.after(2000, self.update_disp)
|
||||||
|
# 启动数据更新定时器
|
||||||
|
self.update_data_job = None
|
||||||
|
self.start_update_data()
|
||||||
|
def createWidgets(self):
|
||||||
|
# 定义每组的颜色
|
||||||
|
self.colors = ["#FFC0CB", "#ADD8E6", "#90EE90", "#FFD700"]
|
||||||
|
# 创建自定义字体
|
||||||
|
self.custom_font = font.Font(family="Arial", size=12, weight='normal')
|
||||||
|
# 创建4个Frame来分组显示元素的值
|
||||||
|
# 断路器的frame
|
||||||
|
title=list(['高压母线断路器','高电压A母线断路器','高电压B母线断路器','低电压母线断路器'])
|
||||||
|
self.frames = []
|
||||||
|
for i in range(4):
|
||||||
|
frame = tk.Frame(self, bg=self.colors[i], padx=10, pady=10)
|
||||||
|
# frame.pack(padx=10, pady=10, expand=True, fill='both')
|
||||||
|
title_label = tk.Label(frame, text=title[i],bg=self.colors[i],relief='solid' ,font=("Arial", 16, "bold"))
|
||||||
|
title_label.grid(row=0, column=0, columnspan=4, pady=(2, 2), sticky="nsew")
|
||||||
|
self.frames.append(frame)
|
||||||
|
self.frames[0].grid(row=0, column=0, sticky='nsew')
|
||||||
|
self.frames[1].grid(row=0, column=1, sticky='nsew')
|
||||||
|
self.frames[2].grid(row=1, column=0, sticky='nsew')
|
||||||
|
self.frames[3].grid(row=1, column=1, sticky='nsew')
|
||||||
|
################################################故障选择#########################################################
|
||||||
|
inputFrame = tk.LabelFrame(self, bg='Azure',text='故障选择',font=self.custom_font ,padx=10, pady=10)
|
||||||
|
inputFrame.grid(row=0, column=2, columnspan=2, padx=2, pady=2, sticky="nsew")
|
||||||
|
# # 添加输入框来更新值 TODO:添加输入框,更新故障信息
|
||||||
|
self.checkboxes = []
|
||||||
|
self.checkboxesVar = []
|
||||||
|
self.faultDict1 = {0:'动力母线绝缘低',
|
||||||
|
1:'A汇流排绝缘低',
|
||||||
|
2:'仪表电源失电',
|
||||||
|
3:'应急电源失电',
|
||||||
|
4:'DC/DC模块过温'}
|
||||||
|
self.faultDict2 = {0:'仪表电源失电',
|
||||||
|
1:'应急电源失电',
|
||||||
|
2:'浸水报警'}
|
||||||
|
self.faultDict3 = {0:'仪表电源失电',
|
||||||
|
1:'应急电源失电',
|
||||||
|
2:'仪表汇流排绝缘低'}
|
||||||
|
self.faultDict4 = {0:'仪表失电',
|
||||||
|
1:'浸水报警'}
|
||||||
|
spl_linenum = 1
|
||||||
|
for i, dictionary in enumerate([self.faultDict1, self.faultDict2, self.faultDict3, self.faultDict4]):
|
||||||
|
self.checkboxes.append([])
|
||||||
|
self.checkboxesVar.append([])
|
||||||
|
spl = Separator(inputFrame, orient='vertical')
|
||||||
|
spl.grid(row=0, column=spl_linenum+i*2, rowspan=5, pady=(2, 2), sticky="nsew")
|
||||||
|
for j, (key, value) in enumerate(dictionary.items()):
|
||||||
|
checkboxVar = tk.IntVar()
|
||||||
|
checkbox = tk.Checkbutton(inputFrame, text=value, variable=checkboxVar,font=self.custom_font,anchor="w",
|
||||||
|
command=lambda i=i, j=j: self.cheak_fault(i, j))
|
||||||
|
checkbox.grid(row=j, column=i*2, padx=1, pady=1, sticky="nsew")
|
||||||
|
self.checkboxes[i].append(checkbox)
|
||||||
|
self.checkboxesVar[i].append(checkboxVar)
|
||||||
|
################################################电路状态#########################################################
|
||||||
|
dispFrame = tk.LabelFrame(self, bg='Azure',text='电路状态',font=self.custom_font ,padx=10, pady=10)
|
||||||
|
dispFrame.grid(row=1, column=2, columnspan=2, padx=2, pady=2, sticky="nsew") # 调整输入框的上下边距并居中显示
|
||||||
|
value = '关闭'
|
||||||
|
self.labelDcDc = tk.Label(dispFrame, text=f"{'DC/DC模块'}:{value}", font=self.custom_font, relief='groove' ,anchor="w")
|
||||||
|
self.labelDcDc.grid(row=0, column=0, padx=1, pady=1, sticky="nsew")
|
||||||
|
self.DcDcbutton = tk.Button(dispFrame, text="TURN", command=self.toggle_DcDc)
|
||||||
|
self.DcDcbutton.grid(row=0, column=1, padx=1, pady=1, sticky="nsew")
|
||||||
|
|
||||||
|
self.labelWaterInput = tk.Label(dispFrame, text=f"{'冷却水进水阀'}:{value}", font=self.custom_font, relief='groove' ,anchor="w")
|
||||||
|
self.labelWaterInput.grid(row=1, column=0, padx=1, pady=1, sticky="nsew")
|
||||||
|
self.buttonWaterInput = tk.Button(dispFrame, text="TURN", command=self.toggle_WaterInput)
|
||||||
|
self.buttonWaterInput.grid(row=1, column=1, padx=1, pady=1, sticky="nsew")
|
||||||
|
|
||||||
|
self.labelWaterOutput = tk.Label(dispFrame, text=f"{'冷却水出水阀'}:{value}", font=self.custom_font, relief='groove' ,anchor="w")
|
||||||
|
self.labelWaterOutput.grid(row=2, column=0, padx=1, pady=1, sticky="nsew")
|
||||||
|
self.buttonWaterOutput = tk.Button(dispFrame, text="TURN", command=self.toggle_WaterOutput)
|
||||||
|
self.buttonWaterOutput.grid(row=2, column=1, padx=1, pady=1, sticky="nsew")
|
||||||
|
|
||||||
|
self.buttonCurrenStateWin = tk.Button(dispFrame, text="显示电路状态", command=self.show_CurrentState)
|
||||||
|
self.buttonCurrenStateWin.grid(row=0, rowspan=3 , columnspan=2 , column=3,padx=10, pady=1, sticky="nsew")
|
||||||
|
|
||||||
|
# 添加更新按钮
|
||||||
|
# self.buttonCurrenStateWin = tk.Button(dispFrame, text="自动更新", command=self.update_currentState)
|
||||||
|
# self.buttonCurrenStateWin.grid(row=0, rowspan=3 , columnspan=2 , column=5,padx=10, pady=1, sticky="nsew")
|
||||||
|
# update_btn = tk.Button(btn_frame, text="立即更新", font=state_font,
|
||||||
|
# command=self.update_currentState)
|
||||||
|
# update_btn.pack(fill=tk.X, padx=5, pady=5)
|
||||||
|
################################################断路器操作#########################################################
|
||||||
|
# 定义四个字典来存储元素的值
|
||||||
|
self.dict1={'燃料电池断路器':'闭合',
|
||||||
|
'动力锂电池断路器':'闭合',
|
||||||
|
'推进电机断路器':'闭合',
|
||||||
|
'仪表锂电池断路器':'闭合',
|
||||||
|
'DC/DC5模块断路器':'闭合',
|
||||||
|
'艏部高压配电断路器':'闭合',
|
||||||
|
'艏部FT4/5断路器':'闭合',
|
||||||
|
'艉舵1/2断路器':'闭合',
|
||||||
|
'艉舵3/4断路器':'闭合',
|
||||||
|
'FB预留断路器':'闭合',
|
||||||
|
'TYZ预留断路器':'闭合',
|
||||||
|
'预留断路器':'闭合'}
|
||||||
|
self.dict2 = {'艏部FT1-3断路器':'闭合',
|
||||||
|
'启闭机构断路器':'闭合',
|
||||||
|
'桅杆舵机断路器':'闭合',
|
||||||
|
'XCZ断路器':'闭合',
|
||||||
|
'艏舵断路器':'闭合',
|
||||||
|
'敞开电缸断路器':'闭合'}
|
||||||
|
self.dict3 = {'仪表锂电池断路器':'闭合',
|
||||||
|
'艏部低压断路器':'闭合',
|
||||||
|
'UNIT4断路器':'闭合',
|
||||||
|
'DC/DC1断路器':'闭合',
|
||||||
|
'预留断路器1':'闭合',
|
||||||
|
'预留断路器2':'闭合',
|
||||||
|
'艉部应急电池开关':'闭合'}
|
||||||
|
self.dict4 = {'UNIT1断路器':'闭合',
|
||||||
|
'UNIT2断路器':'闭合',
|
||||||
|
'UNIT3断路器':'闭合',
|
||||||
|
'UNIT5断路器':'闭合',
|
||||||
|
'艏部抛载断路器':'闭合',
|
||||||
|
'预留断路器1':'闭合',
|
||||||
|
'预留断路器2':'断开',
|
||||||
|
'艏部应急电池开关':'闭合'}
|
||||||
|
self.labels = []
|
||||||
|
for i, dictionary in enumerate([self.dict1, self.dict2, self.dict3, self.dict4]):
|
||||||
|
self.labels.append([])
|
||||||
|
for j, (key, value) in enumerate(dictionary.items()):
|
||||||
|
# 根据元素的值选择颜色
|
||||||
|
if value == "闭合":
|
||||||
|
color = "green"
|
||||||
|
else:
|
||||||
|
color = "red"
|
||||||
|
label = tk.Label(self.frames[i], text=f"{key}: {value}", fg=color, font=self.custom_font, relief='groove' ,anchor="w")
|
||||||
|
if (j%2==0):
|
||||||
|
label.grid(row=j//2 + 1, column=j%2, padx=1, pady=1,sticky="nsew")
|
||||||
|
else:
|
||||||
|
label.grid(row=j//2 + 1, column=j%2+1, padx=1, pady=1,sticky="nsew")
|
||||||
|
self.labels[i].append(label)
|
||||||
|
# 添加按钮来改变字典中的值
|
||||||
|
button = tk.Button(self.frames[i], text="TURN", command=lambda i=i, j=j: self.toggle_value(i, j))
|
||||||
|
if (j%2==0):
|
||||||
|
button.grid(row=j//2+1, column=j%2+1, padx=1, pady=1)
|
||||||
|
else:
|
||||||
|
button.grid(row=j//2+1, column=j%2+2, padx=1, pady=1, sticky="nsew")
|
||||||
|
self.update_disp()
|
||||||
|
|
||||||
|
# 创建保存电流及电压信息的表格
|
||||||
|
self.disHVBData = []
|
||||||
|
self.disHVBAData = []
|
||||||
|
self.disHVBBData = []
|
||||||
|
self.disLVBData = []
|
||||||
|
|
||||||
|
def update_disp(self):
|
||||||
|
for i, dictionary in enumerate([self.dict1, self.dict2, self.dict3, self.dict4]):
|
||||||
|
for j, (key, value) in enumerate(dictionary.items()):
|
||||||
|
# 根据元素的值选择颜色
|
||||||
|
if value == "闭合":
|
||||||
|
color = "green"
|
||||||
|
else:
|
||||||
|
color = "red"
|
||||||
|
self.labels[i][j].config(text=f"{key}: {value}", fg=color)
|
||||||
|
|
||||||
|
|
||||||
|
def toggle_value(self, i, j):
|
||||||
|
dictionary = [self.dict1, self.dict2, self.dict3, self.dict4][i]
|
||||||
|
key = list(dictionary.keys())[j]
|
||||||
|
if dictionary[key] == "闭合":
|
||||||
|
dictionary[key] = "断开"
|
||||||
|
else:
|
||||||
|
dictionary[key] = "闭合"
|
||||||
|
print(f'{key}操作')
|
||||||
|
self.update_disp()
|
||||||
|
|
||||||
|
def toggle_DcDc(self):
|
||||||
|
if (self.labelDcDc.cget("text")[-1] == '开'):
|
||||||
|
self.labelDcDc.config(text=f"{'DC/DC模块'}:关闭")
|
||||||
|
else:
|
||||||
|
self.labelDcDc.config(text=f"{'DC/DC模块'}:打开")
|
||||||
|
print('DC/DC模块操作')
|
||||||
|
|
||||||
|
def toggle_WaterInput(self):
|
||||||
|
if (self.labelWaterInput.cget("text")[-1] == '开'):
|
||||||
|
self.labelWaterInput.config(text=f"{'冷却水进水阀'}:关闭")
|
||||||
|
else:
|
||||||
|
self.labelWaterInput.config(text=f"{'冷却水进水阀'}:打开")
|
||||||
|
print('冷却水进水阀操作')
|
||||||
|
|
||||||
|
def toggle_WaterOutput(self):
|
||||||
|
if (self.labelWaterOutput.cget("text")[-1] == '开'):
|
||||||
|
self.labelWaterOutput.config(text=f"{'冷却水出水阀'}:关闭")
|
||||||
|
else:
|
||||||
|
self.labelWaterOutput.config(text=f"{'冷却水出水阀'}:打开")
|
||||||
|
print('冷却水出水阀操作')
|
||||||
|
|
||||||
|
def cheak_fault(self,i,j):
|
||||||
|
#TODO:实现故障更新和选择
|
||||||
|
print(self.checkboxes[i][j].cget("text"),self.checkboxesVar[i][j].get())
|
||||||
|
# print(self.checkboxesVar[i][j].get())
|
||||||
|
|
||||||
|
def toggle_hex_mode(self):
|
||||||
|
"""切换16进制显示模式"""
|
||||||
|
self.hex_mode = not self.hex_mode
|
||||||
|
self.update_currentState()
|
||||||
|
|
||||||
|
def update_currentState(self):
|
||||||
|
# 更新所有数值显示
|
||||||
|
for struct, name, entry in self.state_entries:
|
||||||
|
# 获取最新值
|
||||||
|
value = getattr(struct, name)
|
||||||
|
# 根据显示模式格式化值
|
||||||
|
if self.hex_mode and isinstance(value, int):
|
||||||
|
display_value = f"0x{value:02X}"
|
||||||
|
else:
|
||||||
|
display_value = str(value)
|
||||||
|
# 更新entry显示
|
||||||
|
entry.config(state='normal')
|
||||||
|
entry.delete(0, tk.END)
|
||||||
|
entry.insert(0, display_value)
|
||||||
|
entry.config(state='readonly')
|
||||||
|
|
||||||
|
print('电路状态已更新')
|
||||||
|
def _create_scrollable_column(self, parent_frame, title, data_struct, state_font):
|
||||||
|
"""创建带滚动条的列"""
|
||||||
|
col_frame = tk.LabelFrame(parent_frame, text=title, font=state_font,
|
||||||
|
bd=2, relief=tk.GROOVE, padx=5, pady=5)
|
||||||
|
col_frame.grid(row=0, column=len(self.col_frames), padx=5, pady=5, sticky="nsew")
|
||||||
|
col_frame.rowconfigure(0, weight=1)
|
||||||
|
col_frame.columnconfigure(0, weight=1)
|
||||||
|
self.col_frames.append(col_frame)
|
||||||
|
|
||||||
|
# 创建滚动条容器
|
||||||
|
canvas = tk.Canvas(col_frame)
|
||||||
|
v_scrollbar = tk.Scrollbar(col_frame, orient="vertical", command=canvas.yview)
|
||||||
|
h_scrollbar = tk.Scrollbar(col_frame, orient="horizontal", command=canvas.xview)
|
||||||
|
|
||||||
|
# 创建可滚动内容框架
|
||||||
|
scrollable_frame = tk.Frame(canvas)
|
||||||
|
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
|
||||||
|
|
||||||
|
# 配置滚动区域
|
||||||
|
def _configure_scrollregion(e):
|
||||||
|
canvas.configure(scrollregion=canvas.bbox("all"))
|
||||||
|
canvas.config(height=min(e.height, 800))
|
||||||
|
canvas.yview_moveto(0)
|
||||||
|
canvas.xview_moveto(0)
|
||||||
|
|
||||||
|
scrollable_frame.bind("<Configure>", _configure_scrollregion)
|
||||||
|
|
||||||
|
# 配置滚动条
|
||||||
|
canvas.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)
|
||||||
|
h_scrollbar.config(command=canvas.xview)
|
||||||
|
v_scrollbar.config(command=canvas.yview)
|
||||||
|
|
||||||
|
# 布局
|
||||||
|
canvas.grid(row=0, column=0, sticky="nsew")
|
||||||
|
v_scrollbar.grid(row=0, column=1, sticky="ns")
|
||||||
|
h_scrollbar.grid(row=1, column=0, sticky="ew")
|
||||||
|
|
||||||
|
# 添加数据项
|
||||||
|
for name, value in data_struct.__dict__.items():
|
||||||
|
row_frame = tk.Frame(scrollable_frame)
|
||||||
|
row_frame.pack(fill=tk.X, padx=5, pady=2)
|
||||||
|
|
||||||
|
name_label = tk.Label(row_frame, text=name, font=state_font, width=30, anchor="w")
|
||||||
|
name_label.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
entry = tk.Entry(row_frame, font=state_font, width=20)
|
||||||
|
entry.pack(side=tk.RIGHT, padx=5, fill=tk.X, expand=True)
|
||||||
|
entry.insert(0, str(value))
|
||||||
|
entry.config(state='readonly')
|
||||||
|
|
||||||
|
self.state_entries.append((data_struct, name, entry))
|
||||||
|
|
||||||
|
def show_CurrentState(self):
|
||||||
|
"""显示当前电路状态窗口"""
|
||||||
|
# 初始化窗口
|
||||||
|
self.currentStateWin = tk.Toplevel(self)
|
||||||
|
self.currentStateWin.title("电路状态")
|
||||||
|
self.currentStateWin.geometry("1400x800")
|
||||||
|
self.currentStateWin.minsize(1000, 600)
|
||||||
|
self.currentStateWin.protocol("WM_DELETE_WINDOW", self.on_close_currentState)
|
||||||
|
|
||||||
|
# 初始化16进制显示模式
|
||||||
|
self.hex_mode = False
|
||||||
|
|
||||||
|
# 创建主容器
|
||||||
|
main_frame = tk.Frame(self.currentStateWin)
|
||||||
|
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||||
|
|
||||||
|
# 配置网格布局
|
||||||
|
for i in range(4):
|
||||||
|
main_frame.columnconfigure(i, weight=1)
|
||||||
|
|
||||||
|
# 创建自定义字体
|
||||||
|
state_font = font.Font(family="Arial", size=10, weight='bold')
|
||||||
|
|
||||||
|
# 初始化状态条目列表
|
||||||
|
self.state_entries = []
|
||||||
|
self.col_frames = []
|
||||||
|
|
||||||
|
# 创建各状态列
|
||||||
|
self._create_scrollable_column(main_frame, "高压母线", self.disHVB, state_font)
|
||||||
|
self._create_scrollable_column(main_frame, "高电压A母线", self.disHVBA, state_font)
|
||||||
|
self._create_scrollable_column(main_frame, "高电压B母线", self.disHVBB, state_font)
|
||||||
|
self._create_scrollable_column(main_frame, "低电压母线", self.disLVB, state_font)
|
||||||
|
|
||||||
|
# 配置主框架布局权重
|
||||||
|
main_frame.rowconfigure(1, weight=1)
|
||||||
|
|
||||||
|
# 添加底部按钮容器
|
||||||
|
btn_frame = tk.Frame(main_frame)
|
||||||
|
btn_frame.grid(row=2, column=0, columnspan=4, pady=10, sticky="sew")
|
||||||
|
|
||||||
|
# 添加更新按钮
|
||||||
|
update_btn = tk.Button(btn_frame, text="立即更新", font=state_font,
|
||||||
|
command=self.update_currentState)
|
||||||
|
update_btn.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# 添加16进制显示切换按钮
|
||||||
|
hex_btn = tk.Button(btn_frame, text="16进制显示", font=state_font,
|
||||||
|
command=self.toggle_hex_mode)
|
||||||
|
hex_btn.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# 启动定时更新
|
||||||
|
self.update_interval = 1000 # 1秒
|
||||||
|
self.schedule_update()
|
||||||
|
|
||||||
|
def on_close_currentState(self):
|
||||||
|
"""窗口关闭回调"""
|
||||||
|
if hasattr(self, 'update_job'):
|
||||||
|
self.currentStateWin.after_cancel(self.update_job)
|
||||||
|
self.currentStateWin.destroy()
|
||||||
|
|
||||||
|
def start_update_data(self):
|
||||||
|
"""启动数据更新定时器"""
|
||||||
|
self.update_data_job = self.root.after(500, self._update_data_loop)
|
||||||
|
|
||||||
|
def stop_update_data(self):
|
||||||
|
"""停止数据更新定时器"""
|
||||||
|
if self.update_data_job:
|
||||||
|
self.root.after_cancel(self.update_data_job)
|
||||||
|
self.update_data_job = None
|
||||||
|
|
||||||
|
def _update_data_loop(self):
|
||||||
|
"""定时更新数据"""
|
||||||
|
self.updata_data()
|
||||||
|
self.update_data_job = self.root.after(500, self._update_data_loop)
|
||||||
|
|
||||||
|
def schedule_update(self):
|
||||||
|
"""安排定时更新"""
|
||||||
|
self.update_currentState()
|
||||||
|
self.update_job = self.currentStateWin.after(self.update_interval, self.schedule_update)
|
||||||
|
def updata_data(self):
|
||||||
|
'''通过这个可以更新数据'''
|
||||||
|
if (self.dict1['燃料电池断路器']=='闭合'):
|
||||||
|
self.disHVB.DCB1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.DCB1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['动力锂电池断路器']=='闭合'):
|
||||||
|
self.disHVB.DCB2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.DCB2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['推进电机断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['仪表锂电池断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['DC/DC5模块断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK3 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK3 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艏部高压配电断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK4 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK4 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艏部FT4/5断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK5 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK5 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艉舵1/2断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK6 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK6 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['艉舵3/4断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK7 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK7 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['FB预留断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK8 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK8 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['TYZ预留断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK9 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK9 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict1['预留断路器']=='闭合'):
|
||||||
|
self.disHVB.ZK10 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVB.ZK10 = 0xAA
|
||||||
|
######################################################
|
||||||
|
if (self.dict2['艏部FT1-3断路器']=='闭合'):
|
||||||
|
self.disHVBA.bowFTDevice123CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.bowFTDevice123CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['启闭机构断路器']=='闭合'):
|
||||||
|
self.disHVBA.actuatorCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.actuatorCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['桅杆舵机断路器']=='闭合'):
|
||||||
|
self.disHVBA.mastSteeringGearControlBoxCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.mastSteeringGearControlBoxCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['XCZ断路器']=='闭合'):
|
||||||
|
self.disHVBA.xczCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.xczCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['艏舵断路器']=='闭合'):
|
||||||
|
self.disHVBA.bowRudderControlBoxCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.bowRudderControlBoxCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict2['敞开电缸断路器']=='闭合'):
|
||||||
|
self.disHVBA.openWaterCoverStartCylinderCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBA.openWaterCoverStartCylinderCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
if (self.dict3['仪表锂电池断路器']=='闭合'):
|
||||||
|
self.disHVBB.lithiumBatteryGroupInstrumentCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.lithiumBatteryGroupInstrumentCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['艏部低压断路器']=='闭合'):
|
||||||
|
self.disHVBB.bowLowVoltageDistributionCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.bowLowVoltageDistributionCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['UNIT4断路器']=='闭合'):
|
||||||
|
self.disHVBB.unit4CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.unit4CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['DC/DC1断路器']=='闭合'):
|
||||||
|
self.disHVBB.dcdc1CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.dcdc1CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['预留断路器1']=='闭合'):
|
||||||
|
self.disHVBB.reservedCircuitBreaker1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.reservedCircuitBreaker1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['预留断路器2']=='闭合'):
|
||||||
|
self.disHVBB.reservedCircuitBreaker2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.reservedCircuitBreaker2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict3['艉部应急电池开关']=='闭合'):
|
||||||
|
self.disHVBB.emergencyLithiumBatteryGroup2CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disHVBB.emergencyLithiumBatteryGroup2CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
if (self.dict4['UNIT1断路器']=='闭合'):
|
||||||
|
self.disLVB.unit1CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit1CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['UNIT2断路器']=='闭合'):
|
||||||
|
self.disLVB.unit2CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit2CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['UNIT3断路器']=='闭合'):
|
||||||
|
self.disLVB.unit3CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit3CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['UNIT5断路器']=='闭合'):
|
||||||
|
self.disLVB.unit5CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.unit5CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['预留断路器1']=='闭合'):
|
||||||
|
self.disLVB.reservedCircuitBreaker1 = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.reservedCircuitBreaker1 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['预留断路器2']=='闭合'):
|
||||||
|
self.disLVB.reservedCircuitBreaker2 = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.reservedCircuitBreaker2 = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['艏部抛载断路器']=='闭合'):
|
||||||
|
self.disLVB.bowPZDeviceCircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.bowPZDeviceCircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
if (self.dict4['艏部应急电池开关']=='闭合'):
|
||||||
|
self.disLVB.emergencyLithiumBatteryGroup1CircuitBreaker = 0x55
|
||||||
|
else:
|
||||||
|
self.disLVB.emergencyLithiumBatteryGroup1CircuitBreaker = 0xAA
|
||||||
|
|
||||||
|
# a = match.sin(time.time())
|
||||||
|
print("更新数据")
|
||||||
|
|
||||||
|
|
||||||
|
def get_date(self):
|
||||||
|
a = self.disHVB.pack()
|
||||||
|
b = self.disHVBA.pack()
|
||||||
|
c = self.disHVBB.pack()
|
||||||
|
d = self.disLVB.pack()
|
||||||
|
return a,b,c,d
|
||||||
|
|
||||||
|
def update_fromMsg(self, data):
|
||||||
|
'''通过这个可以更新数据'''
|
||||||
|
try:
|
||||||
|
# 解析消息头
|
||||||
|
headBuf = data[:6]
|
||||||
|
header = struct.unpack('<BBHH', headBuf)
|
||||||
|
start1 = header[0]
|
||||||
|
start2 = header[1]
|
||||||
|
msg_id = header[2]
|
||||||
|
msg_len = header[3]
|
||||||
|
|
||||||
|
if start1 == 0x40 and start2 == 0x40:
|
||||||
|
if msg_id == 0x0001: # 高压母线配电指令
|
||||||
|
msg = msg_disHVBCmd()
|
||||||
|
msg.unpack(data)
|
||||||
|
self.disHVB.DCB1 = msg.fuelCellCircuitBreaker
|
||||||
|
self.disHVB.DCB2 = msg.powerLithiumBatteryCircuitBreaker
|
||||||
|
self.disHVB.ZK1 = msg.propulsionMotorCircuitBreaker
|
||||||
|
self.disHVB.ZK2 = msg.lithiumBatteryGroupInstrumentCircuitBreaker
|
||||||
|
self.disHVB.ZK3 = msg.dcDc5ModuleCircuitBreaker
|
||||||
|
self.disHVB.ZK4 = msg.bowHighVoltageDistributionBoxCircuitBreaker
|
||||||
|
self.disHVB.ZK5 = msg.sternFTDevice45CircuitBreaker
|
||||||
|
self.disHVB.ZK6 = msg.sternRudderSwitch1CircuitBreaker
|
||||||
|
self.disHVB.ZK7 = msg.sternRudderSwitch2CircuitBreaker
|
||||||
|
self.disHVB.ZK8 = msg.fbReservedCircuitBreaker
|
||||||
|
self.disHVB.ZK9 = msg.tyzReservedCircuitBreaker
|
||||||
|
self.disHVB.ZK10 = msg.reservedCircuitBreaker
|
||||||
|
self.disHVB.inputWater = msg.inputWater
|
||||||
|
self.disHVB.outputWater = msg.outputWater
|
||||||
|
self.disHVB.dcdc5dcdc5Module = msg.dcdc5dcdc5Module
|
||||||
|
|
||||||
|
# 更新dict1
|
||||||
|
self.dict1['燃料电池断路器'] = '闭合' if msg.fuelCellCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['动力锂电池断路器'] = '闭合' if msg.powerLithiumBatteryCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['推进电机断路器'] = '闭合' if msg.propulsionMotorCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['仪表锂电池断路器'] = '闭合' if msg.lithiumBatteryGroupInstrumentCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['DC/DC5模块断路器'] = '闭合' if msg.dcDc5ModuleCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['艏部高压配电断路器'] = '闭合' if msg.bowHighVoltageDistributionBoxCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['艏部FT4/5断路器'] = '闭合' if msg.sternFTDevice45CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['艉舵1/2断路器'] = '闭合' if msg.sternRudderSwitch1CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['艉舵3/4断路器'] = '闭合' if msg.sternRudderSwitch2CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['FB预留断路器'] = '闭合' if msg.fbReservedCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['TYZ预留断路器'] = '闭合' if msg.tyzReservedCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict1['预留断路器'] = '闭合' if msg.reservedCircuitBreaker == 0x55 else '断开'
|
||||||
|
|
||||||
|
elif msg_id == 0x0002: # 高电压A母线配电指令
|
||||||
|
msg = msg_disHVBACmd()
|
||||||
|
msg.unpack(data)
|
||||||
|
self.disHVBA.bowFTDevice123CircuitBreaker = msg.bowFTDevice123CircuitBreaker
|
||||||
|
self.disHVBA.actuatorCircuitBreaker = msg.actuatorCircuitBreaker
|
||||||
|
self.disHVBA.mastSteeringGearControlBoxCircuitBreaker = msg.mastSteeringGearControlBoxCircuitBreaker
|
||||||
|
self.disHVBA.xczCircuitBreaker = msg.xczCircuitBreaker
|
||||||
|
self.disHVBA.bowRudderControlBoxCircuitBreaker = msg.bowRudderControlBoxCircuitBreaker
|
||||||
|
self.disHVBA.openWaterCoverStartCylinderCircuitBreaker = msg.openWaterCoverStartCylinderCircuitBreaker
|
||||||
|
|
||||||
|
# 更新dict2
|
||||||
|
self.dict2['艏部FT1-3断路器'] = '闭合' if msg.bowFTDevice123CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict2['启闭机构断路器'] = '闭合' if msg.actuatorCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict2['桅杆舵机断路器'] = '闭合' if msg.mastSteeringGearControlBoxCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict2['XCZ断路器'] = '闭合' if msg.xczCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict2['艏舵断路器'] = '闭合' if msg.bowRudderControlBoxCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict2['敞开电缸断路器'] = '闭合' if msg.openWaterCoverStartCylinderCircuitBreaker == 0x55 else '断开'
|
||||||
|
|
||||||
|
elif msg_id == 0x0003: # 高电压B母线配电指令
|
||||||
|
msg = msg_disHVBBCmd()
|
||||||
|
msg.unpack(data)
|
||||||
|
self.disHVBB.lithiumBatteryGroupInstrumentCircuitBreaker = msg.lithiumBatteryGroupInstrumentCircuitBreaker
|
||||||
|
self.disHVBB.bowLowVoltageDistributionBoxCircuitBreaker = msg.bowLowVoltageDistributionBoxCircuitBreaker
|
||||||
|
self.disHVBB.unit4InstrumentDC48VCircuitBreaker = msg.unit4InstrumentDC48VCircuitBreaker
|
||||||
|
self.disHVBB.dcC1DCDistributionPanelCircuitBreaker = msg.dcC1DCDistributionPanelCircuitBreaker
|
||||||
|
self.disHVBB.reservedCircuitBreaker1 = msg.reservedCircuitBreaker1
|
||||||
|
self.disHVBB.reservedCircuitBreaker2 = msg.reservedCircuitBreaker2
|
||||||
|
self.disHVBB.emergencyLithiumBatteryGroup2CircuitBreaker = msg.emergencyLithiumBatteryGroup2CircuitBreaker
|
||||||
|
|
||||||
|
# 更新dict3
|
||||||
|
self.dict3['仪表锂电池断路器'] = '闭合' if msg.lithiumBatteryGroupInstrumentCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict3['艏部低压断路器'] = '闭合' if msg.bowLowVoltageDistributionBoxCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict3['UNIT4断路器'] = '闭合' if msg.unit4InstrumentDC48VCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict3['DC/DC1断路器'] = '闭合' if msg.dcC1DCDistributionPanelCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict3['预留断路器1'] = '闭合' if msg.reservedCircuitBreaker1 == 0x55 else '断开'
|
||||||
|
self.dict3['预留断路器2'] = '闭合' if msg.reservedCircuitBreaker2 == 0x55 else '断开'
|
||||||
|
self.dict3['艉部应急电池开关'] = '闭合' if msg.emergencyLithiumBatteryGroup2CircuitBreaker == 0x55 else '断开'
|
||||||
|
|
||||||
|
elif msg_id == 0x0004: # 低电压母线配电指令
|
||||||
|
msg = msg_disLVBCmd()
|
||||||
|
msg.unpack(data)
|
||||||
|
self.disLVB.unit1CircuitBreaker = msg.unit1CircuitBreaker
|
||||||
|
self.disLVB.unit2CircuitBreaker = msg.unit2CircuitBreaker
|
||||||
|
self.disLVB.unit3CircuitBreaker = msg.unit3CircuitBreaker
|
||||||
|
self.disLVB.unit5CircuitBreaker = msg.unit5CircuitBreaker
|
||||||
|
self.disLVB.bowPZDeviceCircuitBreaker = msg.bowPZDeviceCircuitBreaker
|
||||||
|
self.disLVB.reservedCircuitBreaker1 = msg.reservedCircuitBreaker1
|
||||||
|
self.disLVB.reservedCircuitBreaker2 = msg.reservedCircuitBreaker2
|
||||||
|
self.disLVB.emergencyLithiumBatteryGroup1CircuitBreaker = msg.emergencyLithiumBatteryGroup1CircuitBreaker
|
||||||
|
|
||||||
|
# 更新dict4
|
||||||
|
self.dict4['UNIT1断路器'] = '闭合' if msg.unit1CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict4['UNIT2断路器'] = '闭合' if msg.unit2CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict4['UNIT3断路器'] = '闭合' if msg.unit3CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict4['UNIT5断路器'] = '闭合' if msg.unit5CircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict4['艏部抛载断路器'] = '闭合' if msg.bowPZDeviceCircuitBreaker == 0x55 else '断开'
|
||||||
|
self.dict4['预留断路器1'] = '闭合' if msg.reservedCircuitBreaker1 == 0x55 else '断开'
|
||||||
|
self.dict4['预留断路器2'] = '闭合' if msg.reservedCircuitBreaker2 == 0x55 else '断开'
|
||||||
|
self.dict4['艏部应急电池开关'] = '闭合' if msg.emergencyLithiumBatteryGroup1CircuitBreaker == 0x55 else '断开'
|
||||||
|
|
||||||
|
self.update_disp() # 更新界面显示
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error updating from message: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
app = disSys(root)
|
||||||
|
app.pack()
|
||||||
|
root.mainloop()
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font, filedialog
|
||||||
|
from tkinter import Frame
|
||||||
|
from tkinter.ttk import *
|
||||||
|
|
||||||
|
class logWin(Frame):
|
||||||
|
def __init__(self, root):
|
||||||
|
super().__init__(root)
|
||||||
|
self.root = root
|
||||||
|
custom_font = font.Font(family="Arial", size=8)
|
||||||
|
|
||||||
|
# 设置 state 为 tk.DISABLED 禁用编辑功能
|
||||||
|
self.text_box = tk.Text(root, height=10, width=50, font=custom_font, state=tk.DISABLED)
|
||||||
|
self.text_box.grid(row=0, column=0, columnspan=2, sticky='nsew')
|
||||||
|
|
||||||
|
# 创建垂直滚动条
|
||||||
|
scrollbar = tk.Scrollbar(root, command=self.text_box.yview)
|
||||||
|
scrollbar.grid(row=0, column=2, sticky='ns')
|
||||||
|
|
||||||
|
# 将滚动条与 Text 组件关联
|
||||||
|
self.text_box.config(yscrollcommand=scrollbar.set)
|
||||||
|
|
||||||
|
# 创建保存按钮
|
||||||
|
save_button = tk.Button(root, text="保存日志", command=self.save_log)
|
||||||
|
save_button.grid(row=1, column=0, sticky='ew')
|
||||||
|
|
||||||
|
# 创建清空按钮
|
||||||
|
clear_button = tk.Button(root, text="清空日志", command=self.clear_log)
|
||||||
|
clear_button.grid(row=1, column=1, sticky='ew')
|
||||||
|
|
||||||
|
# 配置行和列的权重,使组件能够随窗口大小变化而调整
|
||||||
|
root.grid_rowconfigure(0, weight=1)
|
||||||
|
root.grid_columnconfigure(0, weight=1)
|
||||||
|
root.grid_columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
def display_log(self, log_message):
|
||||||
|
# 启用编辑功能
|
||||||
|
self.text_box.config(state=tk.NORMAL)
|
||||||
|
# 将日志信息添加到 Text 组件中
|
||||||
|
self.text_box.insert(tk.END, log_message + "\n")
|
||||||
|
# 滚动到 Text 组件的底部,以显示最新的日志信息
|
||||||
|
self.text_box.see(tk.END)
|
||||||
|
# 禁用编辑功能
|
||||||
|
self.text_box.config(state=tk.DISABLED)
|
||||||
|
|
||||||
|
def save_log(self):
|
||||||
|
# 打开文件选择对话框
|
||||||
|
file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")])
|
||||||
|
if file_path:
|
||||||
|
# 获取文本框中的内容
|
||||||
|
log_content = self.text_box.get("1.0", tk.END)
|
||||||
|
# 将内容写入文件
|
||||||
|
with open(file_path, "w") as file:
|
||||||
|
file.write(log_content)
|
||||||
|
# 显示保存成功的提示
|
||||||
|
tk.messagebox.showinfo("保存成功", "日志已成功保存到文件。")
|
||||||
|
|
||||||
|
def clear_log(self):
|
||||||
|
# 启用编辑功能
|
||||||
|
self.text_box.config(state=tk.NORMAL)
|
||||||
|
# 清空 Text 组件中的内容
|
||||||
|
self.text_box.delete("1.0", tk.END)
|
||||||
|
# 禁用编辑功能
|
||||||
|
self.text_box.config(state=tk.DISABLED)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("能源管理系统调试")
|
||||||
|
log_win = logWin(root)
|
||||||
|
# 假设您有一个日志消息需要显示
|
||||||
|
for i in range(100):
|
||||||
|
log_win.display_log("这是一条日志信息" + str(i))
|
||||||
|
root.mainloop()
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import tkinter as tk
|
||||||
|
import threading
|
||||||
|
from udpmsg import *
|
||||||
|
from datetime import datetime
|
||||||
|
from tkinter import font
|
||||||
|
import threading
|
||||||
|
from disSys import *
|
||||||
|
from logWin import *
|
||||||
|
from ccuSys import *
|
||||||
|
|
||||||
|
target_ip = '127.0.0.1'
|
||||||
|
target_port = 5000
|
||||||
|
|
||||||
|
def receive_messages(sock, logwin:logWin, disSysWin:disSys):
|
||||||
|
while True:
|
||||||
|
current_time = datetime.now()
|
||||||
|
formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
data, address = sock.recvfrom(4096)
|
||||||
|
# 接受配电系统消息
|
||||||
|
disSysWin.update_fromMsg(data)
|
||||||
|
headBuf = data[:6]
|
||||||
|
header = struct.unpack('<BBHH',headBuf)
|
||||||
|
start1 = data[0]
|
||||||
|
start2 = data[1]
|
||||||
|
msg_id = data[2]
|
||||||
|
msg_len = data[3]
|
||||||
|
if(start1==0x40 and start2==0x40):
|
||||||
|
if(msg_id==0x0001):
|
||||||
|
msg = msg_disHVBCmd()
|
||||||
|
msg.unpack(data)
|
||||||
|
# text_box.insert(tk.END, f"{formatted_time}->接收到来自 {address} | 高压母线配电指令:\n")
|
||||||
|
logWin.display_log(logwin,f"{formatted_time}->接收到来自 {address} | 高压母线配电指令:")
|
||||||
|
elif(msg_id==0x0002):
|
||||||
|
logWin.display_log(logwin,f"{formatted_time}->接收到来自 {address} | 高压汇流排A配电指令:")
|
||||||
|
elif(msg_id==0x0003):
|
||||||
|
logWin.display_log(logwin,f"{formatted_time}->接收到来自 {address} | 高压汇流排B配电指令:")
|
||||||
|
elif(msg_id==0x0004):
|
||||||
|
logWin.display_log(logwin,f"{formatted_time}->接收到来自 {address} | 低压母线配电指令:")
|
||||||
|
elif(start1==0x20 and start2==0x20):
|
||||||
|
if(msg_id==0x0050):
|
||||||
|
logWin.display_log(logwin,f"{formatted_time}->接收到来自 {address} | CCU控制指令:")
|
||||||
|
|
||||||
|
|
||||||
|
def send_messages(sock, logwin:logWin, disSysWin:disSys,ccuSysWin:ccuSys):
|
||||||
|
while True:
|
||||||
|
# 配电消息反馈
|
||||||
|
a,b,c,d = disSysWin.get_date()
|
||||||
|
sock.sendto(a, (target_ip, target_port))
|
||||||
|
sock.sendto(b, (target_ip, target_port))
|
||||||
|
sock.sendto(c, (target_ip, target_port))
|
||||||
|
sock.sendto(d, (target_ip, target_port))
|
||||||
|
|
||||||
|
#TODO复合管控消息反馈
|
||||||
|
e = ccuSysWin.ccuState.pack()
|
||||||
|
sock.sendto(e, (target_ip, target_port))
|
||||||
|
|
||||||
|
threading.Event().wait(1) # 每隔1秒发送一次消息
|
||||||
@@ -0,0 +1,656 @@
|
|||||||
|
import struct
|
||||||
|
|
||||||
|
class msg_CcuStateFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x20
|
||||||
|
self.start2 = 0x20
|
||||||
|
self.id = 0x0041
|
||||||
|
self.length = 0x0000
|
||||||
|
self.currentWorkCondition = 0x00
|
||||||
|
self.fcuState = 80
|
||||||
|
self.fcuFaultLeve = 0x20
|
||||||
|
self.powerLimit = 0x00
|
||||||
|
self.totalPowerGeneration = 0x00
|
||||||
|
self.ch4o = 0x00
|
||||||
|
self.o2 = 0x00
|
||||||
|
self.fcuVoltage = 0x0000
|
||||||
|
self.fcuCurrent = 0x0000
|
||||||
|
self.o2Level = 0x00
|
||||||
|
self.placeholder1 = 0x00
|
||||||
|
self.exchangerTemperature = 0x00
|
||||||
|
self.fcuOutPower = 0x00
|
||||||
|
self.fcuOutIns = 0x00
|
||||||
|
self.fcuVoltageIns = 0x00
|
||||||
|
self.fcuVoltagePower = 0x00
|
||||||
|
self.fcuCurrentIns = 0x00
|
||||||
|
self.fcuCurrentPower = 0x00
|
||||||
|
self.h2Concentration1 = 0x00
|
||||||
|
self.h2Concentration2 = 0x00
|
||||||
|
self.o2Concentration1 = 0x00
|
||||||
|
self.o2Concentration2 = 0x00
|
||||||
|
self.ch4oConcentration1 = 0x00
|
||||||
|
self.ch4oConcentration2 = 0x00
|
||||||
|
self.backpressure1 = 0x00
|
||||||
|
self.backpressure2 = 0x00
|
||||||
|
self.flameDetection = 0x00
|
||||||
|
self.fcuGZ_1L = 0x00
|
||||||
|
self.fcuGZ_1H = 0x00
|
||||||
|
self.fcuGZ_2L = 0x00
|
||||||
|
self.fcuGZ_2H = 0x00
|
||||||
|
self.fcuGZ_3L = 0x00
|
||||||
|
self.fcuGZ_3H = 0x00
|
||||||
|
self.insPosRelayState = 0x00
|
||||||
|
self.insNegRelayState = 0x00
|
||||||
|
self.powerPosRelayState = 0x00
|
||||||
|
self.powerNegRelayState = 0x00
|
||||||
|
self.insBatLimit = 0x00
|
||||||
|
self.powerBatLimit = 0x00
|
||||||
|
self.insBatSoc = 0x00
|
||||||
|
self.powerBatSoc = 0x00
|
||||||
|
self.insBatTotalElectricity = 0x00
|
||||||
|
self.powerBatTotalElectricity = 0x00
|
||||||
|
self.insBatCurrentElectricity = 0x00
|
||||||
|
self.powerBatCurrentElectricity = 0x00
|
||||||
|
self.insChargeState = 0x00
|
||||||
|
self.powerChargeState = 0x00
|
||||||
|
self.insLinkVoltage = 0x00
|
||||||
|
self.insPackVoltage = 0x00
|
||||||
|
self.insCurrent = 0x00
|
||||||
|
self.insPosInsulationResistance = 0x00
|
||||||
|
self.insNegInsulationResistance = 0x00
|
||||||
|
self.powerLinkVoltage = 0x00
|
||||||
|
self.powerPackVoltage = 0x00
|
||||||
|
self.powerCurrent = 0x00
|
||||||
|
self.powerPosInsulationResistance = 0x00
|
||||||
|
self.powerNegInsulationResistance = 0x00
|
||||||
|
self.insEmergencyStatusWord = 0x00
|
||||||
|
self.powerEmergencyStatusWord = 0x00
|
||||||
|
self.insAlarmIdentificationWord = 0x00
|
||||||
|
self.powerAlarmIdentificationWord = 0x00
|
||||||
|
self.insCurrentSocHold1 = 0x00
|
||||||
|
self.insCurrentSocHold2 = 0x00
|
||||||
|
self.insCurrentSocHold3 = 0x00
|
||||||
|
self.fcuCurrentToInsLimit1 = 0x00
|
||||||
|
self.fcuCurrentToinsLimit2 = 0x00
|
||||||
|
self.powerCurrentSocHold1 = 0x00
|
||||||
|
self.powerCurrentSocHold2 = 0x00
|
||||||
|
self.powerCurrentSocHold3 = 0x00
|
||||||
|
self.powerCurrentToInsLimit1 = 0x00
|
||||||
|
self.powerCurrentToinsLimit2 = 0x00
|
||||||
|
self.placeholder2 = 0x00
|
||||||
|
self.placeholder3 = 0x00
|
||||||
|
self.placeholder4 = 0x00
|
||||||
|
self.placeholder5 = 0x00
|
||||||
|
self.checkCode = 0x00
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
self.length = 0x0000
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
|
||||||
|
data = struct.pack('<B', self.start1)
|
||||||
|
data += struct.pack('<B', self.start2)
|
||||||
|
data += struct.pack('<H', self.id)
|
||||||
|
data += struct.pack('<H', self.length)
|
||||||
|
|
||||||
|
# 填充数据
|
||||||
|
data += struct.pack('<B', self.currentWorkCondition)
|
||||||
|
data += struct.pack('<B', self.fcuState)
|
||||||
|
data += struct.pack('<B', self.fcuFaultLeve)
|
||||||
|
data += struct.pack('<f', self.powerLimit)
|
||||||
|
data += struct.pack('<f', self.totalPowerGeneration)
|
||||||
|
data += struct.pack('<f', self.ch4o)
|
||||||
|
data += struct.pack('<f', self.o2)
|
||||||
|
data += struct.pack('<f', self.fcuVoltage)
|
||||||
|
data += struct.pack('<f', self.fcuCurrent)
|
||||||
|
data += struct.pack('<f', self.o2Level)
|
||||||
|
data += struct.pack('<f', self.placeholder1)
|
||||||
|
data += struct.pack('<f', self.exchangerTemperature)
|
||||||
|
data += struct.pack('<f', self.fcuOutPower)
|
||||||
|
data += struct.pack('<f', self.fcuOutIns)
|
||||||
|
data += struct.pack('<f', self.fcuVoltageIns)
|
||||||
|
data += struct.pack('<f', self.fcuVoltagePower)
|
||||||
|
data += struct.pack('<f', self.fcuCurrentIns)
|
||||||
|
data += struct.pack('<f', self.fcuCurrentPower)
|
||||||
|
data += struct.pack('<f', self.h2Concentration1)
|
||||||
|
data += struct.pack('<f', self.h2Concentration2)
|
||||||
|
data += struct.pack('<f', self.o2Concentration1)
|
||||||
|
data += struct.pack('<f', self.o2Concentration2)
|
||||||
|
data += struct.pack('<f', self.ch4oConcentration1)
|
||||||
|
data += struct.pack('<f', self.ch4oConcentration2)
|
||||||
|
data += struct.pack('<f', self.backpressure1)
|
||||||
|
data += struct.pack('<f', self.backpressure2)
|
||||||
|
data += struct.pack('<B', self.flameDetection)
|
||||||
|
data += struct.pack('<B', self.fcuGZ_1L)
|
||||||
|
data += struct.pack('<B', self.fcuGZ_1H)
|
||||||
|
data += struct.pack('<B', self.fcuGZ_2L)
|
||||||
|
data += struct.pack('<B', self.fcuGZ_2H)
|
||||||
|
data += struct.pack('<B', self.fcuGZ_3L)
|
||||||
|
data += struct.pack('<B', self.fcuGZ_3H)
|
||||||
|
data += struct.pack('<B', self.insPosRelayState)
|
||||||
|
data += struct.pack('<B', self.insNegRelayState)
|
||||||
|
data += struct.pack('<B', self.powerPosRelayState)
|
||||||
|
data += struct.pack('<B', self.powerNegRelayState)
|
||||||
|
data += struct.pack('<H', self.insBatLimit)
|
||||||
|
data += struct.pack('<H', self.powerBatLimit)
|
||||||
|
data += struct.pack('<B', self.insBatSoc)
|
||||||
|
data += struct.pack('<B', self.powerBatSoc)
|
||||||
|
data += struct.pack('<H', self.insBatTotalElectricity)
|
||||||
|
data += struct.pack('<H', self.powerBatTotalElectricity)
|
||||||
|
data += struct.pack('<H', self.insBatCurrentElectricity)
|
||||||
|
data += struct.pack('<H', self.powerBatCurrentElectricity)
|
||||||
|
data += struct.pack('<B', self.insChargeState)
|
||||||
|
data += struct.pack('<B', self.powerChargeState)
|
||||||
|
data += struct.pack('<H', self.insLinkVoltage)
|
||||||
|
data += struct.pack('<H', self.insPackVoltage)
|
||||||
|
data += struct.pack('<H', self.insCurrent)
|
||||||
|
data += struct.pack('<H', self.insPosInsulationResistance)
|
||||||
|
data += struct.pack('<H', self.insNegInsulationResistance)
|
||||||
|
data += struct.pack('<H', self.powerLinkVoltage)
|
||||||
|
data += struct.pack('<H', self.powerPackVoltage)
|
||||||
|
data += struct.pack('<H', self.powerCurrent)
|
||||||
|
data += struct.pack('<H', self.powerPosInsulationResistance)
|
||||||
|
data += struct.pack('<H', self.powerNegInsulationResistance)
|
||||||
|
data += struct.pack('<B', self.insEmergencyStatusWord)
|
||||||
|
data += struct.pack('<B', self.powerEmergencyStatusWord)
|
||||||
|
data += struct.pack('<B', self.insAlarmIdentificationWord)
|
||||||
|
data += struct.pack('<B', self.powerAlarmIdentificationWord)
|
||||||
|
data += struct.pack('<B', self.insCurrentSocHold1)
|
||||||
|
data += struct.pack('<B', self.insCurrentSocHold2)
|
||||||
|
data += struct.pack('<B', self.insCurrentSocHold3)
|
||||||
|
data += struct.pack('<B', self.fcuCurrentToInsLimit1)
|
||||||
|
data += struct.pack('<B', self.fcuCurrentToinsLimit2)
|
||||||
|
data += struct.pack('<B', self.powerCurrentSocHold1)
|
||||||
|
data += struct.pack('<B', self.powerCurrentSocHold2)
|
||||||
|
data += struct.pack('<B', self.powerCurrentSocHold3)
|
||||||
|
data += struct.pack('<B', self.powerCurrentToInsLimit1)
|
||||||
|
data += struct.pack('<B', self.powerCurrentToinsLimit2)
|
||||||
|
data += struct.pack('<f', self.placeholder2)
|
||||||
|
data += struct.pack('<f', self.placeholder3)
|
||||||
|
data += struct.pack('<f', self.placeholder4)
|
||||||
|
data += struct.pack('<f', self.placeholder5)
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.checkCode += data[i]
|
||||||
|
# print(self.checkCode)
|
||||||
|
|
||||||
|
data += struct.pack('<I', self.checkCode)
|
||||||
|
|
||||||
|
|
||||||
|
last_index = len(data)
|
||||||
|
# print(struct.unpack('<i',data[last_index-4:last_index]))
|
||||||
|
|
||||||
|
# print(len(data))
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class msg_CcuSetParamFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x20
|
||||||
|
self.start2 = 0x20
|
||||||
|
self.id = 0x0040
|
||||||
|
self.length = 10
|
||||||
|
self.flag = 0x01
|
||||||
|
self.failvreCode = 0x01
|
||||||
|
self.checkCode = 0x01 # 初始值,将在 pack 方法中更新
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
# self.checkCode = self.start1 + self.start2 + self.id + self.length + self.flag + self.failvreCode
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
data = struct.pack('<B', self.start1)
|
||||||
|
data += struct.pack('<B', self.start2)
|
||||||
|
data += struct.pack('<H', self.id)
|
||||||
|
data += struct.pack('<H', self.length)
|
||||||
|
|
||||||
|
# 填充数据
|
||||||
|
data += struct.pack('<B', self.flag)
|
||||||
|
data += struct.pack('<B', self.failvreCode)
|
||||||
|
# 其他参数...
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.checkCode += data[i]
|
||||||
|
data += struct.pack('<I', self.checkCode)
|
||||||
|
return data
|
||||||
|
|
||||||
|
class msg_disHighVolBusFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x20
|
||||||
|
self.start2 = 0x20
|
||||||
|
self.id = 0x0005
|
||||||
|
self.length = 10
|
||||||
|
self.DCB1 = 0x00
|
||||||
|
self.DCB2 = 0x00
|
||||||
|
self.ZK1 = 0x00
|
||||||
|
self.ZK2 = 0x00
|
||||||
|
self.ZK3 = 0x00
|
||||||
|
self.ZK4 = 0x00
|
||||||
|
self.ZK5 = 0x00
|
||||||
|
self.ZK6 = 0x00
|
||||||
|
self.ZK7 = 0x00
|
||||||
|
self.ZK8 = 0x00
|
||||||
|
self.ZK9 = 0x00
|
||||||
|
self.ZK10 = 0x00
|
||||||
|
self.busInsulationLow = 0x00
|
||||||
|
self.busAInsulationHigh = 0x00
|
||||||
|
self.lostPower = 0x00
|
||||||
|
self.lostEmerPower = 0x00
|
||||||
|
self.powerBusVoltage = 0x00
|
||||||
|
self.dcDc5ModuleCurrent = 0x00
|
||||||
|
self.powerBusCurrent = 0x00
|
||||||
|
self.busbarAVoltage = 0x00
|
||||||
|
self.propulsionMotorControlBoxCurrent = 0x00
|
||||||
|
self.busbarACurrent = 0x00
|
||||||
|
self.lithiumBatteryGroupMeterCurrent = 0x00
|
||||||
|
self.bowHighVoltageDistributionBoxCurrent = 0x00
|
||||||
|
self.sternFTDevice45Current = 0x00
|
||||||
|
self.tyzReservedSwitchCurrent = 0x00
|
||||||
|
self.sternRudderSwitch1Current = 0x00
|
||||||
|
self.reservedCurrent1 = 0x00
|
||||||
|
self.sternRudderSwitch2Current = 0x00
|
||||||
|
self.reservedCurrent2 = 0x00
|
||||||
|
self.fbReservedSwitchCurrent = 0x00
|
||||||
|
self.reservedCurrent3 = 0x00
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
data = struct.pack('<B', self.start1)
|
||||||
|
data += struct.pack('<B', self.start2)
|
||||||
|
data += struct.pack('<H', self.id)
|
||||||
|
data += struct.pack('<H', self.length)
|
||||||
|
# 填充数据
|
||||||
|
data += struct.pack('<B', self.DCB1)
|
||||||
|
data += struct.pack('<B', self.DCB2)
|
||||||
|
data += struct.pack('<B', self.ZK1)
|
||||||
|
data += struct.pack('<B', self.ZK2)
|
||||||
|
data += struct.pack('<B', self.ZK3)
|
||||||
|
data += struct.pack('<B', self.ZK4)
|
||||||
|
data += struct.pack('<B', self.ZK5)
|
||||||
|
data += struct.pack('<B', self.ZK6)
|
||||||
|
data += struct.pack('<B', self.ZK7)
|
||||||
|
data += struct.pack('<B', self.ZK8)
|
||||||
|
data += struct.pack('<B', self.ZK9)
|
||||||
|
data += struct.pack('<B', self.ZK10)
|
||||||
|
data += struct.pack('<B', self.busInsulationLow)
|
||||||
|
data += struct.pack('<B', self.busAInsulationHigh)
|
||||||
|
data += struct.pack('<B', self.lostPower)
|
||||||
|
data += struct.pack('<B', self.lostEmerPower)
|
||||||
|
data += struct.pack('<H', self.powerBusVoltage)
|
||||||
|
data += struct.pack('<H', self.dcDc5ModuleCurrent)
|
||||||
|
data += struct.pack('<H', self.powerBusCurrent)
|
||||||
|
data += struct.pack('<H', self.busbarAVoltage)
|
||||||
|
data += struct.pack('<H', self.propulsionMotorControlBoxCurrent)
|
||||||
|
data += struct.pack('<H', self.busbarACurrent)
|
||||||
|
data += struct.pack('<H', self.lithiumBatteryGroupMeterCurrent)
|
||||||
|
data += struct.pack('<H', self.bowHighVoltageDistributionBoxCurrent)
|
||||||
|
data += struct.pack('<H', self.sternFTDevice45Current)
|
||||||
|
data += struct.pack('<H', self.tyzReservedSwitchCurrent)
|
||||||
|
data += struct.pack('<H', self.sternRudderSwitch1Current)
|
||||||
|
data += struct.pack('<H', self.reservedCurrent1)
|
||||||
|
data += struct.pack('<H', self.sternRudderSwitch2Current)
|
||||||
|
data += struct.pack('<H', self.reservedCurrent2)
|
||||||
|
data += struct.pack('<H', self.fbReservedSwitchCurrent)
|
||||||
|
data += struct.pack('<H', self.reservedCurrent3)
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.checkCode += data[i]
|
||||||
|
checkCode_L = self.checkCode & 0xFF
|
||||||
|
data += struct.pack('<B', checkCode_L)
|
||||||
|
return data
|
||||||
|
|
||||||
|
class msg_disHighAVolBusFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x20
|
||||||
|
self.start2 = 0x20
|
||||||
|
self.id = 0x0006
|
||||||
|
self.length = 10
|
||||||
|
self.bowFTDevice123CircuitBreaker = 0x00
|
||||||
|
self.actuatorCircuitBreaker = 0x00
|
||||||
|
self.mastSteeringGearControlBoxCircuitBreaker = 0x00
|
||||||
|
self.xczCircuitBreaker = 0x00
|
||||||
|
self.bowRudderControlBoxCircuitBreaker = 0x00
|
||||||
|
self.openWaterCoverStartCylinderCircuitBreaker = 0x00
|
||||||
|
self.instrumentPowerFailureSignal = 0x00
|
||||||
|
self.emergencyPowerFailureSignal = 0x00
|
||||||
|
self.waterIngressionAlarm = 0x00
|
||||||
|
self.busbarBVoltage = 0x0000
|
||||||
|
self.busbarBCurrent = 0x0000
|
||||||
|
self.bowFTDevice123Current = 0x0000
|
||||||
|
self.actuatorCurrent = 0x0000
|
||||||
|
self.mastSteeringGearControlBoxCurrent = 0x0000
|
||||||
|
self.xczCurrent = 0x0001
|
||||||
|
self.bowRudderControlBoxCurrent = 0x0000
|
||||||
|
self.openWaterCoverStartCylinderCurrent = 0x0000
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
data = struct.pack('<B', self.start1)
|
||||||
|
data += struct.pack('<B', self.start2)
|
||||||
|
data += struct.pack('<H', self.id)
|
||||||
|
data += struct.pack('<H', self.length)
|
||||||
|
# 填充数据
|
||||||
|
data += struct.pack('<B', self.bowFTDevice123CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.actuatorCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.mastSteeringGearControlBoxCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.xczCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.bowRudderControlBoxCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.openWaterCoverStartCylinderCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.instrumentPowerFailureSignal)
|
||||||
|
data += struct.pack('<B', self.emergencyPowerFailureSignal)
|
||||||
|
data += struct.pack('<B', self.waterIngressionAlarm)
|
||||||
|
data += struct.pack('<H', self.busbarBVoltage)
|
||||||
|
data += struct.pack('<H', self.busbarBCurrent)
|
||||||
|
data += struct.pack('<H', self.bowFTDevice123Current)
|
||||||
|
data += struct.pack('<H', self.actuatorCurrent)
|
||||||
|
data += struct.pack('<H', self.mastSteeringGearControlBoxCurrent)
|
||||||
|
data += struct.pack('<H', self.xczCurrent)
|
||||||
|
data += struct.pack('<H', self.bowRudderControlBoxCurrent)
|
||||||
|
data += struct.pack('<H', self.openWaterCoverStartCylinderCurrent)
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.checkCode += data[i]
|
||||||
|
checkCode_L = self.checkCode & 0xFF
|
||||||
|
data += struct.pack('<B', checkCode_L)
|
||||||
|
return data
|
||||||
|
|
||||||
|
class msg_disHighBVolBusFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x20
|
||||||
|
self.start2 = 0x20
|
||||||
|
self.id = 0x0007
|
||||||
|
self.length = 10
|
||||||
|
self.lithiumBatteryGroupInstrumentCircuitBreaker = 0x00
|
||||||
|
self.bowLowVoltageDistributionBoxCircuitBreaker = 0x00
|
||||||
|
self.unit4InstrumentDC48VCircuitBreaker = 0x00
|
||||||
|
self.dcC1DCDistributionPanelCircuitBreaker = 0x00
|
||||||
|
self.reservedCircuitBreaker1 = 0x00
|
||||||
|
self.reservedCircuitBreaker2 = 0x00
|
||||||
|
self.emergencyLithiumBatteryGroup2CircuitBreaker = 0x00
|
||||||
|
self.instrumentPowerFailureSignal = 0x00
|
||||||
|
self.emergencyPowerFailureSignal = 0x00
|
||||||
|
self.instrumentBusbarInsulationLow = 0x00
|
||||||
|
self.instrumentBusbarVoltage = 0x0000
|
||||||
|
self.bowLowVoltageDistributionBoxCurrent = 0x0000
|
||||||
|
self.dcC1InstrumentDC48VCurrent = 0x0000
|
||||||
|
self.reservedCurrent1 = 0x0000
|
||||||
|
self.emergencyLithiumBatteryGroup2Current = 0x0000
|
||||||
|
self.lithiumBatteryGroupInstrumentCurrent = 0x0000
|
||||||
|
self.unit4InstrumentDC48VCurrent = 0x0000
|
||||||
|
self.reservedCurrent2 = 0x0000
|
||||||
|
self.emergency2BusbarVoltage = 0x0000
|
||||||
|
self.compositeEnergyManagementSystemEmergencyDC48VCurrent = 0x0000
|
||||||
|
self.fuelCellSecuritySystemEmergencyDC48VCurrent = 0x0000
|
||||||
|
self.plcControlPowerCurrent = 0x0000
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
data = struct.pack('<B', self.start1)
|
||||||
|
data += struct.pack('<B', self.start2)
|
||||||
|
data += struct.pack('<H', self.id)
|
||||||
|
data += struct.pack('<H', self.length)
|
||||||
|
# 填充数据
|
||||||
|
data += struct.pack('<B', self.lithiumBatteryGroupInstrumentCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.bowLowVoltageDistributionBoxCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.unit4InstrumentDC48VCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.dcC1DCDistributionPanelCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.reservedCircuitBreaker1)
|
||||||
|
data += struct.pack('<B', self.reservedCircuitBreaker2)
|
||||||
|
data += struct.pack('<B', self.emergencyLithiumBatteryGroup2CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.instrumentPowerFailureSignal)
|
||||||
|
data += struct.pack('<B', self.emergencyPowerFailureSignal)
|
||||||
|
data += struct.pack('<B', self.instrumentBusbarInsulationLow)
|
||||||
|
data += struct.pack('<H', self.instrumentBusbarVoltage)
|
||||||
|
data += struct.pack('<H', self.bowLowVoltageDistributionBoxCurrent)
|
||||||
|
data += struct.pack('<H', self.dcC1InstrumentDC48VCurrent)
|
||||||
|
data += struct.pack('<H', self.reservedCurrent1)
|
||||||
|
data += struct.pack('<H', self.emergencyLithiumBatteryGroup2Current)
|
||||||
|
data += struct.pack('<H', self.lithiumBatteryGroupInstrumentCurrent)
|
||||||
|
data += struct.pack('<H', self.unit4InstrumentDC48VCurrent)
|
||||||
|
data += struct.pack('<H', self.reservedCurrent2)
|
||||||
|
data += struct.pack('<H', self.emergency2BusbarVoltage)
|
||||||
|
data += struct.pack('<H', self.compositeEnergyManagementSystemEmergencyDC48VCurrent)
|
||||||
|
data += struct.pack('<H', self.fuelCellSecuritySystemEmergencyDC48VCurrent)
|
||||||
|
data += struct.pack('<H', self.plcControlPowerCurrent)
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.checkCode += data[i]
|
||||||
|
checkCode_L = self.checkCode & 0xFF
|
||||||
|
data += struct.pack('<B', checkCode_L)
|
||||||
|
return data
|
||||||
|
|
||||||
|
class msg_disLowBusFbMsg:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = 0x20
|
||||||
|
self.start2 = 0x20
|
||||||
|
self.id = 0x0008
|
||||||
|
self.length = 10
|
||||||
|
self.unit1CircuitBreaker = 0x00
|
||||||
|
self.unit2CircuitBreaker = 0x00
|
||||||
|
self.unit3CircuitBreaker = 0x00
|
||||||
|
self.unit5CircuitBreaker = 0x00
|
||||||
|
self.bowPZDeviceCircuitBreaker = 0x00
|
||||||
|
self.reservedCircuitBreaker1 = 0x00
|
||||||
|
self.reservedCircuitBreaker2 = 0x00
|
||||||
|
self.emergencyLithiumBatteryGroup1CircuitBreaker = 0x00
|
||||||
|
self.powerFailureSignal = 0x00
|
||||||
|
self.waterIngressionAlarm = 0x00
|
||||||
|
self.instrumentBusbarVoltage = 0x0000
|
||||||
|
self.instrumentBusbarCurrent = 0x0000
|
||||||
|
self.unit1Current = 0x0000
|
||||||
|
self.unit2Current = 0x0000
|
||||||
|
self.unit3Current = 0x0000
|
||||||
|
self.unit5Current = 0x0000
|
||||||
|
self.bowPZDeviceCurrent = 0x0000
|
||||||
|
self.emergencyLithiumBatteryGroup1Current = 0x0000
|
||||||
|
self.emergency1BusbarVoltage = 0x0000
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
# 初始化数据
|
||||||
|
self.checkCode = 0x0000
|
||||||
|
data = struct.pack('<B', self.start1)
|
||||||
|
data += struct.pack('<B', self.start2)
|
||||||
|
data += struct.pack('<H', self.id)
|
||||||
|
data += struct.pack('<H', self.length)
|
||||||
|
# 填充数据
|
||||||
|
data += struct.pack('<B', self.unit1CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.unit2CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.unit3CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.unit5CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.bowPZDeviceCircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.reservedCircuitBreaker1)
|
||||||
|
data += struct.pack('<B', self.reservedCircuitBreaker2)
|
||||||
|
data += struct.pack('<B', self.emergencyLithiumBatteryGroup1CircuitBreaker)
|
||||||
|
data += struct.pack('<B', self.powerFailureSignal)
|
||||||
|
data += struct.pack('<B', self.waterIngressionAlarm)
|
||||||
|
data += struct.pack('<H', self.instrumentBusbarVoltage)
|
||||||
|
data += struct.pack('<H', self.instrumentBusbarCurrent)
|
||||||
|
data += struct.pack('<H', self.unit1Current)
|
||||||
|
data += struct.pack('<H', self.unit2Current)
|
||||||
|
data += struct.pack('<H', self.unit3Current)
|
||||||
|
data += struct.pack('<H', self.unit5Current)
|
||||||
|
data += struct.pack('<H', self.bowPZDeviceCurrent)
|
||||||
|
data += struct.pack('<H', self.emergencyLithiumBatteryGroup1Current)
|
||||||
|
data += struct.pack('<H', self.emergency1BusbarVoltage)
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.checkCode += data[i]
|
||||||
|
checkCode_L = self.checkCode & 0xFF
|
||||||
|
data += struct.pack('<B', checkCode_L)
|
||||||
|
return data
|
||||||
|
|
||||||
|
class msg_disHVBCmd:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = None
|
||||||
|
self.start2 = None
|
||||||
|
self.id = None
|
||||||
|
self.length = None
|
||||||
|
self.fuelCellCircuitBreaker = None
|
||||||
|
self.powerLithiumBatteryCircuitBreaker = None
|
||||||
|
self.propulsionMotorCircuitBreaker = None
|
||||||
|
self.lithiumBatteryGroupInstrumentCircuitBreaker = None
|
||||||
|
self.dcDc5ModuleCircuitBreaker = None
|
||||||
|
self.bowHighVoltageDistributionBoxCircuitBreaker = None
|
||||||
|
self.sternFTDevice45CircuitBreaker = None
|
||||||
|
self.sternRudderSwitch1CircuitBreaker = None
|
||||||
|
self.sternRudderSwitch2CircuitBreaker = None
|
||||||
|
self.fbReservedCircuitBreaker = None
|
||||||
|
self.tyzReservedCircuitBreaker = None
|
||||||
|
self.reservedCircuitBreaker = None
|
||||||
|
self.inputWater = None
|
||||||
|
self.outputWater = None
|
||||||
|
self.dcdc5dcdc5Module = None
|
||||||
|
self.checkCode = None
|
||||||
|
|
||||||
|
def unpack(self,data):
|
||||||
|
try:
|
||||||
|
unpacked_data = struct.unpack('<BBHHBBBBBBBBBBBBBBBB',data)
|
||||||
|
self.start1 = unpacked_data[0]
|
||||||
|
self.start2 = unpacked_data[1]
|
||||||
|
self.id = unpacked_data[2]
|
||||||
|
self.length = unpacked_data[3]
|
||||||
|
self.fuelCellCircuitBreaker = unpacked_data[4]
|
||||||
|
self.powerLithiumBatteryCircuitBreaker = unpacked_data[5]
|
||||||
|
self.propulsionMotorCircuitBreaker = unpacked_data[6]
|
||||||
|
self.lithiumBatteryGroupInstrumentCircuitBreaker = unpacked_data[7]
|
||||||
|
self.dcDc5ModuleCircuitBreaker = unpacked_data[8]
|
||||||
|
self.bowHighVoltageDistributionBoxCircuitBreaker = unpacked_data[9]
|
||||||
|
self.sternFTDevice45CircuitBreaker = unpacked_data[10]
|
||||||
|
self.sternRudderSwitch1CircuitBreaker = unpacked_data[11]
|
||||||
|
self.sternRudderSwitch2CircuitBreaker = unpacked_data[12]
|
||||||
|
self.fbReservedCircuitBreaker = unpacked_data[13]
|
||||||
|
self.tyzReservedCircuitBreaker = unpacked_data[14]
|
||||||
|
self.reservedCircuitBreaker = unpacked_data[15]
|
||||||
|
self.inputWater = unpacked_data[16]
|
||||||
|
self.outputWater = unpacked_data[17]
|
||||||
|
self.dcdc5dcdc5Module = unpacked_data[18]
|
||||||
|
self.checkCode = unpacked_data[19]
|
||||||
|
except struct.error as e:
|
||||||
|
print(f"Error unpacking data: msg_disHVBCmd {e}")
|
||||||
|
|
||||||
|
|
||||||
|
# unsigned char bowFTDevice123CircuitBreaker;
|
||||||
|
# unsigned char actuatorCircuitBreaker;
|
||||||
|
# unsigned char mastSteeringGearControlBoxCircuitBreaker;
|
||||||
|
# unsigned char xczCircuitBreaker;
|
||||||
|
# unsigned char bowRudderControlBoxCircuitBreaker;
|
||||||
|
# unsigned char openWaterCoverStartCylinderCircuitBreaker;
|
||||||
|
class msg_disHVBACmd:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = None
|
||||||
|
self.start2 = None
|
||||||
|
self.id = None
|
||||||
|
self.length = None
|
||||||
|
self.bowFTDevice123CircuitBreaker = None
|
||||||
|
self.actuatorCircuitBreaker = None
|
||||||
|
self.mastSteeringGearControlBoxCircuitBreaker = None
|
||||||
|
self.xczCircuitBreaker = None
|
||||||
|
self.bowRudderControlBoxCircuitBreaker = None
|
||||||
|
self.openWaterCoverStartCylinderCircuitBreaker = None
|
||||||
|
self.checkCode = None
|
||||||
|
def unpack(self,data):
|
||||||
|
try:
|
||||||
|
unpacked_data = struct.unpack('<BBHHBBBBBBB',data)
|
||||||
|
self.start1 = unpacked_data[0]
|
||||||
|
self.start2 = unpacked_data[1]
|
||||||
|
self.id = unpacked_data[2]
|
||||||
|
self.length = unpacked_data[3]
|
||||||
|
self.bowFTDevice123CircuitBreaker = unpacked_data[4]
|
||||||
|
self.actuatorCircuitBreaker = unpacked_data[5]
|
||||||
|
self.mastSteeringGearControlBoxCircuitBreaker = unpacked_data[6]
|
||||||
|
self.xczCircuitBreaker = unpacked_data[7]
|
||||||
|
self.bowRudderControlBoxCircuitBreaker = unpacked_data[8]
|
||||||
|
self.openWaterCoverStartCylinderCircuitBreaker = unpacked_data[9]
|
||||||
|
self.checkCode = unpacked_data[10]
|
||||||
|
except struct.error as e:
|
||||||
|
print(f"Error unpacking data: msg_disHVBACmd {e}")
|
||||||
|
# unsigned char lithiumBatteryGroupInstrumentCircuitBreaker;
|
||||||
|
# unsigned char bowLowVoltageDistributionBoxCircuitBreaker;
|
||||||
|
# unsigned char unit4InstrumentDC48VCircuitBreaker;
|
||||||
|
# unsigned char dcC1DCDistributionPanelCircuitBreaker;
|
||||||
|
# unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
|
||||||
|
# unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
|
||||||
|
# unsigned char emergencyLithiumBatteryGroup2CircuitBreaker;
|
||||||
|
class msg_disHVBBCmd:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = None
|
||||||
|
self.start2 = None
|
||||||
|
self.id = None
|
||||||
|
self.length = None
|
||||||
|
self.lithiumBatteryGroupInstrumentCircuitBreaker = None
|
||||||
|
self.bowLowVoltageDistributionBoxCircuitBreaker = None
|
||||||
|
self.unit4InstrumentDC48VCircuitBreaker = None
|
||||||
|
self.dcC1DCDistributionPanelCircuitBreaker = None
|
||||||
|
self.reservedCircuitBreaker1 = None
|
||||||
|
self.reservedCircuitBreaker2 = None
|
||||||
|
self.emergencyLithiumBatteryGroup2CircuitBreaker = None
|
||||||
|
self.checkCode = None
|
||||||
|
def unpack(self,data):
|
||||||
|
try:
|
||||||
|
unpacked_data = struct.unpack('<BBHHBBBBBBBB',data)
|
||||||
|
self.start1 = unpacked_data[0]
|
||||||
|
self.start2 = unpacked_data[1]
|
||||||
|
self.id = unpacked_data[2]
|
||||||
|
self.length = unpacked_data[3]
|
||||||
|
self.lithiumBatteryGroupInstrumentCircuitBreaker = unpacked_data[4]
|
||||||
|
self.bowLowVoltageDistributionBoxCircuitBreaker = unpacked_data[5]
|
||||||
|
self.unit4InstrumentDC48VCircuitBreaker = unpacked_data[6]
|
||||||
|
self.dcC1DCDistributionPanelCircuitBreaker = unpacked_data[7]
|
||||||
|
self.reservedCircuitBreaker1 = unpacked_data[8]
|
||||||
|
self.reservedCircuitBreaker2 = unpacked_data[9]
|
||||||
|
self.emergencyLithiumBatteryGroup2CircuitBreaker = unpacked_data[10]
|
||||||
|
self.checkCode = unpacked_data[11]
|
||||||
|
except struct.error as e:
|
||||||
|
print(f"Error unpacking data: msg_disHVBBCmd {e}")
|
||||||
|
|
||||||
|
|
||||||
|
# unsigned char unit1CircuitBreaker;
|
||||||
|
# unsigned char unit2CircuitBreaker;
|
||||||
|
# unsigned char unit3CircuitBreaker;
|
||||||
|
# unsigned char unit5CircuitBreaker;
|
||||||
|
# unsigned char bowPZDeviceCircuitBreaker;
|
||||||
|
# unsigned char reservedCircuitBreaker1; // 为了区分,添加了数字后缀
|
||||||
|
# unsigned char reservedCircuitBreaker2; // 为了区分,添加了数字后缀
|
||||||
|
# unsigned char emergencyLithiumBatteryGroup1CircuitBreaker;
|
||||||
|
|
||||||
|
class msg_disLVBCmd:
|
||||||
|
def __init__(self):
|
||||||
|
self.start1 = None
|
||||||
|
self.start2 = None
|
||||||
|
self.id = None
|
||||||
|
self.length = None
|
||||||
|
self.unit1CircuitBreaker = None
|
||||||
|
self.unit2CircuitBreaker = None
|
||||||
|
self.unit3CircuitBreaker = None
|
||||||
|
self.unit5CircuitBreaker = None
|
||||||
|
self.bowPZDeviceCircuitBreaker = None
|
||||||
|
self.reservedCircuitBreaker1 = None
|
||||||
|
self.reservedCircuitBreaker2 = None
|
||||||
|
self.emergencyLithiumBatteryGroup1CircuitBreaker = None
|
||||||
|
self.checkCode = None
|
||||||
|
def unpack(self,data):
|
||||||
|
try:
|
||||||
|
unpacked_data = struct.unpack('<BBHHBBBBBBBBB',data)
|
||||||
|
self.start1 = unpacked_data[0]
|
||||||
|
self.start2 = unpacked_data[1]
|
||||||
|
self.id = unpacked_data[2]
|
||||||
|
self.length = unpacked_data[3]
|
||||||
|
self.unit1CircuitBreaker = unpacked_data[4]
|
||||||
|
self.unit2CircuitBreaker = unpacked_data[5]
|
||||||
|
self.unit3CircuitBreaker = unpacked_data[6]
|
||||||
|
self.unit5CircuitBreaker = unpacked_data[7]
|
||||||
|
self.bowPZDeviceCircuitBreaker = unpacked_data[8]
|
||||||
|
self.reservedCircuitBreaker1 = unpacked_data[9]
|
||||||
|
self.reservedCircuitBreaker2 = unpacked_data[10]
|
||||||
|
self.emergencyLithiumBatteryGroup1CircuitBreaker = unpacked_data[11]
|
||||||
|
self.checkCode = unpacked_data[12]
|
||||||
|
except struct.error as e:
|
||||||
|
print(f"Error unpacking data: msg_disLVBCmd {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# msg = msg_CcuStateFbMsg()
|
||||||
|
msg = msg_disHVBACmd()
|
||||||
|
# msg.pack()
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#include "../src/pPowerManger/udpComm.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
TEST_CASE("udpComm getDate function test", "[udpComm]") {
|
||||||
|
udpComm comm;
|
||||||
|
|
||||||
|
unsigned short year;
|
||||||
|
unsigned char month, day, hour, minute, second, milliseconds;
|
||||||
|
|
||||||
|
bool result = comm.getDate(year, month, day, hour, minute, second, milliseconds);
|
||||||
|
|
||||||
|
// 输出日期和时间信息
|
||||||
|
std::cout << "Year: " << year << std::endl;
|
||||||
|
std::cout << "Month: " << static_cast<int>(month) << std::endl;
|
||||||
|
std::cout << "Day: " << static_cast<int>(day) << std::endl;
|
||||||
|
std::cout << "Hour: " << static_cast<int>(hour) << std::endl;
|
||||||
|
std::cout << "Minute: " << static_cast<int>(minute) << std::endl;
|
||||||
|
std::cout << "Second: " << static_cast<int>(second) << std::endl;
|
||||||
|
std::cout << "Milliseconds: " << static_cast<int>(milliseconds) << std::endl;
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(year >= 2023);
|
||||||
|
REQUIRE(year <= 2030);
|
||||||
|
REQUIRE(month >= 1);
|
||||||
|
REQUIRE(month <= 12);
|
||||||
|
REQUIRE(day >= 1);
|
||||||
|
REQUIRE(day <= 31);
|
||||||
|
REQUIRE(hour >= 0);
|
||||||
|
REQUIRE(hour <= 23);
|
||||||
|
REQUIRE(minute >= 0);
|
||||||
|
REQUIRE(minute <= 59);
|
||||||
|
REQUIRE(second >= 0);
|
||||||
|
REQUIRE(second <= 59);
|
||||||
|
REQUIRE(milliseconds >= 0);
|
||||||
|
REQUIRE(milliseconds <= 999);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user