add logging categories

This commit is contained in:
Simon Stürz 2017-10-17 16:21:31 +02:00
parent e36a15e856
commit 3d0385363f
13 changed files with 448 additions and 268 deletions

View File

@ -4,6 +4,5 @@
Core::Core(QObject *parent) : Core::Core(QObject *parent) :
QObject(parent) QObject(parent)
{ {
m_manager = new ZigbeeManager("/dev/ttyS0", this);
} }

5
loggingcategory.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "loggingcategory.h"
Q_LOGGING_CATEGORY(dcZigbee, "Zigbee")
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")

11
loggingcategory.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef LOGGINGCATEGORY_H
#define LOGGINGCATEGORY_H
#include <QDebug>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(dcZigbee)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
#endif // LOGGINGCATEGORY_H

View File

@ -1,11 +1,70 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <unistd.h>
#include "core.h" #include "core.h"
#include "loggingcategory.h"
static const char *const normal = "\033[0m";
static const char *const warning = "\e[33m";
static const char *const error = "\e[31m";
static QHash<QString, bool> s_loggingFilters;
static void loggingCategoryFilter(QLoggingCategory *category)
{
// If this is a known category
if (s_loggingFilters.contains(category->categoryName())) {
category->setEnabled(QtDebugMsg, s_loggingFilters.value(category->categoryName()));
category->setEnabled(QtWarningMsg, true);
category->setEnabled(QtCriticalMsg, true);
category->setEnabled(QtFatalMsg, true);
} else {
//Disable default debug messages, print only >= warnings
category->setEnabled(QtDebugMsg, false);
category->setEnabled(QtWarningMsg, true);
category->setEnabled(QtCriticalMsg, true);
category->setEnabled(QtFatalMsg, true);
}
}
static void consoleLogHandler(QtMsgType type, const QMessageLogContext& context, const QString& message)
{
switch (type) {
case QtInfoMsg:
fprintf(stdout, " I | %s: %s\n", context.category, message.toUtf8().data());
break;
case QtDebugMsg:
fprintf(stdout, " I | %s: %s\n", context.category, message.toUtf8().data());
break;
case QtWarningMsg:
fprintf(stdout, "%s W | %s: %s%s\n", warning, context.category, message.toUtf8().data(), normal);
break;
case QtCriticalMsg:
fprintf(stdout, "%s C | %s: %s%s\n", error, context.category, message.toUtf8().data(), normal);
break;
case QtFatalMsg:
fprintf(stdout, "%s F | %s: %s%s\n", error, context.category, message.toUtf8().data(), normal);
break;
}
fflush(stdout);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); qInstallMessageHandler(consoleLogHandler);
QCoreApplication application(argc, argv);
s_loggingFilters.insert("Zigbee", true);
s_loggingFilters.insert("ZigbeeInterface", true);
s_loggingFilters.insert("ZigbeeInterfaceTraffic", false);
QLoggingCategory::installFilter(loggingCategoryFilter);
Core core; Core core;
return a.exec(); return application.exec();
} }

View File

@ -13,10 +13,14 @@ SOURCES += main.cpp \
core.cpp \ core.cpp \
zigbeeinterface.cpp \ zigbeeinterface.cpp \
zigbeemanager.cpp \ zigbeemanager.cpp \
zigbee.cpp zigbee.cpp \
zigbeeinterfacemessage.cpp \
loggingcategory.cpp
HEADERS += \ HEADERS += \
core.h \ core.h \
zigbeeinterface.h \ zigbeeinterface.h \
zigbeemanager.h \ zigbeemanager.h \
zigbee.h zigbee.h \
zigbeeinterfacemessage.h \
loggingcategory.h

View File

@ -1 +1,33 @@
#include "zigbee.h" #include "zigbee.h"
QString Zigbee::convertByteToHexString(const quint8 &byte)
{
QString hexString;
QString byteString = QString::number(byte, 16);
if (byteString.count() == 1) {
hexString = QString("0x0%1").arg(byteString);
} else {
hexString = QString("0x%1").arg(byteString);
}
return hexString.toStdString().data();
}
QString Zigbee::convertByteArrayToHexString(const QByteArray &byteArray)
{
QString hexString;
for (int i = 0; i < byteArray.count(); i++) {
hexString.append(convertByteToHexString((quint8)byteArray.at(i)));
if (i != byteArray.count() -1) {
hexString.append(" ");
}
}
return hexString.toStdString().data();
}
QString Zigbee::convertByte16ToHexString(const quint16 &byte)
{
quint8 msbByte = (byte >> 8) & 0xff;
quint8 lsbByte = (byte >> 0) & 0xff;
return convertByteToHexString(msbByte) + convertByteToHexString(lsbByte).remove("0x");
}

