增加了数据库下载的功能
This commit is contained in:
Vendored
+21
-1
@@ -53,7 +53,27 @@
|
|||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"cinttypes": "cpp",
|
"cinttypes": "cpp",
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"queue": "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"
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "disabled",
|
"C_Cpp.errorSquiggles": "disabled",
|
||||||
"marscode.chatLanguage": "cn",
|
"marscode.chatLanguage": "cn",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"HVABFTDev123Cur_uint16": 0,
|
"HVABFTDev123Cur_uint16": 1024,
|
||||||
"HVABactCur_uint16": 0,
|
"HVABactCur_uint16": 0,
|
||||||
"HVABbowRudCur_uint16": 0,
|
"HVABbowRudCur_uint16": 0,
|
||||||
"HVABbusBCur_uint16": 1792,
|
"HVABbusBCur_uint16": 1792,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ INCLUDE_DIRECTORIES(${LOCAL_LIBRARY_DIRS})
|
|||||||
# List the subdirectories to build...
|
# List the subdirectories to build...
|
||||||
#============================================================================
|
#============================================================================
|
||||||
ADD_SUBDIRECTORY(pPowerManger)
|
ADD_SUBDIRECTORY(pPowerManger)
|
||||||
|
ADD_SUBDIRECTORY(appPowerMangerWebUI)
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# END of CMakeLists.txt
|
# END of CMakeLists.txt
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#--------------------------------------------------------
|
||||||
|
# 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 "")
|
||||||
|
|
||||||
|
#find crow库
|
||||||
|
find_package(Crow CONFIG REQUIRED)
|
||||||
|
# Find SQLite3 package
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
|
||||||
|
SET(SRC
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(appPowerMangerWebUI ${SRC})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(appPowerMangerWebUI
|
||||||
|
${MOOS_LIBRARIES}
|
||||||
|
mbutil
|
||||||
|
m
|
||||||
|
pthread
|
||||||
|
Crow::Crow
|
||||||
|
asio::asio
|
||||||
|
jsoncpp
|
||||||
|
SQLiteDB
|
||||||
|
sqlite3)
|
||||||
|
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
<!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">
|
||||||
|
<style>
|
||||||
|
/* 全局样式 */
|
||||||
|
body {
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
background-color: #282c34;
|
||||||
|
color: #ffffff;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
height: 100vh;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr 1fr;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #61dafb;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-status-panel {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #61dafb;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-status i {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-status.connected {
|
||||||
|
color: #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-status.disconnected {
|
||||||
|
color: #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 15px 20px;
|
||||||
|
background: linear-gradient(145deg, #61dafb, #4fa8c7);
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #282c34;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||||
|
background: linear-gradient(145deg, #4fa8c7, #61dafb);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel button i {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #61dafb;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
overflow: auto;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel h2 {
|
||||||
|
color: #61dafb;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-columns {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-column {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-column h3 {
|
||||||
|
color: #61dafb;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-panel {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ccu-state-panel {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dis-sys-panel {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-machine-panel {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<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 class="control-panel">
|
||||||
|
<!-- 其他按钮 -->
|
||||||
|
<button id="download-db">
|
||||||
|
<i class="fas fa-download"></i>
|
||||||
|
下载数据库
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="db-status-panel">
|
||||||
|
<h2>数据库操作</h2>
|
||||||
|
<div class="db-status" id="db-status">
|
||||||
|
<i class="fas fa-database"></i>
|
||||||
|
<span>正在连接数据库...</span>
|
||||||
|
</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="panel log-panel">
|
||||||
|
<h2>运行日志</h2>
|
||||||
|
<pre id="log-data">正在加载...</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel state-machine-panel">
|
||||||
|
<h2>状态机状态</h2>
|
||||||
|
<pre id="state-machine-state">正在加载...</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 更新页面数据的函数
|
||||||
|
function updateData() {
|
||||||
|
fetch('/api/status')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
// 更新DIS系统状态
|
||||||
|
document.getElementById('dis-sys-state').textContent = JSON.stringify(data.disSys, null, 2);
|
||||||
|
|
||||||
|
// 更新CCU状态
|
||||||
|
document.getElementById('ccu-state').textContent = JSON.stringify(data.ccuState, null, 2);
|
||||||
|
|
||||||
|
// 更新运行日志
|
||||||
|
document.getElementById('log-data').textContent = data.logs.join('\n');
|
||||||
|
|
||||||
|
// 更新状态机状态
|
||||||
|
document.getElementById('state-machine-state').textContent = JSON.stringify(data.stateMachine, null, 2);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching data:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据库连接状态
|
||||||
|
function checkDbConnection() {
|
||||||
|
fetch('/api/db-status')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const dbStatus = document.getElementById('db-status');
|
||||||
|
if (data.connected) {
|
||||||
|
dbStatus.className = 'db-status connected';
|
||||||
|
dbStatus.innerHTML = `<i class="fas fa-database"></i><span>已连接到数据库:${data.database}</span>`;
|
||||||
|
} else {
|
||||||
|
dbStatus.className = 'db-status disconnected';
|
||||||
|
dbStatus.innerHTML = `<i class="fas fa-database"></i><span>数据库连接失败</span>`;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const dbStatus = document.getElementById('db-status');
|
||||||
|
dbStatus.className = 'db-status disconnected';
|
||||||
|
dbStatus.innerHTML = `<i class="fas fa-database"></i><span>数据库连接错误</span>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.getElementById('download-db').addEventListener('click', function() {
|
||||||
|
const dbPath = 'data/power_data.db';
|
||||||
|
fetch(dbPath)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return response.blob();
|
||||||
|
})
|
||||||
|
.then(blob => {
|
||||||
|
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);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error downloading database:', error);
|
||||||
|
alert('下载数据库失败,请检查文件路径或网络连接');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 每2秒更新一次数据
|
||||||
|
setInterval(updateData, 2000);
|
||||||
|
updateData(); // 初始加载
|
||||||
|
|
||||||
|
// 每5秒检查一次数据库连接状态
|
||||||
|
setInterval(checkDbConnection, 5000);
|
||||||
|
checkDbConnection(); // 初始检查
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
#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 "../pPowerManger/SQLiteDB.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// 读取 HTML 文件内容
|
||||||
|
string read_file(const string& path) {
|
||||||
|
ifstream file(path);
|
||||||
|
stringstream buffer;
|
||||||
|
buffer << file.rdbuf();
|
||||||
|
return buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
crow::SimpleApp app;
|
||||||
|
SQLiteDB db("/home/zjk/project/H100/H100PowerManger/data/power_data.db");
|
||||||
|
// 初始化 SQLite 数据库
|
||||||
|
|
||||||
|
// 路由返回 HTML 页面
|
||||||
|
CROW_ROUTE(app, "/")([](){
|
||||||
|
// 读取 HTML 文件
|
||||||
|
string html_content = read_file("/home/zjk/project/H100/H100PowerManger/src/appPowerMangerWebUI/index.html");
|
||||||
|
return html_content;
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/api/db-status")
|
||||||
|
([&db]() {
|
||||||
|
crow::json::wvalue response;
|
||||||
|
if (db.isDatabaseConnected("/home/zjk/project/H100/H100PowerManger/data", "power_data.db")) {
|
||||||
|
response["connected"] = true;
|
||||||
|
response["database"] = "YourDatabaseName"; // 替换为实际的数据库名称
|
||||||
|
} else {
|
||||||
|
response["connected"] = false;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/api/download-db")
|
||||||
|
([&db]() {
|
||||||
|
std::ifstream file("/home/zjk/project/H100/H100PowerManger/data/power_data.db", std::ios::binary);
|
||||||
|
if (!file) {
|
||||||
|
return crow::response(404, "Database file not found");
|
||||||
|
}
|
||||||
|
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
// 将 buffer.size() 转换为 std::string
|
||||||
|
std::string contentLength = std::to_string(buffer.size());
|
||||||
|
crow::response response(buffer.size(), contentLength, "application/octet-stream");
|
||||||
|
response.add_header("Content-Disposition", "attachment; filename=power_data.db");
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 启动服务器,监听端口 18080
|
||||||
|
app.port(18080).multithreaded().run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -123,14 +123,7 @@ bool PowerManger::Iterate()
|
|||||||
else
|
else
|
||||||
m_FsmThread.Stop();
|
m_FsmThread.Stop();
|
||||||
// 数据库测试
|
// 数据库测试
|
||||||
PowerData data;
|
|
||||||
// data.id = 1;
|
|
||||||
data.timestamp = "2023-05-22 10:00:00";
|
|
||||||
data.voltage = 12.3 + rand() % 100 / 100.0;
|
|
||||||
data.current = 4.5 + rand() % 100 / 100.0;
|
|
||||||
data.power = 56.7 + rand() % 100 / 100.0;
|
|
||||||
data.temperature = 25.0 + rand() % 100 / 100.0;
|
|
||||||
m_db->insertPowerData(data.voltage, data.current, data.power, data.temperature);
|
|
||||||
//3. 输出报告
|
//3. 输出报告
|
||||||
buildPowerSysReport();
|
buildPowerSysReport();
|
||||||
//4. 打印错误信息
|
//4. 打印错误信息
|
||||||
@@ -281,7 +274,6 @@ bool PowerManger::FsmLoop()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PowerManger::updatePmState()
|
bool PowerManger::updatePmState()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,32 @@ void SQLiteDB::insertStateData(StateData stateData) {
|
|||||||
std::cerr << "Error preparing statement: " << sqlite3_errmsg(m_db) << std::endl;
|
std::cerr << "Error preparing statement: " << sqlite3_errmsg(m_db) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool SQLiteDB::isDatabaseConnected(const std::string& path, const std::string& dbName) {
|
||||||
|
if (!m_db) return false;
|
||||||
|
|
||||||
|
// 尝试执行简单查询验证连接
|
||||||
|
const char* sql = "SELECT name FROM sqlite_master WHERE type='table';";
|
||||||
|
char* errMsg = nullptr;
|
||||||
|
|
||||||
|
int rc = sqlite3_exec(m_db, sql, nullptr, nullptr, &errMsg);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
std::cerr << "Database connection check failed: " << errMsg << std::endl;
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据库路径和名称是否匹配
|
||||||
|
std::string fullPath = path + "/" + dbName;
|
||||||
|
const char* dbPath = sqlite3_db_filename(m_db, "main");
|
||||||
|
|
||||||
|
if (!dbPath || fullPath != dbPath) {
|
||||||
|
std::cerr << "Database path mismatch: expected " << fullPath << ", got " << (dbPath ? dbPath : "null") << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<PowerData> SQLiteDB::getPowerData(int limit) {
|
std::vector<PowerData> SQLiteDB::getPowerData(int limit) {
|
||||||
std::vector<PowerData> data;
|
std::vector<PowerData> data;
|
||||||
if (!m_db) return data;
|
if (!m_db) return data;
|
||||||
@@ -124,4 +150,4 @@ std::vector<PowerData> SQLiteDB::getPowerData(int limit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ public:
|
|||||||
void insertStateData(StateData stateData);
|
void insertStateData(StateData stateData);
|
||||||
std::vector<PowerData> getPowerData(int limit = 100);
|
std::vector<PowerData> getPowerData(int limit = 100);
|
||||||
|
|
||||||
|
//使用函数
|
||||||
|
bool isDatabaseConnected(const std::string& path, const std::string& dbName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sqlite3* m_db;
|
sqlite3* m_db;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,12 +9,8 @@ TEST_CASE("SQLiteDB Test", "[SQLiteDB]") {
|
|||||||
db.createStateTables();
|
db.createStateTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Query Data") {
|
SECTION("Test isDatabaseConnected") {
|
||||||
std::vector<PowerData> results = db.getPowerData();
|
REQUIRE(db.isDatabaseConnected("/home/zjk/project/H100/H100PowerManger/bin","test.db") == true);
|
||||||
REQUIRE(results.size() == 1);
|
|
||||||
REQUIRE(results[0].voltage == 12.5);
|
|
||||||
REQUIRE(results[0].current == 2.5);
|
|
||||||
REQUIRE(results[0].power == 31.25);
|
|
||||||
REQUIRE(results[0].temperature == 25.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user