diff options
author | Karsten Heimrich <karsten.heimrich@theqtcompany.com> | 2016-03-17 14:27:05 +0100 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@theqtcompany.com> | 2016-03-17 16:22:19 +0000 |
commit | 8a5a904441a9a60ab711721a0a6acd8089e74a79 (patch) | |
tree | 06679bd59e75a787ff7485fc3e7c6ae6e984ac1e | |
parent | 71e78c687c5351298fa099121da8a85f07c518b4 (diff) |
Have a means to register a custom data size calculator.
Adds possibility to:
* Override our data size calculation for a function code.
* Implement data size calculation for a custom function code.
Change-Id: I5611990a7bc10c2e90aef0f52aa1eb7ddf440717
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
-rw-r--r-- | src/serialbus/qmodbuspdu.cpp | 55 | ||||
-rw-r--r-- | src/serialbus/qmodbuspdu.h | 6 | ||||
-rw-r--r-- | tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp | 41 |
3 files changed, 102 insertions, 0 deletions
diff --git a/src/serialbus/qmodbuspdu.cpp b/src/serialbus/qmodbuspdu.cpp index 2f20747..ef8d93c 100644 --- a/src/serialbus/qmodbuspdu.cpp +++ b/src/serialbus/qmodbuspdu.cpp @@ -38,9 +38,16 @@ #include "qmodbus_symbols_p.h" #include <QtCore/qdebug.h> +#include <QtCore/qhash.h> QT_BEGIN_NAMESPACE +using ReqSizeCalc = QHash<quint8, QModbusRequest::CalcFuncPtr>; +Q_GLOBAL_STATIC(ReqSizeCalc, requestSizeCalculators); + +using ResSizeCalc = QHash<quint8, QModbusResponse::CalcFuncPtr>; +Q_GLOBAL_STATIC(ResSizeCalc, responseSizeCalculators); + namespace Private { enum struct Type { @@ -525,9 +532,17 @@ int QModbusRequest::minimumDataSize(const QModbusRequest &request) Calculates the expected data size for \a request based on the request's function code and data. Returns the full size of the request's data part; \c {-1} if the size could not be properly calculated. + + \sa minimumDataSize + \sa registerDataSizeCalculator */ int QModbusRequest::calculateDataSize(const QModbusRequest &request) { + if (requestSizeCalculators.exists()) { + if (auto ptr = requestSizeCalculators()->value(request.functionCode(), nullptr)) + return ptr(request); + } + if (request.isException()) return 1; @@ -569,6 +584,22 @@ int QModbusRequest::calculateDataSize(const QModbusRequest &request) } /*! + This function registers a user-defined implementation to calculate the + request data size for function code \a fc. It can be used to extend or + override the implementation inside \l QModbusRequest::calculateDataSize(). + + The \c CalcFuncPtr is a typedef for a pointer to a custom \a calculator + function with the following signature: + \code + int myCalculateDataSize(const QModbusRequest &pdu); + \endcode +*/ +void QModbusRequest::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr calculator) +{ + requestSizeCalculators()->insert(fc, calculator); +} + +/*! \relates QModbusRequest Reads a \a pdu from the \a stream and returns a reference to the stream. @@ -649,9 +680,17 @@ int QModbusResponse::minimumDataSize(const QModbusResponse &response) Calculates the expected data size for \a response, based on the response's function code and data. Returns the full size of the response's data part; \c {-1} if the size could not be properly calculated. + + \sa minimumDataSize + \sa registerDataSizeCalculator */ int QModbusResponse::calculateDataSize(const QModbusResponse &response) { + if (responseSizeCalculators.exists()) { + if (auto ptr = responseSizeCalculators()->value(response.functionCode(), nullptr)) + return ptr(response); + } + if (response.isException()) return 1; @@ -723,6 +762,22 @@ int QModbusResponse::calculateDataSize(const QModbusResponse &response) } /*! + This function registers a user-defined implementation to calculate the + response data size for function code \a fc. It can be used to extend or + override the implementation inside \l QModbusResponse::calculateDataSize(). + + The \c CalcFuncPtr is a typedef for a pointer to a custom \a calculator + function with the following signature: + \code + int myCalculateDataSize(const QModbusResponse &pdu); + \endcode +*/ +void QModbusResponse::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr calculator) +{ + responseSizeCalculators()->insert(fc, calculator); +} + +/*! \relates QModbusResponse Reads a \a pdu from the \a stream and returns a reference to the stream. diff --git a/src/serialbus/qmodbuspdu.h b/src/serialbus/qmodbuspdu.h index 12fd33f..ac85b76 100644 --- a/src/serialbus/qmodbuspdu.h +++ b/src/serialbus/qmodbuspdu.h @@ -198,6 +198,9 @@ public: Q_SERIALBUS_EXPORT static int minimumDataSize(const QModbusRequest &pdu); Q_SERIALBUS_EXPORT static int calculateDataSize(const QModbusRequest &pdu); + using CalcFuncPtr = decltype(&calculateDataSize); + Q_SERIALBUS_EXPORT static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func); + template <typename ... Args> QModbusRequest(FunctionCode code, Args ... newData) : QModbusPdu(code, newData...) @@ -220,6 +223,9 @@ public: Q_SERIALBUS_EXPORT static int minimumDataSize(const QModbusResponse &pdu); Q_SERIALBUS_EXPORT static int calculateDataSize(const QModbusResponse &pdu); + using CalcFuncPtr = decltype(&calculateDataSize); + Q_SERIALBUS_EXPORT static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func); + template <typename ... Args> QModbusResponse(FunctionCode code, Args ... newData) : QModbusPdu(code, newData...) diff --git a/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp b/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp index 76bfea3..592a14e 100644 --- a/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp +++ b/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp @@ -803,6 +803,47 @@ private slots: quint8(0xff)); // dummy additional data QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22); } + + void testCustomCalculator() + { + // request + QModbusRequest request(QModbusRequest::WriteSingleCoil); + request.encodeData(quint8(0x00), quint8(0xac), quint8(0xff), quint8(0x00)); + QCOMPARE(QModbusRequest::calculateDataSize(request), 4); + + QModbusRequest::registerDataSizeCalculator(QModbusRequest::WriteSingleCoil, + [](const QModbusRequest &)->int { + return 15; + }); + QCOMPARE(QModbusRequest::calculateDataSize(request), 15); + + QModbusRequest::registerDataSizeCalculator(QModbusRequest::WriteSingleCoil, nullptr); + QCOMPARE(QModbusRequest::calculateDataSize(request), 4); + + // response + QModbusResponse response(QModbusRequest::WriteSingleCoil); + response.encodeData(quint8(0x00), quint8(0xac), quint8(0xff), quint8(0x00)); + QCOMPARE(QModbusResponse::calculateDataSize(request), 4); + + QModbusResponse::registerDataSizeCalculator(QModbusResponse::WriteSingleCoil, + [](const QModbusResponse &)->int { + return 15; + }); + QCOMPARE(QModbusResponse::calculateDataSize(response), 15); + + QModbusResponse::registerDataSizeCalculator(QModbusResponse::WriteSingleCoil, nullptr); + QCOMPARE(QModbusResponse::calculateDataSize(response), 4); + + // custom + QModbusPdu::FunctionCode custom = QModbusPdu::FunctionCode(0x30); + request.setFunctionCode(custom); + QCOMPARE(QModbusRequest::calculateDataSize(request), -1); + + QModbusRequest::registerDataSizeCalculator(custom, [](const QModbusRequest &)->int { + return 27; + }); + QCOMPARE(QModbusRequest::calculateDataSize(request), 27); + } }; QTEST_MAIN(tst_QModbusPdu) |