189
zigbee.h
View File

@ -2,12 +2,201 @@
#define ZIGBEE_H #define ZIGBEE_H
#include <QObject> #include <QObject>
#include <QString>
#include <QByteArray>
class Zigbee class Zigbee
{ {
Q_GADGET Q_GADGET
public: public:
enum InterfaceMessageType {
/* Common Commands */
Status = 0x8000,
Logging = 0x8001,
DataIndication = 0x8002,
NodeClusterList = 0x8003,
NodeAttributeList = 0x8004,
NodeCommandIdList = 0x8005,
RestartProvisioned = 0x8006,
RestartFactoryNew = 0x8007,
GetVersion = 0x0010,
VersionList = 0x8010,
SetExtendetPanId = 0x0020,
SetChannelMask = 0x0021,
SetSecurity = 0x0022,
SetDeviceType = 0x0023,
StartNetwork = 0x0024,
StartScan = 0x0025,
NetworkJoinedFormed = 0x8024,
NetworkRemoveDevice = 0x0026,
NetworkWhitelistEnable = 0x0027,
AuthenticateDeviceRequest = 0x0028,
AuthenticateDeviceResponse = 0x8028,
OutOfBandCommisioningDataRequest = 0x0029,
OutOfBandCommisioningDataResponse = 0x8029,
Reset = 0x0011,
ErasePersistentData = 0x0012,
ZllFactoryNew = 0x0013,
GetPermitJoin = 0x0014,
GetPermitJoinResponse = 0x8014,
Bind = 0x0030,
BindResponse = 0x8030,
Unbind = 0x0031,
UnbindResponse = 0x8031,
NetworkAdressRequest = 0x0040,
NetworkAdressResponse = 0x8040,
IeeeAddressResponse = 0x0041,
IeeeAddressRequest = 0x8041,
NodeDescriptorRequest = 0x0042,
NodeDescriptorRsponse = 0x8042,
SimpleDescriptorRequest = 0x0043,
SimpleDescriptorResponse = 0x8043,
PowerDescriptorRequest = 0x0044,
PowerDescriptorResponse = 0x8044,
ActiveEndpointRequest = 0x0045,
ActiveEndpointResponse = 0x8045,
MatchDescriptorRequest = 0x0046,
MatchDescriptorResponse = 0x8046,
ManagementLeaveRequest = 0x0047,
ManagementLeaveResponse = 0x8047,
LeaveIndication = 0x8048,
PermitJoiningRequest = 0x0049,
ManagementNetworkUpdateRequest = 0x004A,
ManagementNetworkUpdateResponse = 0x804A,
SystemServerDiscoveryRequest = 0x004B,
SystemServerDiscoveryResponse = 0x804B,
DeviceAnnounce = 0x004D,
ManagementLqiRequest = 0x004E,
ManagementLqiResponse = 0x804E,
/* Group Cluster */
AddGroupRequest = 0x0060,
AddGroupResponse = 0x8060,
ViewGroupRequest = 0x0061,
ViewGroupResponse = 0x8061,
GetGroupMembershipRequest = 0x0062,
GetGroupMembershipResponse = 0x8062,
RemoveGroupRequest = 0x0063,
RemoveGroupResponse = 0x8063,
RemoveAllGroups = 0x0064,
GroupIfIdentify = 0x0065,
/* Identify Cluster */
IdentifySend = 0x0070,
IdentifyQuery = 0x0071,
/* Level Cluster */
MoveToLevel = 0x0080,
MoveToLevelOnOff = 0x0081,
MoveStep = 0x0082,
MoveStopMove = 0x0083,
MoveStopMoveOnOff = 0x0084,
/* Scenes Cluster */
ViewScene = 0x00A0,
ViewSceneResponse = 0x80A0,
AddScene = 0x00A1,
AddSceneResponse = 0x80A1,
RemoveScene = 0x00A2,
RemoveSceneResponse = 0x80A2,
RemoveAllScenes = 0x00A3,
RemoveAllScenesResponse = 0x80A3,
StoreScene = 0x00A4,
StoreSceneResponse = 0x80A4,
RecallScene = 0x00A5,
SceneMembershipRequest = 0x00A6,
SceneMembershipResponse = 0x80A6,
/* Colour Cluster */
MoveToHue = 0x00B0,
MoveHue = 0x00B1,
StepHue = 0x00B2,
MoveToSaturation = 0x00B3,
MoveSaturation = 0x00B4,
StepStaturation = 0x00B5,
MoveToHueSaturation = 0x00B6,
MoveToColor = 0x00B7,
MoveColor = 0x00B8,
StepColor = 0x00B9,
/* ZLL Commands */
/* Touchlink */
InitiateTouchlink = 0x00D0,
TouchlinkStatus = 0x00D1,
TouchlinkFactoryReset = 0x00D2,
/* Identify Cluster */
IdentifyTriggerEffect = 0x00E0,
/* On/Off Cluster */
CluserOnOff = 0x0092,
CluserOnOffTimed = 0x0093,
CluserOnOffEffects = 0x0094,
CluserOnOffUpdate = 0x8095,
/* Scenes Cluster */
AddEnhancedScene = 0x00A7,
ViewEnhancedScene = 0x00A8,
CopyScene = 0x00A9,
/* Colour Cluster */
EnhancedMoveToHue = 0x00BA,
EnhancedMoveHue = 0x00BB,
EnhancedStepHue = 0x00BC,
EnhancedMoveToHueSaturation = 0x00BD,
ColourLoopSet = 0x00BE,
StopMoveStep = 0x00BF,
MoveToColorTemperature = 0x00C0,
MoveColorTemperature = 0x00C1,
StepColorTemperature = 0x00C2,
/* ZHA Commands */
/* Door Lock Cluster */
LockUnlockDoor = 0x00F0,
/* Attributes */
ReadAttributeRequest = 0x0100,
ReadAttributeResponse = 0x8100,
DefaultResponse = 0x8101,
AttributeReport = 0x8102,
WriteAttributeRequest = 0x0110,
WriteAttributeResponse = 0x8110,
ConfigReportingRequest = 0x0120,
ConfigReportingResponse = 0x8120,
ReportAttributes = 0x8121,
AttributeDiscoveryRequest = 0x0140,
AttributeDiscoveryResponse = 0x8140,
/* Persistant data manager messages */
DataManagerAvailableRequest = 0x0300,
DataManagerAvailableResponse = 0x8300,
DataManagerSaveRecordRequest = 0x0200,
DataManagerSaveRecordResponse = 0x8200,
DataManagerLoadRecordRequest = 0x0201,
DataManagerLoadRecordResponse = 0x8201,
DataManagerDeleteAllRecordsRequest = 0x0202,
DataManagerDeleteAllRecordsResponse = 0x8202,
/* Appliance Statistics Cluster 0x0B03 */
// http://www.nxp.com/documents/user_manual/JN-UG-3076.pdf
StatisticsClusterLogMessage = 0x0301, // Was 0x0500, was 0x0301
StatisticsClusterLogMessageResponse = 0x8301,
/* IAS Cluster */
SendIasZoneEnroolResponse = 0x0400,
IasZoneStatusChangeNotify = 0x8401,
};
Q_ENUM(InterfaceMessageType)
static QString convertByteToHexString(const quint8 &byte);
static QString convertByteArrayToHexString(const QByteArray &byteArray);
static QString convertByte16ToHexString(const quint16 &byte);
}; };

