<commit_before>/*
 * Copyright (c) 2016 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_private.h"

#define CC_CHANNELCHANGE_WAIT_TIME         1000
#define CC_CHANNELCHANGE_WAIT_CONFIRM_TIME 10000
#define CC_CHANNELCHANGE_VERIFY_TIME       1000
#define CC_DISCONNECT_CHECK_DELAY 100
#define NETWORK_ATTEMPS 10
#define CC_RECONNECT_CHECK_DELAY  5000
#define CC_RECONNECT_NOW          100

/*! Init the change channel api and helpers.
 */
void DeRestPluginPrivate::initChangeChannelApi()
{
    channelChangeState = CC_Idle;
    ccRetries = 0;
    channelchangeTimer = new QTimer(this);
    channelchangeTimer->setSingleShot(true);
    connect(channelchangeTimer, SIGNAL(timeout()),
            this, SLOT(channelchangeTimerFired()));

    QTimer *wdTimer = new QTimer(this);
    wdTimer->setSingleShot(false);
    connect(wdTimer, SIGNAL(timeout()), this, SLOT(networkWatchdogTimerFired()));
    wdTimer->start(10000);
}


/*! Starts the whole channel changing process if connected.
    \param channel - user input channel
    \return true if connected.
 */
bool DeRestPluginPrivate::startChannelChange(quint8 channel)
{
    if (!isInNetwork())
    {
        return false;
    }

    ccRetries = 0;
    gwZigbeeChannel = channel;
    queSaveDb(DB_CONFIG, DB_SHORT_SAVE_DELAY);

    if (channelChangeState != CC_Idle)
    {
        DBG_Printf(DBG_INFO, "channel change in progress.\n");
        return true;
    }

    channelChangeState = CC_Verify_Channel;
    DBG_Printf(DBG_INFO_L2, "ChannelChangeState: CC_verify_Channel\n");
    channelchangeTimer->start(CC_CHANNELCHANGE_VERIFY_TIME);
    return true;
}


/*! Check if user input channel equals gateway channel.
    \param channel - user input channel
    \return true if equal
 */
bool DeRestPluginPrivate::verifyChannel(quint8 channel)
{

    DBG_Assert(apsCtrl != 0);
    if (!apsCtrl)
    {
        return false;
    }

    if (!isInNetwork())
    {
        return false;
    }

    quint8 currentChannel = apsCtrl->getParameter(deCONZ::ParamCurrentChannel);
    quint64 apsUseExtPanid = apsCtrl->getParameter(deCONZ::ParamApsUseExtendedPANID);
    quint64 tcAddress = apsCtrl->getParameter(deCONZ::ParamTrustCenterAddress);
    quint64 macAddress = apsCtrl->getParameter(deCONZ::ParamMacAddress);
    quint8 deviceType = apsCtrl->getParameter(deCONZ::ParamDeviceType);

    bool ok = true;

    if (currentChannel != channel)
    {
        ok = false;
    }

    if (deviceType == deCONZ::Coordinator)
    {
        if (apsUseExtPanid != 0)
        {
            ok = false;
        }
        else if (tcAddress != macAddress)
        {
            ok = false;
        }
    }

    if (ok)
    {
        DBG_Printf(DBG_INFO, "network configuration verified!\n");
        return true;
    }
    else
    {
        DBG_Printf(DBG_INFO, "network configuration NOT verified!\n");
        return false;
    }
}


/*! Sends request to gateway to change channel
    \param channel - user input channel
 */
