/******************************************************************************************************** * @file zcl_onOffCb.c * * @brief This is the source file for zcl_onOffCb * * @author Zigbee Group * @date 2021 * * @par Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK") * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************************************/ #if (__PROJECT_TL_DIMMABLE_LIGHT__) /********************************************************************** * INCLUDES */ #include "tl_common.h" #include "zb_api.h" #include "zcl_include.h" #include "sampleLight.h" #include "sampleLightCtrl.h" /********************************************************************** * LOCAL VARIABLES */ static ev_timer_event_t *onWithTimedOffTimerEvt = NULL; /********************************************************************** * FUNCTIONS */ /********************************************************************* * @fn sampleLight_onOffInit * * @brief * * @param None * * @return None */ void sampleLight_onOffInit(void) { zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(); sampleLight_onoff(pOnOff->onOff); } /********************************************************************* * @fn sampleLight_updateOnOff * * @brief * * @param None * * @return None */ void sampleLight_updateOnOff(void) { zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(); hwLight_onOffUpdate(pOnOff->onOff); } /********************************************************************* * @fn sampleLight_onoff * * @brief * * @param ZCL_CMD_ONOFF_ON / ZCL_ONOFF_STATUS_OFF * * @return None */ void sampleLight_onoff(u8 cmd) { zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(); if (cmd == ZCL_CMD_ONOFF_ON) { pOnOff->globalSceneControl = TRUE; pOnOff->onOff = ZCL_ONOFF_STATUS_ON; if (pOnOff->onTime == 0) { pOnOff->offWaitTime = 0; } } else if (cmd == ZCL_CMD_ONOFF_OFF) { pOnOff->onOff = ZCL_ONOFF_STATUS_OFF; pOnOff->onTime = 0; } else { if (pOnOff->onOff == ZCL_ONOFF_STATUS_OFF) { pOnOff->globalSceneControl = TRUE; pOnOff->onOff = ZCL_ONOFF_STATUS_ON; if (pOnOff->onTime == 0) { pOnOff->offWaitTime = 0; } } else { pOnOff->onOff = ZCL_ONOFF_STATUS_OFF; pOnOff->onTime = 0; } } light_fresh(); #ifdef ZCL_SCENE zcl_sceneAttr_t *pScene = zcl_sceneAttrGet(); pScene->sceneValid = 0; #endif } /********************************************************************* * @fn sampleLight_OnWithTimedOffTimerCb * * @brief timer event to process the ON_WITH_TIMED_OFF command * * @param arg * * @return 0: timer continue on; -1: timer will be canceled */ static s32 sampleLight_OnWithTimedOffTimerCb(void *arg) { zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(); if ((pOnOff->onOff == ZCL_ONOFF_STATUS_ON) && pOnOff->onTime) { pOnOff->onTime--; if (pOnOff->onTime <= 0) { pOnOff->offWaitTime = 0; sampleLight_onoff(ZCL_CMD_ONOFF_OFF); } } if ((pOnOff->onOff == ZCL_ONOFF_STATUS_OFF) && pOnOff->offWaitTime) { pOnOff->offWaitTime--; if (pOnOff->offWaitTime <= 0) { onWithTimedOffTimerEvt = NULL; return -1; } } if (pOnOff->onTime || pOnOff->offWaitTime) { return 0; } else { onWithTimedOffTimerEvt = NULL; return -1; } } /********************************************************************* * @fn sampleLight_OnWithTimedOffTimerStop * * @brief force to stop the OnWithTimedOff timer * * @param * * @return */ static void sampleLight_OnWithTimedOffTimerStop(void) { if (onWithTimedOffTimerEvt) { TL_ZB_TIMER_CANCEL(&onWithTimedOffTimerEvt); } } /********************************************************************* * @fn sampleLight_onoff_onWithTimedOffProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_onoff_onWithTimedOffProcess(zcl_onoff_onWithTimeOffCmd_t *cmd) { zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(); // Discard if (cmd->onOffCtrl.bits.acceptOnlyWhenOn && (pOnOff->onOff == ZCL_ONOFF_STATUS_OFF)) { return; } if (pOnOff->offWaitTime && (pOnOff->onOff == ZCL_ONOFF_STATUS_OFF)) { pOnOff->offWaitTime = min2(pOnOff->offWaitTime, cmd->offWaitTime); } else { pOnOff->onTime = max2(pOnOff->onTime, cmd->onTime); pOnOff->offWaitTime = cmd->offWaitTime; sampleLight_onoff(ZCL_CMD_ONOFF_ON); } if (pOnOff->onTime < 0xFFFF && pOnOff->offWaitTime < 0xFFFF) { if (pOnOff->onTime || pOnOff->offWaitTime) { sampleLight_OnWithTimedOffTimerStop(); onWithTimedOffTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_OnWithTimedOffTimerCb, NULL, ZCL_ONOFF_TIMER_INTERVAL); } } } /********************************************************************* * @fn sampleLight_onoff_offWithEffectProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_onoff_offWithEffectProcess(zcl_onoff_offWithEffectCmd_t *cmd) { // TODO: FIXED ME sampleLight_onoff(ZCL_CMD_ONOFF_OFF); } /********************************************************************* * @fn sampleLight_onoff_onWithRecallGlobalSceneProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_onoff_onWithRecallGlobalSceneProcess(void) { } /********************************************************************* * @fn sampleLight_onOffCb * * @brief Handler for ZCL ONOFF command. This function will set ONOFF attribute first. * * @param pAddrInfo * @param cmdId - onoff cluster command id * @param cmdPayload * * @return status_t */ status_t sampleLight_onOffCb(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload) { zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(); if (pAddrInfo->dstEp == SAMPLE_LIGHT_ENDPOINT) { switch (cmdId) { case ZCL_CMD_ONOFF_ON: case ZCL_CMD_ONOFF_OFF: case ZCL_CMD_ONOFF_TOGGLE: sampleLight_onoff(cmdId); break; case ZCL_CMD_OFF_WITH_EFFECT: if (pOnOff->globalSceneControl == TRUE) { /* TODO: store its settings in its global scene */ pOnOff->globalSceneControl = FALSE; } sampleLight_onoff_offWithEffectProcess((zcl_onoff_offWithEffectCmd_t *)cmdPayload); break; case ZCL_CMD_ON_WITH_RECALL_GLOBAL_SCENE: if (pOnOff->globalSceneControl == FALSE) { sampleLight_onoff_onWithRecallGlobalSceneProcess(); pOnOff->globalSceneControl = TRUE; } break; case ZCL_CMD_ON_WITH_TIMED_OFF: sampleLight_onoff_onWithTimedOffProcess((zcl_onoff_onWithTimeOffCmd_t *)cmdPayload); break; default: break; } } return ZCL_STA_SUCCESS; } #endif /* __PROJECT_TL_DIMMABLE_LIGHT__ */