View File

@ -1,6 +1,5 @@
#include "zigbeeinterface.h" #include "zigbeeinterface.h"
#include "loggingcategory.h"
#include <QDebug>
ZigbeeInterface::ZigbeeInterface(QObject *parent) : ZigbeeInterface::ZigbeeInterface(QObject *parent) :
QObject(parent), QObject(parent),
@ -15,44 +14,12 @@ bool ZigbeeInterface::available() const
return m_serialPort->isOpen(); return m_serialPort->isOpen();
} }
QString ZigbeeInterface::convertByteToHexString(const quint8 &byte) quint8 ZigbeeInterface::calculateCrc(const quint16 &messageTypeValue, const quint16 &lenghtValue, const QByteArray &data)
{
QString hexString;
QString byteString = QString::number(byte, 16);
if (byteString.count() == 1) {
hexString = QString("0x0%1").arg(byteString);
} else {
hexString = QString("0x%1").arg(byteString);
}
return hexString.toStdString().data();
}
QString ZigbeeInterface::convertByteArrayToHexString(const QByteArray &byteArray)
{
QString hexString;
for (int i = 0; i < byteArray.count(); i++) {
hexString.append(convertByteToHexString((quint8)byteArray.at(i)));
if (i != byteArray.count() -1) {
hexString.append(" ");
}
}
return hexString.toStdString().data();
}
QString ZigbeeInterface::convertByte16ToHexString(const quint16 &byte)
{
quint8 msbByte = (byte >> 8) & 0xff;
quint8 lsbByte = (byte >> 0) & 0xff;
return convertByteToHexString(msbByte) + convertByteToHexString(lsbByte).remove("0x");
}
quint8 ZigbeeInterface::calculateCrc(const quint16 &commandValue, const quint16 &lenghtValue, const QByteArray &data)
{ {
quint8 crc = 0; quint8 crc = 0;
crc ^= (commandValue >> 8) & 0xff; crc ^= (messageTypeValue >> 8) & 0xff;
crc ^= (commandValue >> 0) & 0xff; crc ^= (messageTypeValue >> 0) & 0xff;
crc ^= (lenghtValue >> 8) & 0xff; crc ^= (lenghtValue >> 8) & 0xff;
crc ^= (lenghtValue >> 0) & 0xff; crc ^= (lenghtValue >> 0) & 0xff;
@ -68,16 +35,16 @@ void ZigbeeInterface::streamByte(quint8 byte, bool specialCharacter)
{ {
if (!specialCharacter && byte < 0x10) { if (!specialCharacter && byte < 0x10) {
// Byte stuffing ESC char before stuffed data byte // Byte stuffing ESC char before stuffed data byte
qDebug() << "[out]" << convertByteToHexString(0x02); qCDebug(dcZigbeeInterfaceTraffic()) << "[out]" << Zigbee::convertByteToHexString(0x02);
if (m_serialPort->write(QByteArray::fromRawData("\x02", 1)) < 0) { if (m_serialPort->write(QByteArray::fromRawData("\x02", 1)) < 0) {
qWarning() << "Could not stream ESC byte" << convertByteArrayToHexString(QByteArray::fromRawData("\x02", 1)); qCWarning(dcZigbeeInterface()) << "Could not stream ESC byte" << Zigbee::convertByteArrayToHexString(QByteArray::fromRawData("\x02", 1));
} }
byte ^= 0x10; byte ^= 0x10;
} }
qDebug() << "[out]" << convertByteToHexString(byte); qCDebug(dcZigbeeInterfaceTraffic()) << "[out]" << Zigbee::convertByteToHexString(byte);
if (m_serialPort->write(QByteArray(1, (char)byte)) < 0) { if (m_serialPort->write(QByteArray(1, (char)byte)) < 0) {
qWarning() << "Could not stream byte" << convertByteToHexString(byte); qCWarning(dcZigbeeInterface()) << "Could not stream byte" << Zigbee::convertByteToHexString(byte);
} }
m_serialPort->flush(); m_serialPort->flush();
} }
@ -88,7 +55,7 @@ void ZigbeeInterface::setReadingState(const ZigbeeInterface::ReadingState &state
return; return;
m_readingState = state; m_readingState = state;
qDebug() << m_readingState; qCDebug(dcZigbeeInterfaceTraffic()) << m_readingState;
} }
void ZigbeeInterface::onReadyRead() void ZigbeeInterface::onReadyRead()
@ -99,13 +66,12 @@ void ZigbeeInterface::onReadyRead()
for (int i = 0; i < data.length(); i++) { for (int i = 0; i < data.length(); i++) {
quint8 byte = static_cast<quint8>(data.at(i)); quint8 byte = static_cast<quint8>(data.at(i));
qDebug() << "[ in]" << convertByteToHexString(byte); qCDebug(dcZigbeeInterfaceTraffic()) << "[ in]" << Zigbee::convertByteToHexString(byte);
switch (byte) { switch (byte) {
case 0x01: case 0x01:
//qDebug() << "START message received";
m_crcValue = 0; m_crcValue = 0;
m_commandValue = 0; m_messageTypeValue = 0;
m_lengthValue = 0; m_lengthValue = 0;
m_escapeDetected = false; m_escapeDetected = false;
m_data.clear(); m_data.clear();
@ -113,18 +79,19 @@ void ZigbeeInterface::onReadyRead()
setReadingState(WaitForTypeMsb); setReadingState(WaitForTypeMsb);
break; break;
case 0x02: case 0x02:
//qDebug() << "ESC char received";
m_escapeDetected = true; m_escapeDetected = true;
break; break;
case 0x03: { case 0x03: {
quint8 crc = calculateCrc(m_commandValue, m_lengthValue, m_data); Zigbee::InterfaceMessageType messageType = static_cast<Zigbee::InterfaceMessageType>(m_messageTypeValue);
quint8 crc = calculateCrc(m_messageTypeValue, m_lengthValue, m_data);
if (crc != m_crcValue) { if (crc != m_crcValue) {
qWarning() << "Invalid CRC value" << crc << "!=" << m_crcValue; qCWarning(dcZigbeeInterface()) << "Invalid CRC value" << crc << "!=" << m_crcValue;
} else if (m_data.count() != m_lengthValue) { } else if (m_data.count() != m_lengthValue) {
qWarning() << "ERROR: Invalid data length" << m_data.count() << "!=" << m_lengthValue; qCWarning(dcZigbeeInterface()) << "ERROR:s Invalid data length" << m_data.count() << "!=" << m_lengthValue;
} else { } else {
qDebug() << "<--" << (Type)m_commandValue << convertByte16ToHexString(m_commandValue) << "CRC:" << convertByteToHexString(m_crcValue) << convertByte16ToHexString(m_lengthValue) << convertByteArrayToHexString(m_data); ZigbeeInterfaceMessage message(messageType, m_data);
emit messageReceived((Type)m_commandValue, m_data); qCDebug(dcZigbeeInterface()) << "<--" << message;
emit messageReceived(message);
} }
setReadingState(WaitForStart); setReadingState(WaitForStart);
break; break;
@ -137,17 +104,17 @@ void ZigbeeInterface::onReadyRead()
m_escapeDetected = false; m_escapeDetected = false;
} }
// Read data bytes depending on the reading state
switch (m_readingState) { switch (m_readingState) {
case WaitForStart: case WaitForStart:
break; break;
case WaitForTypeMsb: case WaitForTypeMsb:
m_commandValue = byte; m_messageTypeValue = byte;
m_commandValue <<= 8; m_messageTypeValue <<= 8;
setReadingState(WaitForTypeLsb); setReadingState(WaitForTypeLsb);
break; break;
case WaitForTypeLsb: case WaitForTypeLsb:
m_commandValue |= byte; m_messageTypeValue |= byte;
//qDebug() << "Command:" << convertByte16ToHexString(m_commandValue) << (Type)m_commandValue;
setReadingState(WaitForLenghtMsb); setReadingState(WaitForLenghtMsb);
break; break;
case WaitForLenghtMsb: case WaitForLenghtMsb:
@ -177,7 +144,7 @@ void ZigbeeInterface::onReadyRead()
void ZigbeeInterface::onError(const QSerialPort::SerialPortError &error) void ZigbeeInterface::onError(const QSerialPort::SerialPortError &error)
{ {
qWarning() << "Serial port error:" << error << m_serialPort->errorString(); qCWarning(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString();
} }
bool ZigbeeInterface::enable(const QString &serialPort) bool ZigbeeInterface::enable(const QString &serialPort)
@ -197,13 +164,13 @@ bool ZigbeeInterface::enable(const QString &serialPort)
connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError))); connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError)));
if (!m_serialPort->open(QSerialPort::ReadWrite)) { if (!m_serialPort->open(QSerialPort::ReadWrite)) {
qWarning() << "Could not open serial port" << serialPort; qCWarning(dcZigbeeInterface()) << "Could not open serial port" << serialPort;
delete m_serialPort; delete m_serialPort;
m_serialPort = nullptr; m_serialPort = nullptr;
return false; return false;
} }
qDebug() << "Interface enabled successfully on" << serialPort; qCDebug(dcZigbeeInterface()) << "Interface enabled successfully on" << serialPort;
return true; return true;
} }
@ -217,26 +184,27 @@ void ZigbeeInterface::disable()
delete m_serialPort; delete m_serialPort;
m_serialPort = nullptr; m_serialPort = nullptr;
qDebug() << "Interface disabled"; qCDebug(dcZigbeeInterface()) << "Interface disabled";
} }
void ZigbeeInterface::sendCommand(const ZigbeeInterface::Type &commandType, const QByteArray &data) void ZigbeeInterface::sendMessage(const ZigbeeInterfaceMessage &message)
{ {
quint16 commandValue = static_cast<quint16>(commandType); quint16 messageTypeValue = static_cast<quint16>(message.messageType());
quint16 lengthValue = static_cast<quint16>(data.count()); quint16 lengthValue = static_cast<quint16>(message.data().count());
quint8 crcValue = calculateCrc(commandValue, lengthValue, data);
qDebug() << "-->" << commandType << convertByte16ToHexString(commandValue) << "CRC:" << convertByteToHexString(crcValue) << convertByte16ToHexString(lengthValue) << convertByteArrayToHexString(data); quint8 crcValue = calculateCrc(messageTypeValue, lengthValue, message.data());
qCDebug(dcZigbeeInterface()) << "-->" << message << "crc:" << Zigbee::convertByteToHexString(crcValue) << ", length:" << Zigbee::convertByte16ToHexString(lengthValue);
streamByte(0x01, true); streamByte(0x01, true);
streamByte((commandValue >> 8) & 0xff); streamByte((messageTypeValue >> 8) & 0xff);
streamByte((commandValue >> 0) & 0xff); streamByte((messageTypeValue >> 0) & 0xff);
streamByte((lengthValue >> 8) & 0xff); streamByte((lengthValue >> 8) & 0xff);
streamByte((lengthValue >> 0) & 0xff); streamByte((lengthValue >> 0) & 0xff);
streamByte(crcValue); streamByte(crcValue);
for (int i = 0; i < data.count(); i++) { for (int i = 0; i < message.data().count(); i++) {
streamByte(data.at(i)); streamByte(message.data().at(i));
} }
streamByte(0x03, true); streamByte(0x03, true);
} }

