Watch 1 Star 0 Fork 0

leconiot / z-stackC

Join us
Explore and code with more than 2 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
基于ti cc2530 的z-stack 协议栈,version 3.0.2,June 15, 2018。 spread retract

  • C 92.4%
  • C++ 6.4%
  • HTML 1.0%
  • JavaScript 0.1%
  • Batchfile 0.1%
Clone or download
zcl_general.c 122.13 KB
Copy Edit Raw Blame History
yurenlee authored 2019-06-20 15:07 . zstack init version
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059
/**************************************************************************************************
Filename: zcl_general.c
Revised: $Date: 2015-09-10 09:36:48 -0700 (Thu, 10 Sep 2015) $
Revision: $Revision: 44493 $
Description: Zigbee Cluster Library - General. This application receives all
ZCL messages and initially parses them before passing to application.
Copyright 2006-2015 Texas Instruments Incorporated. All rights reserved.
IMPORTANT: Your use of this Software is limited to those specific rights
granted under the terms of a software license agreement between the user
who downloaded the software, his/her employer (which must be your employer)
and Texas Instruments Incorporated (the "License"). You may not use this
Software unless you agree to abide by the terms of the License. The License
limits your use, and you acknowledge, that the Software may not be modified,
copied or distributed unless embedded on a Texas Instruments microcontroller
or used solely and exclusively in conjunction with a Texas Instruments radio
frequency transceiver, which is integrated into your product. Other than for
the foregoing purpose, you may not use, reproduce, copy, prepare derivative
works of, modify, distribute, perform, display or sell this Software and/or
its documentation for any purpose.
YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
Should you have any questions regarding your right to use this Software,
contact Texas Instruments Incorporated at www.TI.com.
**************************************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "ZComDef.h"
#include "zcl.h"
#include "zcl_general.h"
//#include "ZDApp.h"
#if defined ( INTER_PAN )
#include "stub_aps.h"
#endif
#include "bdb.h"
/*********************************************************************
* MACROS
*/
#define locationTypeAbsolute( a ) ( (a) & LOCATION_TYPE_ABSOLUTE )
#define locationType2D( a ) ( (a) & LOCATION_TYPE_2_D )
#define locationTypeCoordinateSystem( a ) ( (a) & LOCATION_TYPE_COORDINATE_SYSTEM )
#ifdef ZCL_SCENES
#define zclGeneral_ScenesRemaingCapacity() ( ZCL_GEN_MAX_SCENES - zclGeneral_CountAllScenes() )
#endif // ZCL_SCENES
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
typedef struct zclGenCBRec
{
struct zclGenCBRec *next;
uint8 endpoint; // Used to link it into the endpoint descriptor
zclGeneral_AppCallbacks_t *CBs; // Pointer to Callback function
} zclGenCBRec_t;
typedef struct zclGenSceneItem
{
struct zclGenSceneItem *next;
uint8 endpoint; // Used to link it into the endpoint descriptor
zclGeneral_Scene_t scene; // Scene info
} zclGenSceneItem_t;
typedef struct zclGenAlarmItem
{
struct zclGenAlarmItem *next;
uint8 endpoint; // Used to link it into the endpoint descriptor
zclGeneral_Alarm_t alarm; // Alarm info
} zclGenAlarmItem_t;
// Scene NV types
typedef struct
{
uint16 numRecs;
} nvGenScenesHdr_t;
typedef struct zclGenSceneNVItem
{
uint8 endpoint;
zclGeneral_Scene_t scene;
} zclGenSceneNVItem_t;
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* GLOBAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
static zclGenCBRec_t *zclGenCBs = (zclGenCBRec_t *)NULL;
static uint8 zclGenPluginRegisted = FALSE;
#if defined( ZCL_SCENES )
#if !defined ( ZCL_STANDALONE )
static zclGenSceneItem_t *zclGenSceneTable = (zclGenSceneItem_t *)NULL;
#endif
#endif // ZCL_SCENES
#ifdef ZCL_ALARMS
static zclGenAlarmItem_t *zclGenAlarmTable = (zclGenAlarmItem_t *)NULL;
#endif // ZCL_ALARMS
/*********************************************************************
* LOCAL FUNCTIONS
*/
static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg );
static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg );
static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint );
// Device Configuration and Installation clusters
#ifdef ZCL_BASIC
static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_BASIC
#ifdef ZCL_IDENTIFY
static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_IDENTIFY
// Groups and Scenes clusters
#ifdef ZCL_GROUPS
static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg );
static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData );
#endif // ZCL_GROUPS
#ifdef ZCL_SCENES
static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_SCENES
// On/Off and Level Control Configuration clusters
#ifdef ZCL_ON_OFF
static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_ONOFF
#ifdef ZCL_LEVEL_CTRL
static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_LEVEL_CTRL
// Alarms cluster
#ifdef ZCL_ALARMS
static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_ALARMS
// Location cluster
#ifdef ZCL_LOCATION
static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
#endif // ZCL_LOCATION
#ifdef ZCL_SCENES
#if !defined ( ZCL_STANDALONE )
static uint8 zclGeneral_ScenesInitNV( void );
static void zclGeneral_ScenesSetDefaultNV( void );
static void zclGeneral_ScenesWriteNV( void );
static uint16 zclGeneral_ScenesRestoreFromNV( void );
#endif
#endif // ZCL_SCENES
/*********************************************************************
* @fn zclGeneral_RegisterCmdCallbacks
*
* @brief Register an applications command callbacks
*
* @param endpoint - application's endpoint
* @param callbacks - pointer to the callback record.
*
* @return ZMemError if not able to allocate
*/
ZStatus_t zclGeneral_RegisterCmdCallbacks( uint8 endpoint, zclGeneral_AppCallbacks_t *callbacks )
{
zclGenCBRec_t *pNewItem;
zclGenCBRec_t *pLoop;
// Register as a ZCL Plugin
if ( zclGenPluginRegisted == FALSE )
{
zcl_registerPlugin( ZCL_CLUSTER_ID_GEN_BASIC,
ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC,
zclGeneral_HdlIncoming );
#ifdef ZCL_SCENES
// Initialize the Scenes Table
zclGeneral_ScenesInit();
#endif // ZCL_SCENES
zclGenPluginRegisted = TRUE;
}
// Fill in the new profile list
pNewItem = zcl_mem_alloc( sizeof( zclGenCBRec_t ) );
if ( pNewItem == NULL )
return (ZMemError);
pNewItem->next = (zclGenCBRec_t *)NULL;
pNewItem->endpoint = endpoint;
pNewItem->CBs = callbacks;
// Find spot in list
if ( zclGenCBs == NULL )
{
zclGenCBs = pNewItem;
}
else
{
// Look for end of list
pLoop = zclGenCBs;
while ( pLoop->next != NULL )
pLoop = pLoop->next;
// Put new item at end of list
pLoop->next = pNewItem;
}
return ( ZSuccess );
}
#ifdef ZCL_IDENTIFY
/*********************************************************************
* @fn zclGeneral_SendIdentify
*
* @brief Call to send out an Identify Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param identifyTime - how long the device will continue to identify itself (in seconds)
* @param seqNum - identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendIdentify( uint8 srcEP, afAddrType_t *dstAddr,
uint16 identifyTime, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = LO_UINT16( identifyTime );
buf[1] = HI_UINT16( identifyTime );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
COMMAND_IDENTIFY, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 2, buf );
}
/*********************************************************************
* @fn zclGeneral_SendIdentifyEZModeInvoke
*
* @brief Call to send out an Identify EZ-Mode Invoke Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param action - describes the EZ-Mode action to be performed
* @param seqNum - identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendIdentifyEZModeInvoke( uint8 srcEP, afAddrType_t *dstAddr,
uint8 action, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[1];
buf[0] = action;
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
COMMAND_IDENTIFY_EZMODE_INVOKE, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 1, buf );
}
/*********************************************************************
* @fn zclGeneral_SendIdentifyUpdateCommState
*
* @brief Call to send out an Identify Update Commission State Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param action - describes the EZ-Mode action to be performed
* @param commissionStateMask - updates the device's commission state
* @param seqNum - identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendIdentifyUpdateCommState( uint8 srcEP, afAddrType_t *dstAddr,
uint8 action, uint8 commissionStateMask,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = action;
buf[1] = commissionStateMask;
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
COMMAND_IDENTIFY_UPDATE_COMMISSION_STATE, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 2, buf );
}
#ifdef ZCL_LIGHT_LINK_ENHANCE
/*********************************************************************
* @fn zclGeneral_SendIdentifyTriggerEffect
*
* @brief Call to send out a Trigger Effect Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param effectId - identify effect to use
* @param effectVariant - which variant of effect to be triggered
* @param disableDefaultRsp - whether to disable the Default Response command
* @param seqNum - identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendIdentifyTriggerEffect( uint8 srcEP, afAddrType_t *dstAddr,
uint8 effectId, uint8 effectVariant,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = effectId;
buf[1] = effectVariant;
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
COMMAND_IDENTIFY_TRIGGER_EFFECT, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 2, buf );
}
#endif // ZCL_LIGHT_LINK_ENHANCE
/*********************************************************************
* @fn zclGeneral_SendIdentifyQueryResponse
*
* @brief Call to send out an Identify Query Response Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param timeout - how long the device will continue to identify itself (in seconds)
* @param seqNum - identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendIdentifyQueryResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint16 timeout, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = LO_UINT16( timeout );
buf[1] = HI_UINT16( timeout );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
COMMAND_IDENTIFY_QUERY_RSP, TRUE,
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, 2, buf );
}
#endif // ZCL_IDENTIFY
#ifdef ZCL_GROUPS
/*********************************************************************
* @fn zclGeneral_SendGroupRequest
*
* @brief Send a Group Request to a device. You can also use the
* appropriate macro.
*
* @param srcEP - Sending Apps endpoint
* @param dstAddr - where to send the request
* @param cmd - one of the following:
* COMMAND_GROUP_VIEW
* COMMAND_GROUP_REMOVE
* @param groupID -
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendGroupRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint16 groupID, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = LO_UINT16( groupID );
buf[1] = HI_UINT16( groupID );
return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 2, buf ) );
}
/*********************************************************************
* @fn zclGeneral_SendAddGroupRequest
*
* @brief Send the Add Group Request to a device
*
* @param srcEP - Sending Apps endpoint
* @param dstAddr - where to send the request
* @param cmd - one of the following:
* COMMAND_GROUP_ADD
* COMMAND_GROUP_ADD_IF_IDENTIFYING
* @param groupID - pointer to the group structure
* @param groupName - pointer to Group Name. This is a Zigbee
* string data type, so the first byte is the length of the
* name (in bytes), then the name.
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAddGroupRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint16 groupID, uint8 *groupName,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 *pBuf;
uint8 len;
ZStatus_t status;
len = 2; // Group ID
len += groupName[0] + 1; // String + 1 for length
buf = zcl_mem_alloc( len );
if ( buf )
{
pBuf = buf;
*pBuf++ = LO_UINT16( groupID );
*pBuf++ = HI_UINT16( groupID );
*pBuf++ = groupName[0]; // string length
zcl_memcpy( pBuf, &(groupName[1]), groupName[0] );
status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
zcl_mem_free( buf );
}
else
status = ZMemError;
return ( status );
}
/*********************************************************************
* @fn zclGeneral_SendGroupGetMembershipRequest
*
* @brief Send a Get Group Membership (Resposne) Command to a device
*
* @param srcEP - Sending Apps endpoint
* @param dstAddr - where to send the request
* @param cmd - one of the following:
* COMMAND_GROUP_GET_MEMBERSHIP
* COMMAND_GROUP_GET_MEMBERSHIP_RSP
* @param groupID - pointer to the group structure
* @param groupName - pointer to Group Name. This is a Zigbee
* string data type, so the first byte is the length of the
* name (in bytes), then the name.
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendGroupGetMembershipRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 rspCmd, uint8 direction, uint8 capacity,
uint8 grpCnt, uint16 *grpList, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 *pBuf;
uint8 len = 0;
uint8 i;
ZStatus_t status;
if ( rspCmd )
len++; // Capacity
len++; // Group Count
len += sizeof ( uint16 ) * grpCnt; // Group List
buf = zcl_mem_alloc( len );
if ( buf )
{
pBuf = buf;
if ( rspCmd )
*pBuf++ = capacity;
*pBuf++ = grpCnt;
for ( i = 0; i < grpCnt; i++ )
{
*pBuf++ = LO_UINT16( grpList[i] );
*pBuf++ = HI_UINT16( grpList[i] );
}
status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
cmd, TRUE, direction,
disableDefaultRsp, 0, seqNum, len, buf );
zcl_mem_free( buf );
}
else
status = ZMemError;
return ( status );
}
/*********************************************************************
* @fn zclGeneral_SendGroupResponse
*
* @brief Send Group Response (not Group View Response)
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - either COMMAND_GROUP_ADD_RSP or COMMAND_GROUP_REMOVE_RSP
* @param status - group command status
* @param groupID - what group
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendGroupResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 status, uint16 groupID,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[3];
buf[0] = status;
buf[1] = LO_UINT16( groupID );
buf[2] = HI_UINT16( groupID );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, 3, buf );
}
/*********************************************************************
* @fn zclGeneral_SendGroupViewResponse
*
* @brief Call to send Group Response Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - either COMMAND_GROUP_ADD_RSP or COMMAND_GROUP_REMOVE_RSP
* @param status - group command status
* @param grp - group info
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendGroupViewResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint8 status, aps_Group_t *grp, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 len;
ZStatus_t stat;
len = 1 + 2 + 1; // Status + Group ID + name length
if ( status == ZCL_STATUS_SUCCESS )
{
len += grp->name[0]; // String length
}
buf = zcl_mem_alloc( len );
if ( buf )
{
buf[0] = status;
buf[1] = LO_UINT16( grp->ID );
buf[2] = HI_UINT16( grp->ID );
if ( status == ZCL_STATUS_SUCCESS )
{
buf[3] = grp->name[0]; // string length
zcl_memcpy( &buf[4], (&grp->name[1]), grp->name[0] );
}
else //ZCL_STATUS_NOT_FOUND
{
buf[3] = 0;
}
stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
COMMAND_GROUP_VIEW_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
zcl_mem_free( buf );
}
else
{
stat = ZMemError;
}
return ( stat );
}
#endif // ZCL_GROUPS
#ifdef ZCL_SCENES
/*********************************************************************
* @fn zclGeneral_SendAddSceneRequest
*
* @brief Send the (Enhanced) Add Scene Request to a device. You can
* also use the appropriate macro.
*
* @param srcEP - Sending Apps endpoint
* @param dstAddr - where to send the request
* @param scene - pointer to the scene structure
* @param cmd - COMMAND_SCENE_ADD or COMMAND_SCENE_ENHANCED_ADD
* @param disableDefaultRsp - whether to disable the Default Response command
* @param seqNum - sequence number
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAddSceneRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, zclGeneral_Scene_t *scene,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 *pBuf;
uint8 len;
ZStatus_t status;
len = 2 + 1 + 2; // Group ID + Scene ID + transition time
len += scene->name[0] + 1; // String + 1 for length
// Add something for the extension field length
len += scene->extLen;
buf = zcl_mem_alloc( len );
if ( buf )
{
pBuf = buf;
*pBuf++ = LO_UINT16( scene->groupID );
*pBuf++ = HI_UINT16( scene->groupID );
*pBuf++ = scene->ID;
*pBuf++ = LO_UINT16( scene->transTime );
*pBuf++ = HI_UINT16( scene->transTime );
*pBuf++ = scene->name[0]; // string length
zcl_memcpy( pBuf, &(scene->name[1]), scene->name[0] );
pBuf += scene->name[0]; // move pass name
// Add the extension fields
if ( scene->extLen > 0 )
zcl_memcpy( pBuf, scene->extField, scene->extLen );
status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
zcl_mem_free( buf );
}
else
status = ZMemError;
return ( status );
}
/*********************************************************************
* @fn zclGeneral_SendSceneRequest
*
* @brief Send a Scene Request to a device. You can also use the
* appropriate macro.
*
* @param srcEP - Sending Apps endpoint
* @param dstAddr - where to send the request
* @param cmd - one of the following:
* COMMAND_SCENE_VIEW
* COMMAND_SCENE_REMOVE
* COMMAND_SCENE_REMOVE_ALL
* COMMAND_SCENE_STORE
* COMMAND_SCENE_RECALL
* COMMAND_SCENE_GET_MEMBERSHIP
* COMMAND_SCENE_ENHANCED_VIEW
* @param groupID - group ID
* @param sceneID - scene ID (not applicable to COMMAND_SCENE_REMOVE_ALL and
* COMMAND_SCENE_GET_MEMBERSHIP)
* @param disableDefaultRsp - whether to disable the Default Response command
* @param seqNum - sequence number
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendSceneRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint16 groupID, uint8 sceneID,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[3];
uint8 len = 2;
buf[0] = LO_UINT16( groupID );
buf[1] = HI_UINT16( groupID );
if ( cmd != COMMAND_SCENE_REMOVE_ALL && cmd != COMMAND_SCENE_GET_MEMBERSHIP )
{
buf[2] = sceneID;
len++;
}
return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, len, buf ) );
}
/*********************************************************************
* @fn zclGeneral_SendSceneResponse
*
* @brief Send Group Response (not Group View Response)
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - either COMMAND_SCENE_ADD_RSP, COMMAND_SCENE_REMOVE_RSP
* COMMAND_SCENE_STORE_RSP, or COMMAND_SCENE_REMOVE_ALL_RSP
* @param status - scene command status
* @param groupID - what group
* @param sceneID - what scene (not applicable to COMMAND_SCENE_REMOVE_ALL_RSP)
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendSceneResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 status, uint16 groupID,
uint8 sceneID, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[4];
uint8 len = 1 + 2; // Status + Group ID
buf[0] = status;
buf[1] = LO_UINT16( groupID );
buf[2] = HI_UINT16( groupID );
if ( cmd != COMMAND_SCENE_REMOVE_ALL_RSP )
{
buf[3] = sceneID;
len++;
}
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
}
/*********************************************************************
* @fn zclGeneral_SendSceneViewResponse
*
* @brief Call to send Scene (Enahced) View Response Command. You can
* also use the appropriate macro.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - either COMMAND_SCENE_VIEW_RSP or COMMAND_SCENE_ENHANCED_VIEW_RSP
* @param status - scene command status
* @param scene - scene info
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendSceneViewRsp( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 status, zclGeneral_Scene_t *scene,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 *pBuf;
uint8 len = 1 + 2 + 1; // Status + Group ID + Scene ID
ZStatus_t stat;
if ( status == ZCL_STATUS_SUCCESS )
{
len += 2; // Transition Time
len += scene->name[0] + 1; // string + 1 for length
// Add something for the extension field length
len += scene->extLen;
}
buf = zcl_mem_alloc( len );
if ( buf )
{
pBuf = buf;
*pBuf++ = status;
*pBuf++ = LO_UINT16( scene->groupID );
*pBuf++ = HI_UINT16( scene->groupID );
*pBuf++ = scene->ID;
if ( status == ZCL_STATUS_SUCCESS )
{
uint16 transTime = scene->transTime;
if ( cmd == COMMAND_SCENE_ENHANCED_VIEW_RSP )
{
// Transition time is in 1/10s
transTime *= 10;
transTime += scene->transTime100ms;
}
*pBuf++ = LO_UINT16( transTime );
*pBuf++ = HI_UINT16( transTime );
*pBuf++ = scene->name[0]; // string length
if ( scene->name[0] != 0 )
{
zcl_memcpy( pBuf, &(scene->name[1]), scene->name[0] );
pBuf += scene->name[0]; // move pass name
}
// Add the extension fields
if ( scene->extLen > 0 )
zcl_memcpy( pBuf, scene->extField, scene->extLen );
}
stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
zcl_mem_free( buf );
}
else
stat = ZMemError;
return ( stat );
}
/*********************************************************************
* @fn zclGeneral_SendSceneGetMembershipResponse
*
* @brief Call to send Scene Get Membership Response Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param status - scene command status
* @param capacity - remaining capacity of the scene table
* @param sceneCnt - number of scenes in the scene list
* @param sceneList - list of scene IDs
* @param groupID - group ID that scene belongs to
* @param seqNum - sequence number
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendSceneGetMembershipResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint8 status, uint8 capacity, uint8 sceneCnt, uint8 *sceneList,
uint16 groupID, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 *pBuf;
uint8 len = 1 + 1 + 2; // Status + Capacity + Group ID;
uint8 i;
ZStatus_t stat;
if ( status == ZCL_STATUS_SUCCESS )
{
len++; // Scene Count
len += sceneCnt; // Scene List (Scene ID is a single octet)
}
buf = zcl_mem_alloc( len );
if ( buf )
{
pBuf = buf;
*pBuf++ = status;
*pBuf++ = capacity;
*pBuf++ = LO_UINT16( groupID );
*pBuf++ = HI_UINT16( groupID );
if ( status == ZCL_STATUS_SUCCESS )
{
*pBuf++ = sceneCnt;
for ( i = 0; i < sceneCnt; i++ )
*pBuf++ = sceneList[i];
}
stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
COMMAND_SCENE_GET_MEMBERSHIP_RSP, TRUE,
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
zcl_mem_free( buf );
}
else
stat = ZMemError;
return ( stat );
}
#ifdef ZCL_LIGHT_LINK_ENHANCE
/*********************************************************************
* @fn zclGeneral_SendSceneCopy
*
* @brief Send Scene Copy Request to a device
*
* @param srcEP - sending application's endpoint
* @param dstAddr - where to send the request
* @param mode - how scene copy is to proceed
* @param groupIDFrom - group from which scene to be copied
* @param sceneIDFrom - scene from which scene to be copied
* @param groupIDTo - group to which scene to be copied
* @param sceneIDTo - scene to which scene to be copied
* @param disableDefaultRsp - disable Default Response command
* @param seqNum - the identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendSceneCopy( uint8 srcEP, afAddrType_t *dstAddr,
uint8 mode, uint16 groupIDFrom, uint8 sceneIDFrom,
uint16 groupIDTo, uint8 sceneIDTo,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[7];
buf[0] = mode;
buf[1] = LO_UINT16( groupIDFrom );
buf[2] = HI_UINT16( groupIDFrom );
buf[3] = sceneIDFrom;
buf[4] = LO_UINT16( groupIDTo );
buf[5] = HI_UINT16( groupIDTo );
buf[6] = sceneIDTo;
return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
COMMAND_SCENE_COPY, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 7, buf ) );
}
/*********************************************************************
* @fn zclGeneral_SendSceneCopyResponse
*
* @brief Send Scene Copy Response to a device
*
* @param srcEP - sending application's endpoint
* @param dstAddr - where to send the request
* @param status - status of copy scene attemp
* @param groupIDFrom - group from which scene was copied
* @param sceneIDFrom - scene from which scene was copied
* @param disableDefaultRsp - disable Default Response command
* @param seqNum - the identification number for the transaction
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendSceneCopyResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint8 status, uint16 groupIDFrom, uint8 sceneIDFrom,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[4];
buf[0] = status;
buf[1] = LO_UINT16( groupIDFrom );
buf[2] = HI_UINT16( groupIDFrom );
buf[3] = sceneIDFrom;
return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
COMMAND_SCENE_COPY_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, 4, buf ) );
}
#endif // ZCL_LIGHT_LINK_ENHANCE
#endif // ZCL_SCENES
#ifdef ZCL_ON_OFF
#ifdef ZCL_LIGHT_LINK_ENHANCE
/*********************************************************************
* @fn zclGeneral_SendOnOff_CmdOffWithEffect
*
* @brief Call to send out an Off with Effect Command.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param effectId - fading effect to use when switching light off
* @param effectVariant - which variant of effect to be triggered
* @param disableDefaultRsp - whether to disable the Default Response command
* @param seqNum - sequence number
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendOnOff_CmdOffWithEffect( uint8 srcEP, afAddrType_t *dstAddr,
uint8 effectId, uint8 effectVariant,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = effectId;
buf[1] = effectVariant;
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ON_OFF,
COMMAND_OFF_WITH_EFFECT, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 2, buf );
}
/*********************************************************************
* @fn zclGeneral_SendOnOff_CmdOnWithTimedOff
*
* @brief Call to send out an On with Timed Off Command.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param onOffCtrl - how the lamp is to be operated
* @param onTime - the length of time (in 1/10ths second) that the lamp is to remain on, before automatically turning off
* @param offWaitTime - the length of time (in 1/10ths second) that the lamp shall remain off, and guarded to prevent an on command turning the light back on.
* @param disableDefaultRsp - whether to disable the Default Response command
* @param seqNum - sequence number
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendOnOff_CmdOnWithTimedOff ( uint8 srcEP, afAddrType_t *dstAddr,
zclOnOffCtrl_t onOffCtrl, uint16 onTime, uint16 offWaitTime,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[5];
buf[0] = onOffCtrl.byte;
buf[1] = LO_UINT16( onTime );
buf[2] = HI_UINT16( onTime );
buf[3] = LO_UINT16( offWaitTime );
buf[4] = HI_UINT16( offWaitTime );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ON_OFF,
COMMAND_ON_WITH_TIMED_OFF, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 5, buf );
}
#endif // ZCL_LIGHT_LINK_ENHANCE
#endif // ZCL_ON_OFF
#ifdef ZCL_LEVEL_CTRL
/*********************************************************************
* @fn zclGeneral_SendLevelControlMoveToLevelRequest
*
* @brief Call to send out a Level Control Request. You can also use
* the appropriate macro.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - one of the following:
* COMMAND_LEVEL_MOVE_TO_LEVEL or
* COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF
* @param level - what level to move to
* @param transitionTime - how long to take to get to the level (in seconds)
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLevelControlMoveToLevelRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 level, uint16 transTime,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[3];
buf[0] = level;
buf[1] = LO_UINT16( transTime );
buf[2] = HI_UINT16( transTime );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 3, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLevelControlMoveRequest
*
* @brief Call to send out a Level Control Request. You can also use
* the appropriate macro.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - one of the following:
* COMMAND_LEVEL_MOVE or
* COMMAND_LEVEL_MOVE_WITH_ON_OFF
* @param moveMode - LEVEL_MOVE_UP or
* LEVEL_MOVE_DOWN
* @param rate - number of steps to take per second
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLevelControlMoveRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 moveMode, uint8 rate,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[2];
buf[0] = moveMode;
buf[1] = rate;
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 2, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLevelControlStepRequest
*
* @brief Call to send out a Level Control Request. You can also use
* the appropriate macro.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - one of the following:
* COMMAND_LEVEL_STEP
* COMMAND_LEVEL_STEP_WITH_ON_OFF
* @param stepMode - LEVEL_STEP_UP or
* LEVEL_STEP_DOWN
* @param amount - number of levels to step
* @param transitionTime - time, in 1/10ths of a second, to take to perform the step
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLevelControlStepRequest( uint8 srcEP, afAddrType_t *dstAddr,
uint8 cmd, uint8 stepMode, uint8 stepSize, uint16 transTime,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[4];
buf[0] = stepMode;
buf[1] = stepSize;
buf[2] = LO_UINT16( transTime );
buf[3] = HI_UINT16( transTime );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 4, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLevelControlStepRequest
*
* @brief Call to send out a Level Control Request. You can also use
* the appropriate macro.
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - one of the following:
* COMMAND_LEVEL_STOP
* COMMAND_LEVEL_STOP_WITH_ON_OFF
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLevelControlStopRequest( uint8 srcEP, afAddrType_t *dstAddr, uint8 cmd,
uint8 disableDefaultRsp, uint8 seqNum )
{
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 0, NULL );
}
#endif // ZCL_LEVEL_CTRL
#ifdef ZCL_ALARMS
/*********************************************************************
* @fn zclGeneral_SendAlarm
*
* @brief Call to send out an Alarm Request Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param cmd - COMMAND_ALARMS_ALARM
* @param alarmCode - code for the cause of the alarm
* @param clusterID - cluster whose attribute generate the alarm
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAlarm( uint8 srcEP, afAddrType_t *dstAddr,
uint8 alarmCode, uint16 clusterID,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[3];
buf[0] = alarmCode;
buf[1] = LO_UINT16( clusterID );
buf[2] = HI_UINT16( clusterID );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
COMMAND_ALARMS_ALARM, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, 3, buf );
}
/*********************************************************************
* @fn zclGeneral_SendAlarmReset
*
* @brief Call to send out an Alarm Reset Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param alarmCode - code for the cause of the alarm
* @param clusterID - cluster whose attribute generate the alarm
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAlarmReset( uint8 srcEP, afAddrType_t *dstAddr,
uint8 alarmCode, uint16 clusterID,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[3];
buf[0] = alarmCode;
buf[1] = LO_UINT16( clusterID );
buf[2] = HI_UINT16( clusterID );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
COMMAND_ALARMS_RESET, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, 3, buf );
}
/*********************************************************************
* @fn zclGeneral_SendAlarmGetResponse
*
* @brief Call to send out an Alarm Get Response Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param status - SUCCESS or NOT_FOUND
* @param alarmCode - code for the cause of the alarm
* @param clusterID - cluster whose attribute generate the alarm
* @param timeStamp - time at which the alarm occured
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAlarmGetResponse( uint8 srcEP, afAddrType_t *dstAddr,
uint8 status, uint8 alarmCode, uint16 clusterID,
uint32 timeStamp, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[8];
uint8 len = 1; // Status
buf[0] = status;
if ( status == ZCL_STATUS_SUCCESS )
{
len += 1 + 2 + 4; // Alarm code + Cluster ID + Time stamp
buf[1] = alarmCode;
buf[2] = LO_UINT16( clusterID );
buf[3] = HI_UINT16( clusterID );
zcl_buffer_uint32( &buf[4], timeStamp );
}
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
COMMAND_ALARMS_GET_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
}
#ifdef SE_UK_EXT
/*********************************************************************
* @fn zclGeneral_SendAlarmGetEventLog
*
* @brief Call to send out an Alarm Get Event Log Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param pEventLog - pointer to Get Event Log Command
* @param disableDefaultRsp - disable default response
* @param seqNum - ZCL sequence number
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAlarmGetEventLog( uint8 srcEP, afAddrType_t *dstAddr,
zclGetEventLog_t *pEventLog,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[10];
buf[0] = pEventLog->logID;
zcl_buffer_uint32( &buf[1], pEventLog->startTime );
zcl_buffer_uint32( &buf[5], pEventLog->endTime );
buf[9] = pEventLog->numEvents;
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
COMMAND_ALARMS_GET_EVENT_LOG, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, 10, buf );
}
/*********************************************************************
* @fn zclGeneral_SendAlarmPublishEventLog
*
* @brief Call to send out an Alarm Publish Event Log Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param pEventLog - pointer to Publish Event Log Command
* @param disableDefaultRsp - disable default response
* @param seqNum - ZCL sequence number
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendAlarmPublishEventLog( uint8 srcEP, afAddrType_t *dstAddr,
zclPublishEventLog_t *pEventLog,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 *buf;
uint8 *pBuf;
uint8 bufLen;
// Log ID + Command Index + Total Commands + (numSubLogs * ( Event ID + Event Time))
bufLen = 1 + 1 + 1 + (pEventLog->numSubLogs * (1 + 4));
buf = zcl_mem_alloc( bufLen );
if ( buf == NULL )
{
return (ZMemError);
}
pBuf = buf;
*pBuf++ = pEventLog->logID;
*pBuf++ = pEventLog->cmdIndex;
*pBuf++ = pEventLog->totalCmds;
for ( uint8 i = 0; i < pEventLog->numSubLogs; i++ )
{
zclEventLogPayload_t *pLogs = &(pEventLog->pLogs[i]);
*pBuf++ = pLogs->eventId;
pBuf = zcl_buffer_uint32( pBuf, pLogs->eventTime );
}
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
COMMAND_ALARMS_PUBLISH_EVENT_LOG, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
disableDefaultRsp, 0, seqNum, bufLen, buf );
}
#endif // SE_UK_EXT
#endif // ZCL_ALARMS
#ifdef ZCL_LOCATION
/*********************************************************************
* @fn zclGeneral_SendLocationSetAbsolute
*
* @brief Call to send out a Set Absolute Location Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param absLoc - absolute location info
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLocationSetAbsolute( uint8 srcEP, afAddrType_t *dstAddr,
zclLocationAbsolute_t *absLoc,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[10]; // 5 fields (2 octects each)
buf[0] = LO_UINT16( absLoc->coordinate1 );
buf[1] = HI_UINT16( absLoc->coordinate1 );
buf[2] = LO_UINT16( absLoc->coordinate2 );
buf[3] = HI_UINT16( absLoc->coordinate2 );
buf[4] = LO_UINT16( absLoc->coordinate3 );
buf[5] = HI_UINT16( absLoc->coordinate3 );
buf[6] = LO_UINT16( absLoc->power );
buf[7] = HI_UINT16( absLoc->power );
buf[8] = LO_UINT16( absLoc->pathLossExponent );
buf[9] = HI_UINT16( absLoc->pathLossExponent );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
COMMAND_LOCATION_SET_ABSOLUTE, TRUE,
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 10, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLocationSetDevCfg
*
* @brief Call to send out a Set Device Configuration Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param devCfg - device configuration info
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLocationSetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
zclLocationDevCfg_t *devCfg,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[9]; // 4 fields (2 octects each) + 1 field with 1 octect
buf[0] = LO_UINT16( devCfg->power );
buf[1] = HI_UINT16( devCfg->power );
buf[2] = LO_UINT16( devCfg->pathLossExponent );
buf[3] = HI_UINT16( devCfg->pathLossExponent );
buf[4] = LO_UINT16( devCfg->calcPeriod );
buf[5] = HI_UINT16( devCfg->calcPeriod );
buf[6] = devCfg->numMeasurements;
buf[7] = LO_UINT16( devCfg->reportPeriod );
buf[8] = HI_UINT16( devCfg->reportPeriod );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
COMMAND_LOCATION_SET_DEV_CFG, TRUE,
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 9, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLocationGetDevCfg
*
* @brief Call to send out a Get Device Configuration Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param targetAddr - device for which location parameters are being requested
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLocationGetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
uint8 *targetAddr, uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[8];
zcl_memcpy( buf, targetAddr, 8 );
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
COMMAND_LOCATION_GET_DEV_CFG, TRUE,
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 8, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLocationGetData
*
* @brief Call to send out a Get Location Data Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param locaData - location information and channel parameters that are requested.
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLocationGetData( uint8 srcEP, afAddrType_t *dstAddr,
zclLocationGetData_t *locData,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[10]; // bitmap (1) + number responses (1) + IEEE Address (8)
uint8 *pBuf = buf;
uint8 len = 2; // bitmap + number responses
*pBuf = locData->absoluteOnly;
*pBuf |= locData->recalculate << 1;
*pBuf |= locData->brdcastIndicator << 2;
*pBuf |= locData->brdcastResponse << 3;
*pBuf |= locData->compactResponse << 4;
pBuf++; // move past the bitmap field
*pBuf++ = locData->numResponses;
if ( locData->brdcastIndicator == 0 )
{
zcl_memcpy( pBuf, locData->targetAddr, 8 );
len += 8; // ieee addr
}
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
COMMAND_LOCATION_GET_DATA, TRUE,
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, len, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLocationDevCfgResponse
*
* @brief Call to send out a Device Configuration Response Command
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param devCfg - device's location parameters that are requested
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLocationDevCfgResponse( uint8 srcEP, afAddrType_t *dstAddr,
zclLocationDevCfgRsp_t *devCfg,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[10]; // 4 fields (2 octects each) + 2 fields (1 octect each)
uint8 len = 1; // Status
buf[0] = devCfg->status;
if ( devCfg->status == ZCL_STATUS_SUCCESS )
{
buf[1] = LO_UINT16( devCfg->data.power );
buf[2] = HI_UINT16( devCfg->data.power );
buf[3] = LO_UINT16( devCfg->data.pathLossExponent );
buf[4] = HI_UINT16( devCfg->data.pathLossExponent );
buf[5] = LO_UINT16( devCfg->data.calcPeriod );
buf[6] = HI_UINT16( devCfg->data.calcPeriod );
buf[7] = devCfg->data.numMeasurements;
buf[8] = LO_UINT16( devCfg->data.reportPeriod );
buf[9] = HI_UINT16( devCfg->data.reportPeriod );
len += 9;
}
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
COMMAND_LOCATION_DEV_CFG_RSP, TRUE,
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
}
/*********************************************************************
* @fn zclGeneral_SendLocationData
*
* @brief Call to send out location data
*
* @param srcEP - Sending application's endpoint
* @param dstAddr - where you want the message to go
* @param status - indicates whether response to request was successful or not
* @param locData - location information and channel parameters being sent
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_SendLocationData( uint8 srcEP, afAddrType_t *dstAddr, uint8 cmd,
uint8 status, zclLocationData_t *locData,
uint8 disableDefaultRsp, uint8 seqNum )
{
uint8 buf[16];
uint8 *pBuf = buf;
uint8 len = 0;
if ( cmd == COMMAND_LOCATION_DATA_RSP )
{
// Only response command includes a status field
*pBuf++ = status;
len++;
}
if ( cmd != COMMAND_LOCATION_DATA_RSP || status == ZCL_STATUS_SUCCESS )
{
// Notification or Response with successful status
*pBuf++ = locData->type;
*pBuf++ = LO_UINT16( locData->absLoc.coordinate1 );
*pBuf++ = HI_UINT16( locData->absLoc.coordinate1 );
*pBuf++ = LO_UINT16( locData->absLoc.coordinate2 );
*pBuf++ = HI_UINT16( locData->absLoc.coordinate2 );
len += 5;
if ( locationType2D(locData->type) == 0 )
{
// 2D location doesn't have coordinate 3
*pBuf++ = LO_UINT16( locData->absLoc.coordinate3 );
*pBuf++ = HI_UINT16( locData->absLoc.coordinate3 );
len += 2;
}
if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
{
// Compact notification doesn't include these fields
*pBuf++ = LO_UINT16( locData->absLoc.power );
*pBuf++ = HI_UINT16( locData->absLoc.power );
*pBuf++ = LO_UINT16( locData->absLoc.pathLossExponent );
*pBuf++ = HI_UINT16( locData->absLoc.pathLossExponent );
len += 4;
}
if ( locationTypeAbsolute(locData->type) == 0 )
{
// Absolute location doesn't include these fields
if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
{
// Compact notification doesn't include this field
*pBuf++ = locData->calcLoc.locationMethod;
len++;
}
*pBuf++ = locData->calcLoc.qualityMeasure;
*pBuf++ = LO_UINT16( locData->calcLoc.locationAge );
*pBuf++ = HI_UINT16( locData->calcLoc.locationAge );
len += 3;
}
}
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
disableDefaultRsp, 0, seqNum, len, buf );
}
#endif // ZCL_LOCATION
/*********************************************************************
* @fn zclGeneral_FindCallbacks
*
* @brief Find the callbacks for an endpoint
*
* @param endpoint - endpoint to find the application callbacks for
*
* @return pointer to the callbacks
*/
static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint )
{
zclGenCBRec_t *pCBs;
pCBs = zclGenCBs;
while ( pCBs )
{
if ( pCBs->endpoint == endpoint )
return ( pCBs->CBs );
pCBs = pCBs->next;
}
return ( (zclGeneral_AppCallbacks_t *)NULL );
}
/*********************************************************************
* @fn zclGeneral_HdlIncoming
*
* @brief Callback from ZCL to process incoming Commands specific
* to this cluster library or Profile commands for attributes
* that aren't in the attribute list
*
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg )
{
ZStatus_t stat = ZSuccess;
#if defined ( INTER_PAN )
if ( StubAPS_InterPan( pInMsg->msg->srcAddr.panId, pInMsg->msg->srcAddr.endPoint ) )
return ( stat ); // Cluster not supported thru Inter-PAN
#endif
if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
{
// Is this a manufacturer specific command?
if ( pInMsg->hdr.fc.manuSpecific == 0 )
{
stat = zclGeneral_HdlInSpecificCommands( pInMsg );
}
else
{
// We don't support any manufacturer specific command.
stat = ZFailure;
}
}
else
{
// Handle all the normal (Read, Write...) commands -- should never get here
stat = ZFailure;
}
return ( stat );
}
/*********************************************************************
* @fn zclGeneral_HdlInSpecificCommands
*
* @brief Callback from ZCL to process incoming Commands specific
* to this cluster library
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg )
{
ZStatus_t stat;
zclGeneral_AppCallbacks_t *pCBs;
// make sure endpoint exists
pCBs = zclGeneral_FindCallbacks( pInMsg->msg->endPoint );
if ( pCBs == NULL )
return ( ZFailure );
switch ( pInMsg->msg->clusterId )
{
#ifdef ZCL_BASIC
case ZCL_CLUSTER_ID_GEN_BASIC:
stat = zclGeneral_ProcessInBasic( pInMsg, pCBs );
break;
#endif // ZCL_BASIC
#ifdef ZCL_IDENTIFY
case ZCL_CLUSTER_ID_GEN_IDENTIFY:
stat = zclGeneral_ProcessInIdentity( pInMsg, pCBs );
break;
#endif // ZCL_IDENTIFY
#ifdef ZCL_GROUPS
case ZCL_CLUSTER_ID_GEN_GROUPS:
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
stat = zclGeneral_ProcessInGroupsServer( pInMsg );
else
stat = zclGeneral_ProcessInGroupsClient( pInMsg, pCBs );
break;
#endif // ZCL_GROUPS
#ifdef ZCL_SCENES
case ZCL_CLUSTER_ID_GEN_SCENES:
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
stat = zclGeneral_ProcessInScenesServer( pInMsg, pCBs );
else
stat = zclGeneral_ProcessInScenesClient( pInMsg, pCBs );
break;
#endif // ZCL_SCENES
#ifdef ZCL_ON_OFF
case ZCL_CLUSTER_ID_GEN_ON_OFF:
stat = zclGeneral_ProcessInOnOff( pInMsg, pCBs );
break;
#endif // ZCL_ON_OFF
#ifdef ZCL_LEVEL_CTRL
case ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL:
stat = zclGeneral_ProcessInLevelControl( pInMsg, pCBs );
break;
#endif // ZCL_LEVEL_CTRL
#ifdef ZCL_ALARMS
case ZCL_CLUSTER_ID_GEN_ALARMS:
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
stat = zclGeneral_ProcessInAlarmsServer( pInMsg, pCBs );
else
stat = zclGeneral_ProcessInAlarmsClient( pInMsg, pCBs );
break;
#endif // ZCL_ALARMS
#ifdef ZCL_LOCATION
case ZCL_CLUSTER_ID_GEN_LOCATION:
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
stat = zclGeneral_ProcessInLocationServer( pInMsg, pCBs );
else
stat = zclGeneral_ProcessInLocationClient( pInMsg, pCBs );
break;
#endif // ZCL_LOCATION
case ZCL_CLUSTER_ID_GEN_POWER_CFG:
case ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG:
case ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG:
case ZCL_CLUSTER_ID_GEN_TIME:
default:
stat = ZFailure;
break;
}
return ( stat );
}
#ifdef ZCL_BASIC
/*********************************************************************
* @fn zclGeneral_ProcessInBasic
*
* @brief Process in the received Basic Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
{
if ( pInMsg->hdr.commandID > COMMAND_BASIC_RESET_FACT_DEFAULT )
return ( ZFailure ); // Error ignore the command
if ( pCBs->pfnBasicReset )
pCBs->pfnBasicReset();
}
// no Client command
return ( ZSuccess );
}
#endif // ZCL_BASIC
#ifdef ZCL_IDENTIFY
/*********************************************************************
* @fn zclGeneral_ProcessInIdentity
*
* @brief Process in the received Identity Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
{
if ( pInMsg->hdr.commandID == COMMAND_IDENTIFY )
{
uint16 identifyTime;
identifyTime = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
bdb_ZclIdentifyCmdInd( identifyTime, pInMsg->msg->endPoint);
}
else if ( pInMsg->hdr.commandID == COMMAND_IDENTIFY_QUERY )
{
uint16 identifyTime = 0;
// Retrieve Identify Time
zcl_ReadAttrData( pInMsg->msg->endPoint, pInMsg->msg->clusterId,
ATTRID_IDENTIFY_TIME, (uint8 *)&identifyTime, NULL );
// Is device identifying itself?
if ( identifyTime > 0 )
{
zclGeneral_SendIdentifyQueryResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
identifyTime, true, pInMsg->hdr.transSeqNum );
return ( ZCL_STATUS_CMD_HAS_RSP );
}
}
#ifdef ZCL_LIGHT_LINK_ENHANCE
else if ( pInMsg->hdr.commandID == COMMAND_IDENTIFY_TRIGGER_EFFECT )
{
if ( pCBs->pfnIdentifyTriggerEffect )
{
zclIdentifyTriggerEffect_t cmd;
cmd.srcAddr = &(pInMsg->msg->srcAddr);
cmd.effectId = pInMsg->pData[0];
cmd.effectVariant = pInMsg->pData[1];
pCBs->pfnIdentifyTriggerEffect( &cmd );
}
}
#endif //ZCL_LIGHT_LINK_ENHANCE
else
{
return ( ZFailure ); // Error ignore the command
}
}
else // Client Command
{
if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY_RSP )
return ( ZFailure ); // Error ignore the command
zclIdentifyQueryRsp_t rsp;
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.timeout = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
bdb_ZclIdentifyQueryCmdInd( &rsp );
}
return ( ZSuccess );
}
#endif // ZCL_IDENTIFY
#ifdef ZCL_GROUPS
/*********************************************************************
* @fn zclGeneral_AddGroup
*
* @brief Add a Group.
*
* @param endPoint - application endpoint
* @param group - group to be added
* @param pData - pointer to the group info
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData )
{
uint8 nameLen;
uint8 nameSupport = FALSE;
pData += 2; // Move past group ID
nameLen = *pData++;
// Retrieve Name Support attribute
zcl_ReadAttrData( endPoint, ZCL_CLUSTER_ID_GEN_GROUPS,
ATTRID_GROUP_NAME_SUPPORT, &nameSupport, NULL );
if ( nameSupport )
{
if ( nameLen > (APS_GROUP_NAME_LEN-1) )
nameLen = (APS_GROUP_NAME_LEN-1);
group->name[0] = nameLen;
zcl_memcpy( &(group->name[1]), pData, nameLen );
}
return ( aps_AddGroup( endPoint, group ) );
}
/*********************************************************************
* @fn zclGeneral_ProcessInGroupsServer
*
* @brief Process in the received Groups Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg )
{
aps_Group_t group;
aps_Group_t *pGroup;
uint8 *pData;
uint8 status;
uint8 grpCnt;
uint8 grpRspCnt = 0;
uint16 *grpList;
uint16 identifyTime = 0;
uint8 i;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
pData = pInMsg->pData;
group.ID = BUILD_UINT16( pData[0], pData[1] );
switch ( pInMsg->hdr.commandID )
{
case COMMAND_GROUP_ADD:
status = zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
if ( status != ZSuccess )
{
if ( status == ZApsDuplicateEntry )
{
status = ZCL_STATUS_DUPLICATE_EXISTS;
}
else
{
status = ZCL_STATUS_INSUFFICIENT_SPACE;
}
}
#if defined( ZCL_LIGHT_LINK_ENHANCE ) //ZLL allows response to unicast only
if ( UNICAST_MSG( pInMsg->msg ) )
#endif
{
zclGeneral_SendGroupAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, group.ID, true, pInMsg->hdr.transSeqNum );
stat = ZCL_STATUS_CMD_HAS_RSP;
}
break;
case COMMAND_GROUP_VIEW:
#if defined( ZCL_LIGHT_LINK_ENHANCE ) //ZLL allows response to unicast only
if ( UNICAST_MSG( pInMsg->msg ) )
#endif
{
pGroup = aps_FindGroup( pInMsg->msg->endPoint, group.ID );
if ( pGroup )
{
status = ZCL_STATUS_SUCCESS;
}
else
{
// Group not found
status = ZCL_STATUS_NOT_FOUND;
pGroup = &group;
}
zclGeneral_SendGroupViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, pGroup, true, pInMsg->hdr.transSeqNum );
stat = ZCL_STATUS_CMD_HAS_RSP;
}
break;
case COMMAND_GROUP_GET_MEMBERSHIP:
#if defined( ZCL_LIGHT_LINK_ENHANCE ) //ZLL allows response to unicast only
if ( UNICAST_MSG( pInMsg->msg ) )
#endif
{
grpCnt = *pData++;
// Allocate space for the group list
grpList = zcl_mem_alloc( sizeof( uint16 ) * APS_MAX_GROUPS );
if ( grpList != NULL )
{
if ( grpCnt == 0 )
{
// Find out all the groups of which the endpoint is a member.
grpRspCnt = aps_FindAllGroupsForEndpoint( pInMsg->msg->endPoint, grpList );
}
else
{
// Find out the groups (in the list) of which the endpoint is a member.
for ( i = 0; i < grpCnt; i++ )
{
group.ID = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
if ( aps_FindGroup( pInMsg->msg->endPoint, group.ID ) )
grpList[grpRspCnt++] = group.ID;
}
}
if ( grpCnt == 0 || grpRspCnt != 0 )
{
zclGeneral_SendGroupGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
aps_GroupsRemaingCapacity(), grpRspCnt,
grpList, true, pInMsg->hdr.transSeqNum );
}
zcl_mem_free( grpList );
}
else
{
// Couldn't allocate space for the group list -- send a Default Response command back.
zclDefaultRspCmd_t defaultRspCmd;
defaultRspCmd.commandID = pInMsg->hdr.commandID;
defaultRspCmd.statusCode = ZCL_STATUS_INSUFFICIENT_SPACE;
zcl_SendDefaultRspCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
pInMsg->msg->clusterId, &defaultRspCmd,
ZCL_FRAME_SERVER_CLIENT_DIR, true, 0, pInMsg->hdr.transSeqNum );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
}
break;
case COMMAND_GROUP_REMOVE:
#if defined ( ZCL_SCENES )
zclGeneral_RemoveAllScenes( pInMsg->msg->endPoint, group.ID );
#endif
if ( aps_RemoveGroup( pInMsg->msg->endPoint, group.ID ) )
{
status = ZCL_STATUS_SUCCESS;
}
else
{
status = ZCL_STATUS_NOT_FOUND;
}
#if defined( ZCL_LIGHT_LINK_ENHANCE ) //ZLL allows response to unicast only
if ( UNICAST_MSG( pInMsg->msg ) )
#endif
{
zclGeneral_SendGroupRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, group.ID, true, pInMsg->hdr.transSeqNum );
stat = ZCL_STATUS_CMD_HAS_RSP;
}
break;
case COMMAND_GROUP_REMOVE_ALL:
{
uint8 numGroups;
uint16 groupList[APS_MAX_GROUPS];
if ( numGroups = aps_FindAllGroupsForEndpoint( pInMsg->msg->endPoint, groupList ) )
{
for ( i = 0; i < numGroups; i++ )
{
#if defined ( ZCL_SCENES )
zclGeneral_RemoveAllScenes( pInMsg->msg->endPoint, groupList[i] );
#endif
}
aps_RemoveAllGroup( pInMsg->msg->endPoint );
}
}
break;
case COMMAND_GROUP_ADD_IF_IDENTIFYING:
// Retrieve Identify Time
zcl_ReadAttrData( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_IDENTIFY,
ATTRID_IDENTIFY_TIME, (uint8 *)&identifyTime, NULL );
// Is device identifying itself?
if ( identifyTime > 0 )
{
zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
}
break;
default:
stat = ZFailure;
break;
}
return ( stat );
}
/*********************************************************************
* @fn zclGeneral_ProcessInGroupsClient
*
* @brief Process in the received Groups Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
aps_Group_t group;
uint8 *pData = pInMsg->pData;
uint8 grpCnt;
uint8 nameLen;
zclGroupRsp_t rsp;
uint8 i;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
zcl_memset( (uint8*)&rsp, 0, sizeof( zclGroupRsp_t ) );
switch ( pInMsg->hdr.commandID )
{
case COMMAND_GROUP_ADD_RSP:
case COMMAND_GROUP_VIEW_RSP:
case COMMAND_GROUP_REMOVE_RSP:
rsp.status = *pData++;
group.ID = BUILD_UINT16( pData[0], pData[1] );
if ( rsp.status == ZCL_STATUS_SUCCESS && pInMsg->hdr.commandID == COMMAND_GROUP_VIEW_RSP )
{
pData += 2; // Move past ID
nameLen = *pData++;
if ( nameLen > (APS_GROUP_NAME_LEN-1) )
nameLen = (APS_GROUP_NAME_LEN-1);
group.name[0] = nameLen;
zcl_memcpy( &(group.name[1]), pData, nameLen );
rsp.grpName = group.name;
}
if ( pCBs->pfnGroupRsp )
{
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
rsp.grpCnt = 1;
rsp.grpList = &group.ID;
rsp.capacity = 0;
pCBs->pfnGroupRsp( &rsp );
}
break;
case COMMAND_GROUP_GET_MEMBERSHIP_RSP:
{
uint16 *grpList = NULL;
rsp.capacity = *pData++;
grpCnt = *pData++;
if ( grpCnt > 0 )
{
// Allocate space for the group list
grpList = zcl_mem_alloc( sizeof( uint16 ) * grpCnt );
if ( grpList != NULL )
{
rsp.grpCnt = grpCnt;
for ( i = 0; i < grpCnt; i++ )
{
grpList[i] = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
}
}
}
if ( pCBs->pfnGroupRsp )
{
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
rsp.grpList = grpList;
pCBs->pfnGroupRsp( &rsp );
}
if ( grpList != NULL )
{
zcl_mem_free( grpList );
}
}
break;
default:
stat = ZFailure;
break;
}
return ( stat );
}
#endif // ZCL_GROUPS
#if defined( ZCL_SCENES )
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_AddScene
*
* @brief Add a scene for an endpoint
*
* @param endpoint -
* @param scene - new scene item
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_AddScene( uint8 endpoint, zclGeneral_Scene_t *scene )
{
zclGenSceneItem_t *pNewItem;
zclGenSceneItem_t *pLoop;
// Fill in the new profile list
pNewItem = zcl_mem_alloc( sizeof( zclGenSceneItem_t ) );
if ( pNewItem == NULL )
return ( ZMemError );
// Fill in the plugin record.
pNewItem->next = (zclGenSceneItem_t *)NULL;
pNewItem->endpoint = endpoint;
zcl_memcpy( (uint8*)&(pNewItem->scene), (uint8*)scene, sizeof ( zclGeneral_Scene_t ));
// Find spot in list
if ( zclGenSceneTable == NULL )
{
zclGenSceneTable = pNewItem;
}
else
{
// Look for end of list
pLoop = zclGenSceneTable;
while ( pLoop->next != NULL )
pLoop = pLoop->next;
// Put new item at end of list
pLoop->next = pNewItem;
}
// Update NV
zclGeneral_ScenesWriteNV();
return ( ZSuccess );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_FindScene
*
* @brief Find a scene with endpoint and sceneID
*
* @param endpoint -
* @param groupID - what group the scene belongs to
* @param sceneID - ID to look for scene
*
* @return a pointer to the scene information, NULL if not found
*/
zclGeneral_Scene_t *zclGeneral_FindScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
{
zclGenSceneItem_t *pLoop;
// Look for end of list
pLoop = zclGenSceneTable;
while ( pLoop )
{
if ( (pLoop->endpoint == endpoint || endpoint == 0xFF)
&& pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
{
return ( &(pLoop->scene) );
}
pLoop = pLoop->next;
}
return ( (zclGeneral_Scene_t *)NULL );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_FindAllScenesForGroup
*
* @brief Find all the scenes with groupID
*
* @param endpoint - endpoint to look for
* @param sceneList - List to hold scene IDs (should hold APS_MAX_SCENES entries)
*
* @return number of scenes copied to sceneList
*/
uint8 zclGeneral_FindAllScenesForGroup( uint8 endpoint, uint16 groupID, uint8 *sceneList )
{
zclGenSceneItem_t *pLoop;
uint8 cnt = 0;
// Look for end of list
pLoop = zclGenSceneTable;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
sceneList[cnt++] = pLoop->scene.ID;
pLoop = pLoop->next;
}
return ( cnt );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_RemoveScene
*
* @brief Remove a scene with endpoint and sceneID
*
* @param endpoint -
* @param groupID - what group the scene belongs to
* @param sceneID - ID to look for scene
*
* @return TRUE if removed, FALSE if not found
*/
uint8 zclGeneral_RemoveScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
{
zclGenSceneItem_t *pLoop;
zclGenSceneItem_t *pPrev;
// Look for end of list
pLoop = zclGenSceneTable;
pPrev = NULL;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint
&& pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
{
if ( pPrev == NULL )
zclGenSceneTable = pLoop->next;
else
pPrev->next = pLoop->next;
// Free the memory
zcl_mem_free( pLoop );
// Update NV
zclGeneral_ScenesWriteNV();
return ( TRUE );
}
pPrev = pLoop;
pLoop = pLoop->next;
}
return ( FALSE );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_RemoveAllScenes
*
* @brief Remove all scenes with endpoint and group Id
*
* @param endpoint -
* @param groupID - ID to look for group
*
* @return none
*/
void zclGeneral_RemoveAllScenes( uint8 endpoint, uint16 groupID )
{
zclGenSceneItem_t *pLoop;
zclGenSceneItem_t *pPrev;
zclGenSceneItem_t *pNext;
// Look for end of list
pLoop = zclGenSceneTable;
pPrev = NULL;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
{
if ( pPrev == NULL )
zclGenSceneTable = pLoop->next;
else
pPrev->next = pLoop->next;
pNext = pLoop->next;
// Free the memory
zcl_mem_free( pLoop );
pLoop = pNext;
}
else
{
pPrev = pLoop;
pLoop = pLoop->next;
}
}
// Update NV
zclGeneral_ScenesWriteNV();
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_CountScenes
*
* @brief Count the number of scenes for an endpoint
*
* @param endpoint -
*
* @return number of scenes assigned to an endpoint
*/
uint8 zclGeneral_CountScenes( uint8 endpoint )
{
zclGenSceneItem_t *pLoop;
uint8 cnt = 0;
// Look for end of list
pLoop = zclGenSceneTable;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint )
cnt++;
pLoop = pLoop->next;
}
return ( cnt );
}
#endif
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_CountAllScenes
*
* @brief Count the total number of scenes
*
* @param none
*
* @return number of scenes
*/
uint8 zclGeneral_CountAllScenes( void )
{
zclGenSceneItem_t *pLoop;
uint8 cnt = 0;
// Look for end of list
pLoop = zclGenSceneTable;
while ( pLoop )
{
cnt++;
pLoop = pLoop->next;
}
return ( cnt );
}
#endif // ZCL_STANDALONE
/*********************************************************************
* @fn zclGeneral_ReadSceneCountCB
*
* @brief Read the number of scenes currently in the device's
* scene table (i.e., the Scene Count attribute).
*
* Note: This function gets called only when the pointer
* 'dataPtr' to the Scene Count attribute value is
* NULL in the attribute database registered with
* the ZCL.
*
* @param clusterId - cluster that attribute belongs to
* @param attrId - attribute to be read or written
* @param oper - ZCL_OPER_LEN, ZCL_OPER_READ, or ZCL_OPER_WRITE
* @param pValue - pointer to attribute value
* @param pLen - pointer to length of attribute value read
*
* @return status
*/
ZStatus_t zclGeneral_ReadSceneCountCB( uint16 clusterId, uint16 attrId,
uint8 oper, uint8 *pValue, uint16 *pLen )
{
ZStatus_t status = ZCL_STATUS_SUCCESS;
// This callback function should only be called for the Scene Count attribute
switch ( oper )
{
case ZCL_OPER_LEN:
*pLen = 1; // uint8
break;
case ZCL_OPER_READ:
*pValue = zclGeneral_CountAllScenes();
if ( pLen != NULL )
{
*pLen = 1;
}
break;
case ZCL_OPER_WRITE:
// Fall through
default:
status = ZCL_STATUS_SOFTWARE_FAILURE; // should never get here!
break;
}
return ( status );
}
/*********************************************************************
* @fn zclGeneral_ProcessInScenesServer
*
* @brief Process in the received Scenes Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
zclGeneral_Scene_t scene;
zclGeneral_Scene_t *pScene;
uint8 *pData = pInMsg->pData;
uint8 nameLen;
uint8 status;
uint8 sceneCnt = 0;
uint8 *sceneList = NULL;
uint8 sendRsp = TRUE;
uint8 nameSupport = FALSE;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
scene.groupID = BUILD_UINT16( pData[0], pData[1] );
pData += 2; // Move past group ID
scene.ID = *pData++;
switch ( pInMsg->hdr.commandID )
{
case COMMAND_SCENE_ADD:
#ifdef ZCL_LIGHT_LINK_ENHANCE
case COMMAND_SCENE_ENHANCED_ADD:
#endif // ZCL_LIGHT_LINK_ENHANCE
// Parse the rest of the incoming message
scene.transTime = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
if ( pInMsg->hdr.commandID == COMMAND_SCENE_ENHANCED_ADD )
{
// Received transition time is in 1/10 second
scene.transTime100ms = scene.transTime % 10;
scene.transTime /= 10;
}
nameLen= *pData++; // Name length
// Retrieve Name Support attribute
zcl_ReadAttrData( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_SCENES,
ATTRID_SCENES_NAME_SUPPORT, &nameSupport, NULL );
if ( nameSupport )
{
if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
nameLen = (ZCL_GEN_SCENE_NAME_LEN-1);
scene.name[0] = nameLen;
zcl_memcpy( &(scene.name[1]), pData, nameLen );
}
pData += nameLen; // move past name, use original length
scene.extLen = pInMsg->pDataLen - ( (uint16)( pData - pInMsg->pData ) );
if ( scene.extLen > 0 )
{
// Copy the extention field(s)
if ( scene.extLen > ZCL_GEN_SCENE_EXT_LEN )
{
scene.extLen = ZCL_GEN_SCENE_EXT_LEN;
}
zcl_memcpy( scene.extField, pData, scene.extLen );
}
if ( scene.groupID == 0x0000 ||
aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
{
// Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
// does and the corresponding Group exits
pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
{
status = ZCL_STATUS_SUCCESS;
if ( pScene != NULL )
{
// The Scene already exists so update it
pScene->transTime = scene.transTime;
zcl_memcpy( pScene->name, scene.name, ZCL_GEN_SCENE_NAME_LEN );
// Use the new extention field(s)
zcl_memcpy( pScene->extField, scene.extField, scene.extLen );
pScene->extLen = scene.extLen;
// Save Scenes
zclGeneral_ScenesSave();
}
else
{
// The Scene doesn't exist so add it
zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
}
}
else
{
status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
}
}
else
{
status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
}
if ( UNICAST_MSG( pInMsg->msg ) )
{
if ( pInMsg->hdr.commandID == COMMAND_SCENE_ADD )
{
zclGeneral_SendSceneAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, scene.groupID, scene.ID,
true, pInMsg->hdr.transSeqNum );
}
#ifdef ZCL_LIGHT_LINK_ENHANCE
else // COMMAND_SCENE_ENHANCED_ADD
{
zclGeneral_SendSceneEnhancedAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, scene.groupID, scene.ID,
true, pInMsg->hdr.transSeqNum );
}
#endif // ZCL_LIGHT_LINK_ENHANCE
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
case COMMAND_SCENE_VIEW:
#ifdef ZCL_LIGHT_LINK_ENHANCE
case COMMAND_SCENE_ENHANCED_VIEW:
#endif // ZCL_LIGHT_LINK_ENHANCE
pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
if ( pScene != NULL )
{
status = ZCL_STATUS_SUCCESS;
}
else
{
// Scene not found
if ( scene.groupID != 0x0000 &&
aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
{
status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
}
else
{
status = ZCL_STATUS_NOT_FOUND;
}
pScene = &scene;
}
if ( UNICAST_MSG( pInMsg->msg ) )
{
if ( pInMsg->hdr.commandID == COMMAND_SCENE_VIEW )
{
zclGeneral_SendSceneViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, pScene, true, pInMsg->hdr.transSeqNum );
}
#ifdef ZCL_LIGHT_LINK_ENHANCE
else
{
zclGeneral_SendSceneEnhancedViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, pScene, true, pInMsg->hdr.transSeqNum );
}
#endif // ZCL_LIGHT_LINK_ENHANCE
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
case COMMAND_SCENE_REMOVE:
if ( zclGeneral_RemoveScene( pInMsg->msg->endPoint, scene.groupID, scene.ID ) )
{
status = ZCL_STATUS_SUCCESS;
}
else
{
// Scene not found
if ( aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
{
// The Group is not in the Group Table
status = ZCL_STATUS_INVALID_FIELD;
}
else
{
status = ZCL_STATUS_NOT_FOUND;
}
}
if ( UNICAST_MSG( pInMsg->msg ) )
{
// Addressed to this device (not to a group) - send a response back
zclGeneral_SendSceneRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, scene.groupID,
scene.ID, true, pInMsg->hdr.transSeqNum );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
case COMMAND_SCENE_REMOVE_ALL:
if ( scene.groupID == 0x0000 ||
aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
{
zclGeneral_RemoveAllScenes( pInMsg->msg->endPoint, scene.groupID );
status = ZCL_STATUS_SUCCESS;
}
else
{
status = ZCL_STATUS_INVALID_FIELD;
}
if ( UNICAST_MSG( pInMsg->msg ) )
{
// Addressed to this device (not to a group) - send a response back
zclGeneral_SendSceneRemoveAllResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, scene.groupID, true, pInMsg->hdr.transSeqNum );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
case COMMAND_SCENE_STORE:
if ( scene.groupID == 0x0000 ||
aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
{
// Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
// does and the corresponding Group exits
pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
{
uint8 sceneChanged = FALSE;
status = ZCL_STATUS_SUCCESS;
if ( pScene == NULL )
{
// Haven't been added yet
pScene = &scene;
}
if ( pCBs->pfnSceneStoreReq )
{
zclSceneReq_t req;
req.srcAddr = &(pInMsg->msg->srcAddr);
req.scene = pScene;
// Get the latest Scene info
if ( pCBs->pfnSceneStoreReq( &req ) )
{
sceneChanged = TRUE;
}
}
if ( pScene == &scene )
{
// The Scene doesn't exist so add it
zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
}
else if ( sceneChanged )
{
// The Scene already exists so update only NV
zclGeneral_ScenesSave();
}
}
else
{
status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
}
}
else
{
status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
}
if ( UNICAST_MSG( pInMsg->msg ) )
{
// Addressed to this device (not to a group) - send a response back
zclGeneral_SendSceneStoreResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, scene.groupID, scene.ID,
true, pInMsg->hdr.transSeqNum );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
case COMMAND_SCENE_RECALL:
pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
if ( pScene && pCBs->pfnSceneRecallReq )
{
zclSceneReq_t req;
req.srcAddr = &(pInMsg->msg->srcAddr);
req.scene = pScene;
pCBs->pfnSceneRecallReq( &req );
}
// No response
break;
case COMMAND_SCENE_GET_MEMBERSHIP:
// Find all the Scenes corresponding to the Group ID
if ( scene.groupID == 0x0000 ||
aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
{
// Allocate space for the scene list
sceneList = zcl_mem_alloc( ZCL_GEN_MAX_SCENES );
if ( sceneList != NULL )
{
sceneCnt = zclGeneral_FindAllScenesForGroup( pInMsg->msg->endPoint,
scene.groupID, sceneList );
status = ZCL_STATUS_SUCCESS;
if ( ! UNICAST_MSG( pInMsg->msg ) )
{
// Addressed to the Group - ONLY send a response if an entry within the
// Scene Table corresponds to the Group ID
if ( sceneCnt == 0 )
{
sendRsp = FALSE;
}
}
}
else
{
// Couldn't allocate space for the scene list!
status = ZCL_STATUS_INSUFFICIENT_SPACE;
}
}
else
{
// The Group is not in the Group Table - send a response back
status = ZCL_STATUS_INVALID_FIELD;
}
#ifdef ZCL_LIGHT_LINK_ENHANCE //ZLL allows response to unicast only
if ( sendRsp && UNICAST_MSG( pInMsg->msg ) )
#else
if ( sendRsp )
#endif //ZCL_LIGHT_LINK_ENHANCE
{
zclGeneral_SendSceneGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, zclGeneral_ScenesRemaingCapacity(), sceneCnt, sceneList,
scene.groupID, true, pInMsg->hdr.transSeqNum );
}
if ( sceneList != NULL )
zcl_mem_free( sceneList );
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
#ifdef ZCL_LIGHT_LINK_ENHANCE
case COMMAND_SCENE_COPY:
{
uint8 mode;
uint16 groupIDFrom, groupIDTo;
uint8 sceneIDFrom, sceneIDTo;
pData = pInMsg->pData; // different payload format
mode = *pData++;
groupIDFrom = BUILD_UINT16( pData[0], pData[1] ); // from group ID
pData += 2;
sceneIDFrom = *pData++; // from scene ID
groupIDTo = BUILD_UINT16( pData[0], pData[1] ); // to group ID
pData += 2;
if ( (mode & SCENE_COPY_MODE_ALL_BIT) == 0 )
{
sceneIDTo = *pData++; // to scene ID
}
// Make sure the groups exist
if ( ( aps_FindGroup( pInMsg->msg->endPoint, groupIDFrom ) != NULL ) &&
( aps_FindGroup( pInMsg->msg->endPoint, groupIDTo ) != NULL ) )
{
// Allocate space for the scene list
sceneList = zcl_mem_alloc( (mode & SCENE_COPY_MODE_ALL_BIT) ? ZCL_GEN_MAX_SCENES : 1 );
if ( sceneList == NULL )
{
status = ZCL_STATUS_INSUFFICIENT_SPACE; // Couldn't allocate space for the scene list!
}
else
{
status = ZCL_STATUS_SUCCESS;
if ( mode & SCENE_COPY_MODE_ALL_BIT ) // Copy all scenes
{
sceneCnt = zclGeneral_FindAllScenesForGroup( pInMsg->msg->endPoint,
groupIDFrom, sceneList );
}
else // Copy single scene
{
// Make sure the scene exists
pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, groupIDFrom, sceneIDFrom );
if ( pScene != NULL )
{
sceneList[0] = sceneIDFrom;
sceneCnt = 1;
}
else
{
status = ZCL_STATUS_INVALID_FIELD; // Scene not found
}
}
}
if ( status == ZCL_STATUS_SUCCESS )
{
uint8 numScenesToAdd = 0;
uint8 i;
for ( i = 0; i < sceneCnt; i++ )
{
if ( zclGeneral_FindScene( pInMsg->msg->endPoint, groupIDTo, sceneList[i] ) == NULL )
{
numScenesToAdd++;
}
}
if ( zclGeneral_ScenesRemaingCapacity() >= numScenesToAdd )
{
// Copy the scenes
for ( i = 0; i < sceneCnt; i++ )
{
// Ignore scene ID from and scene ID to fields
pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, groupIDFrom, sceneList[i] );
if ( pScene != NULL )
{
zclGeneral_Scene_t *pToScene;
scene = *pScene;
scene.groupID = groupIDTo;
scene.ID = ( (mode & SCENE_COPY_MODE_ALL_BIT) ? sceneList[i] : sceneIDTo );
pToScene = zclGeneral_FindScene( pInMsg->msg->endPoint, groupIDTo, scene.ID );
if( pToScene != NULL )
{
zclGeneral_RemoveScene( pInMsg->msg->endPoint, groupIDTo, scene.ID );
}
// Add the scene
zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
}
}
}
else
{
status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
}
}
}
else
{
status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
}
if ( UNICAST_MSG( pInMsg->msg ) )
{
if ( pScene == NULL )
{
pScene = &scene;
}
// Addressed to this device (not to a group) - send a response back
zclGeneral_SendSceneCopyResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
status, pScene->groupID, pScene->ID,
true, pInMsg->hdr.transSeqNum );
}
if ( sceneList != NULL )
{
zcl_mem_free( sceneList );
}
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
#endif // ZCL_LIGHT_LINK_ENHANCE
default:
stat = ZFailure;
break;
}
return ( stat );
}
/*********************************************************************
* @fn zclGeneral_ProcessInScenesClient
*
* @brief Process in the received Scenes Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
zclGeneral_Scene_t scene;
uint8 *pData = pInMsg->pData;
uint8 nameLen;
zclSceneRsp_t rsp;
uint8 i;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
zcl_memset( (uint8*)&rsp, 0, sizeof( zclSceneRsp_t ) );
// Get the status field first
rsp.status = *pData++;
if ( pInMsg->hdr.commandID == COMMAND_SCENE_GET_MEMBERSHIP_RSP )
{
rsp.capacity = *pData++;
}
scene.groupID = BUILD_UINT16( pData[0], pData[1] );
pData += 2; // Move past group ID
switch ( pInMsg->hdr.commandID )
{
case COMMAND_SCENE_VIEW_RSP:
// Parse the rest of the incoming message
scene.ID = *pData++; // Not applicable to Remove All Response command
scene.transTime = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
nameLen = *pData++; // Name length
if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
nameLen = (ZCL_GEN_SCENE_NAME_LEN-1);
scene.name[0] = nameLen;
zcl_memcpy( &(scene.name[1]), pData, nameLen );
pData += nameLen; // move past name, use original length
//*** Do something with the extension field(s)
// Fall through to callback - break is left off intentionally
case COMMAND_SCENE_ADD_RSP:
case COMMAND_SCENE_REMOVE_RSP:
case COMMAND_SCENE_REMOVE_ALL_RSP:
case COMMAND_SCENE_STORE_RSP:
if ( pCBs->pfnSceneRsp )
{
if ( pInMsg->hdr.commandID != COMMAND_SCENE_REMOVE_ALL_RSP )
{
scene.ID = *pData++;
}
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
rsp.scene = &scene;
pCBs->pfnSceneRsp( &rsp );
}
break;
case COMMAND_SCENE_GET_MEMBERSHIP_RSP:
{
uint8 *sceneList = NULL;
if ( rsp.status == ZCL_STATUS_SUCCESS )
{
uint8 sceneCnt = *pData++;
if ( sceneCnt > 0 )
{
// Allocate space for the scene list
sceneList = zcl_mem_alloc( sceneCnt );
if ( sceneList != NULL )
{
rsp.sceneCnt = sceneCnt;
for ( i = 0; i < sceneCnt; i++ )
sceneList[i] = *pData++;
}
}
}
if ( pCBs->pfnSceneRsp )
{
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
rsp.sceneList = sceneList;
rsp.scene = &scene;
pCBs->pfnSceneRsp( &rsp);
}
if ( sceneList != NULL )
{
zcl_mem_free( sceneList );
}
}
break;
default:
stat = ZFailure;
break;
}
return ( stat );
}
#endif // ZCL_SCENES
#ifdef ZCL_ON_OFF
/*********************************************************************
* @fn zclGeneral_ProcessInCmdOnOff
*
* @brief Process in the received On/Off Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
ZStatus_t stat = ZSuccess;
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
{
switch ( pInMsg->hdr.commandID )
{
case COMMAND_OFF:
case COMMAND_ON:
case COMMAND_TOGGLE:
if ( pCBs->pfnOnOff )
{
pCBs->pfnOnOff( pInMsg->hdr.commandID );
}
break;
#ifdef ZCL_LIGHT_LINK_ENHANCE
case COMMAND_OFF_WITH_EFFECT:
if ( pCBs->pfnOnOff_OffWithEffect )
{
zclOffWithEffect_t cmd;
cmd.srcAddr = &(pInMsg->msg->srcAddr);
cmd.effectId = pInMsg->pData[0];
cmd.effectVariant = pInMsg->pData[1];
pCBs->pfnOnOff_OffWithEffect( &cmd );
}
break;
case COMMAND_ON_WITH_RECALL_GLOBAL_SCENE:
if ( pCBs->pfnOnOff_OnWithRecallGlobalScene )
{
pCBs->pfnOnOff_OnWithRecallGlobalScene();
}
break;
case COMMAND_ON_WITH_TIMED_OFF:
if ( pCBs->pfnOnOff_OnWithTimedOff )
{
zclOnWithTimedOff_t cmd;
cmd.onOffCtrl.byte = pInMsg->pData[0];
cmd.onTime = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
cmd.offWaitTime = BUILD_UINT16( pInMsg->pData[3], pInMsg->pData[4] );
pCBs->pfnOnOff_OnWithTimedOff( &cmd );
}
break;
#endif // ZCL_LIGHT_LINK_ENHANCE
default:
stat = ZFailure;
break;
}
}
// no Client command
return ( stat );
}
#endif // ZCL_ON_OFF
#ifdef ZCL_LEVEL_CTRL
/*********************************************************************
* @fn zclGeneral_ProcessInLevelControl
*
* @brief Process in the received Level Control Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
uint8 withOnOff = FALSE;
ZStatus_t stat = ZSuccess;
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
{
switch ( pInMsg->hdr.commandID )
{
case COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF:
withOnOff = TRUE;
// fall through
case COMMAND_LEVEL_MOVE_TO_LEVEL:
if ( pCBs->pfnLevelControlMoveToLevel )
{
zclLCMoveToLevel_t cmd;
cmd.level = pInMsg->pData[0];
if ( ( cmd.level >= ATTR_LEVEL_MIN_LEVEL ) &&
( cmd.level <= ATTR_LEVEL_MAX_LEVEL ) )
{
cmd.transitionTime = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
cmd.withOnOff = withOnOff;
pCBs->pfnLevelControlMoveToLevel( &cmd );
}
else
{
// level range requested is invalid
stat = ZCL_STATUS_INVALID_VALUE;
}
}
break;
case COMMAND_LEVEL_MOVE_WITH_ON_OFF:
withOnOff = TRUE;
// fall through
case COMMAND_LEVEL_MOVE:
if ( pCBs->pfnLevelControlMove )
{
zclLCMove_t cmd;
cmd.moveMode = pInMsg->pData[0];
cmd.rate = pInMsg->pData[1];
cmd.withOnOff = withOnOff;
pCBs->pfnLevelControlMove( &cmd );
}
break;
case COMMAND_LEVEL_STEP_WITH_ON_OFF:
withOnOff = TRUE;
// fall through
case COMMAND_LEVEL_STEP:
if ( pCBs->pfnLevelControlStep )
{
zclLCStep_t cmd;
cmd.stepMode = pInMsg->pData[0];
cmd.amount = pInMsg->pData[1];
cmd.transitionTime = BUILD_UINT16( pInMsg->pData[2], pInMsg->pData[3] );
cmd.withOnOff = withOnOff;
pCBs->pfnLevelControlStep( &cmd );
}
break;
case COMMAND_LEVEL_STOP:
case COMMAND_LEVEL_STOP_WITH_ON_OFF:
// Both Stop commands are identical
if ( pCBs->pfnLevelControlStop )
{
pCBs->pfnLevelControlStop();
}
break;
default:
stat = ZFailure;
break;
}
}
// no Client command
return ( stat );
}
#endif // ZCL_LEVEL_CTRL
#ifdef ZCL_ALARMS
/*********************************************************************
* @fn zclGeneral_AddAlarm
*
* @brief Add an alarm for a cluster
*
* @param endpoint -
* @param alarm - new alarm item
*
* @return ZStatus_t
*/
ZStatus_t zclGeneral_AddAlarm( uint8 endpoint, zclGeneral_Alarm_t *alarm )
{
zclGenAlarmItem_t *pNewItem;
zclGenAlarmItem_t *pLoop;
// Fill in the new profile list
pNewItem = zcl_mem_alloc( sizeof( zclGenAlarmItem_t ) );
if ( pNewItem == NULL )
return ( ZMemError );
// Fill in the plugin record.
pNewItem->next = (zclGenAlarmItem_t *)NULL;
pNewItem->endpoint = endpoint;
zcl_memcpy( (uint8*)(&pNewItem->alarm), (uint8*)alarm, sizeof ( zclGeneral_Alarm_t ) );
// Find spot in list
if ( zclGenAlarmTable == NULL )
{
zclGenAlarmTable = pNewItem;
}
else
{
// Look for end of list
pLoop = zclGenAlarmTable;
while ( pLoop->next != NULL )
pLoop = pLoop->next;
// Put new item at end of list
pLoop->next = pNewItem;
}
return ( ZSuccess );
}
/*********************************************************************
* @fn zclGeneral_FindAlarm
*
* @brief Find an alarm with alarmCode and clusterID
*
* @param endpoint -
* @param groupID - what group the scene belongs to
* @param sceneID - ID to look for scene
*
* @return a pointer to the alarm information, NULL if not found
*/
zclGeneral_Alarm_t *zclGeneral_FindAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
{
zclGenAlarmItem_t *pLoop;
// Look for the alarm
pLoop = zclGenAlarmTable;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint &&
pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
{
return ( &(pLoop->alarm) );
}
pLoop = pLoop->next;
}
return ( (zclGeneral_Alarm_t *)NULL );
}
/*********************************************************************
* @fn zclGeneral_FindEarliestAlarm
*
* @brief Find an alarm with the earliest timestamp
*
* @param endpoint -
*
* @return a pointer to the alarm information, NULL if not found
*/
zclGeneral_Alarm_t *zclGeneral_FindEarliestAlarm( uint8 endpoint )
{
zclGenAlarmItem_t *pLoop;
zclGenAlarmItem_t earliestAlarm;
zclGenAlarmItem_t *pEarliestAlarm = &earliestAlarm;
pEarliestAlarm->alarm.timeStamp = 0xFFFFFFFF;
// Look for alarm with earliest time
pLoop = zclGenAlarmTable;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint &&
pLoop->alarm.timeStamp < pEarliestAlarm->alarm.timeStamp )
{
pEarliestAlarm = pLoop;
}
pLoop = pLoop->next;
}
if ( pEarliestAlarm->alarm.timeStamp != 0xFFFFFFFF )
return ( &(pEarliestAlarm->alarm) );
// No alarm
return ( (zclGeneral_Alarm_t *)NULL );
}
/*********************************************************************
* @fn zclGeneral_ResetAlarm
*
* @brief Remove an alarm with alarmCode and clusterID
*
* @param endpoint -
* @param alarmCode -
* @param clusterID -
*
* @return TRUE if removed, FALSE if not found
*/
void zclGeneral_ResetAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
{
zclGenAlarmItem_t *pLoop;
zclGenAlarmItem_t *pPrev;
// Look for end of list
pLoop = zclGenAlarmTable;
pPrev = NULL;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint &&
pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
{
if ( pPrev == NULL )
zclGenAlarmTable = pLoop->next;
else
pPrev->next = pLoop->next;
// Free the memory
zcl_mem_free( pLoop );
// Notify the Application so that if the alarm condition still active then
// a new notification will be generated, and a new alarm record will be
// added to the alarm log
// zclGeneral_NotifyReset( alarmCode, clusterID ); // callback function?
return;
}
pPrev = pLoop;
pLoop = pLoop->next;
}
}
/*********************************************************************
* @fn zclGeneral_ResetAllAlarms
*
* @brief Remove all alarms with endpoint
*
* @param endpoint -
* @param notifyApp -
*
* @return none
*/
void zclGeneral_ResetAllAlarms( uint8 endpoint, uint8 notifyApp )
{
zclGenAlarmItem_t *pLoop;
zclGenAlarmItem_t *pPrev;
zclGenAlarmItem_t *pNext;
// Look for end of list
pLoop = zclGenAlarmTable;
pPrev = NULL;
while ( pLoop )
{
if ( pLoop->endpoint == endpoint )
{
if ( pPrev == NULL )
zclGenAlarmTable = pLoop->next;
else
pPrev->next = pLoop->next;
pNext = pLoop->next;
// Free the memory
zcl_mem_free( pLoop );
pLoop = pNext;
}
else
{
pPrev = pLoop;
pLoop = pLoop->next;
}
}
if ( notifyApp )
{
// Notify the Application so that if any alarm conditions still active then
// a new notification will be generated, and a new alarm record will be
// added to the alarm log
// zclGeneral_NotifyResetAll(); // callback function?
}
}
/*********************************************************************
* @fn zclGeneral_ProcessInAlarmsServer
*
* @brief Process in the received Alarms Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
zclAlarm_t alarm;
zclGeneral_Alarm_t *pAlarm;
uint8 *pData = pInMsg->pData;
ZStatus_t stat = ZSuccess;
switch ( pInMsg->hdr.commandID )
{
case COMMAND_ALARMS_RESET:
if ( pCBs->pfnAlarm )
{
alarm.cmdID = pInMsg->hdr.commandID;
alarm.alarmCode = pData[0];
alarm.clusterID = BUILD_UINT16( pData[1], pData[2] );
pCBs->pfnAlarm( pInMsg->hdr.fc.direction, &alarm );
}
else
{
stat = ZCL_STATUS_FAILURE;
}
break;
case COMMAND_ALARMS_RESET_ALL:
if ( pCBs->pfnAlarm )
{
alarm.cmdID = pInMsg->hdr.commandID;
pCBs->pfnAlarm( pInMsg->hdr.fc.direction, &alarm );
}
else
{
stat = ZCL_STATUS_FAILURE;
}
break;
case COMMAND_ALARMS_GET:
if ( pCBs->pfnAlarm )
{
alarm.srcAddr = &(pInMsg->msg->srcAddr);
alarm.cmdID = pInMsg->hdr.commandID;
pCBs->pfnAlarm( pInMsg->hdr.fc.direction, &alarm );
pAlarm = zclGeneral_FindEarliestAlarm( pInMsg->msg->endPoint );
if ( pAlarm )
{
// Send a response back
zclGeneral_SendAlarmGetResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
ZCL_STATUS_SUCCESS, pAlarm->code,
pAlarm->clusterID, pAlarm->timeStamp,
true, pInMsg->hdr.transSeqNum );
// Remove the entry from the Alarm table
zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pAlarm->code, pAlarm->clusterID );
}
else
{
// Send a response back
zclGeneral_SendAlarmGetResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
ZCL_STATUS_NOT_FOUND, 0, 0, 0,
true, pInMsg->hdr.transSeqNum );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
}
else
{
stat = ZCL_STATUS_FAILURE;
}
break;
case COMMAND_ALARMS_RESET_LOG:
if ( pCBs->pfnAlarm )
{
alarm.cmdID = pInMsg->hdr.commandID;
pCBs->pfnAlarm( pInMsg->hdr.fc.direction, &alarm );
zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, FALSE );
}
else
{
stat = ZCL_STATUS_FAILURE;
}
break;
#ifdef SE_UK_EXT
case COMMAND_ALARMS_PUBLISH_EVENT_LOG:
if ( pCBs->pfnPublishEventLog )
{
zclPublishEventLog_t eventLog;
eventLog.logID = *pData++;
eventLog.cmdIndex = *pData++;
eventLog.totalCmds = *pData++;
// First try to find out number of Sub Log Payloads
eventLog.numSubLogs = (pInMsg->pDataLen-3)/(1+4); // event ID + event time
if ( eventLog.numSubLogs > 0 )
{
// Try to alloc space for Log Payload
eventLog.pLogs = (zclEventLogPayload_t *)zcl_mem_alloc( sizeof( zclEventLogPayload_t ) *
eventLog.numSubLogs );
if ( eventLog.pLogs != NULL )
{
// Copy Log Payload
for ( uint8 i = 0; i < eventLog.numSubLogs; i++ )
{
eventLog.pLogs[i].eventId = *pData++;
eventLog.pLogs[i].eventTime = zcl_build_uint32( pData, 4 );
pData += 4;
}
}
else
{
stat = ZCL_STATUS_SOFTWARE_FAILURE;
}
}
else
{
eventLog.pLogs = NULL;
}
if ( stat == ZSuccess )
{
pCBs->pfnPublishEventLog( &(pInMsg->msg->srcAddr), &eventLog );
}
if ( eventLog.pLogs != NULL )
{
zcl_mem_free( eventLog.pLogs );
}
}
break;
#endif // SE_UK_EXT
default:
stat = ZCL_STATUS_UNSUP_CLUSTER_COMMAND;
break;
}
return ( stat );
}
/*********************************************************************
* @fn zclGeneral_ProcessInAlarmsClient
*
* @brief Process in the received Alarms Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
uint8 *pData = pInMsg->pData;
zclAlarm_t alarm;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&alarm, 0, sizeof( zclAlarm_t ) );
switch ( pInMsg->hdr.commandID )
{
case COMMAND_ALARMS_ALARM:
if ( pCBs->pfnAlarm )
{
alarm.srcAddr = &(pInMsg->msg->srcAddr);
alarm.cmdID = pInMsg->hdr.commandID;
alarm.alarmCode = pData[0];
alarm.clusterID = BUILD_UINT16( pData[1], pData[2] );
pCBs->pfnAlarm( pInMsg->hdr.fc.direction, &alarm );
}
else
{
stat = ZCL_STATUS_FAILURE;
}
break;
case COMMAND_ALARMS_GET_RSP:
if ( pCBs->pfnAlarm )
{
alarm.srcAddr = &(pInMsg->msg->srcAddr);
alarm.cmdID = pInMsg->hdr.commandID;
alarm.alarmCode = *pData++;
alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
pCBs->pfnAlarm( pInMsg->hdr.fc.direction, &alarm );
}
else
{
stat = ZCL_STATUS_FAILURE;
}
break;
#ifdef SE_UK_EXT
case COMMAND_ALARMS_GET_EVENT_LOG:
if ( pCBs->pfnGetEventLog )
{
zclGetEventLog_t eventLog;
eventLog.logID = *pData++;
eventLog.startTime = zcl_build_uint32( pData, 4 );
pData += 4;
eventLog.endTime = zcl_build_uint32( pData, 4 );
pData += 4;
eventLog.numEvents = *pData;
pCBs->pfnGetEventLog( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
&eventLog, pInMsg->hdr.transSeqNum );
}
break;
#endif // SE_UK_EXT
default:
stat = ZCL_STATUS_UNSUP_CLUSTER_COMMAND;
break;
}
return ( stat );
}
#endif // ZCL_ALARMS
#ifdef ZCL_LOCATION
/*********************************************************************
* @fn zclGeneral_ProcessInLocationServer
*
* @brief Process in the received Location Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
uint8 *pData = pInMsg->pData;
zclLocation_t cmd;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&cmd, 0, sizeof( zclLocation_t ) );
switch ( pInMsg->hdr.commandID )
{
case COMMAND_LOCATION_SET_ABSOLUTE:
cmd.un.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
if ( pCBs->pfnLocation )
{
cmd.srcAddr = &(pInMsg->msg->srcAddr);
cmd.cmdID = pInMsg->hdr.commandID;
// Update the absolute location info
pCBs->pfnLocation( &cmd );
}
break;
case COMMAND_LOCATION_SET_DEV_CFG:
cmd.un.devCfg.power = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.devCfg.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.devCfg.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
cmd.un.devCfg.numMeasurements = *pData++;
cmd.un.devCfg.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
if ( pCBs->pfnLocation )
{
cmd.srcAddr = &(pInMsg->msg->srcAddr);
cmd.cmdID = pInMsg->hdr.commandID;
// Update the device configuration info
pCBs->pfnLocation( &cmd );
}
break;
case COMMAND_LOCATION_GET_DEV_CFG:
cmd.un.ieeeAddr = pData;
if ( pCBs->pfnLocation )
{
cmd.srcAddr = &(pInMsg->msg->srcAddr);
cmd.cmdID = pInMsg->hdr.commandID;
cmd.seqNum = pInMsg->hdr.transSeqNum;
// Retreive the Device Configuration
pCBs->pfnLocation( &cmd );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
case COMMAND_LOCATION_GET_DATA:
cmd.un.loc.bitmap.locByte = *pData++;
cmd.un.loc.numResponses = *pData++;
if ( cmd.un.loc.brdcastResponse == 0 ) // command is sent as a unicast
zcl_memcpy( cmd.un.loc.targetAddr, pData, 8 );
if ( pCBs->pfnLocation )
{
cmd.srcAddr = &(pInMsg->msg->srcAddr);
cmd.cmdID = pInMsg->hdr.commandID;
cmd.seqNum = pInMsg->hdr.transSeqNum;
// Retreive the Location Data
pCBs->pfnLocation( &cmd );
}
stat = ZCL_STATUS_CMD_HAS_RSP;
break;
default:
stat = ZFailure;
break;
}
return ( stat );
}
/*********************************************************************
* @fn zclGeneral_ProcessInLocationDataRsp
*
* @brief Process in the received Location Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static void zclGeneral_ProcessInLocationDataRsp( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
uint8 *pData = pInMsg->pData;
zclLocationRsp_t rsp;
zcl_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
if ( pCBs->pfnLocationRsp )
{
if ( pInMsg->hdr.commandID == COMMAND_LOCATION_DATA_RSP )
rsp.un.loc.status = *pData++;
if ( pInMsg->hdr.commandID != COMMAND_LOCATION_DATA_RSP ||
rsp.un.loc.status == ZCL_STATUS_SUCCESS )
{
rsp.un.loc.data.type = *pData++;
rsp.un.loc.data.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
rsp.un.loc.data.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
if ( locationType2D( rsp.un.loc.data.type ) == 0 )
{
rsp.un.loc.data.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
}
if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
{
rsp.un.loc.data.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
rsp.un.loc.data.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
}
if ( locationTypeAbsolute( rsp.un.loc.data.type ) == 0 )
{
if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
rsp.un.loc.data.calcLoc.locationMethod = *pData++;
rsp.un.loc.data.calcLoc.qualityMeasure = *pData++;
rsp.un.loc.data.calcLoc.locationAge = BUILD_UINT16( pData[0], pData[1] );
}
}
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
// Notify the Application
pCBs->pfnLocationRsp( &rsp );
}
}
/*********************************************************************
* @fn zclGeneral_ProcessInLocationClient
*
* @brief Process in the received Location Command.
*
* @param pInMsg - pointer to the incoming message
*
* @return ZStatus_t
*/
static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg,
zclGeneral_AppCallbacks_t *pCBs )
{
uint8 *pData = pInMsg->pData;
zclLocationRsp_t rsp;
ZStatus_t stat = ZSuccess;
zcl_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
switch ( pInMsg->hdr.commandID )
{
case COMMAND_LOCATION_DEV_CFG_RSP:
if ( pCBs->pfnLocationRsp )
{
rsp.un.devCfg.status = *pData++;
if ( rsp.un.devCfg.status == ZCL_STATUS_SUCCESS )
{
rsp.un.devCfg.data.power = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
rsp.un.devCfg.data.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
rsp.un.devCfg.data.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
pData += 2;
rsp.un.devCfg.data.numMeasurements = *pData++;
rsp.un.devCfg.data.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
// Notify the Application
pCBs->pfnLocationRsp( &rsp );
}
}
break;
case COMMAND_LOCATION_DATA_RSP:
case COMMAND_LOCATION_DATA_NOTIF:
case COMMAND_LOCATION_COMPACT_DATA_NOTIF:
zclGeneral_ProcessInLocationDataRsp( pInMsg, pCBs );
break;
case COMMAND_LOCATION_RSSI_PING:
if ( pCBs->pfnLocationRsp )
{
rsp.un.locationType = *pData;
rsp.srcAddr = &(pInMsg->msg->srcAddr);
rsp.cmdID = pInMsg->hdr.commandID;
// Notify the Application
pCBs->pfnLocationRsp( &rsp );
}
break;
default:
stat = ZFailure;
break;
}
return ( stat );
}
#endif // ZCL_LOCATION
#ifdef ZCL_SCENES
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_ScenesInitNV
*
* @brief Initialize the NV Scene Table Items
*
* @param none
*
* @return number of scenes
*/
static uint8 zclGeneral_ScenesInitNV( void )
{
uint8 status;
uint16 size;
size = (uint16)((sizeof ( nvGenScenesHdr_t ))
+ ( sizeof( zclGenSceneNVItem_t ) * ZCL_GEN_MAX_SCENES ));
status = zcl_nv_item_init( ZCD_NV_SCENE_TABLE, size, NULL );
if ( status != ZSUCCESS )
{
zclGeneral_ScenesSetDefaultNV();
}
return status;
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_ScenesSetDefaultNV
*
* @brief Write the defaults to NV
*
* @param none
*
* @return none
*/
static void zclGeneral_ScenesSetDefaultNV( void )
{
nvGenScenesHdr_t hdr;
// Initialize the header
hdr.numRecs = 0;
// Save off the header
zcl_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_ScenesWriteNV
*
* @brief Save the Scene Table in NV
*
* @param none
*
* @return none
*/
static void zclGeneral_ScenesWriteNV( void )
{
nvGenScenesHdr_t hdr;
zclGenSceneItem_t *pLoop;
zclGenSceneNVItem_t item;
hdr.numRecs = 0;
// Look for end of list
pLoop = zclGenSceneTable;
while ( pLoop )
{
// Build the record
item.endpoint = pLoop->endpoint;
zcl_memcpy( &(item.scene), &(pLoop->scene), sizeof ( zclGeneral_Scene_t ) );
// Save the record to NV
zcl_nv_write( ZCD_NV_SCENE_TABLE,
(uint16)((sizeof( nvGenScenesHdr_t )) + (hdr.numRecs * sizeof ( zclGenSceneNVItem_t ))),
sizeof ( zclGenSceneNVItem_t ), &item );
hdr.numRecs++;
pLoop = pLoop->next;
}
// Save off the header
zcl_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_ScenesRestoreFromNV
*
* @brief Restore the Scene table from NV
*
* @param none
*
* @return Number of entries restored
*/
static uint16 zclGeneral_ScenesRestoreFromNV( void )
{
uint16 x;
nvGenScenesHdr_t hdr;
zclGenSceneNVItem_t item;
uint16 numAdded = 0;
if ( zcl_nv_read( ZCD_NV_SCENE_TABLE, 0, sizeof(nvGenScenesHdr_t), &hdr ) == ZSuccess )
{
// Read in the device list
for ( x = 0; x < hdr.numRecs; x++ )
{
if ( zcl_nv_read( ZCD_NV_SCENE_TABLE,
(uint16)(sizeof(nvGenScenesHdr_t) + (x * sizeof ( zclGenSceneNVItem_t ))),
sizeof ( zclGenSceneNVItem_t ), &item ) == ZSUCCESS )
{
// Add the scene
if ( zclGeneral_AddScene( item.endpoint, &(item.scene) ) == ZSuccess )
{
numAdded++;
}
}
}
}
return ( numAdded );
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_ScenesInit
*
* @brief Initialize the scenes table
*
* @param none
*
* @return none
*/
void zclGeneral_ScenesInit( void )
{
// Initialize NV items
zclGeneral_ScenesInitNV();
// Restore the Scene table
zclGeneral_ScenesRestoreFromNV();
}
#endif // ZCL_STANDALONE
#if !defined ( ZCL_STANDALONE )
/*********************************************************************
* @fn zclGeneral_ScenesSave
*
* @brief Save the scenes table
*
* @param none
*
* @return none
*/
void zclGeneral_ScenesSave( void )
{
// Update NV
zclGeneral_ScenesWriteNV();
}
#endif // ZCL_STANDALONE
#endif // ZCL_SCENES
/***************************************************************************
****************************************************************************/

Comment ( 0 )

Sign in for post a comment

C
1
https://gitee.com/leconiot/z-stack.git
git@gitee.com:leconiot/z-stack.git
leconiot
z-stack
z-stack
2ef2f0ca00f3b973e8299afcfc8c3f8441edb76d

Help Search