Add basic structure of DoorLock cluster for testing

pull/13/head
Simon Stürz 2020-11-06 15:28:52 +01:00
parent 0c6924e3f2
commit 6b92b27c1f
6 changed files with 392 additions and 2 deletions

View File

@ -16,6 +16,7 @@ SOURCES += \
backends/nxp/interface/zigbeeinterfacenxpreply.cpp \
backends/nxp/zigbeebridgecontrollernxp.cpp \
backends/nxp/zigbeenetworknxp.cpp \
zcl/closures/zigbeeclusterdoorlock.cpp \
zcl/general/zigbeeclusteridentify.cpp \
zcl/general/zigbeeclusterlevelcontrol.cpp \
zcl/general/zigbeeclusteronoff.cpp \
@ -68,6 +69,7 @@ HEADERS += \
backends/nxp/interface/zigbeeinterfacenxpreply.h \
backends/nxp/zigbeebridgecontrollernxp.h \
backends/nxp/zigbeenetworknxp.h \
zcl/closures/zigbeeclusterdoorlock.h \
zcl/general/zigbeeclusteridentify.h \
zcl/general/zigbeeclusterlevelcontrol.h \
zcl/general/zigbeeclusteronoff.h \

View File

@ -0,0 +1,144 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 "zigbeeclusterdoorlock.h"
#include "zigbeenetworkreply.h"
#include "loggingcategory.h"
#include "zigbeenetwork.h"
#include "zigbeeutils.h"
#include <QDataStream>
ZigbeeClusterDoorLock::ZigbeeClusterDoorLock(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) :
ZigbeeCluster(network, node, endpoint, ZigbeeClusterLibrary::ClusterIdDoorLock, direction, parent)
{
}
ZigbeeClusterReply *ZigbeeClusterDoorLock::lockDoor(const QByteArray code)
{
QByteArray payload;
if (!code.isEmpty()) {
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(Zigbee::OctetString);
for (int i = 0; i < code.length(); i++) {
stream << static_cast<quint8>(code.at(i));
}
}
return executeClusterCommand(Command::CommandLockDoor, payload);
}
ZigbeeClusterReply *ZigbeeClusterDoorLock::unlockDoor(const QByteArray code)
{
QByteArray payload;
if (!code.isEmpty()) {
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(Zigbee::OctetString);
for (int i = 0; i < code.length(); i++) {
stream << static_cast<quint8>(code.at(i));
}
}
return executeClusterCommand(Command::CommandUnlockDoor, payload);
}
ZigbeeClusterReply *ZigbeeClusterDoorLock::toggle(const QByteArray code)
{
QByteArray payload;
if (!code.isEmpty()) {
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(Zigbee::OctetString);
for (int i = 0; i < code.length(); i++) {
stream << static_cast<quint8>(code.at(i));
}
}
return executeClusterCommand(Command::CommandToggle, payload);
}
ZigbeeClusterReply *ZigbeeClusterDoorLock::unlockDoorWithTimeout(quint16 timeoutSeconds, const QByteArray code)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << timeoutSeconds;
if (!code.isEmpty()) {
stream << static_cast<quint8>(Zigbee::OctetString);
for (int i = 0; i < code.length(); i++) {
stream << static_cast<quint8>(code.at(i));
}
}
return executeClusterCommand(Command::CommandUnlockWithTimeout, payload);
}
ZigbeeClusterDoorLock::LockState ZigbeeClusterDoorLock::lockState() const
{
return m_lockState;
}
ZigbeeClusterDoorLock::DoorState ZigbeeClusterDoorLock::doorState() const
{
return m_doorState;
}
void ZigbeeClusterDoorLock::setAttribute(const ZigbeeClusterAttribute &attribute)
{
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
if (hasAttribute(attribute.id())) {
m_attributes[attribute.id()] = attribute;
emit attributeChanged(attribute);
} else {
m_attributes.insert(attribute.id(), attribute);
emit attributeChanged(attribute);
}
switch (attribute.id()) {
case AttributeLockState:
m_lockState = static_cast<LockState>(attribute.dataType().toUInt8());
emit lockStateChanged(m_lockState);
break;
case AttributeDoorState:
m_doorState = static_cast<DoorState>(attribute.dataType().toUInt8());
emit doorStateChanged(m_doorState);
break;
}
}
void ZigbeeClusterDoorLock::processDataIndication(ZigbeeClusterLibrary::Frame frame)
{
//qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame;
// Increase the tsn for continuouse id increasing on both sides
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
}

View File