View File

@ -4,6 +4,9 @@
#include <QObject> #include <QObject>
#include <QSerialPort> #include <QSerialPort>
#include "zigbee.h"
#include "zigbeeinterfacemessage.h"
class ZigbeeInterface : public QObject class ZigbeeInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -19,190 +22,6 @@ public:
}; };
Q_ENUM(ReadingState) Q_ENUM(ReadingState)
enum Type {
/* Common Commands */
Status = 0x8000,
Logging = 0x8001,
DataIndication = 0x8002,
NodeClusterList = 0x8003,
NodeAttributeList = 0x8004,
NodeCommandIdList = 0x8005,
RestartProvisioned = 0x8006,
RestartFactoryNew = 0x8007,
GetVersion = 0x0010,
VersionList = 0x8010,
SetExtendetPanId = 0x0020,
SetChannelMask = 0x0021,
SetSecurity = 0x0022,
SetDeviceType = 0x0023,
StartNetwork = 0x0024,
StartScan = 0x0025,
NetworkJoinedFormed = 0x8024,
NetworkRemoveDevice = 0x0026,
NetworkWhitelistEnable = 0x0027,
AuthenticateDeviceRequest = 0x0028,
AuthenticateDeviceResponse = 0x8028,
OutOfBandCommisioningDataRequest = 0x0029,
OutOfBandCommisioningDataResponse = 0x8029,
Reset = 0x0011,
ErasePersistentData = 0x0012,
ZllFactoryNew = 0x0013,
GetPermitJoin = 0x0014,
GetPermitJoinResponse = 0x8014,
Bind = 0x0030,
BindResponse = 0x8030,
Unbind = 0x0031,
UnbindResponse = 0x8031,
NetworkAdressRequest = 0x0040,
NetworkAdressResponse = 0x8040,
IeeeAddressResponse = 0x0041,
IeeeAddressRequest = 0x8041,
NodeDescriptorRequest = 0x0042,
NodeDescriptorRsponse = 0x8042,
SimpleDescriptorRequest = 0x0043,
SimpleDescriptorResponse = 0x8043,
PowerDescriptorRequest = 0x0044,
PowerDescriptorResponse = 0x8044,
ActiveEndpointRequest = 0x0045,
ActiveEndpointResponse = 0x8045,
MatchDescriptorRequest = 0x0046,
MatchDescriptorResponse = 0x8046,
ManagementLeaveRequest = 0x0047,
ManagementLeaveResponse = 0x8047,
LeaveIndication = 0x8048,
PermitJoiningRequest = 0x0049,
ManagementNetworkUpdateRequest = 0x004A,
ManagementNetworkUpdateResponse = 0x804A,
SystemServerDiscoveryRequest = 0x004B,
SystemServerDiscoveryResponse = 0x804B,
DeviceAnnounce = 0x004D,
ManagementLqiRequest = 0x004E,
ManagementLqiResponse = 0x804E,
/* Group Cluster */
AddGroupRequest = 0x0060,
AddGroupResponse = 0x8060,
ViewGroupRequest = 0x0061,
ViewGroupResponse = 0x8061,
GetGroupMembershipRequest = 0x0062,
GetGroupMembershipResponse = 0x8062,
RemoveGroupRequest = 0x0063,
RemoveGroupResponse = 0x8063,
RemoveAllGroups = 0x0064,
GroupIfIdentify = 0x0065,
/* Identify Cluster */
IdentifySend = 0x0070,
IdentifyQuery = 0x0071,
/* Level Cluster */
MoveToLevel = 0x0080,
MoveToLevelOnOff = 0x0081,
MoveStep = 0x0082,
MoveStopMove = 0x0083,
MoveStopMoveOnOff = 0x0084,
/* Scenes Cluster */
ViewScene = 0x00A0,
ViewSceneResponse = 0x80A0,
AddScene = 0x00A1,
AddSceneResponse = 0x80A1,
RemoveScene = 0x00A2,
RemoveSceneResponse = 0x80A2,
RemoveAllScenes = 0x00A3,
RemoveAllScenesResponse = 0x80A3,
StoreScene = 0x00A4,
StoreSceneResponse = 0x80A4,
RecallScene = 0x00A5,
SceneMembershipRequest = 0x00A6,
SceneMembershipResponse = 0x80A6,
/* Colour Cluster */
MoveToHue = 0x00B0,
MoveHue = 0x00B1,
StepHue = 0x00B2,
MoveToSaturation = 0x00B3,
MoveSaturation = 0x00B4,
StepStaturation = 0x00B5,
MoveToHueSaturation = 0x00B6,
MoveToColor = 0x00B7,
MoveColor = 0x00B8,
StepColor = 0x00B9,
/* ZLL Commands */
/* Touchlink */
InitiateTouchlink = 0x00D0,
TouchlinkStatus = 0x00D1,
TouchlinkFactoryReset = 0x00D2,
/* Identify Cluster */
IdentifyTriggerEffect = 0x00E0,
/* On/Off Cluster */
CluserOnOff = 0x0092,
CluserOnOffTimed = 0x0093,
CluserOnOffEffects = 0x0094,
CluserOnOffUpdate = 0x8095,
/* Scenes Cluster */
AddEnhancedScene = 0x00A7,
ViewEnhancedScene = 0x00A8,
CopyScene = 0x00A9,
/* Colour Cluster */
EnhancedMoveToHue = 0x00BA,
EnhancedMoveHue = 0x00BB,
EnhancedStepHue = 0x00BC,
EnhancedMoveToHueSaturation = 0x00BD,
ColourLoopSet = 0x00BE,
StopMoveStep = 0x00BF,
MoveToColorTemperature = 0x00C0,
MoveColorTemperature = 0x00C1,
StepColorTemperature = 0x00C2,
/* ZHA Commands */
/* Door Lock Cluster */
LockUnlockDoor = 0x00F0,
/* Attributes */
ReadAttributeRequest = 0x0100,
ReadAttributeResponse = 0x8100,
DefaultResponse = 0x8101,
AttributeReport = 0x8102,
WriteAttributeRequest = 0x0110,
WriteAttributeResponse = 0x8110,
ConfigReportingRequest = 0x0120,
ConfigReportingResponse = 0x8120,
ReportAttributes = 0x8121,
AttributeDiscoveryRequest = 0x0140,
AttributeDiscoveryResponse = 0x8140,
/* Persistant data manager messages */
DataManagerAvailableRequest = 0x0300,
DataManagerAvailableResponse = 0x8300,
DataManagerSaveRecordRequest = 0x0200,
DataManagerSaveRecordResponse = 0x8200,
DataManagerLoadRecordRequest = 0x0201,
DataManagerLoadRecordResponse = 0x8201,
DataManagerDeleteAllRecordsRequest = 0x0202,
DataManagerDeleteAllRecordsResponse = 0x8202,
/* Appliance Statistics Cluster 0x0B03 */
// http://www.nxp.com/documents/user_manual/JN-UG-3076.pdf
StatisticsClusterLogMessage = 0x0301, // Was 0x0500, was 0x0301
StatisticsClusterLogMessageResponse = 0x8301,
/* IAS Cluster */
SendIasZoneEnroolResponse = 0x0400,
IasZoneStatusChangeNotify = 0x8401,
};
Q_ENUM(Type)
explicit ZigbeeInterface(QObject *parent = nullptr); explicit ZigbeeInterface(QObject *parent = nullptr);
bool available() const; bool available() const;
@ -215,16 +34,12 @@ private:
ReadingState m_readingState; ReadingState m_readingState;
quint8 m_crcValue; quint8 m_crcValue;
quint8 m_currentValue; quint8 m_currentValue;
quint16 m_commandValue; quint16 m_messageTypeValue;
quint16 m_lengthValue; quint16 m_lengthValue;
QByteArray m_data; QByteArray m_data;
bool m_escapeDetected; bool m_escapeDetected;
QString convertByteToHexString(const quint8 &byte); quint8 calculateCrc(const quint16 &messageTypeValue, const quint16 &lenghtValue, const QByteArray &data);
QString convertByteArrayToHexString(const QByteArray &byteArray);
QString convertByte16ToHexString(const quint16 &byte);
quint8 calculateCrc(const quint16 &commandValue, const quint16 &lenghtValue, const QByteArray &data);
void streamByte(quint8 byte, bool specialCharacter = false); void streamByte(quint8 byte, bool specialCharacter = false);
@ -232,7 +47,7 @@ private:
signals: signals:
void availableChanged(const bool &available); void availableChanged(const bool &available);
void messageReceived(const Type &commandType, const QByteArray &data = QByteArray()); void messageReceived(const ZigbeeInterfaceMessage &message);
private slots: private slots:
void onReadyRead(); void onReadyRead();
@ -242,7 +57,7 @@ public slots:
bool enable(const QString &serialPort = "/dev/ttyS0"); bool enable(const QString &serialPort = "/dev/ttyS0");
void disable(); void disable();
void sendCommand(const Type &commandType, const QByteArray &data = QByteArray()); void sendMessage(const ZigbeeInterfaceMessage &message);
}; };

