mirror of
https://github.com/Utyff/Zintercom.git
synced 2026-01-12 09:17:41 +03:00
fixed the work of inputs and outputs on the target board (button and call) implemented sleep mode in battery mode (end device) power attributes are always advertised, (used only in battery mode) implemented bind to another device (notify about a call to the intercom) minor changes in the code (syntactic)
417 lines
13 KiB
C
417 lines
13 KiB
C
|
|
#include "AF.h"
|
|
#include "OSAL.h"
|
|
#include "OSAL_Clock.h"
|
|
#include "OSAL_PwrMgr.h"
|
|
#include "ZComDef.h"
|
|
#include "ZDApp.h"
|
|
#include "ZDObject.h"
|
|
#include "math.h"
|
|
|
|
#include "nwk_util.h"
|
|
#include "zcl.h"
|
|
#include "zcl_app.h"
|
|
#include "zcl_diagnostic.h"
|
|
#include "zcl_general.h"
|
|
#include "zcl_ms.h"
|
|
|
|
#include "bdb.h"
|
|
#include "bdb_interface.h"
|
|
#include "bdb_touchlink.h"
|
|
#include "bdb_touchlink_target.h"
|
|
|
|
#include "gp_interface.h"
|
|
|
|
#include "Debug.h"
|
|
|
|
#include "OnBoard.h"
|
|
|
|
#include "commissioning.h"
|
|
#include "factory_reset.h"
|
|
/* HAL */
|
|
|
|
#include "hal_drivers.h"
|
|
|
|
#include "hal_key.h"
|
|
#include "hal_led.h"
|
|
#include "hal_adc.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "battery.h"
|
|
|
|
#include "version.h"
|
|
|
|
/*********************************************************************
|
|
* MACROS
|
|
*/
|
|
|
|
/*********************************************************************
|
|
* CONSTANTS
|
|
*/
|
|
|
|
/*********************************************************************
|
|
* TYPEDEFS
|
|
*/
|
|
|
|
/*********************************************************************
|
|
* GLOBAL VARIABLES
|
|
*/
|
|
byte zclApp_TaskID;
|
|
|
|
/*********************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
*/
|
|
//void user_delay_ms(uint32_t period);
|
|
//void user_delay_ms(uint32_t period) { MicroWait(period * 1000); }
|
|
/*********************************************************************
|
|
* LOCAL VARIABLES
|
|
*/
|
|
|
|
|
|
/*********************************************************************
|
|
* LOCAL FUNCTIONS
|
|
*/
|
|
|
|
static void zclApp_BasicResetCB(void);
|
|
static void zclApp_RestoreAttributesFromNV(void);
|
|
static void zclApp_SaveAttributesToNV(void);
|
|
static void zclApp_HandleKeys(byte portAndAction, byte keyCode);
|
|
static ZStatus_t zclApp_ReadWriteAuthCB(afAddrType_t *srcAddr, zclAttrRec_t *pAttr, uint8 oper);
|
|
|
|
static void zclApp_Report(void);
|
|
static void zclApp_OneReport(void);
|
|
static void zclApp_ConfigInit(bool restart);
|
|
|
|
static void zclApp_BtnClick(bool hold);
|
|
static void zclApp_RingRun(void);
|
|
static void zclApp_RingEnd(void);
|
|
|
|
//static uint32 pressTime = 0;
|
|
|
|
/*********************************************************************
|
|
* ZCL General Profile Callback table
|
|
*/
|
|
static zclGeneral_AppCallbacks_t zclApp_CmdCallbacks = {
|
|
zclApp_BasicResetCB, // Basic Cluster Reset command
|
|
NULL, // Identify Trigger Effect command
|
|
NULL, // On/Off cluster commands
|
|
NULL, // On/Off cluster enhanced command Off with Effect
|
|
NULL, // On/Off cluster enhanced command On with Recall Global Scene
|
|
NULL, // On/Off cluster enhanced command On with Timed Off
|
|
NULL, // RSSI Location command
|
|
NULL // RSSI Location Response command
|
|
};
|
|
void zclApp_Init(byte task_id) {
|
|
HalLedSet(HAL_LED_ALL, HAL_LED_MODE_BLINK);
|
|
|
|
zclApp_RestoreAttributesFromNV();
|
|
|
|
zclApp_TaskID = task_id;
|
|
|
|
bdb_RegisterSimpleDescriptor(&zclApp_FirstEP);
|
|
|
|
zclGeneral_RegisterCmdCallbacks(zclApp_FirstEP.EndPoint, &zclApp_CmdCallbacks);
|
|
|
|
zcl_registerAttrList(zclApp_FirstEP.EndPoint, zclApp_AttrsCount, zclApp_AttrsFirstEP);
|
|
|
|
zcl_registerReadWriteCB(zclApp_FirstEP.EndPoint, NULL, zclApp_ReadWriteAuthCB);
|
|
zcl_registerForMsg(zclApp_TaskID);
|
|
RegisterForKeys(zclApp_TaskID);
|
|
|
|
LREP("Build %s \r\n", zclApp_DateCodeNT);
|
|
|
|
zclApp_ConfigInit(TIMER_START);
|
|
#if defined( ZIC_BATTERY_MODE )
|
|
ZMacSetTransmitPower(TX_PWR_PLUS_4); // set 4dBm
|
|
#endif
|
|
}
|
|
static void zclApp_HandleKeys(byte portAndAction, byte keyCode) {
|
|
|
|
LREP("zclApp_HandleKeys portAndAction=0x%X keyCode=0x%X\r\n", portAndAction, keyCode);
|
|
zclCommissioning_HandleKeys(portAndAction, keyCode);
|
|
|
|
if (portAndAction & 0x01) { //P0 Ring
|
|
afAddrType_t inderect_DstAddr = {.addrMode = (afAddrMode_t)AddrNotPresent, .endPoint = 0, .addr.shortAddr = 0};
|
|
if (portAndAction & HAL_KEY_PRESS) {
|
|
osal_pwrmgr_task_state(zclApp_TaskID, PWRMGR_HOLD);
|
|
LREPMaster("Ring start\r\n");
|
|
HalLedSet(LED_PIN, HAL_LED_MODE_BLINK);
|
|
zclGeneral_SendOnOff_CmdOn(zclApp_FirstEP.EndPoint, &inderect_DstAddr, FALSE, bdb_getZCLFrameCounter());
|
|
osal_start_reload_timer(zclApp_TaskID, APP_RING_RUN_EVT, 500);
|
|
}
|
|
if (portAndAction & HAL_KEY_RELEASE) {
|
|
zclApp_RingEnd();
|
|
zclGeneral_SendOnOff_CmdOff(zclApp_FirstEP.EndPoint, &inderect_DstAddr, FALSE, bdb_getZCLFrameCounter());
|
|
osal_pwrmgr_task_state(zclApp_TaskID, PWRMGR_CONSERVE);
|
|
}
|
|
|
|
}
|
|
|
|
if (portAndAction & 0x04) { //P2 Btn
|
|
zclFactoryResetter_HandleKeys(portAndAction, keyCode);
|
|
if (portAndAction & HAL_KEY_PRESS) {
|
|
zclApp_State.pressTime = osal_getClock();
|
|
LREPMaster("Key press\r\n");
|
|
LREP("pressTime = %d\r\n", zclApp_State.pressTime);
|
|
}
|
|
if (portAndAction & HAL_KEY_RELEASE) {
|
|
#if defined( ZIC_BATTERY_MODE )
|
|
zclBattery_Report();
|
|
#endif
|
|
LREPMaster("Key release\r\n");
|
|
uint32 holdTime = osal_getClock() - zclApp_State.pressTime;
|
|
LREP("holdTime = %d \r\n", holdTime);
|
|
if (holdTime < 1) {
|
|
osal_start_reload_timer(zclApp_TaskID, APP_BTN_CLICK_EVT, 50);
|
|
}
|
|
else {
|
|
osal_start_reload_timer(zclApp_TaskID, APP_BTN_HOLD_EVT, 50);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16 zclApp_event_loop(uint8 task_id, uint16 events) {
|
|
LREP("events 0x%x \r\n", events);
|
|
if (events & SYS_EVENT_MSG) {
|
|
afIncomingMSGPacket_t *MSGpkt;
|
|
while ((MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(zclApp_TaskID))) {
|
|
LREP("MSGpkt->hdr.event 0x%X clusterId=0x%X\r\n", MSGpkt->hdr.event, MSGpkt->clusterId);
|
|
switch (MSGpkt->hdr.event) {
|
|
case KEY_CHANGE:
|
|
zclApp_HandleKeys(((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys);
|
|
break;
|
|
|
|
case ZCL_INCOMING_MSG:
|
|
if (((zclIncomingMsg_t *)MSGpkt)->attrCmd) {
|
|
osal_mem_free(((zclIncomingMsg_t *)MSGpkt)->attrCmd);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Release the memory
|
|
osal_msg_deallocate((uint8 *)MSGpkt);
|
|
}
|
|
// return unprocessed events
|
|
return (events ^ SYS_EVENT_MSG);
|
|
}
|
|
if (events & APP_REPORT_EVT) {
|
|
LREPMaster("APP_REPORT_EVT\r\n");
|
|
zclApp_Report();
|
|
return (events ^ APP_REPORT_EVT);
|
|
}
|
|
|
|
if (events & APP_SAVE_ATTRS_EVT) {
|
|
LREPMaster("APP_SAVE_ATTRS_EVT\r\n");
|
|
zclApp_SaveAttributesToNV();
|
|
zclApp_ConfigInit(TIMER_RESTART);
|
|
return (events ^ APP_SAVE_ATTRS_EVT);
|
|
}
|
|
|
|
if (events & APP_BTN_CLICK_EVT) {
|
|
LREPMaster("APP_BTN_CLICK_EVT\r\n");
|
|
zclApp_BtnClick(false);
|
|
return (events ^ APP_BTN_CLICK_EVT);
|
|
}
|
|
|
|
if (events & APP_RING_RUN_EVT) {
|
|
LREPMaster("APP_RING_RUN_EVT\r\n");
|
|
zclApp_RingRun();
|
|
return (events ^ APP_RING_RUN_EVT);
|
|
}
|
|
|
|
|
|
if (events & APP_BTN_HOLD_EVT) {
|
|
LREPMaster("APP_BTN_HOLD_EVT\r\n");
|
|
zclApp_BtnClick(true);
|
|
return (events ^ APP_BTN_HOLD_EVT);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void zclApp_RingRun(void) {
|
|
|
|
zclApp_State.RingRunStep++;
|
|
LREP("zclApp_State.RingRunStep %d\r\n", zclApp_State.RingRunStep);
|
|
LREP("zclApp_State.State %d\r\n", zclApp_State.State);
|
|
switch (zclApp_State.State) {
|
|
case Idle:
|
|
zclApp_State.State = Ring;
|
|
zclApp_OneReport();
|
|
if (zclApp_Config.ModeOpen == Drop){
|
|
zclApp_State.State = Droped;
|
|
HalLedSet(CATCH_PIN, HAL_LED_MODE_ON);
|
|
}
|
|
break;
|
|
case Ring:
|
|
if ((zclApp_Config.ModeOpen == Once) || (zclApp_Config.ModeOpen == Always)){
|
|
if (zclApp_State.RingRunStep > (zclApp_Config.TimeRing * 2)) {
|
|
zclApp_State.State = Talk;
|
|
HalLedSet(CATCH_PIN, HAL_LED_MODE_ON);
|
|
HalLedSet(ANSWER_PIN, HAL_LED_MODE_ON);
|
|
zclApp_OneReport();
|
|
}
|
|
}
|
|
break;
|
|
case Talk:
|
|
if ((zclApp_Config.ModeOpen == Once) || (zclApp_Config.ModeOpen == Always)){
|
|
if (zclApp_State.RingRunStep > ((zclApp_Config.TimeRing + zclApp_Config.TimeTalk) * 2)) {
|
|
zclApp_State.State = Open;
|
|
HalLedSet(OPEN_PIN, HAL_LED_MODE_ON);
|
|
zclApp_OneReport();
|
|
}
|
|
}
|
|
break;
|
|
case Open:
|
|
if ((zclApp_Config.ModeOpen == Once) || (zclApp_Config.ModeOpen == Always)){
|
|
if (zclApp_State.RingRunStep > ((zclApp_Config.TimeRing + zclApp_Config.TimeTalk+ zclApp_Config.TimeOpen) * 2)) {
|
|
zclApp_RingEnd();
|
|
}
|
|
}
|
|
break;
|
|
case Droped:
|
|
switch (zclApp_State.RingRunStep) {
|
|
case 2:
|
|
zclApp_OneReport();
|
|
HalLedSet(ANSWER_PIN, HAL_LED_MODE_ON);
|
|
break;
|
|
case 3:
|
|
zclApp_RingEnd();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static void zclApp_RingEnd(void) {
|
|
LREPMaster("Ring end\r\n");
|
|
if (zclApp_Config.ModeSound == true) {
|
|
HalLedSet(CATCH_PIN, HAL_LED_MODE_OFF);
|
|
}
|
|
HalLedSet(ANSWER_PIN, HAL_LED_MODE_OFF);
|
|
HalLedSet(OPEN_PIN, HAL_LED_MODE_OFF);
|
|
osal_stop_timerEx(zclApp_TaskID, APP_RING_RUN_EVT);
|
|
osal_clear_event(zclApp_TaskID, APP_RING_RUN_EVT);
|
|
zclApp_State.RingRunStep = 0;
|
|
zclApp_State.State = Idle;
|
|
if (zclApp_Config.ModeOpen == Once) {
|
|
zclApp_Config.ModeOpen = Never;
|
|
}
|
|
zclApp_OneReport();
|
|
}
|
|
|
|
static void zclApp_BtnClick(bool hold) {
|
|
|
|
static uint8 currentBtnClickPhase = 0;
|
|
LREP("currentBtnClickPhase %d\r\n", currentBtnClickPhase);
|
|
switch (currentBtnClickPhase++) {
|
|
case 0:
|
|
if (hold) {
|
|
zclApp_Config.ModeSound = !zclApp_Config.ModeSound;
|
|
HalLedSet(CATCH_PIN, !zclApp_Config.ModeSound);
|
|
}
|
|
else {
|
|
if (zclApp_Config.ModeOpen < Drop) {
|
|
zclApp_Config.ModeOpen++;
|
|
}
|
|
else {
|
|
zclApp_Config.ModeOpen = Never;
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
zclApp_OneReport();
|
|
break;
|
|
case 2:
|
|
if (hold) {
|
|
HalLedBlink(LED_PIN, zclApp_Config.ModeSound+1, 50, 750);
|
|
}
|
|
else {
|
|
HalLedBlink(LED_PIN, zclApp_Config.ModeOpen+1, 50, 250);
|
|
}
|
|
break;
|
|
default:
|
|
if (hold) {
|
|
osal_stop_timerEx(zclApp_TaskID, APP_BTN_HOLD_EVT);
|
|
osal_clear_event(zclApp_TaskID, APP_BTN_HOLD_EVT);
|
|
}
|
|
else {
|
|
osal_stop_timerEx(zclApp_TaskID, APP_BTN_CLICK_EVT);
|
|
osal_clear_event(zclApp_TaskID, APP_BTN_CLICK_EVT);
|
|
}
|
|
currentBtnClickPhase = 0;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static void zclApp_Report(void) {
|
|
zclApp_OneReport();
|
|
}
|
|
|
|
static void zclApp_OneReport(void) {
|
|
//HalLedSet(LED_PIN, HAL_LED_MODE_BLINK);
|
|
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, ZCL_INTERCOM, ATTRID_STATE);
|
|
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, ZCL_INTERCOM, ATTRID_MODEOPEN);
|
|
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, ZCL_INTERCOM, ATTRID_MODESOUND);
|
|
}
|
|
|
|
static void zclApp_BasicResetCB(void) {
|
|
LREPMaster("BasicResetCB\r\n");
|
|
zclApp_ResetAttributesToDefaultValues();
|
|
zclApp_SaveAttributesToNV();
|
|
}
|
|
|
|
static ZStatus_t zclApp_ReadWriteAuthCB(afAddrType_t *srcAddr, zclAttrRec_t *pAttr, uint8 oper) {
|
|
LREPMaster("AUTH CB called\r\n");
|
|
osal_start_timerEx(zclApp_TaskID, APP_SAVE_ATTRS_EVT, 2000);
|
|
return ZSuccess;
|
|
}
|
|
|
|
static void zclApp_SaveAttributesToNV(void) {
|
|
uint8 writeStatus = osal_nv_write(NW_APP_CONFIG, 0, sizeof(application_config_t), &zclApp_Config);
|
|
LREP("Saving attributes to NV write=%d\r\n", writeStatus);
|
|
}
|
|
|
|
static void zclApp_ConfigInit(bool restart) {
|
|
if (restart) {
|
|
LREP("Stop report timer event\r\n");
|
|
osal_stop_timerEx(zclApp_TaskID, APP_REPORT_EVT);
|
|
osal_clear_event(zclApp_TaskID, APP_REPORT_EVT);
|
|
}
|
|
uint32 ReportInterval = (uint32)zclApp_Config.TimeReport * (uint32)60;
|
|
LREP("Start report with interval %d seconds\r\n", ReportInterval);
|
|
osal_start_reload_timer(zclApp_TaskID, APP_REPORT_EVT, ((uint32)ReportInterval*(uint32)1000));
|
|
if (zclApp_Config.ModeSound == false) {
|
|
HalLedSet(CATCH_PIN, HAL_LED_MODE_ON);
|
|
}
|
|
else {
|
|
HalLedSet(CATCH_PIN, HAL_LED_MODE_OFF);
|
|
}
|
|
}
|
|
|
|
static void zclApp_RestoreAttributesFromNV(void) {
|
|
uint8 status = osal_nv_item_init(NW_APP_CONFIG, sizeof(application_config_t), NULL);
|
|
LREP("Restoring attributes from NV status=%d \r\n", status);
|
|
if (status == NV_ITEM_UNINIT) {
|
|
uint8 writeStatus = osal_nv_write(NW_APP_CONFIG, 0, sizeof(application_config_t), &zclApp_Config);
|
|
LREP("NV was empty, writing %d\r\n", writeStatus);
|
|
}
|
|
if (status == ZSUCCESS) {
|
|
LREPMaster("Reading from NV\r\n");
|
|
osal_nv_read(NW_APP_CONFIG, 0, sizeof(application_config_t), &zclApp_Config);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
****************************************************************************/
|