kiug / qmodbus Goto Github PK
View Code? Open in Web Editor NEWModbus library (http://libmodbus.org) wrapper for Qt framework.
License: GNU Lesser General Public License v3.0
Modbus library (http://libmodbus.org) wrapper for Qt framework.
License: GNU Lesser General Public License v3.0
Hi, reviewing the code base of qmodbus, I miss a consistent error handling concept.
Normally, we have to distinguish between:
lastError()
(current code)Some examples:
void QModbusBits::setValue (unsigned int index, bool value)
{
operator[](index) = value; // no error handling at all, in release mode SEGFAULT when using invalid index
}
qint8 QModbusRegisters::getInteger8 (int index, bool low)
{
if (size () <= (int)index) {
modbusError.set (OUT_OF_RANGE_ENO);
// error flag is set, but function continues to run until SEGFAULT further below
// instead, should throw an exception or raise and assertion
}
else {
modbusError.clear();
}
qint16 value = 0;
((qint16 *) &value)[0] = at (index);
if ( low )
return getLowByte( value );
else
return getHighByte( value );
}
void QModbusMaster::setResponseTimeout (uint32_t sec, uint32_t usec)
{
// struct timeval timeout;
// timeout.tv_sec = sec;
// timeout.tv_usec = usec;
// modbus_set_response_timeout ((modbus_t *) ctx, &timeout);
modbus_set_response_timeout ((modbus_t *) ctx, sec, usec);
// Error handling, i.e. check for return code is missing; user code has no
// way to know that setting the time out may have failed
}
I suggest the following error handling concept:
Example code:
// setter functions - return value for convenience, same as
// manually checking for modbusMaster->lastError().isValid()
if (!modbusMaster->setSomeValue(x,y))
qCritical() << modbusMaster->lastError().message();
// getter functions - user code is responsible for checking return value,
// as errors are anticipated
int hl = modbusMaster->getHeaderLength();
if (modbusMaster->lastError().isValid())
qCritical() << modbusMaster->lastError().message();
// Option A)
// checking for invalid arguments via ASSERTS - may be problematic, as asserts are not
// being used in release code and if index is provided by user input, software could SEGFAULT
void QModbusRegisters::setValue (int index, quint16 value) {
// assert should deliver context information on programmers error
Q_ASSERT_X(index >= 0 && index < size(), "QModbusRegisters::setValue", "index out of range");
operator [] (index) = value;
}
// Option B)
// check errors via Exception class (as QModbus is C++ code, exceptions are ok)
class QModbusException : public std::exception {
public:
QModbusException();
QModbusException(const QModbusException&);
QModbusException(const QString & context, const QString & msg);
};
void QModbusRegisters::setValue (int index, quint16 value) {
// assert should deliver context information on programmers error
if (index >= 0 && index < size())
throw QModbusException("QModbusRegisters::setValue", QString("Index %1 out of range (size = %2)").arg(index).arg(size());
operator [] (index) = value;
}
If we can decide error handling of QModbus I would go through the code and provide a patch via pull request.
What do you think about it?
Hi,
just wanted to let you know that you have a consistent bug when writing Float32 and Int32 encoded values into Modbus on little endian systems (linux etc.). This effectively causes Float32_abcd to be written as cdab encoding into modbus stream.
Here is the problem:
void QModbusRegisters::setFloat32 (unsigned int index, float value)
{
if (size () <= (int)index + 1) {
modbusError.set (OUT_OF_RANGE_ENO);
}
else {
modbusError.clear ();
}
twoRegistersRepresentation valueRep;
valueRep.float32 = value;
operator [] (index) = valueRep.component[0];
operator [] (index + 1) = valueRep.component[1];
}
The problem is the use of the union twoRegistersRepresentation
.
Example: Float value 20.1 has binary expression in big endian as:
0x41a0147b
(see https://www.h-schmidt.net/FloatConverter/IEEE754.html)
where 0x41a0 encodes 20, and 0x137b encodes .1
This is abcd notation. The setFloat32() code, however, writes as cdab (i.e. results in 0x147b41a0 in the Modbus byte stream). The Modbus standard, however, requires abcd (big endian) encoding to be used in the byte stream.
This should be fixed, or clarified by adding a suffix setFloat32_cdab
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.