@ -0,0 +1,237 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEECLUSTERDOORLOCK_H
#define ZIGBEECLUSTERDOORLOCK_H
#include <QObject>
#include "zcl/zigbeecluster.h"
#include "zcl/zigbeeclusterreply.h"
class ZigbeeNode;
class ZigbeeNetwork;
class ZigbeeNodeEndpoint;
class ZigbeeNetworkReply;
class ZigbeeClusterDoorLock : public ZigbeeCluster
{
Q_OBJECT
friend class ZigbeeNode;
friend class ZigbeeNetwork;
public:
enum Attribute {
// Basic information
AttributeLockState = 0x0000, // M
AttributeLockType = 0x0001, // M
AttributeActuatorEnabled = 0x0002, // M
AttributeDoorState = 0x0003,
AttributeDoorOpenEvents = 0x0004,
AttributeDoorClosedEvents = 0x0005,
AttributeOpenPeriod = 0x0006,
// User, Pin, Schedule, Log information
AttributeNumberOfLogRecordsSupported = 0x0010,
AttributeNumberOfTotalUsersSupported = 0x0011,
AttributeNumberOfPinUsersSupported = 0x0012,
AttributeNumberOfRfidUsersSupported = 0x0013,
AttributeNumberOfWeekDaySchedulesSupportedPerUser = 0x0014,
AttributeNumberOfYearDaySchedulesSupportedPerUser = 0x0015,
AttributeNumberOfHolidaySchedulesSupported = 0x0016,
AttributeMaxPinCodeLength = 0x0017,
AttributeMinPinCodeLenght = 0x0018,
AttributeMaxRfidCodeLength = 0x0019,
AttributeMinRfidCodeLength = 0x001a,
// Operational settings
AttributeEnableLogging = 0x0020,
AttributeLanguage = 0x0021,
AttributeLedSettings = 0x0022,
AttributeAutoRelockTime = 0x0023,
AttributeSoundVolume = 0x0024,
AttributeOperatingMode = 0x0025,
AttributeSupportedOperatingModes = 0x0026,
AttributeDefaultConfigurationRegister = 0x0027,
AttributeEnableLocalProgramming = 0x0028,
AttributeEnableOneTouchLocking = 0x0029,
AttributeEnableInsideStatusLed = 0x002a,
AttributeEnablePrivacyModeButton = 0x002b,
// Security settings
AttributeWrongCodeEntryLimit = 0x0030,
AttributeUserCodeTemporaryDisableTime = 0x0031,
AttributeSendPinOverTheAir = 0x0032,
AttributeRequirePinForRfOperation = 0x0033,
AttributeZigbeeSecurityLevel = 0x0034,
// Alarm and event masks
AttributeAlarmMask = 0x0040,
AttributeKeypadOperationEventMask = 0x0041,
AttributeRfOperationEventMask = 0x0042,
AttributeManualOperationEventMask = 0x0043,
AttributeRfidOperationEventMask = 0x0044,
AttributeKeypadProgrammingEventMask = 0x0045,
AttributeRfProgrammingEventMask = 0x0046,
AttributeRfidProgrammingEventMask = 0x0047
};
Q_ENUM(Attribute)
enum Command {
CommandLockDoor = 0x00, // M
CommandUnlockDoor = 0x01, // M
CommandToggle = 0x02,
CommandUnlockWithTimeout = 0x03,
CommandGetLogRecord = 0x04,
CommandSetPinCode = 0x05,
CommandGetPinCode = 0x06,
CommandClearPinCode = 0x07,
CommandClearAllPinCodes = 0x08,
CommandSetUserStatus = 0x09,
CommandGetUserStatus = 0x0a,
CommandSetWeekdaySchedule = 0x0b,
CommandGetWeekdaySchedule = 0x0c,
CommandClearWeekdaySchedule = 0x0d,
CommandSetYearDaySchedule = 0x0e,
CommandGetYearDaySchedule = 0x0f,
CommandClearYearDaySchedule = 0x10,
CommandSetHolidaySchedule = 0x11,
CommandGetHolidaySchedule = 0x12,
CommandClearHolidaySchedule = 0x13,
CommandSetUserType = 0x14,
CommandGetUserType = 0x15,
CommandSetRfidCode = 0x16,
CommandGetRfidCode = 0x17,
CommandClearRfidCode = 0x18,
CommandClearAllRfidCodes = 0x19
};
Q_ENUM(Command)
// AttributeLockState (0x0000)
enum LockState {
LockStateNotFullyLocked = 0x00,
LockStateLocked = 0x01,
LockStateUnlocked = 0x02,
LockStateUndefined = 0xff
};
Q_ENUM(LockState)
// AttributeLockType (0x0001)
enum LockType {
LockTypeDeadBolt = 0x00,
LockTypeMagnetic = 0x01,
LockTypeOther = 0x02,
LockTypeMortise = 0x03,
LockTypeRim = 0x04,
LockTypeLatchBolt = 0x05,
LockTypeCylindricalLock = 0x06,
LockTypeTubularLock = 0x07,
LockTypeInterconnectedLock = 0x08,
LockTypeDeadLatch = 0x09,
LockTypeDoorFurniture = 0x0a
};
Q_ENUM(LockType)
// AttributeDoorState (0x0003)
enum DoorState {
DoorStateOpen = 0x00,
DoorStateColsed = 0x01,
DoorStateErrorJammed = 0x02,
DoorStateErrorForcedOpen = 0x03,
DoorStateErrorUnspecified = 0x04,
DoorStateUndefined = 0xff
};
Q_ENUM(DoorState)
// AttributeOperatingMode (0x0025)
enum OperationMode {
OperationModeNormal = 0x00,
OperationModeVacation = 0x01,
OperationModePrivacy = 0x02,
OperationModeNoRfLockUnlock = 0x03,
OperationModePassage = 0x04
};
Q_ENUM(OperationMode)
// AttributeSupportedOperatingModes (0x0026)
enum SupportedOperationMode {
SupportedOperationModeNormal = 0x0000,
SupportedOperationModeVacation = 0x0001,
SupportedOperationModePrivacy = 0x0002,
SupportedOperationModeNoRfLockUnlock = 0x0004,
SupportedOperationModePassage = 0x0008
};
Q_ENUM(SupportedOperationMode)
Q_DECLARE_FLAGS(SupportedOperationModes, SupportedOperationMode)
// AttributeLedSettings (0x0022)
enum LedSettings {
LedSettingsNeverUserLedSignalisation = 0x00,
LedSettingsUseLedSignalisationExceptAccessAllowedEvents = 0x01,
LedSettingsUseLedSignalisationAllEvents = 0x02
};
Q_ENUM(LedSettings)
// AttributeSoundVolume (0x0024)
enum SoundVolume {
SoundVolumeSilentMode = 0x00,
SoundVolumeLowVolume = 0x01,
SoundVolumeHighVolume = 0x02
};
Q_ENUM(SoundVolume)
explicit ZigbeeClusterDoorLock(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
// Note: with HA 1.2, this commands have optional a RFID code or PIN code
ZigbeeClusterReply *lockDoor(const QByteArray code = QByteArray());
ZigbeeClusterReply *unlockDoor(const QByteArray code = QByteArray());
ZigbeeClusterReply *toggle(const QByteArray code = QByteArray());
ZigbeeClusterReply *unlockDoorWithTimeout(quint16 timeoutSeconds, const QByteArray code = QByteArray());
// TODO: rest of the commands
LockState lockState() const;
DoorState doorState() const;
private:
LockState m_lockState = LockStateUndefined;
DoorState m_doorState = DoorStateUndefined;
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
protected:
void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;
signals:
void lockStateChanged(LockState lockState);
void doorStateChanged(DoorState doorState);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterDoorLock::SupportedOperationModes)
#endif // ZIGBEECLUSTERDOORLOCK_H

View File

@ -99,6 +99,8 @@ void ZigbeeClusterOta::processDataIndication(ZigbeeClusterLibrary::Frame frame)
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(StatuCodeNoImageAvailable);
// Note: if there would be an image available, the response would be success, followed by manufacturer code, image type, file version of image and file size
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandQueryNextImageResponse, frame.header.transactionSequenceNumber, payload);
connect(reply, &ZigbeeClusterReply::finished, this, [](){
qCDebug(dcZigbeeCluster()) << "OTA image request response for image query sent successfully to requested node.";

View File

@ -30,8 +30,6 @@
#include "zigbeenode.h"
#include "loggingcategory.h"
#include "zcl/general/zigbeeclusterbasic.h"
quint8 ZigbeeNodeEndpoint::endpointId() const
{
return m_endpointId;
@ -197,6 +195,11 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(ZigbeeClusterLibrary::ClusterId
return new ZigbeeClusterOccupancySensing(m_network, m_node, this, direction, this);
break;
// Colsures
case ZigbeeClusterLibrary::ClusterIdDoorLock:
return new ZigbeeClusterDoorLock(m_network, m_node, this, direction, this);
break;
// Lighting
case ZigbeeClusterLibrary::ClusterIdColorControl:
return new ZigbeeClusterColorControl(m_network, m_node, this, direction, this);

View File

@ -43,6 +43,8 @@
#include "zcl/general/zigbeeclusterlevelcontrol.h"
#include "zcl/general/zigbeeclusterpowerconfiguration.h"
#include "zcl/closures/zigbeeclusterdoorlock.h"
#include "zcl/measurement/zigbeeclusteroccupancysensing.h"
#include "zcl/measurement/zigbeeclusterilluminancemeasurment.h"
#include "zcl/measurement/zigbeeclustertemperaturemeasurement.h"