View File

@ -0,0 +1,39 @@
#include "zigbeeinterfacemessage.h"
ZigbeeInterfaceMessage::ZigbeeInterfaceMessage()
{
}
ZigbeeInterfaceMessage::ZigbeeInterfaceMessage(const Zigbee::InterfaceMessageType &messageType, const QByteArray &data):
m_messageType(messageType),
m_data(data)
{
}
Zigbee::InterfaceMessageType ZigbeeInterfaceMessage::messageType() const
{
return m_messageType;
}
void ZigbeeInterfaceMessage::setMessageType(const Zigbee::InterfaceMessageType &messageType)
{
m_messageType = messageType;
}
QByteArray ZigbeeInterfaceMessage::data() const
{
return m_data;
}
void ZigbeeInterfaceMessage::setData(const QByteArray &data)
{
m_data = data;
}
QDebug operator<<(QDebug dbg, const ZigbeeInterfaceMessage &message)
{
dbg.nospace().noquote() << "InterfaceMessage(" << message.messageType() << Zigbee::convertByteArrayToHexString(message.data()) << ")";
return dbg.space();
}

29
zigbeeinterfacemessage.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef ZIGBEEINTERFACEMESSAGE_H
#define ZIGBEEINTERFACEMESSAGE_H
#include <QObject>
#include <QDebug>
#include "zigbee.h"
class ZigbeeInterfaceMessage
{
public:
ZigbeeInterfaceMessage();
ZigbeeInterfaceMessage(const Zigbee::InterfaceMessageType &messageType, const QByteArray &data = QByteArray());
Zigbee::InterfaceMessageType messageType() const;
void setMessageType(const Zigbee::InterfaceMessageType &messageType);
QByteArray data() const;
void setData(const QByteArray &data);
private:
Zigbee::InterfaceMessageType m_messageType;
QByteArray m_data;
};
QDebug operator<<(QDebug dbg, const ZigbeeInterfaceMessage &message);
#endif // ZIGBEEINTERFACEMESSAGE_H

