* Copyright (c) 2016-2021 dresden elektronik ingenieurtechnik gmbh.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
*/
#include "de_web_plugin.h"
#include "de_web_plugin_private.h"
#include "zdp/zdp.h"
The manager will observe and ensure the global permit join state.
*/
void DeRestPluginPrivate::initPermitJoin()
{
permitJoinFlag = false;
permitJoinTimer = new QTimer(this);
permitJoinTimer->setSingleShot(false);
connect(permitJoinTimer, SIGNAL(timeout()),
this, SLOT(permitJoinTimerFired()));
permitJoinTimer->start(1000);
}
\param duration specifies the interval in which joining is enabled
- 0 disabled
- >0 duration in seconds until joining will be disabled
*/
void DeRestPluginPrivate::setPermitJoinDuration(int duration)
{
if (gwPermitJoinDuration != duration)
{
gwPermitJoinDuration = duration;
}
permitJoinLastSendTime.invalidate();
}
This is done every PERMIT_JOIN_SEND_INTERVAL to ensure
any node in the network has the same settings.
*/
void DeRestPluginPrivate::permitJoinTimerFired()
{
Q_Q(DeRestPlugin);
if (!q->pluginActive() || !apsCtrl)
{
return;
}
if (gwPermitJoinDuration > 0)
{
gwPermitJoinDuration--;
if (!permitJoinFlag)
{
permitJoinFlag = true;
enqueueEvent(Event(RConfig, REventPermitjoinEnabled, gwPermitJoinDuration));
}
else
{
enqueueEvent(Event(RConfig, REventPermitjoinRunning, gwPermitJoinDuration));
}
if (DEV_TestManaged())
{
}
else if ((gwPermitJoinDuration % 10) == 0)
{
int i = 0;
const deCONZ::Node *node = nullptr;
while (apsCtrl->getNode(i, &node) == 0)
{
if (node && !node->isZombie() &&
!node->nodeDescriptor().isNull() && node->nodeDescriptor().receiverOnWhenIdle())
{
addLightNode(node);
}
i++;
}
}
updateEtag(gwConfigEtag);
}
if (!isInNetwork())
{
return;
}
auto ctrlPermitJoin = apsCtrl->getParameter(deCONZ::ParamPermitJoin);
if (ctrlPermitJoin > 0 && gwPermitJoinDuration == 0)
{
apsCtrl->setPermitJoin(gwPermitJoinDuration);
permitJoinLastSendTime.invalidate();
}
if (!permitJoinFlag)
{
}
else if (!permitJoinLastSendTime.isValid() || (permitJoinLastSendTime.elapsed() > PERMIT_JOIN_SEND_INTERVAL && !gwdisablePermitJoinAutoOff))
{
deCONZ::ApsDataRequest apsReq;
quint8 tcSignificance = 0x01;
apsReq.setDstAddressMode(deCONZ::ApsNwkAddress);
apsReq.dstAddress().setNwk(deCONZ::BroadcastRouters);
apsReq.setProfileId(ZDP_PROFILE_ID);
apsReq.setClusterId(ZDP_MGMT_PERMIT_JOINING_REQ_CLID);
apsReq.setDstEndpoint(ZDO_ENDPOINT);
apsReq.setSrcEndpoint(ZDO_ENDPOINT);
#if QT_VERSION < QT_VERSION_CHECK(5,15,0)
apsReq.setTxOptions(0);
#endif
apsReq.setRadius(0);
QDataStream stream(&apsReq.asdu(), QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
static_assert (PERMIT_JOIN_SEND_INTERVAL / 1000 < 180, "permit join send interval < 180 seconds");
static_assert (PERMIT_JOIN_SEND_INTERVAL / 1000 > 30, "permit join send interval > 30 seconds");
int duration = qMin(gwPermitJoinDuration, (PERMIT_JOIN_SEND_INTERVAL / 1000) + 5);
stream << ZDP_NextSequenceNumber();
stream << static_cast<quint8>(duration);
stream << tcSignificance;
apsCtrl->setPermitJoin(duration);
if (apsCtrl->apsdeDataRequest(apsReq) == deCONZ::Success)
{
DBG_Printf(DBG_INFO, "send permit join, duration: %d\n", duration);
permitJoinLastSendTime.restart();
if (gwPermitJoinDuration > 0)
{
GP_SendProxyCommissioningMode(apsCtrl, zclSeq++);
}
}
else
{
DBG_Printf(DBG_INFO, "send permit join failed\n");
}
}
if (gwPermitJoinDuration == 0 && permitJoinFlag)
{
permitJoinApiKey.clear();
permitJoinFlag = false;
enqueueEvent(Event(RConfig, REventPermitjoinDisabled, 0));
}
}
void DeRestPluginPrivate::permitJoin(int seconds)
{
if (seconds > 0)
{
int tmp = gwNetworkOpenDuration;
gwNetworkOpenDuration = seconds;
startSearchSensors();
startSearchLights();
gwNetworkOpenDuration = tmp;
}
else
{
gwPermitJoinDuration = 0;
}
}