pct.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. /**************************************************************************************************
  2. Filename: pct.c
  3. Revised: $Date: 2007-08-02 09:20:10 -0700 (Thu,02 Aug 2007) $
  4. Revision: $Revision: 15001 $
  5. Description: This module implements the PCT functionality and contains the
  6. init and event loop functions
  7. Copyright 2009 Texas Instruments Incorporated. All rights reserved.
  8. IMPORTANT: Your use of this Software is limited to those specific rights
  9. granted under the terms of a software license agreement between the user
  10. who downloaded the software, his/her employer (which must be your employer)
  11. and Texas Instruments Incorporated (the "License"). You may not use this
  12. Software unless you agree to abide by the terms of the License. The License
  13. limits your use, and you acknowledge, that the Software may not be modified,
  14. copied or distributed unless embedded on a Texas Instruments microcontroller
  15. or used solely and exclusively in conjunction with a Texas Instruments radio
  16. frequency transceiver, which is integrated into your product. Other than for
  17. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  18. works of, modify, distribute, perform, display or sell this Software and/or
  19. its documentation for any purpose.
  20. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  21. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  22. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  23. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  24. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  25. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  26. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  27. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  28. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  29. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  30. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  31. Should you have any questions regarding your right to use this Software,
  32. contact Texas Instruments Incorporated at www.TI.com.
  33. **************************************************************************************************/
  34. /*********************************************************************
  35. This application is designed for the test purpose of the SE profile which
  36. exploits the following clusters for a PCT configuration:
  37. General Basic
  38. General Alarms
  39. General Time
  40. General Key Establishment
  41. SE Demand Response and Load Control
  42. Key control:
  43. SW1: Join Network
  44. SW2: N/A
  45. SW3: N/A
  46. SW4: N/A
  47. *********************************************************************/
  48. /*********************************************************************
  49. * INCLUDES
  50. */
  51. #include "OSAL.h"
  52. #include "OSAL_Clock.h"
  53. #include "ZDApp.h"
  54. #include "AddrMgr.h"
  55. #include "se.h"
  56. #include "pct.h"
  57. #include "zcl_general.h"
  58. #include "zcl_se.h"
  59. #include "zcl_key_establish.h"
  60. #include "onboard.h"
  61. /* HAL */
  62. #include "hal_lcd.h"
  63. #include "hal_led.h"
  64. #include "hal_key.h"
  65. /*********************************************************************
  66. * MACROS
  67. */
  68. // There is no attribute in the Mandatory Reportable Attribute list for now
  69. #define zcl_MandatoryReportableAttribute( a ) ( a == NULL )
  70. /*********************************************************************
  71. * CONSTANTS
  72. */
  73. /*********************************************************************
  74. * TYPEDEFS
  75. */
  76. /*********************************************************************
  77. * GLOBAL VARIABLES
  78. */
  79. /*********************************************************************
  80. * GLOBAL FUNCTIONS
  81. */
  82. /*********************************************************************
  83. * LOCAL VARIABLES
  84. */
  85. static uint8 pctTaskID; // osal task id for load control device
  86. static devStates_t pctNwkState; // network state variable
  87. static uint8 pctTransID; // transaction id
  88. static afAddrType_t ESPAddr; // ESP destination address
  89. static uint8 linkKeyStatus; // status variable from get link key function
  90. static zclCCReportEventStatus_t rsp; // structure for report event status
  91. /*********************************************************************
  92. * LOCAL FUNCTIONS
  93. */
  94. static void pct_HandleKeys( uint8 shift, uint8 keys );
  95. #if defined (ZCL_KEY_ESTABLISH)
  96. static uint8 pct_KeyEstablish_ReturnLinkKey( uint16 shortAddr );
  97. #endif // ZCL_KEY_ESTABLISH
  98. #if defined ( ZCL_ALARMS )
  99. static void pct_ProcessAlarmCmd( uint8 srcEP, afAddrType_t *dstAddr,
  100. uint16 clusterID, zclFrameHdr_t *hdr, uint8 len, uint8 *data );
  101. #endif // ZCL_ALARMS
  102. static void pct_ProcessIdentifyTimeChange( void );
  103. /*************************************************************************/
  104. /*** Application Callback Functions ***/
  105. /*************************************************************************/
  106. // Foundation Callback functions
  107. static uint8 pct_ValidateAttrDataCB( zclAttrRec_t *pAttr, zclWriteRec_t *pAttrInfo );
  108. // General Cluster Callback functions
  109. static void pct_BasicResetCB( void );
  110. static void pct_IdentifyCB( zclIdentify_t *pCmd );
  111. static void pct_IdentifyQueryRspCB( zclIdentifyQueryRsp_t *pRsp );
  112. static void pct_AlarmCB( zclAlarm_t *pAlarm );
  113. // SE Callback functions
  114. static void pct_LoadControlEventCB( zclCCLoadControlEvent_t *pCmd,
  115. afAddrType_t *srcAddr, uint8 status, uint8 seqNum);
  116. static void pct_CancelLoadControlEventCB( zclCCCancelLoadControlEvent_t *pCmd,
  117. afAddrType_t *srcAddr, uint8 seqNum );
  118. static void pct_CancelAllLoadControlEventsCB( zclCCCancelAllLoadControlEvents_t *pCmd,
  119. afAddrType_t *srcAddr, uint8 seqNum);
  120. static void pct_ReportEventStatusCB( zclCCReportEventStatus_t *pCmd,
  121. afAddrType_t *srcAddr, uint8 seqNum );
  122. static void pct_GetScheduledEventCB( zclCCGetScheduledEvent_t *pCmd,
  123. afAddrType_t *srcAddr, uint8 seqNum);
  124. /************************************************************************/
  125. /*** Functions to process ZCL Foundation ***/
  126. /*** incoming Command/Response messages ***/
  127. /************************************************************************/
  128. static void pct_ProcessZCLMsg( zclIncomingMsg_t *msg );
  129. #if defined ( ZCL_READ )
  130. static uint8 pct_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
  131. #endif // ZCL_READ
  132. #if defined ( ZCL_WRITE )
  133. static uint8 pct_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
  134. #endif // ZCL_WRITE
  135. static uint8 pct_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
  136. #if defined ( ZCL_DISCOVER )
  137. static uint8 pct_ProcessInDiscRspCmd( zclIncomingMsg_t *pInMsg );
  138. #endif // ZCL_DISCOVER
  139. /*********************************************************************
  140. * ZCL General Clusters Callback table
  141. */
  142. static zclGeneral_AppCallbacks_t pct_GenCmdCallbacks =
  143. {
  144. pct_BasicResetCB, // Basic Cluster Reset command
  145. pct_IdentifyCB, // Identify command
  146. pct_IdentifyQueryRspCB, // Identify Query Response command
  147. NULL, // On/Off cluster commands
  148. NULL, // Level Control Move to Level command
  149. NULL, // Level Control Move command
  150. NULL, // Level Control Step command
  151. NULL, // Level Control Stop command
  152. NULL, // Group Response commands
  153. NULL, // Scene Store Request command
  154. NULL, // Scene Recall Request command
  155. NULL, // Scene Response command
  156. pct_AlarmCB, // Alarm (Response) command
  157. NULL, // RSSI Location command
  158. NULL, // RSSI Location Response command
  159. };
  160. /*********************************************************************
  161. * ZCL SE Clusters Callback table
  162. */
  163. static zclSE_AppCallbacks_t pct_SECmdCallbacks =
  164. {
  165. NULL, // Get Profile Command
  166. NULL, // Get Profile Response
  167. NULL, // Request Mirror Command
  168. NULL, // Request Mirror Response
  169. NULL, // Mirror Remove Command
  170. NULL, // Mirror Remove Response
  171. NULL, // Get Current Price
  172. NULL, // Get Scheduled Price
  173. NULL, // Publish Price
  174. NULL, // Display Message Command
  175. NULL, // Cancel Message Command
  176. NULL, // Get Last Message Command
  177. NULL, // Message Confirmation
  178. pct_LoadControlEventCB, // Load Control Event
  179. pct_CancelLoadControlEventCB, // Cancel Load Control Event
  180. pct_CancelAllLoadControlEventsCB, // Cancel All Load Control Events
  181. pct_ReportEventStatusCB, // Report Event Status
  182. pct_GetScheduledEventCB, // Get Scheduled Event
  183. };
  184. /*********************************************************************
  185. * @fn pct_Init
  186. *
  187. * @brief Initialization function for the ZCL App Application.
  188. *
  189. * @param uint8 task_id - pct task id
  190. *
  191. * @return none
  192. */
  193. void pct_Init( uint8 task_id )
  194. {
  195. pctTaskID = task_id;
  196. // setup ESP destination address
  197. ESPAddr.addrMode = (afAddrMode_t)Addr16Bit;
  198. ESPAddr.endPoint = PCT_ENDPOINT;
  199. ESPAddr.addr.shortAddr = 0;
  200. // register SE endpoint
  201. zclSE_Init( &pctSimpleDesc );
  202. // Register the ZCL General Cluster Library callback functions
  203. zclGeneral_RegisterCmdCallbacks( PCT_ENDPOINT, &pct_GenCmdCallbacks );
  204. // Register the ZCL SE Cluster Library callback functions
  205. zclSE_RegisterCmdCallbacks( PCT_ENDPOINT, &pct_SECmdCallbacks );
  206. // Register the application's attribute list
  207. zcl_registerAttrList( PCT_ENDPOINT, PCT_MAX_ATTRIBUTES, pctAttrs );
  208. // Register the application's cluster option list
  209. zcl_registerClusterOptionList( PCT_ENDPOINT, PCT_MAX_OPTIONS, pctOptions );
  210. // Register the application's attribute data validation callback function
  211. zcl_registerValidateAttrData( pct_ValidateAttrDataCB );
  212. // Register the Application to receive the unprocessed Foundation command/response messages
  213. zcl_registerForMsg( pctTaskID );
  214. // Register for all key events - This app will handle all key events
  215. RegisterForKeys( pctTaskID );
  216. // Start the timer to sync LoadControl timer with the osal timer
  217. osal_start_timerEx( pctTaskID, PCT_UPDATE_TIME_EVT, PCT_UPDATE_TIME_PERIOD );
  218. }
  219. /*********************************************************************
  220. * @fn pct_event_loop
  221. *
  222. * @brief Event Loop Processor for PCT
  223. *
  224. * @param uint8 task_id - the osal task id
  225. * @param uint16 events - the event bitmask
  226. *
  227. * @return none
  228. */
  229. uint16 pct_event_loop( uint8 task_id, uint16 events )
  230. {
  231. afIncomingMSGPacket_t *MSGpkt;
  232. if ( events & SYS_EVENT_MSG )
  233. {
  234. while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( pctTaskID )) )
  235. {
  236. switch ( MSGpkt->hdr.event )
  237. {
  238. case ZCL_INCOMING_MSG:
  239. // Incoming ZCL foundation command/response messages
  240. pct_ProcessZCLMsg( (zclIncomingMsg_t *)MSGpkt );
  241. break;
  242. case KEY_CHANGE:
  243. pct_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
  244. break;
  245. case ZDO_STATE_CHANGE:
  246. pctNwkState = (devStates_t)(MSGpkt->hdr.status);
  247. if (ZG_SECURE_ENABLED)
  248. {
  249. if ( pctNwkState == DEV_END_DEVICE )
  250. {
  251. // check to see if link key had already been established
  252. linkKeyStatus = pct_KeyEstablish_ReturnLinkKey(ESPAddr.addr.shortAddr);
  253. if (linkKeyStatus != ZSuccess)
  254. {
  255. // send out key establishment request
  256. osal_set_event( pctTaskID, PCT_KEY_ESTABLISHMENT_REQUEST_EVT);
  257. }
  258. }
  259. }
  260. NLME_SetPollRate ( SE_DEVICE_POLL_RATE ); // per smart energy spec end device polling requirement of not to poll < 7.5 seconds
  261. break;
  262. default:
  263. break;
  264. }
  265. // Release the memory
  266. osal_msg_deallocate( (uint8 *)MSGpkt );
  267. }
  268. // return unprocessed events
  269. return (events ^ SYS_EVENT_MSG);
  270. }
  271. // event to intiate key establishment request
  272. if ( events & PCT_KEY_ESTABLISHMENT_REQUEST_EVT )
  273. {
  274. zclGeneral_KeyEstablish_InitiateKeyEstablishment(pctTaskID, &ESPAddr, pctTransID);
  275. return ( events ^ PCT_KEY_ESTABLISHMENT_REQUEST_EVT );
  276. }
  277. // handle processing of identify timeout event triggered by an identify command
  278. if ( events & PCT_IDENTIFY_TIMEOUT_EVT )
  279. {
  280. if ( pctIdentifyTime > 0 )
  281. {
  282. pctIdentifyTime--;
  283. }
  284. pct_ProcessIdentifyTimeChange();
  285. return ( events ^ PCT_IDENTIFY_TIMEOUT_EVT );
  286. }
  287. // event to get current time
  288. if ( events & PCT_UPDATE_TIME_EVT )
  289. {
  290. pctTime = osal_getClock();
  291. osal_start_timerEx( pctTaskID, PCT_UPDATE_TIME_EVT, PCT_UPDATE_TIME_PERIOD );
  292. return ( events ^ PCT_UPDATE_TIME_EVT );
  293. }
  294. // event to handle pct load control complete event
  295. if ( events & PCT_LOAD_CTRL_EVT )
  296. {
  297. // pct load control evt completed
  298. // Send response back
  299. // DisableDefaultResponse is set to false - it is recommended to turn on
  300. // default response since Report Event Status Command does not have
  301. // a response.
  302. rsp.eventStatus = EVENT_STATUS_LOAD_CONTROL_EVENT_COMPLETED;
  303. zclSE_LoadControl_Send_ReportEventStatus( PCT_ENDPOINT, &ESPAddr,
  304. &rsp, false, pctTransID );
  305. HalLcdWriteString("PCT Evt Complete", HAL_LCD_LINE_3);
  306. HalLedSet(HAL_LED_4, HAL_LED_MODE_OFF);
  307. return ( events ^ PCT_LOAD_CTRL_EVT );
  308. }
  309. // Discard unknown events
  310. return 0;
  311. }
  312. /*********************************************************************
  313. * @fn pct_ProcessIdentifyTimeChange
  314. *
  315. * @brief Called to blink led for specified IdentifyTime attribute value
  316. *
  317. * @param none
  318. *
  319. * @return none
  320. */
  321. static void pct_ProcessIdentifyTimeChange( void )
  322. {
  323. if ( pctIdentifyTime > 0 )
  324. {
  325. osal_start_timerEx( pctTaskID, PCT_IDENTIFY_TIMEOUT_EVT, 1000 );
  326. HalLedBlink ( HAL_LED_4, 0xFF, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME );
  327. }
  328. else
  329. {
  330. HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
  331. osal_stop_timerEx( pctTaskID, PCT_IDENTIFY_TIMEOUT_EVT );
  332. }
  333. }
  334. #if defined (ZCL_KEY_ESTABLISH)
  335. /*********************************************************************
  336. * @fn pct_KeyEstablish_ReturnLinkKey
  337. *
  338. * @brief This function get the requested link key
  339. *
  340. * @param shortAddr - short address of the partner.
  341. *
  342. * @return none
  343. */
  344. static uint8 pct_KeyEstablish_ReturnLinkKey( uint16 shortAddr )
  345. {
  346. APSME_LinkKeyData_t* keyData;
  347. uint8 status = ZFailure;
  348. AddrMgrEntry_t entry;
  349. // Look up the long address of the device
  350. entry.user = ADDRMGR_USER_DEFAULT;
  351. entry.nwkAddr = shortAddr;
  352. if ( AddrMgrEntryLookupNwk( &entry ) )
  353. {
  354. // check for APS link key data
  355. APSME_LinkKeyDataGet( entry.extAddr, &keyData );
  356. if ( (keyData != NULL) && (keyData->key != NULL) )
  357. {
  358. status = ZSuccess;
  359. }
  360. }
  361. else
  362. {
  363. // It's an unknown device
  364. status = ZInvalidParameter;
  365. }
  366. return status;
  367. }
  368. #endif // ZCL_KEY_ESTABLISH
  369. /*********************************************************************
  370. * @fn pct_HandleKeys
  371. *
  372. * @brief Handles all key events for this device.
  373. *
  374. * @param shift - true if in shift/alt.
  375. * @param keys - bit field for key events. Valid entries:
  376. * HAL_KEY_SW_4
  377. * HAL_KEY_SW_3
  378. * HAL_KEY_SW_2
  379. * HAL_KEY_SW_1
  380. *
  381. * @return none
  382. */
  383. static void pct_HandleKeys( uint8 shift, uint8 keys )
  384. {
  385. // Shift is used to make each button/switch dual purpose.
  386. if ( shift )
  387. {
  388. if ( keys & HAL_KEY_SW_1 )
  389. {
  390. }
  391. if ( keys & HAL_KEY_SW_2 )
  392. {
  393. }
  394. if ( keys & HAL_KEY_SW_3 )
  395. {
  396. }
  397. if ( keys & HAL_KEY_SW_4 )
  398. {
  399. }
  400. }
  401. else
  402. {
  403. if ( keys & HAL_KEY_SW_1 )
  404. {
  405. ZDOInitDevice(0); // join the network
  406. }
  407. if ( keys & HAL_KEY_SW_2 )
  408. {
  409. }
  410. if ( keys & HAL_KEY_SW_3 )
  411. {
  412. }
  413. if ( keys & HAL_KEY_SW_4 )
  414. {
  415. }
  416. }
  417. }
  418. /*********************************************************************
  419. * @fn pct_ValidateAttrDataCB
  420. *
  421. * @brief Check to see if the supplied value for the attribute data
  422. * is within the specified range of the attribute.
  423. *
  424. * @param pAttr - pointer to attribute
  425. * @param pAttrInfo - pointer to attribute info
  426. *
  427. * @return TRUE if data valid. FALSE otherwise.
  428. */
  429. static uint8 pct_ValidateAttrDataCB( zclAttrRec_t *pAttr, zclWriteRec_t *pAttrInfo )
  430. {
  431. uint8 valid = TRUE;
  432. switch ( pAttrInfo->dataType )
  433. {
  434. case ZCL_DATATYPE_BOOLEAN:
  435. if ( ( *(pAttrInfo->attrData) != 0 ) && ( *(pAttrInfo->attrData) != 1 ) )
  436. valid = FALSE;
  437. break;
  438. default:
  439. break;
  440. }
  441. return ( valid );
  442. }
  443. /*********************************************************************
  444. * @fn pct_BasicResetCB
  445. *
  446. * @brief Callback from the ZCL General Cluster Library to set all
  447. * the attributes of all the clusters to their factory defaults
  448. *
  449. * @param none
  450. *
  451. * @return none
  452. */
  453. static void pct_BasicResetCB( void )
  454. {
  455. // user should handle setting attributes to factory defaults here
  456. }
  457. /*********************************************************************
  458. * @fn pct_IdentifyCB
  459. *
  460. * @brief Callback from the ZCL General Cluster Library when
  461. * it received an Identity Command for this application.
  462. *
  463. * @param pCmd - pointer to structure for identify command
  464. *
  465. * @return none
  466. */
  467. static void pct_IdentifyCB( zclIdentify_t *pCmd )
  468. {
  469. pctIdentifyTime = pCmd->identifyTime;
  470. pct_ProcessIdentifyTimeChange();
  471. }
  472. /*********************************************************************
  473. * @fn pct_IdentifyQueryRspCB
  474. *
  475. * @brief Callback from the ZCL General Cluster Library when
  476. * it received an Identity Query Response Command for this application.
  477. *
  478. * @param pRsp - pointer to structure for identify query response
  479. *
  480. * @return none
  481. */
  482. static void pct_IdentifyQueryRspCB( zclIdentifyQueryRsp_t *pRsp )
  483. {
  484. // add user code here
  485. }
  486. /*********************************************************************
  487. * @fn pct_AlarmCB
  488. *
  489. * @brief Callback from the ZCL General Cluster Library when
  490. * it received an Alarm request or response command for
  491. * this application.
  492. *
  493. * @param pAlarm - pointer to structure for alarm command
  494. *
  495. * @return none
  496. */
  497. static void pct_AlarmCB( zclAlarm_t *pAlarm )
  498. {
  499. // add user code here
  500. }
  501. #if defined (ZCL_LOAD_CONTROL)
  502. /*********************************************************************
  503. * @fn pct_SendReportEventStatus
  504. *
  505. * @brief Callback from the ZCL SE Profile Message Cluster Library when
  506. * it received a Load Control Event Command for
  507. * this application.
  508. *
  509. * @param afAddrType_t *srcAddr - pointer to source address
  510. * @param uint8 seqNum - sequence number for this event
  511. * @param uint32 eventID - event ID for this event
  512. * @param uint32 startTime - start time for this event
  513. * @param uint8 eventStatus - status for this event
  514. * @param uint8 criticalityLevel - criticality level for this event
  515. * @param uint8 eventControl - event control for this event
  516. *
  517. * @return none
  518. */
  519. static void pct_SendReportEventStatus( afAddrType_t *srcAddr, uint8 seqNum,
  520. uint32 eventID, uint32 startTime,
  521. uint8 eventStatus, uint8 criticalityLevel,
  522. uint8 eventControl )
  523. {
  524. // Mandatory fields - use the incoming data
  525. rsp.issuerEventID = eventID;
  526. rsp.eventStartTime = startTime;
  527. rsp.criticalityLevelApplied = criticalityLevel;
  528. rsp.eventControl = eventControl;
  529. rsp.eventStatus = eventStatus;
  530. rsp.signatureType = SE_PROFILE_SIGNATURE_TYPE_ECDSA;
  531. // pct_Signature is a static array.
  532. // value can be changed in pct_data.c
  533. osal_memcpy( rsp.signature, pctSignature, SE_PROFILE_SIGNATURE_LENGTH );
  534. // Optional fields - fill in with non-used value by default
  535. rsp.coolingTemperatureSetPointApplied = SE_OPTIONAL_FIELD_TEMPERATURE_SET_POINT;
  536. rsp.heatingTemperatureSetPointApplied = SE_OPTIONAL_FIELD_TEMPERATURE_SET_POINT;
  537. rsp.averageLoadAdjustment = SE_OPTIONAL_FIELD_INT8;
  538. rsp.dutyCycleApplied = SE_OPTIONAL_FIELD_UINT8;
  539. // Send response back
  540. // DisableDefaultResponse is set to false - it is recommended to turn on
  541. // default response since Report Event Status Command does not have
  542. // a response.
  543. zclSE_LoadControl_Send_ReportEventStatus( PCT_ENDPOINT, srcAddr,
  544. &rsp, false, seqNum );
  545. }
  546. #endif // ZCL_LOAD_CONTROL
  547. /*********************************************************************
  548. * @fn pct_LoadControlEventCB
  549. *
  550. * @brief Callback from the ZCL SE Profile Load Contro Cluster Library when
  551. * it received a Load Control Event Command for
  552. * this application.
  553. *
  554. * @param pCmd - pointer to load control event command
  555. * @param srcAddr - source address
  556. * @param status - event status
  557. * @param seqNum - sequence number of this command
  558. *
  559. * @return none
  560. */
  561. static void pct_LoadControlEventCB( zclCCLoadControlEvent_t *pCmd,
  562. afAddrType_t *srcAddr, uint8 status,
  563. uint8 seqNum)
  564. {
  565. #if defined ( ZCL_LOAD_CONTROL )
  566. // According to the Smart Metering Specification, upon receipt
  567. // of the Load Control Event command, the receiving device shall
  568. // send Report Event Status command back.
  569. uint8 eventStatus;
  570. if ( status == ZCL_STATUS_INVALID_FIELD )
  571. {
  572. // If the incoming message has invalid fields in it
  573. // Send response back with status: rejected
  574. eventStatus = EVENT_STATUS_LOAD_CONTROL_EVENT_REJECTED;
  575. }
  576. else
  577. { // Send response back with status: received
  578. eventStatus = EVENT_STATUS_LOAD_CONTROL_EVENT_RECEIVED;
  579. }
  580. // Send response back
  581. pct_SendReportEventStatus( srcAddr, seqNum, pCmd->issuerEvent,
  582. pCmd->startTime, eventStatus,
  583. pCmd->criticalityLevel, pCmd->eventControl);
  584. if ( status != ZCL_STATUS_INVALID_FIELD )
  585. {
  586. // Start the Load Control Event
  587. if ( pCmd->issuerEvent == LOADCONTROL_EVENT_ID )
  588. {
  589. if ( pCmd->startTime == START_TIME_NOW ) // start time = NOW
  590. {
  591. // send back status event = load control event started
  592. eventStatus = EVENT_STATUS_LOAD_CONTROL_EVENT_STARTED;
  593. pct_SendReportEventStatus( srcAddr, seqNum, pCmd->issuerEvent,
  594. pCmd->startTime, eventStatus,
  595. pCmd->criticalityLevel, pCmd->eventControl);
  596. if ( pCmd->deviceGroupClass == ONOFF_LOAD_DEVICE_CLASS ) // is this one for residential on/off load?
  597. {
  598. HalLcdWriteString("Load Evt Started", HAL_LCD_LINE_3);
  599. }
  600. else if ( pCmd->deviceGroupClass == HVAC_DEVICE_CLASS ) // is this one for HVAC compressor/furnace?
  601. {
  602. HalLcdWriteString("PCT Evt Started", HAL_LCD_LINE_3);
  603. }
  604. HalLedBlink ( HAL_LED_4, 0, 50, 500 );
  605. osal_start_timerEx( pctTaskID, PCT_LOAD_CTRL_EVT,
  606. (PCT_LOAD_CTRL_PERIOD * (pCmd->durationInMinutes)) );
  607. }
  608. }
  609. }
  610. #endif // ZCL_LOAD_CONTROL
  611. }
  612. /*********************************************************************
  613. * @fn pct_CancelLoadControlEventCB
  614. *
  615. * @brief Callback from the ZCL SE Profile Load Control Cluster Library when
  616. * it received a Cancel Load Control Event Command for
  617. * this application.
  618. *
  619. * @param pCmd - pointer to structure for Cancel Load Control Event command
  620. * @param scrAddr - source address
  621. * @param seqNum - sequence number for this command
  622. *
  623. * @return none
  624. */
  625. static void pct_CancelLoadControlEventCB( zclCCCancelLoadControlEvent_t *pCmd,
  626. afAddrType_t *srcAddr, uint8 seqNum )
  627. {
  628. #if defined ( ZCL_LOAD_CONTROL )
  629. if ( 0 ) // User shall replace the if condition with "if the event exist"
  630. {
  631. // If the event exist, stop the event, and respond with status: cancelled
  632. // Cancel the event here
  633. // Use the following sample code to send response back.
  634. /*
  635. pct_SendReportEventStatus( srcAddr, seqNum, pCmd->issuerEventID,
  636. // startTime
  637. EVENT_STATUS_LOAD_CONTROL_EVENT_CANCELLED, // eventStatus
  638. // Criticality level
  639. // eventControl };
  640. */
  641. }
  642. else
  643. {
  644. // If the event does not exist, respond with status: rejected
  645. // The rest of the mandatory fields are not available, therefore,
  646. // set to optional value
  647. pct_SendReportEventStatus( srcAddr, seqNum, pCmd->issuerEventID,
  648. SE_OPTIONAL_FIELD_UINT32, // startTime
  649. EVENT_STATUS_LOAD_CONTROL_EVENT_RECEIVED, // eventStatus
  650. SE_OPTIONAL_FIELD_UINT8, // Criticality level
  651. SE_OPTIONAL_FIELD_UINT8 ); // eventControl
  652. }
  653. #endif // ZCL_LOAD_CONTROL
  654. }
  655. /*********************************************************************
  656. * @fn pct_CancelAllLoadControlEventsCB
  657. *
  658. * @brief Callback from the ZCL SE Profile Load Control Cluster Library when
  659. * it received a Cancel All Load Control Event Command for
  660. * this application.
  661. *
  662. * @param pCmd - pointer to structure for Cancel All Load Control Event command
  663. * @param scrAddr - source address
  664. * @param seqNum - sequence number for this command
  665. *
  666. * @return none
  667. */
  668. static void pct_CancelAllLoadControlEventsCB( zclCCCancelAllLoadControlEvents_t *pCmd,
  669. afAddrType_t *srcAddr, uint8 seqNum )
  670. {
  671. // Upon receipt of Cancel All Load Control Event Command,
  672. // the receiving device shall look up the table for all events
  673. // and send a seperate response for each event
  674. }
  675. /*********************************************************************
  676. * @fn pct_ReportEventStatusCB
  677. *
  678. * @brief Callback from the ZCL SE Profile Load Contro Cluster Library when
  679. * it received a Report Event Status Command for
  680. * this application.
  681. *
  682. * @param pCmd - pointer to structure for Report Event Status command
  683. * @param scrAddr - source address
  684. * @param seqNum - sequence number for this command
  685. *
  686. * @return none
  687. */
  688. static void pct_ReportEventStatusCB( zclCCReportEventStatus_t *pCmd,
  689. afAddrType_t *srcAddr, uint8 seqNum)
  690. {
  691. // add user code here
  692. }
  693. /*********************************************************************
  694. * @fn pct_GetScheduledEventCB
  695. *
  696. * @brief Callback from the ZCL SE Profile Load Control Cluster Library when
  697. * it received a Get Scheduled Event Command for
  698. * this application.
  699. *
  700. * @param pCmd - pointer to structure for Get Scheduled Event command
  701. * @param scrAddr - source address
  702. * @param seqNum - sequence number for this command
  703. *
  704. * @return none
  705. */
  706. static void pct_GetScheduledEventCB( zclCCGetScheduledEvent_t *pCmd,
  707. afAddrType_t *srcAddr, uint8 seqNum )
  708. {
  709. // add user code here
  710. }
  711. /******************************************************************************
  712. *
  713. * Functions for processing ZCL Foundation incoming Command/Response messages
  714. *
  715. *****************************************************************************/
  716. /*********************************************************************
  717. * @fn pct_ProcessZCLMsg
  718. *
  719. * @brief Process ZCL Foundation incoming message
  720. *
  721. * @param pInMsg - message to process
  722. *
  723. * @return none
  724. */
  725. static void pct_ProcessZCLMsg( zclIncomingMsg_t *pInMsg )
  726. {
  727. switch ( pInMsg->zclHdr.commandID )
  728. {
  729. #if defined ( ZCL_READ )
  730. case ZCL_CMD_READ_RSP:
  731. pct_ProcessInReadRspCmd( pInMsg );
  732. break;
  733. #endif // ZCL_READ
  734. #if defined ( ZCL_WRITE )
  735. case ZCL_CMD_WRITE_RSP:
  736. pct_ProcessInWriteRspCmd( pInMsg );
  737. break;
  738. #endif // ZCL_WRITE
  739. case ZCL_CMD_DEFAULT_RSP:
  740. pct_ProcessInDefaultRspCmd( pInMsg );
  741. break;
  742. #if defined ( ZCL_DISCOVER )
  743. case ZCL_CMD_DISCOVER_RSP:
  744. pct_ProcessInDiscRspCmd( pInMsg );
  745. break;
  746. #endif // ZCL_DISCOVER
  747. default:
  748. break;
  749. }
  750. if ( pInMsg->attrCmd != NULL )
  751. {
  752. // free the parsed command
  753. osal_mem_free( pInMsg->attrCmd );
  754. pInMsg->attrCmd = NULL;
  755. }
  756. }
  757. #if defined ( ZCL_READ )
  758. /*********************************************************************
  759. * @fn pct_ProcessInReadRspCmd
  760. *
  761. * @brief Process the "Profile" Read Response Command
  762. *
  763. * @param pInMsg - incoming message to process
  764. *
  765. * @return none
  766. */
  767. static uint8 pct_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg )
  768. {
  769. zclReadRspCmd_t *readRspCmd;
  770. uint8 i;
  771. readRspCmd = (zclReadRspCmd_t *)pInMsg->attrCmd;
  772. for (i = 0; i < readRspCmd->numAttr; i++)
  773. {
  774. // Notify the originator of the results of the original read attributes
  775. // attempt and, for each successfull request, the value of the requested
  776. // attribute
  777. }
  778. return TRUE;
  779. }
  780. #endif // ZCL_READ
  781. #if defined ( ZCL_WRITE )
  782. /*********************************************************************
  783. * @fn pct_ProcessInWriteRspCmd
  784. *
  785. * @brief Process the "Profile" Write Response Command
  786. *
  787. * @param pInMsg - incoming message to process
  788. *
  789. * @return none
  790. */
  791. static uint8 pct_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg )
  792. {
  793. zclWriteRspCmd_t *writeRspCmd;
  794. uint8 i;
  795. writeRspCmd = (zclWriteRspCmd_t *)pInMsg->attrCmd;
  796. for (i = 0; i < writeRspCmd->numAttr; i++)
  797. {
  798. // Notify the device of the results of the its original write attributes
  799. // command.
  800. }
  801. return TRUE;
  802. }
  803. #endif // ZCL_WRITE
  804. /*********************************************************************
  805. * @fn pct_ProcessInDefaultRspCmd
  806. *
  807. * @brief Process the "Profile" Default Response Command
  808. *
  809. * @param pInMsg - incoming message to process
  810. *
  811. * @return none
  812. */
  813. static uint8 pct_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg )
  814. {
  815. // zclDefaultRspCmd_t *defaultRspCmd = (zclDefaultRspCmd_t *)pInMsg->attrCmd;
  816. // Device is notified of the Default Response command.
  817. return TRUE;
  818. }
  819. #if defined ( ZCL_DISCOVER )
  820. /*********************************************************************
  821. * @fn pct_ProcessInDiscRspCmd
  822. *
  823. * @brief Process the "Profile" Discover Response Command
  824. *
  825. * @param pInMsg - incoming message to process
  826. *
  827. * @return none
  828. */
  829. static uint8 pct_ProcessInDiscRspCmd( zclIncomingMsg_t *pInMsg )
  830. {
  831. zclDiscoverRspCmd_t *discoverRspCmd;
  832. uint8 i;
  833. discoverRspCmd = (zclDiscoverRspCmd_t *)pInMsg->attrCmd;
  834. for ( i = 0; i < discoverRspCmd->numAttr; i++ )
  835. {
  836. // Device is notified of the result of its attribute discovery command.
  837. }
  838. return TRUE;
  839. }
  840. #endif // ZCL_DISCOVER
  841. /****************************************************************************
  842. ****************************************************************************/