Author SHA1 Message Date
zjk 811fbf2924 完善功能 2025-04-02 21:31:51 +08:00
zjk 341630f547 增加了moos变量显示的webui功能 2025-03-04 11:17:16 +08:00
zjk 16cffa296a 优化了web界面,下载功能等 2025-03-02 14:35:21 +08:00
zjk 0fbe95bc45 增加了notify的方法 2025-02-27 22:42:57 +08:00
zjk 1e295aeeb3 优化了实现,采用websocket 2025-02-27 22:37:21 +08:00
zjk 9cc3140651 完善了部分逻辑,优化网页 2025-02-27 20:27:33 +08:00
zjk 02d54a585a 优化了前端文件的机构 2025-02-27 10:56:24 +08:00
zjk 115ee57b14 优化了主页的读取方式 2025-02-27 10:00:42 +08:00
zjk 4ee5cbfb86 增加了次级配电状态,设备状态表,设备上电指令的订阅\解析\发布等功能 2025-02-20 23:15:37 +08:00
zjk d89a1936ee 增加了MOOSDB消息的订阅和处理函数 2025-02-19 22:03:27 +08:00
zjk 75575f935c 增加了交互变量的状态,增加了设备状态和设备表的json解析和生成函数,修复了设备表类和通信协议中不同的地方 2025-02-19 17:18:39 +08:00
zjk 5b9934c6f2 与MOOSDB的交互消息的Key 2025-02-19 09:00:49 +08:00
zjk 14f7890d77 增加了解析上位机指令的功能 2025-02-18 23:01:29 +08:00
zjk 7dac85505b 为操作指令增加了数据库写入代码 2025-02-18 18:46:17 +08:00
zjk a179789b3f 增加了udp的测试代码,增加了时间获取函数,完善了ccu发送指令的函数 2025-02-18 16:57:11 +08:00
zjk 2599050c1f 增加了配电和ccu数据的数据库存储功能 2025-02-18 13:09:47 +08:00
zjk 1aa46629a7 增加了配电控制器操作代码 2025-02-17 21:57:45 +08:00
zjk 59202d20aa Merge branch 'main' of https://gitea.zhaojingkui.xyz/zjk/H100PowerManger 2025-02-13 22:28:52 +08:00
zjk 845360c46b 增加了driver文件,并且删除了编译过程文件 2025-02-13 22:26:37 +08:00
zjk df8a23fd46 增加了driver文件 2025-02-13 22:24:17 +08:00
zjk 6d00ecfbf2 完善了数据库功能,将udp单独编译为一个静态库 2025-02-13 22:00:15 +08:00
zjk 25b4e0d688 删除了不使用的文件 2025-02-13 15:44:21 +08:00
zjk 734226a33a 增加了下载功能 2025-02-13 12:58:13 +08:00
zjk f83f737a79 增加了数据库下载的功能 2025-02-13 09:34:12 +08:00
zjk ed0d7f7fe0 为状态机增加了线程运行,并补充了数据库 2025-02-10 21:30:53 +08:00
zjk 59faa14afb 增加了数据库及测试程序 2025-02-10 16:37:22 +08:00
zjk e072f2b9d4 优化了测试界面 2025-02-08 15:12:08 +08:00
zjk 6f5de4b614 增加了新的调试界面,优化了一些功能 2025-02-06 12:01:18 +08:00
zjk c824caa27e 优化了disSys的代码,增加了16进制显示的功能 2025-01-21 21:21:58 +08:00
zjk 0d5ffb31ce 更够实时更新弹窗的数据 2025-01-21 20:12:38 +08:00
zjk 57dd677271 增加了状态显示弹窗 2025-01-21 19:34:23 +08:00
zjk d2961cf005 使用状态机增加了初始状态和故障状态,编写了gui调试程序 2025-01-02 18:28:47 +08:00
zjk d9d715326a 修复了事件跳转状态跳转的问题,但是目前事件跳转仍然不完善,返回使用指针跳转的状态 2024-12-02 23:21:55 +08:00
zjk ec595ac1dc 增加了状态机代码 2024-11-26 18:27:08 +08:00
zjk 6374e60b91 修复了UDP通信的BUG并优化了相关代码,增加了json报告功能 2024-11-23 17:28:51 +08:00
zjk abd91d0e88 优化了UDP通信代码,增加了消息的时间戳 2024-11-21 18:13:26 +08:00
zjk eb2877f03f 优化udp通信代码,增加配电系统通信解析,增加能源系统状态定义 2024-11-20 18:38:45 +08:00
zjk 4693ce2619 增加了通信协议解析的功能 2024-11-19 09:58:31 +08:00
zjk 590662d7a5 增加了消息读取的功能,并且添加了python测试脚本 2024-11-14 18:22:58 +08:00
zjk e2bfa98754 增加了UDP通信和部分复合管控交互消息定义 2024-10-24 18:15:56 +08:00
zjk dfd13848ef 创建工程并增加了json支持 2024-10-22 17:28:15 +08:00
zjk 985b667200 Initial commit 2024-10-22 14:17:42 +08:00
67 changed files with 12249 additions and 38 deletions
+242
View File
@@ -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
+85
View File
@@ -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
View File
@@ -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 )
+3
View File
@@ -0,0 +1,3 @@
# H100PowerManger
H100 能源管理程序
+8
View File
@@ -0,0 +1,8 @@
//------------------------------------------------
// pPowerManger config block
ProcessConfig = pPowerManger
{
AppTick = 5
CommsTick = 4
}
+379
View File
@@ -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">&times;</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);
}
+1058
View File
File diff suppressed because it is too large Load Diff
+166
View File
@@ -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">&times;</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>
Executable
+46
View File
@@ -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}
Executable
+15
View File
@@ -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 {} \;
+47
View File
@@ -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": 0,
"HVBBCCUCur_uint16": 0,
"HVBBFCSSecurSysCur_uint16": 0,
"HVBBbatInsCur_uint16": 0,
"HVBBbowLowVolDisBoxCur_uint16": 0,
"HVBBdcC1InsCur_uint16": 0,
"HVBBemer2BusVol_uint16": 0,
"HVBBemerBatCur_uint16": 0,
"HVBBinsBusVol_uint16": 0,
"HVBBplcCur_uint16": 0,
"HVBBreservedCur1_uint16": 0,
"HVBBreservedCur2_uint16": 0,
"HVBBunit4Cur_uint16": 0,
"HVBFTDev45Cur_uint16": 0,
"HVBbatGroupCur_uint16": 0,
"HVBbowHVolDisBoxCur_uint16": 0,
"HVBbusACur_uint16": 0,
"HVBbusAVol_uint16": 0,
"HVBdcDc5Cur_uint16": 0,
"HVBfbCur_uint16": 0,
"HVBmotorCur_uint16": 0,
"HVBpowerBusCur_uint16": 0,
"HVBpowerBusVol_uint16": 0,
"HVBreservedCur1_uint16": 0,
"HVBreservedCur2_uint16": 0,
"HVBreservedCur3_uint16": 0,
"HVBsternRud1Cur_uint16": 0,
"HVBsternRud2Cur_uint16": 0,
"HVBtyzCur_uint16": 0,
"LVBBbowPZDevCur_uint16": 0,
"LVBBemerBatCur_uint16": 0,
"LVBBemerBusVol_uint16": 0,
"LVBBinsBusCur_uint16": 0,
"LVBBunit1Cur_uint16": 0,
"LVBBunit2Cur_uint16": 0,
"LVBBunit3Cur_uint16": 0,
"LVBBunit5Cur_uint16": 0,
"LVBinsBusVol_uint16": 0
}
+10
View File
@@ -0,0 +1,10 @@
{
"HVolABusBreaker_unit16": 0,
"HVolBBusBreaker_unit16": 0,
"HVolBusBreaker_uint16": 0,
"LVolBusBreaker_uint16": 0,
"faultCode_array":
[
0
]
}
+30
View File
@@ -0,0 +1,30 @@
{
"backpressure1_fp32": 0.0,
"backpressure2_fp32": 0.0,
"ch4oConcent1_fp32": 0.0,
"ch4oConcent2_fp32": 0.0,
"ch4o_fp32": 0.0,
"excTemp_fp32": 0.0,
"faultCode1_uint16": 0,
"faultCode2_uint16": 0,
"faultCode3_uint16": 0,
"fcuCurIns_fp32": 0.0,
"fcuCurPower_fp32": 0.0,
"fcuCur_fp32": 0.0,
"fcuFaultLeve_uint8": 0,
"fcuOutIns_fp32": 0.0,
"fcuOutPower_fp32": 0.0,
"fcuState_uint8": 0,
"fcuVolIns_fp32": 0.0,
"fcuVolPower_fp32": 0.0,
"fcuVol_fp32": 0.0,
"flameDet_uint8": 0,
"h2Concent1_fp32": 0.0,
"h2Concent2_fp32": 0.0,
"o2Concent1_fp32": 0.0,
"o2Concent2_fp32": 0.0,
"o2Level_fp32": 0.0,
"o2_fp32": 0.0,
"powLimit_fp32": 0.0,
"powerGen_fp32": 0.0
}
+38
View File
@@ -0,0 +1,38 @@
{
"fcuCurToInsLimit1_uint8": 0,
"fcuCurToinsLimit2_uint8": 0,
"insBatCurElect_uint16": 0,
"insBatLimit_uint16": 0,
"insBatSoc_uint8": 0,
"insBatTotalElect_uint16": 0,
"insChargeState_uint8": 0,
"insCurSocHold1_uint8": 0,
"insCurSocHold2_uint8": 0,
"insCurSocHold3_uint8": 0,
"insCurrent_uint16": 0,
"insLinkVol_uint16": 0,
"insNegRelayState_uint8": 0,
"insNegRes_uint16": 0,
"insPackVol_uint16": 0,
"insPosRelayState_uint8": 0,
"insPosRes_uint16": 0,
"insfaultCode_uint8": 0,
"powBatCurElect_uint16": 0,
"powBatSoc_uint8": 0,
"powBatTotalElect_uint16": 0,
"powChargeState_uint8": 0,
"powCurSocHold1_uint8": 0,
"powCurSocHold2_uint8": 0,
"powCurSocHold3_uint8": 0,
"powCurToInsLimit1_uint8": 0,
"powCurToinsLimit2_uint8": 0,
"powCur_uint16": 0,
"powLinkVol_uint16": 0,
"powNegRelayState_uint8": 0,
"powNegRes_uint16": 0,
"powPosRelayState_uint8": 0,
"powPosRes_uint16": 0,
"powerBatLimit_uint16": 0,
"powerPackVol_uint16": 0,
"powfaultCode_uint8": 0
}
+12
View File
@@ -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
}
+5
View File
@@ -0,0 +1,5 @@
{
"powerCMD":0,
"modCMD":0,
"workCMD":0
}
+64
View File
@@ -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
}
+5
View File
@@ -0,0 +1,5 @@
{
"powerCMD":0,
"modCMD":0,
"workCMD":0
}
-20
View File
@@ -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>
+11
View File
@@ -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
+33
View File
@@ -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
}
+159
View File
@@ -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
}
+41
View File
@@ -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
}
+54
View File
@@ -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
}
+401
View File
@@ -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"
+5
View File
@@ -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.
+24
View File
@@ -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
##############################################################################
+37
View File
@@ -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)
+230
View File
@@ -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;
}
+170
View File
@@ -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_)
+305
View File
@@ -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;
}
+72
View File
@@ -0,0 +1,72 @@
#--------------------------------------------------------
# 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
PowerManger.cpp
PowerManger_Info.cpp
udpComm.cpp
fsm.cpp
main.cpp
SQLiteDB.cpp
driver.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
fsm.cpp)
SET(DRIVER_SRC
driver.cpp)
SET(POWERMANGE_SRC
PowerManger.cpp
PowerManger_Info.cpp
udpComm.cpp
fsm.cpp
SQLiteDB.cpp
driver.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})
File diff suppressed because it is too large Load Diff
+188
View File
@@ -0,0 +1,188 @@
/*
* @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 "fsm.h"
#include "SQLiteDB.h"
#include "driver.h"
#define VAR_TO_STR(var) #var
#define IPORT 5000
#define CCUPORT 5001
#define CCUHOST "127.0.0.1"
#define MAX_UDP_PKT_SIZE 65535
#define SKEW_TOLERANCE 5
//能源管理反馈的消息
#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"
//控制消息
//TODO:实现上位机交互控制功能
#define DB_TO_PM_MSCMD "uPower_sysState_cmd"
#define DB_TO_PM_EQUIPMENTCMD "uPower_equState_cmd"
#define DB_TO_PM_SUBDISSTATE "uDevice_secdistState_st"
class PowerManger : public AppCastingMOOSApp
{
public:
PowerManger();
~PowerManger();
public:
bool ListenLoopUDP();
bool FsmLoop();
protected: // Standard MOOSApp functions to overload
bool OnNewMail(MOOSMSG_LIST &NewMail);
bool Iterate();
bool OnConnectToServer();
bool OnStartUp();
bool buildReport();
void registerVariables();
protected:
void updateTime(){m_current_time = MOOSTime();}
bool IsSkewed(double dfTimeNow, double * pdfSkew = NULL);
string getTypeName(const string typeName);
bool inline saveStringToJsonFile(const string &strJson, const string &strFileName);
//数据库
SQLiteDB* m_db;
bool writeDataToDB();
//通信状态变量及操作函数
XPCUdpSocket* setUdpScoket(long lPort);
bool updatePmState();
bool updateConnectState();
int connectState;
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;
protected:
//===========================交互状态变量==================================
Driver m_driver; //设备驱动
pmState m_pmCurrentState; //能源系统的当前状态
disSysBreakerList m_currentDisBreakerState; //配电断路器状态
disSysBreakerList m_targetDisBreakerState;
DriverTable m_currentDriverState;
DriverTable m_MSDriverCmd;
DriverTable m_subDisSysCmd;
DriverTable m_subDisSysState;
//===========================================================================
//系统运行状态
unsigned char workCondition;
unsigned char currentMod;
unsigned char powerState;
unsigned char falutLevel;
vector<unsigned int> faultCode;
unsigned int soc;
unsigned int sustainableTime;
// 配电和CCU的反馈状态
msg_CcuStateFbMsg m_CcuCurrentState;
msg_disHighVolBusFbMsg m_disHighVolBusCurrentState;
msg_disHighAVolBusFbMsg m_disHighAVolBusCurrentState;
msg_disHighBVolBusFbMsg m_disHighBVolBusCurrentState;
msg_disLowBusFbMsg m_disLowBusState;
//下位机操作函数
ccuColCmd m_CcuColCmd;
void disSysOption();
void ccuOption();
char getBreakerOption(char cmd);
void initControlCmd();
//上位机操作函数
MSControlCmd m_msCmd;
bool buildPowerSysReport();
bool getMsCmdFromJson(MSControlCmd &cmd,const string &strJson);
private:
udpComm m_udpComm;
XPCUdpSocket *m_pCcuUdpComm;
CMOOSThread m_ListenThread;
CMOOSThread m_FsmThread;
long m_lPort;
unsigned int m_nReceiveBufferSizeKB;
unsigned int m_nSendBufferSizeKB;
double m_current_time;
unsigned int m_faultNum;
unsigned int m_ticker;
public:
//===========================状态机实现==============================================
void printState(FSM_State st, string desp);
bool FSM_RUN_IS_OK = true;
StateData m_stateData;
FSM_State m_pmState; //当前状态
string m_pmEvent;
FSM m_fsm;
//初始化状态
FSM_State m_Inite_s1;
static int handleInite_s1(FSM_State &fsm, void* pData);
//待机状态
FSM_State m_Standby_s2;
static int handleStandby_s2(FSM_State &fsm, void* pData);
//岸基备航
// FSM_State m_ShoreReady_s3;
//水中备航
//自动工况
//故障处理
FSM_State m_Fault_s99;
static int handleFault_s99(FSM_State &fsm, void* pData);
//======================================================================================
int checkError();
bool shutdown();
bool powerOn();
bool powerOff();
};
#endif
+115
View File
@@ -0,0 +1,115 @@
/****************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: PowerManger_Info.cpp */
/* DATE: December 29th, 1963 */
/****************************************************************/
#include <cstdlib>
#include <iostream>
#include "PowerManger_Info.h"
#include "ColorParse.h"
#include "ReleaseInfo.h"
using namespace std;
//----------------------------------------------------------------
// Procedure: showSynopsis
void showSynopsis()
{
blk("SYNOPSIS: ");
blk("------------------------------------ ");
blk(" The pPowerManger application is used for ");
blk(" ");
blk(" ");
blk(" ");
blk(" ");
}
//----------------------------------------------------------------
// Procedure: showHelpAndExit
void showHelpAndExit()
{
blk(" ");
blu("=============================================================== ");
blu("Usage: pPowerManger file.moos [OPTIONS] ");
blu("=============================================================== ");
blk(" ");
showSynopsis();
blk(" ");
blk("Options: ");
mag(" --alias","=<ProcessName> ");
blk(" Launch pPowerManger with the given process name ");
blk(" rather than pPowerManger. ");
mag(" --example, -e ");
blk(" Display example MOOS configuration block. ");
mag(" --help, -h ");
blk(" Display this help message. ");
mag(" --interface, -i ");
blk(" Display MOOS publications and subscriptions. ");
mag(" --version,-v ");
blk(" Display the release version of pPowerManger. ");
blk(" ");
blk("Note: If argv[2] does not otherwise match a known option, ");
blk(" then it will be interpreted as a run alias. This is ");
blk(" to support pAntler launching conventions. ");
blk(" ");
exit(0);
}
//----------------------------------------------------------------
// Procedure: showExampleConfigAndExit
void showExampleConfigAndExit()
{
blk(" ");
blu("=============================================================== ");
blu("pPowerManger Example MOOS Configuration ");
blu("=============================================================== ");
blk(" ");
blk("ProcessConfig = pPowerManger ");
blk("{ ");
blk(" AppTick = 4 ");
blk(" CommsTick = 4 ");
blk(" ");
blk("} ");
blk(" ");
exit(0);
}
//----------------------------------------------------------------
// Procedure: showInterfaceAndExit
void showInterfaceAndExit()
{
blk(" ");
blu("=============================================================== ");
blu("pPowerManger INTERFACE ");
blu("=============================================================== ");
blk(" ");
showSynopsis();
blk(" ");
blk("SUBSCRIPTIONS: ");
blk("------------------------------------ ");
blk(" NODE_MESSAGE = src_node=alpha,dest_node=bravo,var_name=FOO, ");
blk(" string_val=BAR ");
blk(" ");
blk("PUBLICATIONS: ");
blk("------------------------------------ ");
blk(" Publications are determined by the node message content. ");
blk(" ");
exit(0);
}
//----------------------------------------------------------------
// Procedure: showReleaseInfoAndExit
void showReleaseInfoAndExit()
{
showReleaseInfo("pPowerManger", "gpl");
exit(0);
}
+18
View File
@@ -0,0 +1,18 @@
/****************************************************************/
/* NAME: */
/* ORGN: MIT, Cambridge MA */
/* FILE: PowerManger_Info.h */
/* DATE: Dececmber 29th, 1963 */
/****************************************************************/
#ifndef PowerManger_INFO_HEADER
#define PowerManger_INFO_HEADER
void showSynopsis();
void showHelpAndExit();
void showExampleConfigAndExit();
void showInterfaceAndExit();
void showReleaseInfoAndExit();
#endif
File diff suppressed because it is too large Load Diff
+91
View File
@@ -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
+139
View File
@@ -0,0 +1,139 @@
#ifndef CCUUDPMSG__H
#define CCUUDPMSG__H
#include "pmSysvariable.h"
#define CCU_UDPMSG_START1 0x20
#define CCU_UDPMSG_START2 0x20
#define DIS_MSG_HEAD1 0x40
#define DIS_MSG_HEAD2 0x40
#define CCU_CMD_ID 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
+146
View File
@@ -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
+103
View File
@@ -0,0 +1,103 @@
#include "fsm.h"
#include <iostream>
FSM::FSM(/* args */)
{
idStateMap.clear();
handleMap.clear();
stateMap.clear();
};
FSM::~FSM()
{
};
int FSM::run(FSM_State &fsm,void* data)
{
FSM_Handle handle = handleMap[fsm.id];
return handle(fsm,data);
}
int FSM::RegisterHandleFunction(FSM_State* fsm, FSM_Handle handle)
{
if(fsm == NULL)
return -1;
if(handleMap.count(fsm->id) > 0)
return -1;
handleMap[fsm->id] = handle;
return 0;
}
int FSM::unRegisterHandleFunction(FSM_State* fsm)
{
if(fsm == NULL)
return -1;
if(handleMap.count(fsm->id) <= 0)
return -1;
handleMap.erase(fsm->id);
return 0;
}
int FSM::RegisterState(std::string name, unsigned int id,FSM_State &state)
{
if(stateMap.count(name) > 0)
return -1;
if(idStateMap.count(id) > 0)
return -1;
state.name = name;
state.id = id;
stateMap[name] = state;
idStateMap[id] = state;
return 0;
}
unsigned int FSM::getStateId(std::string name)
{
return stateMap[name].id;
}
FSM_State FSM::getState(std::string name)
{
return stateMap[name];
}
int FSM::RegisterEvent(FSM_State* fsm, std::string event, FSM_State *state)
{
if(fsm == NULL)
return -1;
fsm->event[event] = state;
return 0;
}
int FSM::unRegisterEvent(FSM_State* fsm, std::string event)
{
if(fsm == NULL)
return -1;
if(fsm->event.count(event) <= 0)
return -1;
fsm->event.erase(event);
return 0;
}
int FSM::run(FSM_State *fsm,void* data, std::string event)
{
if(fsm->event.count(event) <= 0)
{
std::cout << "no event" << std::endl;
return run(*(fsm),data);
}
else
{
int r = run(*(fsm),data);
// fsm = fsm->event[event];
*fsm = *fsm->event[event];
// std::cout << "event " << event <<std::endl;
// std::cout << "fsm" << fsm->name << std::endl;
return r;
}
}
// int FSM::run(FSM_State *fsm,void* data)
// {
// return run(*fsm,data);
// }
+40
View File
@@ -0,0 +1,40 @@
#ifndef FSM_H
#define FSM_H
#include <string>
#include <map>
typedef struct FSM_State
{
std::string name;
unsigned int id;
std::map<std::string,FSM_State*> event;
}FSM_State;
typedef int (*FSM_Handle)(FSM_State &fsm, void *data);
// typedef int (*FSM_EventHandle)(FSM_State &fsm,std::string event,void *data);
class FSM
{
public:
FSM();
~FSM();
std::map<unsigned int, FSM_Handle> handleMap;
std::map<std::string, FSM_State> stateMap;
std::map<unsigned int, FSM_State> idStateMap;
int run(FSM_State &fsm,void* data);
int run(FSM_State *fsm,void* data, std::string event);
//TODO: 事件注册机制实现
int RegisterEvent(FSM_State* fsm, std::string event, FSM_State *state);
int unRegisterEvent(FSM_State* fsm, std::string event);
int RegisterState(std::string name, unsigned int id,FSM_State &state);
FSM_State getState(std::string name);
unsigned int getStateId(std::string name);
int RegisterHandleFunction(FSM_State* fsm, FSM_Handle handle);
int unRegisterHandleFunction(FSM_State* fsm);
};
#endif
+52
View File
@@ -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);
}
+364
View File
@@ -0,0 +1,364 @@
#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;
#endif
+556
View File
@@ -0,0 +1,556 @@
#include "udpComm.h"
#include <iostream>
#include <memory>
udpComm::udpComm()
{
}
udpComm::~udpComm() {}
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
{
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;
}
+78
View File
@@ -0,0 +1,78 @@
#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){
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
-18
View File
@@ -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)
+44
View File
@@ -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####################################################################
+65
View File
@@ -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;
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+52
View File
@@ -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()
+42
View File
@@ -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()
+255
View File
@@ -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()
+121
View File
@@ -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()
+57
View File
@@ -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()
+44
View File
@@ -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()
+105
View File
@@ -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秒发送一次消息
+458
View File
@@ -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()
+664
View File
@@ -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()
+78
View File
@@ -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()
+59
View File
@@ -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秒发送一次消息
+656
View File
@@ -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()
+37
View File
@@ -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);
}