void DeRestPluginPrivate::changeChannel(quint8 channel)
{
    if (!apsCtrl)
    {
    }
    else if ((gwDeviceAddress.ext() & deMacPrefix) != deMacPrefix)
    {
        // require valid mac address
    }
    else if (ccRetries < 3)
    {
        DBG_Assert(channel >= 11 && channel <= 26);
        if (apsCtrl && (channel >= 11) && (channel <= 26))
        {
            uint8_t nwkUpdateId = (apsCtrl->getParameter(deCONZ::ParamNetworkUpdateId));
            if (nwkUpdateId < 255)
            {
                nwkUpdateId++;
            }
            else if (nwkUpdateId == 255)
            {
                nwkUpdateId = 1;
            }
            const quint8 zdpSeq = (qrand() % 255);
            const quint32 scanChannels = (1 << static_cast<uint>(channel));
            const quint8 scanDuration = 0xfe; //special value = channel change

            DBG_Printf(DBG_INFO, "change channel with nwkUpdateId = %u\n", nwkUpdateId);

            apsCtrl->setParameter(deCONZ::ParamCurrentChannel, channel);
            apsCtrl->setParameter(deCONZ::ParamNetworkUpdateId, nwkUpdateId);

            deCONZ::ApsDataRequest req;

            req.setTxOptions(nullptr);
            req.setDstEndpoint(ZDO_ENDPOINT);
            req.setDstAddressMode(deCONZ::ApsNwkAddress);
            req.dstAddress().setNwk(deCONZ::BroadcastRouters);
            req.setProfileId(ZDP_PROFILE_ID);
            req.setClusterId(ZDP_MGMT_NWK_UPDATE_REQ_CLID);
            req.setSrcEndpoint(ZDO_ENDPOINT);
            req.setRadius(0);

            QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
            stream.setByteOrder(QDataStream::LittleEndian);
            stream << zdpSeq;
            stream << scanChannels;
            stream << scanDuration;
            stream << nwkUpdateId;

            if (apsCtrl && apsCtrl->apsdeDataRequest(req) == deCONZ::Success)
            {
                channelChangeApsRequestId = req.id();
                DBG_Printf(DBG_INFO, "change channel to %d, channel mask = 0x%08lX\n", channel, scanChannels);
                channelChangeState = CC_WaitConfirm;
                channelchangeTimer->start(CC_CHANNELCHANGE_WAIT_CONFIRM_TIME);
                DBG_Printf(DBG_INFO_L2, "ChannelChangeState: CC_WaitConfirm\n");
                return;<commit_msg>Broadcast channel change command to rxOnWhenIdle instead only routers<commit_after>/*
 * Copyright (c) 2016 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_private.h"

#define CC_CHANNELCHANGE_WAIT_TIME         1000
#define CC_CHANNELCHANGE_WAIT_CONFIRM_TIME 10000
#define CC_CHANNELCHANGE_VERIFY_TIME       1000
#define CC_DISCONNECT_CHECK_DELAY 100
#define NETWORK_ATTEMPS 10
#define CC_RECONNECT_CHECK_DELAY  5000
#define CC_RECONNECT_NOW          100

/*! Init the change channel api and helpers.
 */
void DeRestPluginPrivate::initChangeChannelApi()
{
    channelChangeState = CC_Idle;
    ccRetries = 0;
    channelchangeTimer = new QTimer(this);
    channelchangeTimer->setSingleShot(true);
    connect(channelchangeTimer, SIGNAL(timeout()),
            this, SLOT(channelchangeTimerFired()));

    QTimer *wdTimer = new QTimer(this);
    wdTimer->setSingleShot(false);
    connect(wdTimer, SIGNAL(timeout()), this, SLOT(networkWatchdogTimerFired()));
    wdTimer->start(10000);
}


/*! Starts the whole channel changing process if connected.
    \param channel - user input channel
    \return true if connected.
 */
bool DeRestPluginPrivate::startChannelChange(quint8 channel)
{
    if (!isInNetwork())
    {
        return false;
    }

    ccRetries = 0;
    gwZigbeeChannel = channel;
    queSaveDb(DB_CONFIG, DB_SHORT_SAVE_DELAY);

    if (channelChangeState != CC_Idle)
    {
        DBG_Printf(DBG_INFO, "channel change in progress.\n");
        return true;
    }

    channelChangeState = CC_Verify_Channel;
    DBG_Printf(DBG_INFO_L2, "ChannelChangeState: CC_verify_Channel\n");
    channelchangeTimer->start(CC_CHANNELCHANGE_VERIFY_TIME);
    return true;
}


/*! Check if user input channel equals gateway channel.
    \param channel - user input channel
    \return true if equal
 */
bool DeRestPluginPrivate::verifyChannel(quint8 channel)
{

    DBG_Assert(apsCtrl != 0);
    if (!apsCtrl)
    {
        return false;
    }

    if (!isInNetwork())
    {
        return false;
    }

    quint8 currentChannel = apsCtrl->getParameter(deCONZ::ParamCurrentChannel);
    quint64 apsUseExtPanid = apsCtrl->getParameter(deCONZ::ParamApsUseExtendedPANID);
    quint64 tcAddress = apsCtrl->getParameter(deCONZ::ParamTrustCenterAddress);
    quint64 macAddress = apsCtrl->getParameter(deCONZ::ParamMacAddress);
    quint8 deviceType = apsCtrl->getParameter(deCONZ::ParamDeviceType);

    bool ok = true;

    if (currentChannel != channel)
    {
        ok = false;
    }

    if (deviceType == deCONZ::Coordinator)
    {
        if (apsUseExtPanid != 0)
        {
            ok = false;
        }
        else if (tcAddress != macAddress)
        {
            ok = false;
        }
    }

    if (ok)
    {
        DBG_Printf(DBG_INFO, "network configuration verified!\n");
        return true;
    }
    else
    {
        DBG_Printf(DBG_INFO, "network configuration NOT verified!\n");
        return false;
    }
}


/*! Sends request to gateway to change channel
    \param channel - user input channel
 */
void DeRestPluginPrivate::changeChannel(quint8 channel)
{
    if (!apsCtrl)
    {
    }
    else if ((gwDeviceAddress.ext() & deMacPrefix) != deMacPrefix)
    {
        // require valid mac address
    }
    else if (ccRetries < 3)
    {
        DBG_Assert(channel >= 11 && channel <= 26);
        if (apsCtrl && (channel >= 11) && (channel <= 26))
        {
            uint8_t nwkUpdateId = (apsCtrl->getParameter(deCONZ::ParamNetworkUpdateId));
            if (nwkUpdateId < 255)
            {
                nwkUpdateId++;
            }
            else if (nwkUpdateId == 255)
            {
                nwkUpdateId = 1;
            }
            const quint8 zdpSeq = (qrand() % 255);
            const quint32 scanChannels = (1 << static_cast<uint>(channel));
            const quint8 scanDuration = 0xfe; //special value = channel change

            DBG_Printf(DBG_INFO, "change channel with nwkUpdateId = %u\n", nwkUpdateId);

            apsCtrl->setParameter(deCONZ::ParamCurrentChannel, channel);
            apsCtrl->setParameter(deCONZ::ParamNetworkUpdateId, nwkUpdateId);

            deCONZ::ApsDataRequest req;

            req.setTxOptions(nullptr);
            req.setDstEndpoint(ZDO_ENDPOINT);
            req.setDstAddressMode(deCONZ::ApsNwkAddress);
            req.dstAddress().setNwk(deCONZ::BroadcastRxOnWhenIdle);
            req.setProfileId(ZDP_PROFILE_ID);
            req.setClusterId(ZDP_MGMT_NWK_UPDATE_REQ_CLID);
            req.setSrcEndpoint(ZDO_ENDPOINT);
            req.setRadius(0);

            QDataStream stream(&req.asdu(), QIODevice::WriteOnly);
            stream.setByteOrder(QDataStream::LittleEndian);
            stream << zdpSeq;
            stream << scanChannels;
            stream << scanDuration;
            stream << nwkUpdateId;

            if (apsCtrl && apsCtrl->apsdeDataRequest(req) == deCONZ::Success)
            {
                channelChangeApsRequestId = req.id();
                DBG_Printf(DBG_INFO, "change channel to %d, channel mask = 0x%08lX\n", channel, scanChannels);
                channelChangeState = CC_WaitConfirm;
                channelchangeTimer->start(CC_CHANNELCHANGE_WAIT_CONFIRM_TIME);
                DBG_Printf(DBG_INFO_L2, "ChannelChangeState: CC_WaitConfirm\n");
                return;
{'fraction_non_alphanumeric': 0.09875646727784333, 'fraction_numerical': 0.014704547517472997, 'mean_word_length': 2.630313014827018, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4356998', 'n_tokens_mistral': 3517, 'n_tokens_neox': 3305, 'n_words': 711}