View File

@ -1,4 +1,5 @@
#include "zigbeemanager.h" #include "zigbeemanager.h"
#include "loggingcategory.h"
ZigbeeManager::ZigbeeManager(const QString &serialPort, QObject *parent) : ZigbeeManager::ZigbeeManager(const QString &serialPort, QObject *parent) :
QObject(parent), QObject(parent),
@ -6,9 +7,16 @@ ZigbeeManager::ZigbeeManager(const QString &serialPort, QObject *parent) :
{ {
m_interface = new ZigbeeInterface(this); m_interface = new ZigbeeInterface(this);
connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeManager::onMessageReceived);
if (!m_interface->enable(m_serialPort)) {
qCWarning(dcZigbee()) << "Could not enable ZigbeeInterface on" << m_serialPort;
return;
}
initController();
m_interface->enable(m_serialPort);
m_interface->sendCommand(ZigbeeInterface::DataManagerAvailableResponse, QByteArray::fromRawData("\x00\x00", 2));
} }
QString ZigbeeManager::serialPort() const QString ZigbeeManager::serialPort() const
@ -25,3 +33,17 @@ void ZigbeeManager::setSerialPort(const QString &serialPort)
m_interface->disable(); m_interface->disable();
m_interface->enable(m_serialPort); m_interface->enable(m_serialPort);
} }
void ZigbeeManager::initController()
{
ZigbeeInterfaceMessage message;
message.setMessageType(Zigbee::DataManagerAvailableResponse);
message.setData(QByteArray::fromRawData("\x00\x00", 2));
m_interface->sendMessage(message);
}
void ZigbeeManager::onMessageReceived(const ZigbeeInterfaceMessage &message)
{
qCDebug(dcZigbee()) << message;
}

View File

@ -3,7 +3,9 @@
#include <QObject> #include <QObject>
#include "zigbee.h"
#include "zigbeeinterface.h" #include "zigbeeinterface.h"
#include "zigbeeinterfacemessage.h"
class ZigbeeManager : public QObject class ZigbeeManager : public QObject
{ {
@ -18,8 +20,14 @@ private:
ZigbeeInterface *m_interface; ZigbeeInterface *m_interface;
QString m_serialPort; QString m_serialPort;
// Controller methods
void initController();
signals: signals:
private slots:
void onMessageReceived(const ZigbeeInterfaceMessage &message);
public slots: public slots:
}; };