modbus-tool: Introduce string endianess
parent
fd80c7e99a
commit
7fc32167d6
|
|
@ -133,10 +133,12 @@ qint64 ModbusDataUtils::convertToInt64(const QVector<quint16> ®isters, ByteOr
|
|||
return result;
|
||||
}
|
||||
|
||||
QString ModbusDataUtils::convertToString(const QVector<quint16> ®isters)
|
||||
QString ModbusDataUtils::convertToString(const QVector<quint16> ®isters, ByteOrder characterByteOrder)
|
||||
{
|
||||
QByteArray bytes;
|
||||
QDataStream stream(&bytes, QIODevice::WriteOnly);
|
||||
// Note: some devices use little endian within the register uint16 representation of the 2 characters.
|
||||
stream.setByteOrder(characterByteOrder == ByteOrderBigEndian ? QDataStream::BigEndian : QDataStream::LittleEndian);
|
||||
for (int i = 0; i < registers.count(); i++) {
|
||||
stream << registers.at(i);
|
||||
}
|
||||
|
|
@ -239,11 +241,13 @@ QVector<quint16> ModbusDataUtils::convertFromInt64(qint64 value, ByteOrder byteO
|
|||
return values;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromString(const QString &value, quint16 stringLength)
|
||||
QVector<quint16> ModbusDataUtils::convertFromString(const QString &value, quint16 stringLength, ByteOrder characterByteOrder)
|
||||
{
|
||||
Q_ASSERT_X(value.length() <= stringLength, "ModbusDataUtils", "cannot convert a string which is bigger than the desired register vector.");
|
||||
QByteArray data = value.toLatin1() + QByteArray('\0', stringLength - value.count());
|
||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||
// Note: some devices use little endian within the register uint16 representation of the 2 characters.
|
||||
stream.setByteOrder(characterByteOrder == ByteOrderBigEndian ? QDataStream::BigEndian : QDataStream::LittleEndian);
|
||||
QVector<quint16> values;
|
||||
for (int i = 0; i < stringLength; i++) {
|
||||
quint16 registerValue = 0;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public:
|
|||
static qint32 convertToInt32(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static quint64 convertToUInt64(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static qint64 convertToInt64(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QString convertToString(const QVector<quint16> ®isters);
|
||||
static QString convertToString(const QVector<quint16> ®isters, ByteOrder characterByteOrder = ByteOrderLittleEndian);
|
||||
static float convertToFloat32(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static double convertToFloat64(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ public:
|
|||
static QVector<quint16> convertFromInt32(qint32 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromUInt64(quint64 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromInt64(qint64 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromString(const QString &value, quint16 stringLength);
|
||||
static QVector<quint16> convertFromString(const QString &value, quint16 stringLength, ByteOrder characterByteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromFloat32(float value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromFloat64(double value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ The basic structure of the modbus register JSON looks like following example:
|
|||
"className": "MyConnection",
|
||||
"protocol": "BOTH",
|
||||
"endianness": "BigEndian",
|
||||
"stringEndianness": "BigEndian",
|
||||
"errorLimitUntilNotReachable": 10,
|
||||
"checkReachableRegister": "registerPropertyName",
|
||||
"enums": [
|
||||
|
|
@ -138,6 +139,19 @@ There are 2 possibilities:
|
|||
* `BigEndian`: default if not specified: register bytes come in following order `[0, 1, 2, 3]`: `ABCD`
|
||||
* `LittleEndian`: register bytes come in following order `[0, 1, 2, 3]`: `CDAB`
|
||||
|
||||
|
||||
## String endianness
|
||||
|
||||
When converting multiple registers to a string, some modbus devices use a different endianess within a register.
|
||||
One register contains 2 bytes, miltiple registers in a row build up a string. The string endianess tells the generated class how to parse those strings.
|
||||
|
||||
There are 2 possibilities:
|
||||
|
||||
* `BigEndian`: default if not specified: register bytes come in following order `[0, 1], [2, 3]`: `ABCD`
|
||||
* `LittleEndian`: register bytes come in following order `[1, 0] [3, 2]`: `BADC`
|
||||
|
||||
Please not that the overall endianess of the device does not change the order of the register regarding strings since in modbus a normal register is definded as big endian. Only multiple registers combined to a numeric data type will be taken into account by the `endianess` property.
|
||||
|
||||
## Enums
|
||||
|
||||
Many modbus devices provide inforation using `Enums`, indicating a special state trough a defined list of values. If a register implements an enum, you can define it in the `enums` section. The `name` property defines the name of the enum, and the script will generate a c++ enum definition from this section. Each enum value will then be generated using `<EnumName><EnumValueName> = <value>`.
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ def getConversionToValueMethod(registerDefinition):
|
|||
elif registerDefinition['type'] == 'float64':
|
||||
return ('ModbusDataUtils::convertFromFloat64(%s, m_endianness)' % propertyName)
|
||||
elif registerDefinition['type'] == 'string':
|
||||
return ('ModbusDataUtils::convertFromString(%s)' % propertyName)
|
||||
return ('ModbusDataUtils::convertFromString(%s, m_stringEndianness)' % propertyName)
|
||||
|
||||
|
||||
def getValueConversionMethod(registerDefinition):
|
||||
|
|
@ -334,7 +334,7 @@ def getValueConversionMethod(registerDefinition):
|
|||
elif registerDefinition['type'] == 'float64':
|
||||
return ('ModbusDataUtils::convertToFloat64(values, m_endianness)')
|
||||
elif registerDefinition['type'] == 'string':
|
||||
return ('ModbusDataUtils::convertToString(values)')
|
||||
return ('ModbusDataUtils::convertToString(values, m_stringEndianness)')
|
||||
|
||||
|
||||
def writeBlockGetMethodDeclarations(fileDescriptor, registerDefinitions):
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ def writeTcpHeaderFile():
|
|||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder endianness() const;')
|
||||
writeLine(headerFile, ' void setEndianness(ModbusDataUtils::ByteOrder endianness);')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder stringEndianness() const;')
|
||||
writeLine(headerFile, ' void setStringEndianness(ModbusDataUtils::ByteOrder stringEndianness);')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' uint checkReachableRetries() const;')
|
||||
writeLine(headerFile, ' void setCheckReachableRetries(uint checkReachableRetries);')
|
||||
writeLine(headerFile)
|
||||
|
|
@ -117,6 +120,7 @@ def writeTcpHeaderFile():
|
|||
writeLine(headerFile, ' void updateFinished();')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' void endiannessChanged(ModbusDataUtils::ByteOrder endianness);')
|
||||
writeLine(headerFile, ' void stringEndiannessChanged(ModbusDataUtils::ByteOrder stringEndianness);')
|
||||
writeLine(headerFile)
|
||||
|
||||
writePropertyChangedSignals(headerFile, registerJson['registers'])
|
||||
|
|
@ -148,6 +152,7 @@ def writeTcpHeaderFile():
|
|||
# Private members
|
||||
writeLine(headerFile, 'private:')
|
||||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness)
|
||||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_stringEndianness = ModbusDataUtils::ByteOrder%s;' % stringEndianness)
|
||||
writeLine(headerFile, ' quint16 m_slaveId = 1;')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' bool m_reachable = false;')
|
||||
|
|
@ -259,6 +264,22 @@ def writeTcpSourceFile():
|
|||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::stringEndianness() const' % (className))
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' return m_stringEndianness;')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
writeLine(sourceFile, 'void %s::setStringEndianness(ModbusDataUtils::ByteOrder stringEndianness)' % (className))
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' if (m_stringEndianness == stringEndianness)')
|
||||
writeLine(sourceFile, ' return;')
|
||||
writeLine(sourceFile,)
|
||||
writeLine(sourceFile, ' m_stringEndianness = stringEndianness;')
|
||||
writeLine(sourceFile, ' emit stringEndiannessChanged(m_stringEndianness);')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
# Property get methods
|
||||
writePropertyGetSetMethodImplementationsTcp(sourceFile, className, registerJson['registers'])
|
||||
if 'blocks' in registerJson:
|
||||
|
|
@ -445,6 +466,9 @@ def writeRtuHeaderFile():
|
|||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder endianness() const;')
|
||||
writeLine(headerFile, ' void setEndianness(ModbusDataUtils::ByteOrder endianness);')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder stringEndianness() const;')
|
||||
writeLine(headerFile, ' void setStringEndianness(ModbusDataUtils::ByteOrder stringEndianness);')
|
||||
writeLine(headerFile)
|
||||
|
||||
# Write registers get method declarations
|
||||
writePropertyGetSetMethodDeclarationsRtu(headerFile, registerJson['registers'])
|
||||
|
|
@ -486,6 +510,7 @@ def writeRtuHeaderFile():
|
|||
writeLine(headerFile, ' void updateFinished();')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' void endiannessChanged(ModbusDataUtils::ByteOrder endianness);')
|
||||
writeLine(headerFile, ' void stringEndiannessChanged(ModbusDataUtils::ByteOrder stringEndianness);')
|
||||
writeLine(headerFile)
|
||||
writePropertyChangedSignals(headerFile, registerJson['registers'])
|
||||
if 'blocks' in registerJson:
|
||||
|
|
@ -518,6 +543,7 @@ def writeRtuHeaderFile():
|
|||
writeLine(headerFile, 'private:')
|
||||
writeLine(headerFile, ' ModbusRtuMaster *m_modbusRtuMaster = nullptr;')
|
||||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness)
|
||||
writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_stringEndianness = ModbusDataUtils::ByteOrder%s;' % stringEndianness)
|
||||
writeLine(headerFile, ' quint16 m_slaveId = 1;')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' bool m_reachable = false;')
|
||||
|
|
@ -645,6 +671,21 @@ def writeRtuSourceFile():
|
|||
writeLine(sourceFile, ' m_endianness = endianness;')
|
||||
writeLine(sourceFile, ' emit endiannessChanged(m_endianness);')
|
||||
writeLine(sourceFile, '}')
|
||||
|
||||
writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::stringEndianness() const' % (className))
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' return m_stringEndianness;')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
writeLine(sourceFile, 'void %s::setStringEndianness(ModbusDataUtils::ByteOrder stringEndianness)' % (className))
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' if (m_stringEndianness == stringEndianness)')
|
||||
writeLine(sourceFile, ' return;')
|
||||
writeLine(sourceFile,)
|
||||
writeLine(sourceFile, ' m_stringEndianness = stringEndianness;')
|
||||
writeLine(sourceFile, ' emit stringEndiannessChanged(m_stringEndianness);')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
# Property get methods
|
||||
|
|
@ -828,6 +869,11 @@ endianness = 'BigEndian'
|
|||
if 'endianness' in registerJson:
|
||||
endianness = registerJson['endianness']
|
||||
|
||||
stringEndianness = 'BigEndian'
|
||||
if 'stringEndianness' in registerJson:
|
||||
stringEndianness = registerJson['stringEndianness']
|
||||
|
||||
|
||||
errorLimitUntilNotReachable = 10
|
||||
if 'errorLimitUntilNotReachable' in registerJson:
|
||||
errorLimitUntilNotReachable = registerJson['errorLimitUntilNotReachable']
|
||||
|
|
@ -875,6 +921,7 @@ logger.debug('Script path: %s' % scriptPath)
|
|||
logger.debug('Output directory: %s' % outputDirectory)
|
||||
logger.debug('Class name prefix: %s' % classNamePrefix)
|
||||
logger.debug('Endianness: %s' % endianness)
|
||||
logger.debug('String endianness: %s' % stringEndianness)
|
||||
logger.debug('Error limit until not reachable: %s' % errorLimitUntilNotReachable)
|
||||
logger.debug('Check reachable register: %s' % checkReachableRegister['id'])
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue