/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2020, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea-zigbee. * This project including source code and documentation is protected by copyright law, and * remains the property of nymea GmbH. All rights, including reproduction, publication, * editing and translation, are reserved. The use of this project is subject to the terms of a * license agreement to be concluded with nymea GmbH in accordance with the terms * of use of nymea GmbH, available under https://nymea.io/license * * GNU Lesser General Public License Usage * Alternatively, this project may be redistributed and/or modified under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; version 3. * this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this project. * If not, see . * * For any further details and any questions please contact us under contact@nymea.io * or see our FAQ/Licensing Information on https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "zigbeedatatype.h" #include "zigbeeutils.h" #include #include ZigbeeDataType::ZigbeeDataType() { setDataType(Zigbee::NoData); } ZigbeeDataType::ZigbeeDataType(const ZigbeeDataType &other) { setDataType(other.dataType()); m_data = other.data(); } ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data): m_data(data) { setDataType(dataType); // TODO: verify data length and consistency /* switch (dataType) { case Zigbee::NoData: break; case Zigbee::Data8: break; case Zigbee::Data16: break; case Zigbee::Data24: break; case Zigbee::Data32: break; case Zigbee::Data40: break; case Zigbee::Data48: break; case Zigbee::Data56: break; case Zigbee::Data64: break; case Zigbee::Bool: break; case Zigbee::BitMap8: break; case Zigbee::BitMap16: break; case Zigbee::BitMap24: break; case Zigbee::BitMap32: break; case Zigbee::BitMap40: break; case Zigbee::BitMap48: break; case Zigbee::BitMap56: break; case Zigbee::BitMap64: break; case Zigbee::Uint8: 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; } */ } ZigbeeDataType::ZigbeeDataType(quint8 value) { setDataType(Zigbee::Uint8); m_data.clear(); QDataStream stream(&m_data, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << value; } ZigbeeDataType::ZigbeeDataType(quint16 value) { setDataType(Zigbee::Uint16); 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(qint8 value) { setDataType(Zigbee::Int8); m_data.clear(); QDataStream stream(&m_data, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << value; } ZigbeeDataType::ZigbeeDataType(qint16 value) { setDataType(Zigbee::Int16); m_data.clear(); QDataStream stream(&m_data, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << value; } ZigbeeDataType::ZigbeeDataType(qint32 value, Zigbee::DataType dataType) { Q_ASSERT_X(dataType == Zigbee::Int24 || dataType == Zigbee::Int32, "ZigbeeDataType", "invalid data type for qint32 constructor"); setDataType(dataType); m_data.clear(); QDataStream stream(&m_data, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << value; if (m_dataType == Zigbee::Int24) { m_data.chop(1); } } ZigbeeDataType::ZigbeeDataType(qint64 value, Zigbee::DataType dataType) { Q_ASSERT_X(dataType == Zigbee::Int40 || dataType == Zigbee::Int48 || dataType == Zigbee::Int56 || dataType == Zigbee::Int64, "ZigbeeDataType", "invalid data type for qint64 constructor"); setDataType(dataType); m_data.clear(); QDataStream stream(&m_data, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << value; if (m_dataType == Zigbee::Int40) { m_data.chop(3); } else if (m_dataType == Zigbee::Int48) { m_data.chop(2); } else if (m_dataType == Zigbee::Int56) { 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(1) : static_cast(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(value.length()); for (int i = 0; i < value.length(); i++) { stream << static_cast(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(value.length()); for (int i = 0; i < value.length(); i++) { stream << static_cast(value.at(i).toLatin1()); } } } quint8 ZigbeeDataType::toUInt8(bool *ok) const { if (ok) *ok = true; if (m_data.count() != 1) { if (ok) *ok = false; return 0; } return static_cast(m_data.at(0)); } quint16 ZigbeeDataType::toUInt16(bool *ok) const { if (ok) *ok = true; quint16 value = 0; if (m_data.count() != 2) { 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) { // Make it 32 bit for converting QByteArray convertedData(m_data); convertedData.append(static_cast(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; } // Make it 64 bit for converting QByteArray convertedData(m_data); for (int i = 0; i < 3; i++) convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } case Zigbee::Uint48: { if (m_data.count() != 6) { if (ok) *ok = false; break; } // Make it 64 bit for converting QByteArray convertedData(m_data); for (int i = 0; i < 2; i++) convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } case Zigbee::Uint56: { if (m_data.count() != 7) { if (ok) *ok = false; break; } // Make it 64 bit for converting QByteArray convertedData(m_data); convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } case Zigbee::Uint64: { if (m_data.count() != 8) { if (ok) *ok = false; break; } QDataStream stream(m_data); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } default: if (ok) *ok = false; break; } return value; } qint8 ZigbeeDataType::toInt8(bool *ok) const { if (ok) *ok = true; if (m_data.count() != 1) { if (ok) *ok = false; return 0; } return static_cast(m_data.at(0)); } qint16 ZigbeeDataType::toInt16(bool *ok) const { if (ok) *ok = true; qint16 value = 0; if (m_data.count() != 2 || m_dataType != Zigbee::Int16) { if (ok) *ok = false; return value; } QDataStream stream(m_data); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; return value; } qint32 ZigbeeDataType::toInt32(bool *ok) const { if (ok) *ok = true; qint32 value = 0; // Verify the data type if (m_dataType != Zigbee::Int24 && m_dataType != Zigbee::Int32) { 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) { // Make it 32 bit for converting QByteArray convertedData(m_data); convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; } else { QDataStream stream(m_data); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; } return value; } qint64 ZigbeeDataType::toInt64(bool *ok) const { if (ok) *ok = true; qint64 value = 0; switch (m_dataType) { case Zigbee::Int40: { if (m_data.count() != 5) { if (ok) *ok = false; break; } // Make it 64 bit for converting QByteArray convertedData(m_data); for (int i = 0; i < 3; i++) convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } case Zigbee::Int48: { if (m_data.count() != 6) { if (ok) *ok = false; break; } // Make it 64 bit for converting QByteArray convertedData(m_data); for (int i = 0; i < 2; i++) convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } case Zigbee::Int56: { if (m_data.count() != 7) { if (ok) *ok = false; break; } // Make it 64 bit for converting QByteArray convertedData(m_data); convertedData.append(static_cast(0)); QDataStream stream(convertedData); stream.setByteOrder(QDataStream::LittleEndian); stream >> value; break; } case Zigbee::Int64: { if (m_data.count() != 8) { if (ok) *ok = false; break; } 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); } bool ZigbeeDataType::isValid() const { // FIXME: implement validate data depending on the type return m_dataType != Zigbee::NoData && !m_data.isNull(); } int ZigbeeDataType::typeLength(Zigbee::DataType dataType) { int length = 0; switch (dataType) { case Zigbee::NoData: break; case Zigbee::Data8: length = 1; break; case Zigbee::Data16: length = 2; break; case Zigbee::Data24: length = 3; break; case Zigbee::Data32: length = 4; break; case Zigbee::Data40: length = 5; break; case Zigbee::Data48: length = 6; break; case Zigbee::Data56: length = 7; break; case Zigbee::Data64: length = 8; break; case Zigbee::Bool: length = 1; break; case Zigbee::BitMap8: length = 1; break; case Zigbee::BitMap16: length = 2; break; case Zigbee::BitMap24: length = 3; break; case Zigbee::BitMap32: length = 4; break; case Zigbee::BitMap40: length = 5; break; case Zigbee::BitMap48: length = 6; break; case Zigbee::BitMap56: length = 7; break; case Zigbee::BitMap64: length = 8; break; case Zigbee::Uint8: length = 1; break; case Zigbee::Uint16: length = 2; break; case Zigbee::Uint24: length = 3; break; case Zigbee::Uint32: length = 4; break; case Zigbee::Uint40: length = 5; break; case Zigbee::Uint48: length = 6; break; case Zigbee::Uint56: length = 7; break; case Zigbee::Uint64: length = 8; break; case Zigbee::Int8: length = 1; break; case Zigbee::Int16: length = 2; break; case Zigbee::Int24: length = 3; break; case Zigbee::Int32: length = 4; break; case Zigbee::Int40: length = 5; break; case Zigbee::Int48: length = 6; break; case Zigbee::Int56: length = 7; break; case Zigbee::Int64: length = 8; break; case Zigbee::Enum8: length = 1; break; case Zigbee::Enum16: length = 2; break; case Zigbee::FloatSemi: length = 2; break; case Zigbee::FloatSingle: length = 4; break; case Zigbee::FloatDouble: length = 8; break; case Zigbee::OctetString: // first byte is length length = -1; break; case Zigbee::CharString: // first byte is length length = -1; break; case Zigbee::LongOctetString: // first 2 byte is length length = -2; break; case Zigbee::LongCharString: // first 2 byte is length length = -2; break; case Zigbee::Array: // 2 + sum of lengths of content length = -3; break; case Zigbee::Structure: // 2 + sum of lengths of content length = -3; break; case Zigbee::Set: // sum of lengths of content length = -4; break; case Zigbee::Bag: // sum of lengths of content length = -4; break; case Zigbee::TimeOfDay: length = 4; break; case Zigbee::Date: length = 4; break; case Zigbee::UtcTime: length = 4; break; case Zigbee::Cluster: length = 2; break; case Zigbee::Attribute: length = 2; break; case Zigbee::BacnetId: length = 4; break; case Zigbee::IeeeAddress: length = 8; break; case Zigbee::BitKey128: length = 16; break; case Zigbee::Unknown: break; } return length; } ZigbeeDataType &ZigbeeDataType::operator=(const ZigbeeDataType &other) { setDataType(other.dataType()); m_data = other.data(); return *this; } bool ZigbeeDataType::operator==(const ZigbeeDataType &other) const { return m_dataType == other.dataType() && m_data == other.data(); } bool ZigbeeDataType::operator!=(const ZigbeeDataType &other) const { return !operator==(other); } 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) { // FIXME: print data depending on the datatype debug.nospace() << "ZigbeeDataType(" << dataType.name(); switch (dataType.dataType()) { case Zigbee::OctetString: case Zigbee::LongOctetString: case Zigbee::LongCharString: case Zigbee::CharString: debug.nospace() << ", " << dataType.toString(); break; default: debug.nospace() << ", " << ZigbeeUtils::convertByteArrayToHexString(dataType.data()); } debug.nospace() << ")"; return debug.space(); }