summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@theqtcompany.com>2016-03-17 14:27:05 +0100
committerKarsten Heimrich <karsten.heimrich@theqtcompany.com>2016-03-17 16:22:19 +0000
commit8a5a904441a9a60ab711721a0a6acd8089e74a79 (patch)
tree06679bd59e75a787ff7485fc3e7c6ae6e984ac1e
parent71e78c687c5351298fa099121da8a85f07c518b4 (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.cpp55
-rw-r--r--src/serialbus/qmodbuspdu.h6
-rw-r--r--tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp41
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)