Start implementing data type converter

pull/7/head
Simon Stürz 2020-05-26 15:58:12 +02:00
parent 396c86a0d2
commit ab560a9c55
3 changed files with 608 additions and 181 deletions

View File

@ -1,181 +1,15 @@
#include "zigbeedatatype.h"
#include "zigbeeutils.h"
#include <QtGlobal>
#include <QDataStream>
ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data):
m_dataType(dataType),
m_data(data)
{
switch (dataType) {
case Zigbee::NoData:
m_name = "No data";
m_className = "Null";
m_typeLength = typeLength(m_dataType);
m_data.clear();
break;
case Zigbee::Data8:
m_name = "8-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data16:
m_name = "16-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data24:
m_name = "24-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data32:
m_name = "32-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data40:
m_name = "40-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data48:
m_name = "48-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data56:
m_name = "56-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data64:
m_name = "64-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Bool:
m_name = "Bool";
m_className = "Logical discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap8:
m_name = "8-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap16:
m_name = "16-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap24:
m_name = "24-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap32:
m_name = "32-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap40:
m_name = "40-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap48:
m_name = "48-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap56:
m_name = "56-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap64:
m_name = "64-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint8:
m_name = "Unsigned 8-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint16:
break;
case Zigbee::Uint24:
break;
case Zigbee::Uint32:
break;
case Zigbee::Uint40:
break;
case Zigbee::Uint48:
break;
case Zigbee::Uint56:
break;
case Zigbee::Uint64:
break;
case Zigbee::Int8:
break;
case Zigbee::Int16:
break;
case Zigbee::Int24:
break;
case Zigbee::Int32:
break;
case Zigbee::Int40:
break;
case Zigbee::Int48:
break;
case Zigbee::Int56:
break;
case Zigbee::Int64:
break;
case Zigbee::Enum8:
break;
case Zigbee::Enum16:
break;
case Zigbee::FloatSemi:
break;
case Zigbee::FloatSingle:
break;
case Zigbee::FloatDouble:
break;
case Zigbee::OctetString:
break;
case Zigbee::CharString:
break;
case Zigbee::LongOctetString:
break;
case Zigbee::LongCharString:
break;
case Zigbee::Array:
break;
case Zigbee::Structure:
break;
case Zigbee::Set:
break;
case Zigbee::Bag:
break;
case Zigbee::TimeOfDay:
break;
case Zigbee::Date:
break;
case Zigbee::UtcTime:
break;
case Zigbee::Cluster:
break;
case Zigbee::Attribute:
break;
case Zigbee::BacnetId:
break;
case Zigbee::IeeeAddress:
break;
case Zigbee::BitKey128:
break;
case Zigbee::Unknown:
break;
}
setDataType(dataType);
// TODO: verify data length and consistency
@ -299,6 +133,282 @@ ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data
}
ZigbeeDataType::ZigbeeDataType(quint8 value, Zigbee::DataType dataType) :
m_dataType(dataType)
{
Q_ASSERT_X(dataType == Zigbee::Uint8, "ZigbeeDataType", "invalid data type for quint8 constructor");
setDataType(dataType);
m_data.clear();
QDataStream stream(&m_data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << value;
}
ZigbeeDataType::ZigbeeDataType(quint16 value, Zigbee::DataType dataType)
{
Q_ASSERT_X(dataType == Zigbee::Uint16, "ZigbeeDataType", "invalid data type for quint16 constructor");
setDataType(dataType);
m_data.clear();
QDataStream stream(&m_data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << value;
}
ZigbeeDataType::ZigbeeDataType(quint32 value, Zigbee::DataType dataType)
{
Q_ASSERT_X(dataType == Zigbee::Uint24 || dataType == Zigbee::Uint32, "ZigbeeDataType", "invalid data type for quint32 constructor");
setDataType(dataType);
m_data.clear();
QDataStream stream(&m_data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << value;
if (m_dataType == Zigbee::Uint24) {
m_data.chop(1);
}
}
ZigbeeDataType::ZigbeeDataType(quint64 value, Zigbee::DataType dataType)
{
Q_ASSERT_X(dataType == Zigbee::Uint40 || dataType == Zigbee::Uint48 || dataType == Zigbee::Uint56 || dataType == Zigbee::Uint64, "ZigbeeDataType", "invalid data type for quint64 constructor");
setDataType(dataType);
m_data.clear();
QDataStream stream(&m_data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << value;
if (m_dataType == Zigbee::Uint40) {
m_data.chop(3);
} else if (m_dataType == Zigbee::Uint48) {
m_data.chop(2);
} else if (m_dataType == Zigbee::Uint56) {
m_data.chop(1);
}
}
ZigbeeDataType::ZigbeeDataType(bool value)
{
setDataType(Zigbee::Bool);
m_data.clear();
QDataStream stream(&m_data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << (value ? static_cast<quint8>(1) : static_cast<quint8>(0));
}
ZigbeeDataType::ZigbeeDataType(const QString &value, Zigbee::DataType dataType)
{
Q_ASSERT_X(dataType == Zigbee::OctetString || dataType == Zigbee::CharString || dataType == Zigbee::LongOctetString || dataType == Zigbee::LongCharString, "ZigbeeDataType", "invalid data type for QString constructor");
setDataType(dataType);
m_data.clear();
QDataStream stream(&m_data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
if (dataType == Zigbee::OctetString || dataType == Zigbee::CharString) {
Q_ASSERT_X(value.length() <= 255, "ZigbeeDataType", "the given string is too long for this datatype. Maximum size is 255");
stream << static_cast<quint8>(value.length());
for (int i = 0; i < value.length(); i++) {
stream << static_cast<quint8>(value.at(i).toLatin1());
}
} else if (dataType == Zigbee::LongOctetString || dataType == Zigbee::LongCharString) {
Q_ASSERT_X(value.length() <= 0xffff, "ZigbeeDataType", "the given string is too long for this datatype. Maximum size is 0xffff");
stream << static_cast<quint16>(value.length());
for (int i = 0; i < value.length(); i++) {
stream << static_cast<quint16>(value.at(i).toLatin1());
}
}
}
quint8 ZigbeeDataType::toUInt8(bool *ok) const
{
*ok = true;
if (m_data.count() != 1 || m_dataType != Zigbee::Uint8) {
*ok = false;
return 0;
}
return static_cast<quint8>(m_data.at(0));
}
quint16 ZigbeeDataType::toUInt16(bool *ok) const
{
if (ok) *ok = true;
quint16 value = 0;
if (m_data.count() != 2 || m_dataType != Zigbee::Uint16) {
if (ok) *ok = false;
return value;
}
QDataStream stream(m_data);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
return value;
}
quint32 ZigbeeDataType::toUInt32(bool *ok) const
{
if (ok) *ok = true;
quint32 value = 0;
// Verify the data type
if (m_dataType != Zigbee::Uint24 && m_dataType != Zigbee::Uint32) {
if (ok) *ok = false;
return value;
}
// Make sure there is enought data
if (m_data.count() != 3 && m_data.count() != 4) {
if (ok) *ok = false;
return value;
}
if (m_data.count() == 3) {
// Note: make it 32 bit
QByteArray convertedData(m_data);
convertedData.append(static_cast<char>(0));
QDataStream stream(convertedData);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
} else {
QDataStream stream(m_data);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
}
return value;
}
quint64 ZigbeeDataType::toUInt64(bool *ok) const
{
if (ok) *ok = true;
quint64 value = 0;
switch (m_dataType) {
case Zigbee::Uint40: {
if (m_data.count() != 5) {
if (ok) *ok = false;
break;
}
// Note: make it 64 bit for converting
QByteArray convertedData(m_data);
for (int i = 0; i < 3; i++)
convertedData.append(static_cast<char>(0));
QDataStream stream(convertedData);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
break;
}
case Zigbee::Uint48: {
if (m_data.count() != 6) {
if (ok) *ok = false;
break;
}
// Note: make it 64 bit for converting
QByteArray convertedData(m_data);
for (int i = 0; i < 2; i++)
convertedData.append(static_cast<char>(0));
QDataStream stream(convertedData);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
break;
}
case Zigbee::Uint56: {
if (m_data.count() != 7) {
if (ok) *ok = false;
break;
}
// Note: make it 64 bit for converting
QByteArray convertedData(m_data);
convertedData.append(static_cast<char>(0));
QDataStream stream(convertedData);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
break;
}
case Zigbee::Uint64: {
if (m_data.count() != 8) {
if (ok) *ok = false;
break;
}
// Note: make it 64 bit for converting
QDataStream stream(m_data);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> value;
break;
}
default:
if (ok) *ok = false;
break;
}
return value;
}
bool ZigbeeDataType::toBool(bool *ok) const
{
if (ok) *ok = true;
bool value = false;
if (m_data.count() != 1) {
if (ok) *ok = false;
return value;
}
if (m_data.at(0) != 0) {
value = true;
}
return value;
}
QString ZigbeeDataType::toString(bool *ok) const
{
if (ok) *ok = true;
QString value;
if (m_dataType == Zigbee::OctetString || m_dataType == Zigbee::CharString) {
quint8 length = m_data.at(0);
value = QString::fromUtf8(m_data.right(length));
} else if (m_dataType == Zigbee::LongOctetString || m_dataType == Zigbee::LongCharString) {
quint16 length = 0;
QDataStream lengthStream(m_data.left(2));
lengthStream.setByteOrder(QDataStream::LittleEndian);
lengthStream >> length;
value = QString::fromUtf8(m_data.right(length));
} else {
if (ok) *ok = false;
}
return value;
}
Zigbee::DataType ZigbeeDataType::dataType() const
{
return m_dataType;
}
QString ZigbeeDataType::name() const
{
return m_name;
}
QString ZigbeeDataType::className() const
{
return m_className;
}
QByteArray ZigbeeDataType::data() const
{
return m_data;
}
int ZigbeeDataType::dataLength() const
{
return typeLength(m_dataType);
@ -434,27 +544,27 @@ int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
break;
case Zigbee::LongOctetString:
// first 2 byte is length
length = -1;
length = -2;
break;
case Zigbee::LongCharString:
// first 2 byte is length
length = -1;
length = -2;
break;
case Zigbee::Array:
// 2 + sum of lengths of content
length = -1;
length = -3;
break;
case Zigbee::Structure:
// 2 + sum of lengths of content
length = -1;
length = -3;
break;
case Zigbee::Set:
// 2 + sum of lengths of content
length = -1;
// sum of lengths of content
length = -4;
break;
case Zigbee::Bag:
// 2 + sum of lengths of content
length = -1;
// sum of lengths of content
length = -4;
break;
case Zigbee::TimeOfDay:
length = 4;
@ -486,3 +596,297 @@ int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
return length;
}
void ZigbeeDataType::setDataType(Zigbee::DataType dataType)
{
m_dataType = dataType;
switch (dataType) {
case Zigbee::NoData:
m_name = "No data";
m_className = "Null";
m_typeLength = typeLength(m_dataType);
m_data.clear();
break;
case Zigbee::Data8:
m_name = "8-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data16:
m_name = "16-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data24:
m_name = "24-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data32:
m_name = "32-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data40:
m_name = "40-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data48:
m_name = "48-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data56:
m_name = "56-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Data64:
m_name = "64-bit data";
m_className = "General data discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Bool:
m_name = "Bool";
m_className = "Logical discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap8:
m_name = "8-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap16:
m_name = "16-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap24:
m_name = "24-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap32:
m_name = "32-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap40:
m_name = "40-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap48:
m_name = "48-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap56:
m_name = "56-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitMap64:
m_name = "64-bit bitmap";
m_className = "Bitmap discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint8:
m_name = "Unsigned 8-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint16:
m_name = "Unsigned 16-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint24:
m_name = "Unsigned 24-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint32:
m_name = "Unsigned 32-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint40:
m_name = "Unsigned 40-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint48:
m_name = "Unsigned 48-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint56:
m_name = "Unsigned 56-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Uint64:
m_name = "Unsigned 64-bit integer";
m_className = "Unsigned integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int8:
m_name = "Signed 8-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int16:
m_name = "Signed 16-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int24:
m_name = "Signed 24-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int32:
m_name = "Signed 32-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int40:
m_name = "Signed 40-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int48:
m_name = "Signed 48-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int56:
m_name = "Signed 56-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Int64:
m_name = "Signed 64-bit integer";
m_className = "Signed integer analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Enum8:
m_name = "8-bit enumeration";
m_className = "Enumeration discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Enum16:
m_name = "16-bit enumeration";
m_className = "Enumeration discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::FloatSemi:
m_name = "Semi-precision";
m_className = "Floating point analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::FloatSingle:
m_name = "Single precision";
m_className = "Floating point analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::FloatDouble:
m_name = "Double precision";
m_className = "Floating point analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::OctetString:
m_name = "Octet string";
m_className = "String discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::CharString:
m_name = "Character string";
m_className = "String discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::LongOctetString:
m_name = "Long octet string";
m_className = "String discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::LongCharString:
m_name = "Long character string";
m_className = "String discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Array:
m_name = "Array";
m_className = "Ordered sequence discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Structure:
m_name = "Structure";
m_className = "Ordered sequence discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Set:
m_name = "Set";
m_className = "Collection discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Bag:
m_name = "Bag";
m_className = "Collection discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::TimeOfDay:
m_name = "Time of day";
m_className = "Time analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Date:
m_name = "Date";
m_className = "Time analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::UtcTime:
m_name = "UTC time";
m_className = "Time analog";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Cluster:
m_name = "Cluster ID";
m_className = "Identifier discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Attribute:
m_name = "Attribute ID";
m_className = "Identifier discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BacnetId:
m_name = "BACnet OID";
m_className = "Identifier discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::IeeeAddress:
m_name = "IEEE address";
m_className = "Miscellaneous discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::BitKey128:
m_name = "128-bit security key";
m_className = "Miscellaneous discrete";
m_typeLength = typeLength(m_dataType);
break;
case Zigbee::Unknown:
break;
}
}
QDebug operator<<(QDebug debug, const ZigbeeDataType &dataType)
{
debug.nospace() << "ZigbeeDataType(" << dataType.name();
debug.nospace() << ", " << ZigbeeUtils::convertByteArrayToHexString(dataType.data());
debug.nospace() << ")";
return debug.space();
}

View File

@ -3,11 +3,29 @@
#include "zigbee.h"
class ZigbeeDataType
{
public:
ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data = QByteArray());
ZigbeeDataType(quint8 value, Zigbee::DataType dataType = Zigbee::Uint8);
ZigbeeDataType(quint16 value, Zigbee::DataType dataType = Zigbee::Uint16);
ZigbeeDataType(quint32 value, Zigbee::DataType dataType = Zigbee::Uint32);
ZigbeeDataType(quint64 value, Zigbee::DataType dataType = Zigbee::Uint64);
ZigbeeDataType(bool value);
ZigbeeDataType(const QString &value, Zigbee::DataType dataType = Zigbee::CharString);
quint8 toUInt8(bool *ok = nullptr) const;
quint16 toUInt16(bool *ok = nullptr) const;
quint32 toUInt32(bool *ok = nullptr) const;
quint64 toUInt64(bool *ok = nullptr) const;
bool toBool(bool *ok = nullptr) const;
QString toString(bool *ok = nullptr) const;
Zigbee::DataType dataType() const;
QString name() const;
QString className() const;
@ -22,6 +40,10 @@ private:
QString m_name = "Unknown";
QString m_className = "Null";
int m_typeLength = 0;
void setDataType(Zigbee::DataType dataType);
};
QDebug operator<<(QDebug debug, const ZigbeeDataType &dataType);
#endif // ZIGBEEDATATYPE_H

View File

@ -36,6 +36,7 @@
#include <QBitArray>
#include "zigbee.h"
#include "zigbeedatatype.h"
#include "zcl/zigbeecluster.h"