Files
CalibratorLauncher/procedure/functionregistry.cpp
2026-01-02 19:20:35 +09:00

480 lines
17 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "functionregistry.h"
#include <QDebug>
#include <QtMath>
#include <QRandomGenerator>
#include <QThread>
// =============================================================================
// 單例實現
// =============================================================================
FunctionRegistry *FunctionRegistry::m_instance = nullptr;
FunctionRegistry *FunctionRegistry::instance()
{
if (!m_instance)
{
m_instance = new FunctionRegistry();
}
return m_instance;
}
FunctionRegistry::FunctionRegistry(QObject *parent)
: QObject(parent)
{
registerBuiltinFunctions();
}
FunctionRegistry::~FunctionRegistry()
{
}
// =============================================================================
// 函數註冊
// =============================================================================
bool FunctionRegistry::registerFunction(const QString &functionType,
const QStringList &parameterNames,
FunctionCallback callback,
const QString &displayName,
const QString &description,
const QString &category)
{
FunctionMetadata metadata;
metadata.functionType = functionType;
metadata.parameterNames = parameterNames;
metadata.callback = callback;
metadata.displayName = displayName.isEmpty() ? functionType : displayName;
metadata.description = description;
metadata.category = category;
return registerFunction(metadata);
}
bool FunctionRegistry::registerFunction(const FunctionMetadata &metadata)
{
if (metadata.functionType.isEmpty())
{
qWarning() << "無法註冊空函數類型";
return false;
}
if (m_functions.contains(metadata.functionType))
{
qWarning() << "函數已存在,將被覆蓋:" << metadata.functionType;
}
m_functions[metadata.functionType] = metadata;
qDebug() << "註冊函數:" << metadata.functionType << "分類:" << metadata.category;
emit functionRegistered(metadata.functionType);
return true;
}
bool FunctionRegistry::unregisterFunction(const QString &functionType)
{
if (!m_functions.contains(functionType))
{
return false;
}
m_functions.remove(functionType);
emit functionUnregistered(functionType);
return true;
}
bool FunctionRegistry::hasFunction(const QString &functionType) const
{
return m_functions.contains(functionType);
}
QStringList FunctionRegistry::getAllFunctionTypes() const
{
return m_functions.keys();
}
QStringList FunctionRegistry::getFunctionsByCategory(const QString &category) const
{
QStringList result;
for (auto it = m_functions.begin(); it != m_functions.end(); ++it)
{
if (it.value().category == category)
{
result.append(it.key());
}
}
return result;
}
FunctionRegistry::FunctionMetadata FunctionRegistry::getFunctionMetadata(const QString &functionType) const
{
if (m_functions.contains(functionType))
{
return m_functions[functionType];
}
return FunctionMetadata();
}
// =============================================================================
// 參數處理
// =============================================================================
QVariantMap FunctionRegistry::normalizeParameters(const FunctionMetadata &metadata,
const QVariant &parameters)
{
QVariantMap result;
if (parameters.type() == QVariant::Map)
{
result = parameters.toMap();
}
else if (parameters.type() == QVariant::List)
{
QVariantList list = parameters.toList();
for (int i = 0; i < qMin(list.size(), metadata.parameterNames.size()); i++)
{
result[metadata.parameterNames[i]] = list[i];
}
}
// 應用默認值
for (auto it = metadata.defaultParameters.begin(); it != metadata.defaultParameters.end(); ++it)
{
if (!result.contains(it.key()))
{
result[it.key()] = it.value();
}
}
return result;
}
bool FunctionRegistry::validateParameters(const FunctionMetadata &metadata,
const QVariantMap &params)
{
Q_UNUSED(metadata)
Q_UNUSED(params)
// 簡單驗證 - 可以擴展
return true;
}
// =============================================================================
// 函數執行
// =============================================================================
QVariantList FunctionRegistry::executeFunction(const QString &functionType,
const QVariant &parameters)
{
if (!m_functions.contains(functionType))
{
qWarning() << "找不到函數:" << functionType;
emit functionExecuted(functionType, false);
return QVariantList();
}
const FunctionMetadata &metadata = m_functions[functionType];
QVariantMap params = normalizeParameters(metadata, parameters);
if (!validateParameters(metadata, params))
{
qWarning() << "參數驗證失敗:" << functionType;
emit functionExecuted(functionType, false);
return QVariantList();
}
try
{
QVariantList result = metadata.callback(params);
emit functionExecuted(functionType, true);
return result;
}
catch (const std::exception &e)
{
qWarning() << "函數執行異常:" << functionType << "-" << e.what();
emit functionExecuted(functionType, false);
return QVariantList();
}
catch (...)
{
qWarning() << "函數執行未知異常:" << functionType;
emit functionExecuted(functionType, false);
return QVariantList();
}
}
// =============================================================================
// 內建函數註冊
// =============================================================================
void FunctionRegistry::registerBuiltinFunctions()
{
// --------------------------------------------------
// 電阻測量函數
// --------------------------------------------------
registerFunction("RESISTANCE_4WIRE", {"channel", "range", "samples"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
double range = params.value("range", 1000.0).toDouble();
int samples = params.value("samples", 10).toInt();
Q_UNUSED(samples)
qDebug() << "四線電阻測量: 通道=" << channel << "量程=" << range;
// 模擬數據
double resistance = 100.0 + QRandomGenerator::global()->bounded(1.0);
double temperature = (resistance - 100.0) / 0.385;
QVariantList result;
result << resistance << temperature;
return result; }, "四線電阻測量", "使用四線法測量電阻,消除導線電阻影響", "measurement");
registerFunction("RESISTANCE_2WIRE", {"channel", "range", "samples"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
double range = params.value("range", 1000.0).toDouble();
Q_UNUSED(range)
qDebug() << "二線電阻測量: 通道=" << channel;
double resistance = 100.0 + QRandomGenerator::global()->bounded(2.0);
QVariantList result;
result << resistance;
return result; }, "二線電阻測量", "使用二線法測量電阻", "measurement");
// --------------------------------------------------
// 電壓測量函數
// --------------------------------------------------
registerFunction("VOLTAGE_V", {"channel", "range", "samples"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
double range = params.value("range", 10.0).toDouble();
Q_UNUSED(range)
qDebug() << "電壓測量: 通道=" << channel;
double voltage = 5.0 + QRandomGenerator::global()->bounded(0.1);
QVariantList result;
result << voltage;
return result; }, "電壓測量", "測量直流電壓", "measurement");
registerFunction("VOLTAGE_MV", {"channel", "range", "samples"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
Q_UNUSED(channel)
double voltage_mv = 10.0 + QRandomGenerator::global()->bounded(1.0);
QVariantList result;
result << voltage_mv;
return result; }, "毫伏測量", "測量毫伏級電壓", "measurement");
// --------------------------------------------------
// 電流測量函數
// --------------------------------------------------
registerFunction("CURRENT_MA", {"channel", "range", "samples"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
Q_UNUSED(channel)
double current_ma = 12.0 + QRandomGenerator::global()->bounded(0.5);
QVariantList result;
result << current_ma;
return result; }, "毫安電流測量", "測量毫安級電流如4-20mA信號", "measurement");
registerFunction("CURRENT_A", {"channel", "range", "samples"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
Q_UNUSED(channel)
double current_a = 1.0 + QRandomGenerator::global()->bounded(0.1);
QVariantList result;
result << current_a;
return result; }, "安培電流測量", "測量安培級電流", "measurement");
// --------------------------------------------------
// 絕緣測量函數
// --------------------------------------------------
registerFunction("INSULATION", {"channel", "voltage", "duration"}, [](const QVariantMap &params) -> QVariantList
{
double voltage = params.value("voltage", 500.0).toDouble();
double insulation_resistance = 500.0 + QRandomGenerator::global()->bounded(100.0);
double leakage_current = voltage / (insulation_resistance * 1e6) * 1e6;
QVariantList result;
result << insulation_resistance << leakage_current;
return result; }, "絕緣電阻測量", "測量絕緣電阻和漏電流", "measurement");
// --------------------------------------------------
// 溫度測量函數
// --------------------------------------------------
registerFunction("TEMPERATURE_RTD", {"channel", "rtd_type", "wire_mode"}, [](const QVariantMap &params) -> QVariantList
{
QString rtdType = params.value("rtd_type", "PT100").toString();
Q_UNUSED(rtdType)
double resistance = 100.0 + QRandomGenerator::global()->bounded(10.0);
double temperature = (resistance - 100.0) / 0.385;
QVariantList result;
result << temperature << resistance;
return result; }, "RTD溫度測量", "使用RTD如PT100測量溫度", "measurement");
registerFunction("TEMPERATURE_TC", {"channel", "tc_type", "cjc_channel"}, [](const QVariantMap &params) -> QVariantList
{
QString tcType = params.value("tc_type", "K").toString();
Q_UNUSED(tcType)
double voltage_mv = 4.0 + QRandomGenerator::global()->bounded(1.0);
double temperature = voltage_mv / 0.040;
QVariantList result;
result << temperature << voltage_mv;
return result; }, "熱電偶溫度測量", "使用熱電偶測量溫度", "measurement");
// --------------------------------------------------
// 數據採集函數
// --------------------------------------------------
registerFunction("DATA_ACQUISITION", {"channels", "sample_rate", "duration"}, [](const QVariantMap &params) -> QVariantList
{
QVariantList channels = params.value("channels").toList();
double sampleRate = params.value("sample_rate", 1000.0).toDouble();
double duration = params.value("duration", 1.0).toDouble();
int sampleCount = static_cast<int>(sampleRate * duration);
QVariantList dataArray;
QVariantList timestamps;
for (int i = 0; i < qMin(sampleCount, 100); i++) { // 限制最大樣本數
QVariantList sample;
for (int ch = 0; ch < channels.size(); ch++) {
sample << QRandomGenerator::global()->bounded(10.0);
}
dataArray << QVariant(sample);
timestamps << (i / sampleRate);
}
QVariantList result;
result << QVariant(dataArray) << QVariant(timestamps);
return result; }, "數據採集", "多通道數據採集", "acquisition");
// --------------------------------------------------
// 輸出控制函數
// --------------------------------------------------
registerFunction("SET_VOLTAGE", {"channel", "voltage"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
double voltage = params.value("voltage", 0.0).toDouble();
qDebug() << "設置電壓輸出: 通道=" << channel << "電壓=" << voltage;
QVariantList result;
result << true;
return result; }, "設置電壓輸出", "設置指定通道的電壓輸出", "output");
registerFunction("SET_CURRENT", {"channel", "current_ma"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
double current_ma = params.value("current_ma", 0.0).toDouble();
qDebug() << "設置電流輸出: 通道=" << channel << "電流=" << current_ma << "mA";
QVariantList result;
result << true;
return result; }, "設置電流輸出", "設置指定通道的電流輸出", "output");
registerFunction("SET_RESISTANCE", {"channel", "resistance"}, [](const QVariantMap &params) -> QVariantList
{
int channel = params.value("channel", 1).toInt();
double resistance = params.value("resistance", 100.0).toDouble();
qDebug() << "設置電阻輸出: 通道=" << channel << "電阻=" << resistance << "Ω";
QVariantList result;
result << true;
return result; }, "設置電阻輸出", "設置指定通道的模擬電阻輸出", "output");
// --------------------------------------------------
// 計算函數
// --------------------------------------------------
registerFunction("CALCULATE_ERROR", {"measured", "standard"}, [](const QVariantMap &params) -> QVariantList
{
double measured = params.value("measured", 0.0).toDouble();
double standard = params.value("standard", 1.0).toDouble();
double error = measured - standard;
double errorPercent = (standard != 0.0) ? (error / standard * 100.0) : 0.0;
QVariantList result;
result << error << errorPercent;
return result; }, "計算誤差", "計算測量值與標準值的誤差", "calculation");
registerFunction("CALCULATE_AVERAGE", {"values"}, [](const QVariantMap &params) -> QVariantList
{
QVariantList values = params.value("values").toList();
if (values.isEmpty()) {
QVariantList result;
result << 0.0 << 0.0 << 0.0 << 0.0;
return result;
}
double sum = 0.0;
double minVal = values[0].toDouble();
double maxVal = values[0].toDouble();
for (const QVariant &v : values) {
double val = v.toDouble();
sum += val;
minVal = qMin(minVal, val);
maxVal = qMax(maxVal, val);
}
double average = sum / values.size();
double sumSquares = 0.0;
for (const QVariant &v : values) {
double diff = v.toDouble() - average;
sumSquares += diff * diff;
}
double stdDev = qSqrt(sumSquares / values.size());
QVariantList result;
result << average << stdDev << minVal << maxVal;
return result; }, "計算平均值", "計算數值的平均值、標準差、最小值和最大值", "calculation");
// --------------------------------------------------
// 控制函數
// --------------------------------------------------
registerFunction("DELAY", {"duration_ms"}, [](const QVariantMap &params) -> QVariantList
{
int duration_ms = params.value("duration_ms", 1000).toInt();
qDebug() << "延遲:" << duration_ms << "ms";
QThread::msleep(duration_ms);
QVariantList result;
result << true;
return result; }, "延遲", "等待指定時間", "control");
registerFunction("WAIT_STABLE", {"channel", "threshold", "timeout"}, [](const QVariantMap &params) -> QVariantList
{
int timeout = params.value("timeout", 30000).toInt();
QThread::msleep(qMin(timeout, 2000));
double finalValue = 100.0 + QRandomGenerator::global()->bounded(0.05);
QVariantList result;
result << true << finalValue;
return result; }, "等待穩定", "等待測量值穩定在閾值範圍內", "control");
qDebug() << "已註冊" << m_functions.size() << "個內建函數";
}