480 lines
17 KiB
C++
480 lines
17 KiB
C++
#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 ¶meterNames,
|
||
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 ¶meters)
|
||
{
|
||
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 ¶ms)
|
||
{
|
||
Q_UNUSED(metadata)
|
||
Q_UNUSED(params)
|
||
// 簡單驗證 - 可以擴展
|
||
return true;
|
||
}
|
||
|
||
// =============================================================================
|
||
// 函數執行
|
||
// =============================================================================
|
||
|
||
QVariantList FunctionRegistry::executeFunction(const QString &functionType,
|
||
const QVariant ¶meters)
|
||
{
|
||
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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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 ¶ms) -> 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() << "個內建函數";
|
||
}
|