This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LAUNCHXL-CC1352R1: ZNP ZTool-script for zed_sampleswitch working with zigbee2mqtt

Part Number: LAUNCHXL-CC1352R1

Hello,

I successfully managed that the ZigBee Switch-example (simplelink_cc13x2_26x2_sdk_3_20_00_68\examples\rtos\CC1352R1_LAUNCHXL\zstack\zed_sw) running on a CC1352R1-Launchpad (Board #1) is detected by the zigbee2mqtt-gateway (www.zigbee2mqtt.io) , i got the message "interview successful" when subscribing to the MQTT broker. In the sniffer i see the exchange of three ZCL_CMD_READ commands with each 3 attributes and their corresponding ZCL_CMD_READ_RSP commands, where e.g. the attributes "ATTRID_BASIC_MODEL_ID", "ATTRID_BASIC_MANUFACTURER_NAME", "ATTRID_BASIC_POWER_SOURCE" etc. are requested from the zed_switch by the coordinator.

Now i want to "clone" the behaviour of the zed_sw_CC1352R1_LAUNCHXL_tirtos_ccs-project with a ZNP (running also on a CC1352 hardware, Board #2). I wrote a ZTool script that configure an endpoint with the same clusters like in the zed_sw-firmware.

Nevertheless, the coordinator of the zigbee2mqtt gateways behaves differently and terminates the communication after the first "read attribute" command, as i can see in the sniffer-logs. The result is an "interview failed" message of the mqtt gateway.

My questions:
1. Can anybody help me to figure out why my ZNP-node (Board #2) behaves differently than the board #1 programmed with the zed_sw program? Why is the coordinator not requesting the second and third "read attributes" command? Please see my both Ubiqua capture-files.
Because the coordinator is the same in both scenarious, i guess there is something i am missing in my ZNP script, making its behaviour not 100% equal to that of board #1. But i do not see any difference in the sniffer logs.

2. Does anybody know how the internal logic of the zigbee2mqtt "interview"-process works? Where is it programmed that the coordinator starts with asking for the e.g. Model-ID attribute? It would be nice if i could get out some more debug-info  from the zigbee2mqtt-gateway, showing me why the interview-process actually failed.

Thanks a lot for every help,
best regards Albert

UbiquaCaptureFilesOfzigbee2mqtt.zip

  • I suppose you might not set some attributes in Basic cluster such as ZCL version (attribute ID:0x0000), Application version (attribute ID:0x0001), Stack version (attribute ID:0x0003), Hardware version (attribute ID:0x0003), and Date code (attribute ID:0x0006) in your ZNP application (Board #2). You can try to add those attributes to your Basic cluster to see if the issue can be solved. You can also refer to for discussions about zigbee2mqtt "interview failed" message.

  • Hello a.poetsch,

    What exactly does your Z-Tool script do?  The one difference I notice from the Simple Descriptor Responses is that the successful device has an Application Device ID of 0x0103 (On/Off Light Switch) whereas the failed device's is 0x0100 (On/Off Light).  You will probably need to debug the gateway application to find the reason it does not continue to send Basic Read Attributes.  Perhaps  can help with this.

    Regards,
    Ryan

  • The interview process of zigbee2mqtt is implemented here: https://github.com/Koenkk/zigbee-herdsman/blob/master/src/controller/model/device.ts#L294. When starting zigbee2mqtt with 'DEBUG=zigbee-herdsman:controller* npm start` you can see debug output of the interview procedure. Note that for this you have to be on the zigbee2mqtt dev branch. Further questions regarding zigbee2mqtt/zigbee-herdsman should not be posted here, but here: https://github.com/Koenkk/zigbee-herdsman/issues.

  • Dear e2e-forum members,

    Thank you all for your helpful tips! I have come a bit further, but still have not managed to write a ZNP-ZTool script, which can pair successfully with the zigbee2mqtt gateway.
    To remember, i want to "clone" the behaviour of the zed_sw_CC1352R1_LAUNCHXL_tirtos_ccs-project with a ZTool-script and a ZNP.
    The problem is still that the board running the ZNP is not paired successfully to the mqtt-gateway.

    i modified the DeviceID as Ryan observed, and also built in an identifyQuery()-command in my ZTool-script (i saw on the sniffer that the TI switch example is doing this also).

    Further, i checked the logs from zigbee2mqtt as suggested. There i can see a difference between my both boards in the order of the receiving of the messages containing e.g. the "identifyTime"-Attributes.
    Also i can see that the debug-message "zigbee-herdsman:controller:device Interview - got 'modelId,manufacturerName,powerSource' ...." is missing in the zigbee-herdsman-Log from  the ZNP-board, although the information was transmitted, as you can see in the sniffer-Log. 

    My questions are now:
    when i see the following Log-entries (3 times!):
    zigbee-herdsman:controller:log Received 'zcl' data '{"frame":{"Header":{"frameControl":{"frameType":1,"manufacturerSpecific":false,"direction":0,"disableDefaultResponse":true},"transactionSequenceNumber":1,"manufacturerCode":null,"commandIdentifier":1},"Payload":{},"Cluster":{"ID":3,"attributes":{"identifyTime":{"ID":0,"type":33,"name":"identifyTime"},"identifyCommissionState":{"ID":1,"type":255,"name":"identifyCommissionState"}},"name":"genIdentify","commands":{"identify":{"ID":0,"parameters":[{"name":"identifytime","type":33}],"name":"identify"},"identifyQuery":{"ID":1,"parameters":[],"name":"identifyQuery"},"ezmodeInvoke":{"ID":2,"parameters":[{"name":"action","type":32}],"name":"ezmodeInvoke"},"updateCommissionState":{"ID":3,"parameters":[{"name":"action","type":32},{"name":"commstatemask","type":32}],"name":"updateCommissionState"},"triggerEffect":{"ID":64,"parameters":[{"name":"effectid","type":32},{"name":"effectvariant","type":32}],"name":"triggerEffect"}},"commandsResponse":{"identifyQueryRsp":{"ID":0,"parameters":[{"name":"timeout","type":33}],"name":"identifyQueryRsp"}}}},"networkAddress":29487,"endpoint":8,"linkquality":97,"groupID":0}'
     
     Why i cannot see this content in any of the sniffer logs?

     I also do not know if this is the reason that the gateway-Coord does not issue any further READ ATTRIBUTE commands to my ZNP-switch?
     
    Further questions:
     @ : How can i add the attribute-list within a ZTOOL-script, as i can do with zcl_registerAttrList() in the firmware? When issuing a ZB_AF_REGISTER_REQUEST, i can only register the input/output clusters of an endpoint, but how to register the Attributes with ZTool?
     Could be my problem anyway be related with e.g. the missing Identify-Attributes?
     
     Please find my ZTool script and all the log files attached. Maybe someone could try to reproduce my scenario with the attached ZTool-script and the slightly modified "devices.js" converter-file from zigbee2mqtt, where i added the zigbeeModel: ['TI_Switch'] to match my Model-ID-Attribute.
     Thanks again for your help!

    @ : i think my problem is more related to some missing commands in my ZTool script, thats why i prefer to post my questions here and not at https://github.com/Koenkk/zigbee-herdsman/issues, but please tell me if you think it would be a better idea to ask at that forum. Thank you!

    ZTool-script_and_SnifferLogs_and_MQTTbridgeLogs.zip

  • Hi a.poetsch,

    Your Z-Tool script uses ZDO_STARTUP_FROM_APP which executes bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING); on the ZNP, however it does not start F&B (BDB_COMMISSIONING_MODE_FINDING_BINDING) which explains the differences in Identify behavior.

    Registering an endpoint, required for the ZDO, is necessary for establishing device behavior on the ZNP.  This is different from registering attributes, required for the ZCL which is application-specific.  As the application should reside on Z-Tool/MCU/gateway, not the ZNP, it is that host's responsibility to register attributes.  Please keep in mind that the ZNP does not contain a Zigbee switch application as you continue to develop this project.

    Regards,
    Ryan

  • Hi Ryan,
    thank you for your explanation. As far as I'm concerned, ZTool can be used to send commands to the ZNP, just as another "host" application (eg MCU) does, right? But can it be that the ZTool scripting engine only supports a limited set of the full ZNP API?
    The TI Linux-gateway as an example (or any other MCU-ZNP combination) uses a ZNP as well, so there must be the possibility to register the (Application-) attributes for the ZCL via e.g. the UART-interface, right? so why is it not possible with ZTool?

    As you say "As the application should reside on Z-Tool..." , i don't understand why i should not be able to  implement an Application (e.g. a Switch) using ZTool? 
    I know that the ZNP itself does not contain an application, but in combination with ZTool as "host" i thought it is possible to implement any (simple) ZigBee-application? At least it would be very helpful during the development phase to test different ZigBee commands, because you save the time to flash the MCU with every little change...
    Thanks again for a short explanation...

  • Hi a.poetsch,

    As far as I am aware, Z-Tool utilizes all of the MT commands provided in the API guide.  And yes, a switch (or any) application can reside on the Z-Tool host.  But since the ZCL resides on the application side then Z-Tool would be solely responsible for registering and maintaining attributes.  Therefore no UART communication to the ZNP is required.  If you further review the TI Linux gateway project you will find that the ZCL exists entirely on the Linux host.  This and zigbee2mqtt are good resources for creating your own host application.

    Regards,
    Ryan

  • To sum up: it is not necessary  (and not even possible) to communicate between the ZTool-Host-application and the ZNP to register the cluster attributes (as YiKai Chen suggested in his first answer).

    Unfortunately, I still do not understand the following statement from you , Ryan: "Z-Tool would be solely responsible for registering and maintaining attributes". So can you tell me how? or is it just like this: as soon as someone (eg the Coord) wants to read an attribute of my ZED, I get a callback within my ZTool script with the ZCL command "Read Attribute" and i answer with the appropriate ZCL Read Attribute Response command?

    I will take a closer look at the Linux gateway application if I have time...

    At the moment I think I have to understand the zigbee2mqtt application more, why it does not send any further "read attributes"-commands to my ZED?
    Maybe Koen Kanters can help me a bit :) ?

    Regards, Albert

  • YK's direct words were "ZNP application (Board #2)" which I believe he meant as the application which resides on the host.

    Yes, your understanding of attribute reads are correct.

    I believe Koen is willing to help but you will need to post a question to the Github as advised.

    Regards,
    Ryan

  • Zigbee2mqtt stops the read attributes (probably) because the devices fails to respond to earlier read attribute requests. When sniffing (https://www.zigbee2mqtt.io/how_tos/how_to_sniff_zigbee_traffic.html) you will probably see the zigbee2mqtt reads e.g. the model ID but the device fails to respond.

  • @ Koen Kanters: As you can see in my Ubiqua-Sniffer Log Files (attached in my previous posts) my ZNP-Enddevice is responding to the first (and only) Read Attributes Cmd from the coord with the according Read Attribute Response Cmd containing 3 Attributes (Model-ID,ManufacturerName and PowerSource), so I do not see that the end device fails to respond. But then the Coord stops to send out further Read Attribute requests... 

    Maybe the timing could be an issue, that my ZTool-Script (also included in my previous post) takes too much time for the response because of my Logging-output to ZTool? 

    Can you tell me where i find the logic within zigbee2mqtt where the Read-Attributes-Requests/Responses are processed? Is there a similar debug-possibility like for the interview-procedure as you told me ( DEBUG=zigbee-herdsman:controller* npm start)?

    Regards, Albert

  • Thanks to the help of Koen Kanters given in his own forum (github.com/.../738 ) i have found my problem: My ZTool script didn't send the correct transaction sequence number in the ReadAttributeResponse, so the zigbee2mqtt-gateway ignored this response and in turn the interview process failed.

    Now I have a working ZTool script attached, for everybody who is interested... (change file-ending from .txt to .zjs)
    Thank you all for your help!

    /**************************************************************************************************
      Filename:       startup_my3.0-ZNP-Enddevice-Switch.zjs
      
      ZTool script for use with a ZNP that trys to emulate the behaviour of the TI ZigBee Switch (EndDevice) example 
      (as found in e.g. simplelink_cc13x2_26x2_sdk_3_20_00_68\examples\rtos\CC1352R1_LAUNCHXL\zstack\zed_sw) 
      
      This script is intended to work with the zigbee2mqtt-gateway https://www.zigbee2mqtt.io/
      you must add this zigbeeModel to devices.js to get the ZNP successfully interviewed with the gateway:
        //TexasInstruments SimpleLink CC1352/CC2650 Demoboards mit ZStack-Firmware
        {
            zigbeeModel: ['TI_Switch'],
            model: 'TI_Switch (Launchpad)',
            vendor: 'TexasInstruments (TI)',
            description: 'TI Hardware running ZStack Switch Demo',
            supports: 'on/off',
            fromZigbee: [fz.cmdToggle, fz.genOnOff_cmdOn,fz.genOnOff_cmdOff],
            toZigbee: [],
        }
      
      
      7.Nov 2019, Albert Poetsch
      11.Nov 2019, added correct  ZCL_transactionSequenceNumber in ZCL_CMD_READ_RSP
      14.Nov 2019, added ZCL Toggle-Command for demonstration purpose
    **************************************************************************************************/
    
    
    
    import System;
    import System.Text;
    import TI.ZPI2;
    
    class TheScript
    {
      // Set this variable to the COM port assigned to the target device.
    	//private var comPort : String = "COM21";
    	private var comPort : String = "ZNP";
    
      // Set to 'true' when running the ZNP in order to reset the devices and startup the network.
      private var ZNP_RUN : boolean = true;
      private var SUCCESS : int = 0;
    
      // Set this variable to 'true' to enable the display of log messages (i.e. verbose mode).
      private var showLogMsgs : boolean = true;
    
      // Variables set by the incoming message handler to enable "re-try until success" looping.
      private var gotRstRsp           : boolean = false;
      private var gotCfgRsp           : boolean = false;
      private var gotRegRsp           : boolean = false;
      private var gotStartRsp         : boolean = false;
      private var gotStateRsp         : boolean = false; //set true as soon we have a settled state (DEV_END_DEVICE, DEV_ROUTER, DEV_ZB_COORD)
      private var gotBDBcommissioningSuccess  : boolean = false; //set true when we receive a APP_CNF_BDB_COMMISSIONING_NOTIFICATION with status Success 
      
      private var gotAfReqExtRsp      : boolean = false;
      private var gotAfIncExt         : boolean = false;
      private var gotAfStoreRsp       : boolean = false;
      private var gotAfRetrieveRsp    : boolean = false;
      private var gotDevRsp           : boolean = false;
      private var gotEpRsp            : boolean = false;
      private var gotSdescRsp         : boolean = false;
      private var gotTogRsp         : boolean = false;
      private var gotIEEERsp         : boolean = false;
      private var gotDevAnn         : boolean = false;
      
    //Definitions of ProfileID, DeviceID and ClusterIDs are found in the document ZIGBEE HOME AUTOMATION PUBLIC  APPLICATION PROFILE
    //(Default) Trust Center Link Key is found in Chapter 5.3.1  (Start Up Parameters) and Chapter 5.3.3 Security Parameters
    //DeviceIDs are in chapter  5.7 Device Descriptors
    //ClusterIDs are in chapter  5.9 Cluster List
      private var ZCL_HA_PROFILE_ID : UInt16 =  0x0104;						//profile definition
       
      private var ZCL_CLUSTER_ID_GEN_BASIC 			: UInt16 = 0x0000;		//cluster definition, see zcl.h
      private var ZCL_CLUSTER_ID_GEN_POWER_CFG 		: UInt16 = 0x0001;		//cluster definition, see zcl.h 
      private var ZCL_CLUSTER_ID_GEN_IDENTIFY 		: UInt16 = 0x0003;		//cluster definition
      private var ZCL_CLUSTER_ID_GEN_GROUPS 		: UInt16 = 0x0004;		//cluster definition
      private var ZCL_CLUSTER_ID_GEN_SCENES 		: UInt16 = 0x0005;		//cluster definition  
      private var ZCL_CLUSTER_ID_GEN_ON_OFF 		: UInt16 = 0x0006;		//cluster definition
      private var ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL 	: int = 0x0008;		    //cluster definition
      private var ZCL_CLUSTER_ID_GEN_BINARY_INPUT_BASIC 	: int = 0x000F;		//cluster definition
      private var ZCL_CLUSTER_ID_OTA 	                    : int = 0x0019;		//cluster definition
      
                                    
      private var ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK : int = 0x0101;		//cluster definition (FunctionalDomain: Closures)
      private var ZCL_CLUSTER_ID_HVAC_THERMOSTAT 	: int = 0x0201;		//cluster definition
      private var ZCL_CLUSTER_ID_MS_ILLUMINANCE_MEASUREMENT 	: int = 0x0400;		//cluster definition
      private var ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT 	: int = 0x0402;		//cluster definition (FunctionalDomain: Measurement & Sensing)
      
      
      private var ATTRID_BASIC_ZCL_VERSION          : int = 0x0000;         //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_APPL_VERSION         : int = 0x0001;         //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_STACK_VERSION        : int = 0x0002;         //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_HW_VERSION           : int = 0x0003;         //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_MANUFACTURER_NAME	: int = 0x0004;         //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_MODEL_ID	            : int = 0x0005;	        //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_DATE_CODE            : int = 0x0006;
      private var ATTRID_BASIC_POWER_SOURCE	        : int = 0x0007;	        //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_BASIC_SW_BUILD_ID          : int = 0x4000;         //attribute ID (Basic Cluster Attributes of General,  zcl_general.h)
      private var ATTRID_HVAC_THERMOSTAT_LOCAL_TEMPERATURE	: int = 0x0000;	//attribute ID
      private var ATTRID_HVAC_THERMOSTAT_OUTDOOR_TEMPERATURE: int = 0x0001;	//attribute ID
      private var ATTRID_MS_ILLUMINANCE_MEASURED_VALUE		: int = 0x0000;	//attribute ID
      
      private var POWER_SOURCE_MAINS_1_PHASE : int = 0x01; //Power Source Attribute values (Basic Cluster Attribute of General,  zcl_general.h)
      private var POWER_SOURCE_BATTERY		 : int = 0x03; //Power Source Attribute values (Basic Cluster Attribute of General,  zcl_general.h)
     
      private var ZCL_DATATYPE_UINT8        : int = 0x20;	//Data Types, see zcl.h
      private var ZCL_DATATYPE_ENUM8		: int = 0x30;	//Data Types, see zcl.h
      private var ZCL_DATATYPE_CHAR_STR		: int = 0x42;	//Data Types, see zcl.h
      
      private var ZCL_HA_DEVICEID_METER_INTERFACE : int =  	0x0053;		//device definition (FunctionalDomain: Generic) 
      private var ZCL_HA_DEVICEID_DOOR_LOCK : int =  		0x000A;		//device definition (FunctionalDomain: Generic) 
      private var ZCL_HA_DEVICEID_ON_OFF_LIGHT            : UInt16 = 	0x0100;  	//device definition (FunctionalDomain: Lighting)
      private var ZCL_HA_DEVICEID_ON_OFF_LIGHT_SWITCH     : UInt16 = 	0x0103;  	//device definition (FunctionalDomain: Lighting)
      private var ZCL_HA_DEVICEID_SIMPLE_SENSOR     : int = 	0x000C;  	//device definition (FunctionalDomain: Generic), see zcl_ha.h
      private var ZCL_HA_DEVICEID_HEATING_COOLING_UNIT : int =  0x0300;	//device definition (FunctionalDomain: HVAC)
      private var ZCL_HA_DEVICEID_THERMOSTAT : int =  0x0301;			//device definition (FunctionalDomain: HVAC)
      private var ZCL_HA_DEVICEID_DOOR_LOCK_CONTROLLER : int =  0x000B;	//device definition
      
      private var ZCL_FRAME_CLIENT_SERVER_DIR    	: int =  0x00;	//Frame Client/Server Directions
      private var ZCL_DATATYPE_UINT16 				: int =  0x21;
      private var ZCL_DATATYPE_INT16 				: int =  0x29;
      
      private var ZCL_CMD_READ                      : int =  0x00; /*** ZCL Foundation Command IDs ***/ //see zcl.h 
      private var ZCL_CMD_READ_RSP                  : int =  0x01;
      private var ZCL_CMD_WRITE                     : int =  0x02;
      private var ZCL_CMD_WRITE_UNDIVIDED           : int =  0x03;
      private var ZCL_CMD_WRITE_RSP                 : int =  0x04;
      private var ZCL_CMD_WRITE_NO_RSP              : int =  0x05;
      private var ZCL_CMD_CONFIG_REPORT             : int =  0x06;
      private var ZCL_CMD_CONFIG_REPORT_RSP         : int =  0x07;
      private var ZCL_CMD_REPORT                    : int =  0x0a;
      private var ZCL_CMD_DEFAULT_RSP               : int =  0x0b;
      private var ZCL_STATUS_SUCCESS                : int =  0x00;
      private var ZCL_STATUS_UNSUPPORTED_ATTRIBUTE  : int =  0x86;
      private var ZCL_STATUS_INVALID_VALUE          : int =  0x87;
      private var ZCL_STATUS_INVALID_DATA_TYPE      : int =  0x8D;
      
      private var COMMAND_IDENTIFY_QUERY            : int =  0x01; //Identify Cluster Commands
      
     
      private var COMMAND_OFF               : int =  0x00; /*** ZCL General On/Off-Cluster Command IDs ***/ //see zcl_general.h 
      private var COMMAND_ON                : int =  0x01;
      private var COMMAND_TOGGLE            : int =  0x02;
      
      private var AF_DEFAULT_RADIUS : int = 0x1E;
     
      //clusters 
      //for 1.Endpoint
      private var inClusterCnt_ep1        : Byte    = 2;  //see ZStack zed_sampleswitch-Example
      private var outClusterCnt_ep1       : Byte    = 3;  //see ZStack zed_sampleswitch-Example
      //private var inClusterCnt_ep1        : Byte    = 1;  //only for Philips Hue Dimmer
      //private var outClusterCnt_ep1       : Byte    = 6;  //only for Philips Hue Dimmer
      private var inClusterList_ep1 = new Array(inClusterCnt_ep1); 
      private var outClusterList_ep1 = new Array(outClusterCnt_ep1);
      private var sourceEndpoint_ep1        		: Byte    = 0x08; //self-defined by user, copied from ZStack zed_sampleswitch-Example
      private var sourceEndpoint_ep1_PhilipsRWL021  : Byte    = 0x01;
      
      //for 2.Endpoint (only for emulating Philips HueDimmer)
      private var inClusterCnt_ep2        : Byte    = 5;
      private var outClusterCnt_ep2       : Byte    = 1;
      private var inClusterList_ep2 = new Array(inClusterCnt_ep2);
      private var outClusterList_ep2 = new Array(outClusterCnt_ep2);  
      private var sourceEndpoint_ep2_PhilipsRWL021  : Byte    = 0x02;
      
    
      private var ZCD_NV_STARTUP_OPTION     : Byte = 0x03; //OSAL NV item ID, see zcomdef.h
      private var ZCD_NV_LOGICAL_TYPE     : Byte = 0x87; //OSAL NV item ID, see zcomdef.h 
      private var NV_STARTUP_OPTION_VAL : Byte = 0x03;	// 0x03 = clear configuration (ZCD_STARTOPT_DEFAULT_CONFIG_STATE (0x01) && ZCD_STARTOPT_DEFAULT_NETWORK_STATE (0x02))
      private var ZG_DEVICETYPE_COORDINATOR     : Byte = 0x00; //Values for ZCD_NV_LOGICAL_TYPE (zgDeviceLogicalType), see zglobals.h
      private var ZG_DEVICETYPE_ROUTER          : Byte = 0x01; //Values for ZCD_NV_LOGICAL_TYPE (zgDeviceLogicalType), see zglobals.h
      private var ZG_DEVICETYPE_ENDDEVICE       : Byte = 0x02; //Values for ZCD_NV_LOGICAL_TYPE (zgDeviceLogicalType), see zglobals.h
    
      private var cfgArr = new Array(256);        // Make big enough for any configuration item.
      private var retrieveBuf = new Array(1024);  // Make big enough for any huge message attempted.
      private var retrieveTot           : UInt16 = 741;
      private var retrieveLen           : Byte = 247;
      private var retrieveIdx           : UInt16;
      private var devaddr_Short               : UInt16;
      private var devaddr_Long               : UInt64;
    
    
      //DATA REQUEST VARIABLES
      private var drData = new Array(99);
      private var drCluster           : UInt16;
      private var drTrans          : Byte;
      private var drOption           : Byte;
      private var drRadius           : Byte = 0x1E;//AF_DEFAULT_RADIUS
      private var drLen           : Byte;   //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload) 
    
      //INCOMING MESSAGES VARIABLES
      private var imData = new Array(99);
      private var imGroup           : UInt16;
      private var imCluster           : UInt16;
      private var imSrcAddr           : UInt16;
      private var imSrcEndp           : Byte;
      private var imDstEndp           : Byte;
      private var imLen           : Byte;  //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload) 
    
    
      
      // Main class function that effects the work of this test script.
      function run()
      {
        logMsg("Hello Albert, bringup ZNP!"); //logMsg -> Log siehe file "Trace.log" 
      
        // Subscribe to the incoming message handler.
        ZEngine.add_OnMessageZPI2(this.msgHandler);
    
        if (ZNP_RUN)
        {
          // Force a device out of the boot loader wait routine (no bad effect when SBL is not present).
          sysReset(comPort);
    
          // Set the Startup_Option to Clear Configuration in NV and reset to effect the action.
          cfgArr[0] = NV_STARTUP_OPTION_VAL;
          writeCfg(comPort , ZCD_NV_STARTUP_OPTION, 0x01, cfgArr);
          sysReset(comPort);
          
          // Setup the device type
          //cfgArr[0] = ZG_DEVICETYPE_ROUTER;                    // Set Logical Device Type to ZigBee Router (ZG_DEVICETYPE_ROUTER = 0x01).
          cfgArr[0] = ZG_DEVICETYPE_ENDDEVICE;
          writeCfg(comPort, ZCD_NV_LOGICAL_TYPE, 0x01, cfgArr);
          
          cfgArr[0] = true;
          writeCfg(comPort, 0x8F, 0x01, cfgArr);// Set ZCD_NV_ZDO_DIRECT_CB to true to receive ZDO related messages (ZCD_NV_ZDO_DIRECT_CB address = 0x8F)
           
    	 // register EndPoint by defining Profile (ZCL_HA_PROFILE_ID), Device (ZCL_HA_DEVICEID_ON_OFF_LIGHT), Version, Input & Output Cluster-list 
         //afRegisterRequest_FirstEndpoint_PhilipsRWL021(comPort); //only for Philips HueDimmer
         //afRegisterRequest_SecondEndpoint_PhilipsRWL021(comPort);//only for Philips HueDimmer
        
         afRegisterRequest_FirstEndpoint(comPort); //see ZStack zed_sampleswitch-Example
        
         startReq(comPort);  //ZDO_STARTUP_FROM_APP
        
        
        //logMsg("Albert , send identifyQuery!");
        //prepare_data_for_identifyQuery();
        //afDataReq(comPort, 0xFFFF, 0xFF,sourceEndpoint_ep1); //parameters: (comm, destination-nwk-addr, destination-endpoint, source-endpoint)
        
        
        logMsg("ZNP now prepared to be a EndDevice (with a Switch-Endpoint), ...");
        
    		 
            while(1){
                
                prepare_data_for_ZCLcmd_GeneralOnOff_COMMAND_TOGGLE(0);
                afDataReq(comPort, 0x0000, 0x08,sourceEndpoint_ep1); //parameters: (comm, destination-nwk-addr, destination-endpoint, source-endpoint) 0x0000 = ShortAddress of Coord
                ZEngine.Pause(4000);
    			
    			//prepare_data_for_ZCLcmd_GeneralOnOff_COMMAND_ON(0);
                //afDataReq(comPort, 0x0000, 0x08,sourceEndpoint_ep1); //parameters: (comm, destination-nwk-addr, destination-endpoint, source-endpoint) 0x0000 = ShortAddress of Coord
                //ZEngine.Pause(3000);
                
    			//prepare_data_for_ZCLcmd_GeneralOnOff_COMMAND_OFF(0);
                //afDataReq(comPort, 0x0000, 0x08,sourceEndpoint_ep1); //parameters: (comm, destination-nwk-addr, destination-endpoint, source-endpoint) 0x0000 = ShortAddress of Coord
                //ZEngine.Pause(3000);
              
                
                //logMsg("press key to toggle light...");
                //ZEngine.Pause(); //Pause current script until a key is pressed.
    			
    			
    			//wait for incoming messages (e.g. TemperatureSensor reports)
            }
    
        }
    
        ZEngine.Complete(true);
      }
    
    //################################################################################################################  
    //########### IMPLEMENTATION OF LOCAL FUNCTIONS ##################################################################
    //################################################################################################################  
    
    
    function prepare_data_for_identifyQuery()
    {
        //prepare Read Attributes Response Command (ZCL spec chapter 2.5.2 , Revision 6-Jän2016)
          drCluster = ZCL_CLUSTER_ID_GEN_IDENTIFY;
          drTrans = 0;
          drOption = 0x0;
          drLen = 3; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
           
          //----ZCL Header: (3 bytes) ------------------------------
          drData[0] = 0x11; //Frame control (of ZCL Header)
                    //	Frame Control: 0x11
    
          drData[1] = 0x01; //transaction sequence number (of ZCL Header)
          drData[2] = COMMAND_IDENTIFY_QUERY; 
      }
    
     
    function prepare_data_for_ZCLcmdReadResponse_setting1(ZCL_transactionSequenceNumber: Byte) 
    {
        //prepare Read Attributes Response Command (ZCL spec chapter 2.5.2 , Revision 6-Jän2016)
          drCluster = ZCL_CLUSTER_ID_GEN_BASIC;
          drTrans = 0;
          drOption = 0x0;
          drLen = 43; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
           
          //----ZCL Header: (3 bytes) ------------------------------
          drData[0] = 0x18; //Frame control (of ZCL Header)
                    //	Frame Control: 0x18
                    //···· ··00 = Frame Type: [0x0] Command Acts Across the Entire Profile
                    //···· ·0·· = Manufacturer Specific: [0x0] Manufacturer Code Not Included in the ZCL Frame
                    //···· 1··· = Direction: [0x1] From Server to Client
                    //···1 ···· = Disable Default Response: [0x1] Yes
                    //000· ···· = Reserved: 0x0
    	  drData[1] = ZCL_transactionSequenceNumber; //transaction sequence number (of ZCL Header, not of NWK-Frame)
          drData[2] = ZCL_CMD_READ_RSP; //General Command Frame: [0x01] Read Attributes Response
          //------ZCL Payload: (28 bytes)---------------
          //----Attribute #1 (11bytes)--------------------------
          drData[3] = ATTRID_BASIC_MODEL_ID & 0xFF; //16bit Attribute ID
          drData[4] = (ATTRID_BASIC_MODEL_ID >> 8) & 0xFF ;          
          drData[5] = SUCCESS; //Status
          drData[6] = ZCL_DATATYPE_CHAR_STR; //Attribute Data Type
          drData[7] = 9;   //Length of Attribute Value
          drData[8] = 0x54; //String "TI_Switch"
          drData[9] = 0x49;
          drData[10] = 0x5f;
          drData[11] = 0x53;
          drData[12] = 0x77;
          drData[13] = 0x69;
          drData[14] = 0x74;
          drData[15] = 0x63;
          drData[16] = 0x68;
          //----Attribute #2 (12bytes) --------------------------
          drData[17] = ATTRID_BASIC_MANUFACTURER_NAME & 0xFF; //16bit Attribute ID
          drData[18] = (ATTRID_BASIC_MANUFACTURER_NAME >> 8) & 0xFF ;          
          drData[19] = SUCCESS; //Status
          drData[20] = ZCL_DATATYPE_CHAR_STR; //Attribute Data Type
          drData[21] = 16;   //Length of Attribute Value
          drData[22] = 0x54; //String "TexasInstruments"
          drData[23] = 0x65;
          drData[24] = 0x78;
          drData[25] = 0x61;
          drData[26] = 0x73;
          drData[27] = 0x49;
          drData[28] = 0x6e;
          drData[29] = 0x73;
          drData[30] = 0x74;
          drData[31] = 0x72;
          drData[32] = 0x75;
          drData[33] = 0x6d;
          drData[34] = 0x65;
          drData[35] = 0x6e;
          drData[36] = 0x74;
          drData[37] = 0x73;
          //----Attribute #3 (5 bytes)--------------------------
          drData[38] = ATTRID_BASIC_POWER_SOURCE & 0xFF; //16bit Attribute ID
          drData[39] = (ATTRID_BASIC_POWER_SOURCE >> 8) & 0xFF ;          
          drData[40] = SUCCESS; //Status
          drData[41] = ZCL_DATATYPE_ENUM8; //Attribute Data Type
          drData[42] = POWER_SOURCE_MAINS_1_PHASE; //POWER_SOURCE_BATTERY;   //Attribute Value          
      }
    
     
     function prepare_data_for_ZCLcmdReadResponse_setting1_PhilipsRWL021() 
    {
        //prepare Read Attributes Response Command (ZCL spec chapter 2.5.2 , Revision 6-Jän2016)
          drCluster = ZCL_CLUSTER_ID_GEN_BASIC;
          drTrans = 0;
          drOption = 0x0;
          drLen = 31; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
           
          //----ZCL Header: (3 bytes) ------------------------------
          drData[0] = 0x18; //Frame control (of ZCL Header)
                    //	Frame Control: 0x18
                    //···· ··00 = Frame Type: [0x0] Command Acts Across the Entire Profile
                    //···· ·0·· = Manufacturer Specific: [0x0] Manufacturer Code Not Included in the ZCL Frame
                    //···· 1··· = Direction: [0x1] From Server to Client
                    //···1 ···· = Disable Default Response: [0x1] Yes
                    //000· ···· = Reserved: 0x0
          drData[1] = 0x00; //transaction sequence number (of ZCL Header)
          drData[2] = ZCL_CMD_READ_RSP; //General Command Frame: [0x01] Read Attributes Response
          //------ZCL Payload: (28 bytes)---------------
          //----Attribute #1 (11bytes)--------------------------
          drData[3] = ATTRID_BASIC_MODEL_ID & 0xFF; //16bit Attribute ID
          drData[4] = (ATTRID_BASIC_MODEL_ID >> 8) & 0xFF ;          
          drData[5] = SUCCESS; //Status
          drData[6] = ZCL_DATATYPE_CHAR_STR; //Attribute Data Type
          drData[7] = 6;   //Length of Attribute Value
          drData[8] = 0x52; //String "RWL021"
          drData[9] = 0x57;
          drData[10] = 0x4C;
          drData[11] = 0x30;
          drData[12] = 0x32;
          drData[13] = 0x31;
          //----Attribute #2 (12bytes) --------------------------
          drData[14] = ATTRID_BASIC_MANUFACTURER_NAME & 0xFF; //16bit Attribute ID
          drData[15] = (ATTRID_BASIC_MANUFACTURER_NAME >> 8) & 0xFF ;          
          drData[16] = SUCCESS; //Status
          drData[17] = ZCL_DATATYPE_CHAR_STR; //Attribute Data Type
          drData[18] = 7;   //Length of Attribute Value
          drData[19] = 0x50; //String "Philips"
          drData[20] = 0x68;
          drData[21] = 0x69;
          drData[22] = 0x6c;
          drData[23] = 0x69;
          drData[24] = 0x70;
          drData[25] = 0x73;
          //----Attribute #3 (5 bytes)--------------------------
          drData[26] = ATTRID_BASIC_POWER_SOURCE & 0xFF; //16bit Attribute ID
          drData[27] = (ATTRID_BASIC_POWER_SOURCE >> 8) & 0xFF ;          
          drData[28] = SUCCESS; //Status
          drData[29] = ZCL_DATATYPE_ENUM8; //Attribute Data Type
          drData[30] = POWER_SOURCE_BATTERY;   //Attribute Value          
      }
    
    function prepare_data_for_ZCLcmdReadResponse_setting2(ZCL_transactionSequenceNumber: Byte) 
    {
        //prepare Read Attributes Response Command (ZCL spec chapter 2.5.2 , Revision 6-Jän2016)
          drCluster = ZCL_CLUSTER_ID_GEN_BASIC;
          drTrans = 0;
          drOption = 0x0;
          drLen = 14; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
           
          //----ZCL Header: (3 bytes) ------------------------------
          drData[0] = 0x18; //Frame control (of ZCL Header)
                    //	Frame Control: 0x18
                    //···· ··00 = Frame Type: [0x0] Command Acts Across the Entire Profile
                    //···· ·0·· = Manufacturer Specific: [0x0] Manufacturer Code Not Included in the ZCL Frame
                    //···· 1··· = Direction: [0x1] From Server to Client
                    //···1 ···· = Disable Default Response: [0x1] Yes
                    //000· ···· = Reserved: 0x0
    	  drData[1] = ZCL_transactionSequenceNumber; //transaction sequence number (of ZCL Header, not of NWK-Frame)
          drData[2] = ZCL_CMD_READ_RSP; //General Command Frame: [0x01] Read Attributes Response
          //------ZCL Payload: (28 bytes)---------------
          //----Attribute #1 (5bytes)--------------------------
          drData[3] = ATTRID_BASIC_ZCL_VERSION & 0xFF; //16bit Attribute ID
          drData[4] = (ATTRID_BASIC_ZCL_VERSION >> 8) & 0xFF ;          
          drData[5] = SUCCESS; //Status
          drData[6] = ZCL_DATATYPE_UINT8; //Attribute Data Type
          drData[7] = 0x03;   //kopiert vom SnifferLog vom zed-switch-example
    	  //----Attribute #2 (3bytes) --------------------------
          drData[8] = ATTRID_BASIC_APPL_VERSION & 0xFF; //16bit Attribute ID
          drData[9] = (ATTRID_BASIC_APPL_VERSION >> 8) & 0xFF ;
          drData[10] = 0x86;   //(unsupported attribute) kopiert vom Wireshark SnifferLog vom zed-switch-example
    	  //----Attribute #3 (3 bytes)--------------------------
          drData[11] = ATTRID_BASIC_STACK_VERSION & 0xFF; //16bit Attribute ID
          drData[12] = (ATTRID_BASIC_STACK_VERSION >> 8) & 0xFF ;
          drData[13] = 0x86;   //(unsupported attribute) kopiert vom Wireshark SnifferLog vom zed-switch-example
    }
    
    function prepare_data_for_ZCLcmdReadResponse_setting3(ZCL_transactionSequenceNumber: Byte) 
    {
        //prepare Read Attributes Response Command (ZCL spec chapter 2.5.2 , Revision 6-Jän2016)
          drCluster = ZCL_CLUSTER_ID_GEN_BASIC;
          drTrans = 0;
          drOption = 0x0;
          drLen = 14; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
           
          //----ZCL Header: (3 bytes) ------------------------------
          drData[0] = 0x18; //Frame control (of ZCL Header)
                    //	Frame Control: 0x18
                    //···· ··00 = Frame Type: [0x0] Command Acts Across the Entire Profile
                    //···· ·0·· = Manufacturer Specific: [0x0] Manufacturer Code Not Included in the ZCL Frame
                    //···· 1··· = Direction: [0x1] From Server to Client
                    //···1 ···· = Disable Default Response: [0x1] Yes
                    //000· ···· = Reserved: 0x0
    	  drData[1] = ZCL_transactionSequenceNumber; //transaction sequence number (of ZCL Header, not of NWK-Frame)
          drData[2] = ZCL_CMD_READ_RSP; //General Command Frame: [0x01] Read Attributes Response
          //------ZCL Payload: (28 bytes)---------------
          //----Attribute #1 (5bytes)--------------------------
          drData[3] = ATTRID_BASIC_HW_VERSION & 0xFF; //16bit Attribute ID
          drData[4] = (ATTRID_BASIC_HW_VERSION >> 8) & 0xFF ;          
          drData[5] = SUCCESS; //Status
          drData[6] = ZCL_DATATYPE_UINT8; //Attribute Data Type
          drData[7] = 0x00;   //kopiert vom SnifferLog vom zed-switch-example
    	  //----Attribute #2 (3bytes) --------------------------
          drData[8] = ATTRID_BASIC_DATE_CODE & 0xFF; //16bit Attribute ID
          drData[9] = (ATTRID_BASIC_DATE_CODE >> 8) & 0xFF ;
          drData[10] = 0x86;   //(unsupported attribute) kopiert vom Wireshark SnifferLog vom zed-switch-example
    	  //----Attribute #3 (3 bytes)--------------------------
          drData[11] = ATTRID_BASIC_SW_BUILD_ID & 0xFF; //16bit Attribute ID
          drData[12] = (ATTRID_BASIC_SW_BUILD_ID >> 8) & 0xFF ;
          drData[13] = 0x86;   //(unsupported attribute) kopiert vom Wireshark SnifferLog vom zed-switch-example
    }
    
    function prepare_data_for_ZCLcmd_GeneralOnOff_COMMAND_TOGGLE(ZCL_transactionSequenceNumber: Byte) 
    {
    	  drCluster = ZCL_CLUSTER_ID_GEN_ON_OFF;
    	  drTrans = 0;
    	  drOption = 0x0;
    	  drLen = 3; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
    	  //----ZCL Header: (3 bytes) ------------------------------
    	  drData[0] = 0x01;//frame control (chapter2.3.1.1,page40):0x01 = Command is specific to this cluster(->ToggleCmd of OnOff-Cluster),
    						//NOT manufacturer specific,
    						//direction=0:command is being sent from client side of a cluster to server side of a cluster
    						//always return default response command
    	  drData[1] = ZCL_transactionSequenceNumber; 
    	  drData[2] = COMMAND_TOGGLE; //CmdID of Toggle-cmd of Cluster OnOff (see table 3.39 chapter 3.8.2.3 (page 146) of ZCL-spec)
    	  //------ZCL Payload: (0 bytes)---------------
    	  //no ZCL-Payload for this command  because we are sending a cluster-specific command, not the value of an attribute)
    }
    
    function prepare_data_for_ZCLcmd_GeneralOnOff_COMMAND_ON(ZCL_transactionSequenceNumber: Byte) 
    {
    	  drCluster = ZCL_CLUSTER_ID_GEN_ON_OFF;
    	  drTrans = 0;
    	  drOption = 0x0;
    	  drLen = 3; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
    	  //----ZCL Header: (3 bytes) ------------------------------
    	  drData[0] = 0x01;//frame control (chapter2.3.1.1,page40):0x01 = Command is specific to this cluster(->ToggleCmd of OnOff-Cluster),
    						//NOT manufacturer specific,
    						//direction=0:command is being sent from client side of a cluster to server side of a cluster
    						//always return default response command
    	  drData[1] = ZCL_transactionSequenceNumber; 
    	  drData[2] = COMMAND_ON; //CmdID of Toggle-cmd of Cluster OnOff (see table 3.39 chapter 3.8.2.3 (page 146) of ZCL-spec)
    	  //------ZCL Payload: (0 bytes)---------------
    	  //no ZCL-Payload for this command  because we are sending a cluster-specific command, not the value of an attribute)
    }
    
    function prepare_data_for_ZCLcmd_GeneralOnOff_COMMAND_OFF(ZCL_transactionSequenceNumber: Byte) 
    {
    	  drCluster = ZCL_CLUSTER_ID_GEN_ON_OFF;
    	  drTrans = 0;
    	  drOption = 0x0;
    	  drLen = 3; //Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload)
    	  //----ZCL Header: (3 bytes) ------------------------------
    	  drData[0] = 0x01;//frame control (chapter2.3.1.1,page40):0x01 = Command is specific to this cluster(->ToggleCmd of OnOff-Cluster),
    						//NOT manufacturer specific,
    						//direction=0:command is being sent from client side of a cluster to server side of a cluster
    						//always return default response command
    	  drData[1] = ZCL_transactionSequenceNumber; 
    	  drData[2] = COMMAND_OFF; //CmdID of Toggle-cmd of Cluster OnOff (see table 3.39 chapter 3.8.2.3 (page 146) of ZCL-spec)
    	  //------ZCL Payload: (0 bytes)---------------
    	  //no ZCL-Payload for this command  because we are sending a cluster-specific command, not the value of an attribute)
    }
      
      
    // process incoming ZCL message (= APS Payload: ZCL Header and ZCL Payload).
      function processIncomingZCLMsg(comm : String) {
    	var ZCL_Header_FrameControl 	: Byte	= 0;
    	var ZCL_Header_TransSequNumber 	: Byte	= 0;
    	var ZCL_Header_CmdIdentifier 	: Byte	= 0;
    	var attID : UInt16	= 0;
    	var attributeData : UInt16 =0;
        var numOf16bitAttributes : Byte = 0;
      
    	//-----ZCL Header---
    	//imData[0]: Frame Control
        //imData[1]: TransactionNumber (if Manufactorer code is omitted)
        //imData[2]: Command identifier
    	//imData[xxx]: ZCL payload	
    	
    	ZCL_Header_FrameControl = imData[0];
    	ZCL_Header_TransSequNumber = imData[1];
    	ZCL_Header_CmdIdentifier = imData[2];
        
        
    	//logMsg("Albert, got ZCL message with TransSequNumber " + ZCL_Header_TransSequNumber);
    	
        switch (ZCL_Header_CmdIdentifier)
        {
            case ZCL_CMD_READ: 	//check for  Read Attributes Command (ZCL spec chapter 2.5.1 , Revision 6-Jän2016)
                {
                  //imLen ist Länge in Bytes der gesamten APS-Payload (ZCL Header inklusive Payload, Attributes sind 16bit)          
                  numOf16bitAttributes = (imLen-3)/2;  //3 ist länge von ZCL Header, /2 weil 16bit-Attributes             
                  logMsg("Albert, process incoming ZCL_CMD_READ command with " + numOf16bitAttributes + " attributes");
                  
                  //--------ZCL Payload--------------------
                  //Attribute identifier (16bits each)  
                  for (var idx = 0; idx < numOf16bitAttributes; idx++)
                  {
                    attID = (imData[idx*2+3+1] << 8) | imData[idx*2+3]; //offset idx 3, first 16bit attribute starts at (imData[3+1] << 8) | imData[idx+3] 
                    logMsg("attribute #" + idx + ": 0x" + attID.ToString("X"));
                  }
    			  //Alternativ: etwas kompakter und ohne numOf16bitAttributes-Zwischenberechnung
                  // for (var idx = 3; idx < imLen; idx+=2)
                  // {
                    // attID = (imData[idx+1] << 8) | imData[idx]; //offset idx 3 weil ab (imData[3+1] << 8) | imData[idx+3]  das erste Attribute beginnt;
                    // logMsg("attribute #" + idx + ": 0x" + attID.ToString("X"));
                  // }
                  
                  //send back the according ZCL_CMD_READ_RSP
                  //ToDo: make this dynamic, but for now its hardcoded to work with the zigbee2MQTT-interview-process, quick&dirty
                  attID = (imData[4] << 8) | imData[3]; //get first Attribute             
                    logMsg("first attribute in list: 0x" + attID.ToString("X"));
                  if(attID == ATTRID_BASIC_MODEL_ID){ 
                    prepare_data_for_ZCLcmdReadResponse_setting1(ZCL_Header_TransSequNumber); //send back 3 Attributes: ATTRID_BASIC_MODEL_ID, ATTRID_BASIC_MANUFACTURER_NAME and ATTRID_BASIC_POWER_SOURCE
                    //prepare_data_for_ZCLcmdReadResponse_setting1_PhilipsRWL021();
                    
                    logMsg("Albert , send CMD_READ-Response_setting1!");
                    //afDataReq(comm, imSrcAddr, imSrcEndp,0x01); //parameters: (comm, destination-nwk-addr, destination-endpoint, source-endpoint)   wie bei Hue Dimmer (BITTE NACHPRÜFEN on Endpoint stimmt!)
                    afDataReq(comm, imSrcAddr, imSrcEndp,sourceEndpoint_ep1); //parameters: (comm, destination-nwk-addr, destination-endpoint, source-endpoint)   wie bei zed_sampleswitch
                  }else if(attID == ATTRID_BASIC_ZCL_VERSION){ 
                    prepare_data_for_ZCLcmdReadResponse_setting2(ZCL_Header_TransSequNumber); //send back 3 Attributes: ATTRID_BASIC_ZCL_VERSION, ATTRID_BASIC_APPL_VERSION and ATTRID_BASIC_STACK_VERSION
                    logMsg("Albert , send CMD_READ-Response_setting2!");
    				afDataReq(comm, imSrcAddr, imSrcEndp,sourceEndpoint_ep1);
    			  }else if(attID == ATTRID_BASIC_HW_VERSION){ 
                     prepare_data_for_ZCLcmdReadResponse_setting3(ZCL_Header_TransSequNumber); //send back 3 Attributes: ATTRID_BASIC_HW_VERSION, ATTRID_BASIC_DATE_CODE and ATTRID_BASIC_SW_BUILD_ID
                    logMsg("Albert , send CMD_READ-Response_setting3!");
    				afDataReq(comm, imSrcAddr, imSrcEndp,sourceEndpoint_ep1);
                  }
    			  else{              
    				//...todo!!! unsupported attributes requested...
                      logMsg("...ToDo Albert, send further CMD_READ-Response for the other attributes..!");
                  }
                  
                  break;
                }
            
            case ZCL_CMD_CONFIG_REPORT_RSP: 	//check for General Command Frame: [0x07] Configure Reporting Response
                {
                     logMsg("Todo Albert, ZCL_CMD_CONFIG_REPORT_RSP!!!");
                    logMsg("received Configure Reporting Response for Cluster 0x" +  imCluster.ToString("X") + " from Source 0x" + imSrcAddr.ToString("X") + " Endpoint #" + imSrcEndp);
                    break;
                }
    		
    		case ZCL_CMD_REPORT: 	//check for General Command Frame: [0x0A] Report Attributes
                {
                logMsg("Todo Albert , ZCL_CMD_REPORT!!!");
                    break;
                }
            case ZCL_CMD_CONFIG_REPORT:
                {
                logMsg("Todo Albert , ZCL_CMD_CONFIG_REPORT!!!");
                    break;
                }
            case ZCL_CMD_DEFAULT_RSP:
                {
                logMsg("Todo Albert , ZCL_CMD_DEFAULT_RSP!!!");
                    break;
                }            
            default:
    		{
    		  logMsg("unhandled incoming ZCL General Command Frame 0x" + ZCL_Header_CmdIdentifier.ToString("X") );
    		  break;
    		}
        }
      }
    
    
    
    // Send a ZDO_IEEE_ADDR_REQ message.
      function ieeeAddr(comm : String, addr : UInt16) {
         var req : ZDO_IEEE_ADDR_REQ  = new ZDO_IEEE_ADDR_REQ ();
         req.ShortAddr = addr;
          gotIEEERsp = false;
          while(!gotIEEERsp)
          {
              logMsg("Albert , ZDO_IEEE_ADDR_REQ to 0x" + req.ShortAddr.ToString("X"));
              ZEngine.Send(comm, req);
              ZEngine.Pause(2000);
          }
      }
      
     // Wait for a ZDO_END_DEVICE_ANNCE_IND message.
      function edAnnce() {
          gotDevAnn = false;
          while(!gotDevAnn)
          {
    		// wait until we receive a ZDO_END_DEVICE_ANNCE_IND indication
              ZEngine.Pause(1000);
          }
      }
      
     
      
      
      // Send a ZDO_ACTIVE_EP_REQ message.
      function epReq(comm : String, dst : UInt16, aoi : UInt16) {
        var req : ZDO_ACTIVE_EP_REQ  = new ZDO_ACTIVE_EP_REQ ();
        req.DstAddr = dst;
        req.NWKAddrOfInterest = aoi;
        gotEpRsp = false;
        while(!gotEpRsp)
        {
            //logMsg("ZDO_ACTIVE_EP_REQ to " + comm);
            ZEngine.Send(comm, req);
            ZEngine.Pause(4000);
        }
      }
      
      // Send a ZDO_SIMPLE_DESC_REQ message.
      function simDescReq(comm : String, dst : UInt16, aoi : UInt16, dstEp : Byte) {
        var req : ZDO_SIMPLE_DESC_REQ  = new ZDO_SIMPLE_DESC_REQ ();
        req.DstAddr = dst;
        req.NWKAddrOfInterest = aoi;
        req.Endpoint = dstEp;
        gotSdescRsp = false;
        //isLight = false;
        while(!gotSdescRsp)
        {
          logMsg("send ZDO_SIMPLE_DESC_REQ to " + comm + " EndPoint " + dstEp);
          ZEngine.Send(comm, req);
          ZEngine.Pause(3000);  //wait a bit, EndDevice is sleeping and must awake to answer the request
        }
      }
      
      
      // sends ZDO_MGMT_PERMIT_JOIN_REQUEST
      function permJoinReq(comm : String, dst : UInt16, duration : Byte, sig : Byte)
      {
         var req : ZDO_MGMT_PERMIT_JOIN_REQUEST  = new ZDO_MGMT_PERMIT_JOIN_REQUEST ();
         req.AddrMode = 0x02;
         req.DstAddr = dst;
         req.Duration = duration;
         req.TCSignificance = sig;
    
         ZEngine.Send(comm, req);
         ZEngine.Pause(2000);
      }
      // sends ZDO_MGMT_LQI_REQ
      function lqiReq(comm : String, dst : UInt16, start : Byte)
      {
         var req : ZDO_MGMT_LQI_REQ = new ZDO_MGMT_LQI_REQ ();
         req.DstAddr = dst;
         req.StartIndex = start;
    
         ZEngine.Send(comm, req);
         ZEngine.Pause(2000);
      }
    
    
      // Send a UTIL_GET_DEVICE_INFO message.
      function util_get_devInfo(comm : String)
      {
         var req : UTIL_GET_DEVICE_INFO  = new UTIL_GET_DEVICE_INFO ();
          gotDevRsp = false;
          while(!gotDevRsp)
          {
              ZEngine.Send(comm, req);
              ZEngine.Pause(2000);
          }
          logMsg("dev response");
      }
    
    
      //Send a AF_DATA_REQUEST message.
      //function afDataReq(comm : String, dst : UInt16, dstEp : Byte)
      function afDataReq(comm : String, dst : UInt16, dstEp : Byte,  srcEp : Byte)
      {
        var req : AF_DATA_REQUEST  = new AF_DATA_REQUEST ();
        req.DstAddr = dst;                   
        req.DestEndpoint = dstEp;            
        req.SrcEndpoint = srcEp;    
        req.ClusterID = drCluster;          
        req.TransID = drTrans;               
        req.Options = drOption;
        req.Radius = drRadius;               
        req.Len = drLen;
        logMsg("Albert, send AF_DATA_REQUEST to 0x" + req.DstAddr.ToString("X") + " Endpoint " + req.DestEndpoint + " (" + req.Len + " Bytes)");
        for (var idx = 0; idx < drLen; idx++)
        {
              req.Data[idx] = drData[idx];
        }
        ZEngine.Send(comm, req);
        ZEngine.Pause(1000);
      }
    
    //################################################################################################################  
    //########### START OF INCOMING MESSAGE HANDLER ##################################################################
    //################################################################################################################
      // Handler for incoming messages.
      function msgHandler(comm : String, id : MESSAGE_ID, msg : Object)
      {
        switch (id)
        {
        
        case MESSAGE_ID.SYS_RESET_RESPONSE:
        {
            gotRstRsp=true;
            //logMsg("INCOMING MESSAGE HANDLER: System reseted!");
          break;
        }
        
        case MESSAGE_ID.UTIL_GET_DEVICE_INFO_RESPONSE:
        {
            var devRsp : UTIL_GET_DEVICE_INFO_RESPONSE = msg;
            if (devRsp.Status == SUCCESS && devRsp.NumAssocDevices != 0)
            {
                gotDevRsp = true;
                devaddr_Short = devRsp.AssocDevicesList[0];
            }
    
          break;
        }
    
    
    	case MESSAGE_ID.ZDO_ACTIVE_EP_RSP:
        {
            var epRsp : ZDO_ACTIVE_EP_RSP = msg;
            if (epRsp.Status == SUCCESS && epRsp.ActiveEPCount != 0)
            {
                //gotEpRsp=true;
                logMsg("rx'ed active EP-List from 0x" + epRsp.NwkAddr.ToString("X") + " with " + epRsp.ActiveEPCount + " entries:");
                
                for (var idx = 0; idx < epRsp.ActiveEPCount; idx++)
                {
                    //simDescReq(comPort, epRsp.SrcAddr, epRsp.SrcAddr, epRsp.ActiveEPList[idx]);
                    logMsg("epRsp.ActiveEPList[" + idx + "]: " + epRsp.ActiveEPList[idx])
    				
    				//check if the expected Endpoint is in our list
    				//if (epRsp.ActiveEPList[idx] == expected_EndPoint_of_mobileSensor)
    				//{
    				//	gotEpRsp=true;
    				//	logMsg(" expected Endpoint " + epRsp.ActiveEPList[idx] + " is in our list!");
    				//	dstEndPoint = epRsp.ActiveEPList[idx];			
    				//}
                }
                //logMsg("save first EP in list: " + epRsp.ActiveEPList[0]);
                //dstEndPoint = epRsp.ActiveEPList[0];
            }
          break;
        }
    	
    	case MESSAGE_ID.ZDO_SIMPLE_DESC_RSP:
        {
            var smpdRsp : ZDO_SIMPLE_DESC_RSP = msg;
            //if (smpdRsp.Status == SUCCESS && smpdRsp.ProfileID == ZCL_HA_PROFILE_ID && smpdRsp.DeviceID == LIGHT)
            if (smpdRsp.Status == SUCCESS && smpdRsp.ProfileID == ZCL_HA_PROFILE_ID)
            {
                gotSdescRsp = true;
                //isLight = true;
                
                logMsg("SimpleDescriptorRsp of EP " +  smpdRsp.Endpoint + " of device 0x" + smpdRsp.NwkAddr.ToString("X") + ":");
                logMsg("NumInClusters: " +  smpdRsp.NumInClusters);
                for (var idx = 0; idx < smpdRsp.NumInClusters; idx++)
                {
                    logMsg("smpdRsp.InClusterList[" + idx + "]: 0x" + smpdRsp.InClusterList[idx].ToString("X"))
                }
                logMsg("NumOutCluster: " + smpdRsp.NumOutClusters);
                for (var idx = 0; idx < smpdRsp.NumOutClusters; idx++)
                {
                    logMsg("smpdRsp.OutClusterList[" + idx + "]: 0x" + smpdRsp.OutClusterList[idx].ToString("X"))
                }
            }
          break;
        }
    	
    	
        case MESSAGE_ID.ZDO_IEEE_ADDR_RSP:
        {
            var ieeeRsp : ZDO_IEEE_ADDR_RSP = msg;
            if (ieeeRsp.Status == SUCCESS )
            {
                gotIEEERsp=true;
                //ieeeAddrOfCoord = ieeeRsp.IEEEAddr;
                //logMsg("ieeeAddrOfCoord: 0x" + ieeeAddrOfCoord.ToString("X"));
                logMsg("got ieeeAddr: 0x" + ieeeRsp.IEEEAddr.ToString("X"));
            }
          break;
        }
        
        case MESSAGE_ID.SYS_RESET_RESPONSE:
        {
                gotRstRsp=true;
                logMsg("System reseted!");
          break;
        }
    
        case MESSAGE_ID.SYS_OSAL_NV_WRITE_SRSP:
        //(alt: case MESSAGE_ID.ZB_WRITE_CONFIGURATION_RSP:)
        {
          var cfgRsp : SYS_OSAL_NV_WRITE_SRSP = msg;
          //var cfgRsp : ZB_WRITE_CONFIGURATION_RSP = msg;
          if (cfgRsp.Status == SUCCESS)
          {
            gotCfgRsp = true;
          }
          break;
        }
    
        case MESSAGE_ID.AF_REGISTER_SRSP:
        {
          var regRsp : AF_REGISTER_SRSP = msg;
    
          if (regRsp.Status == SUCCESS)
          {
            gotRegRsp = true;
          }
          break;
        }
    
        // case MESSAGE_ID.ZB_START_REQUEST_RSP:
        // {
          // gotStartRsp = true;
          // break;
        // }
        case MESSAGE_ID.ZDO_STARTUP_FROM_APP_SRSP:
        {
          gotStartRsp = true;    //stimmt das, passt das ???
          break;
        }
    
    	case MESSAGE_ID.DEBUG_STRING:
        {
    	  var dbgStr : DEBUG_STRING = msg;
    
    	  	  
    	  logMsg("*************************************************");
          logMsg("Rx'ed DEBUG_STRING !! ");
          logMsg("*************************************************");
          break;
        }
    
        case MESSAGE_ID.ZDO_END_DEVICE_ANNCE_IND:
        {
    	  var zdoDevInd : ZDO_END_DEVICE_ANNCE_IND = msg;
          devaddr_Short = zdoDevInd.NwkAddr;
          devaddr_Long = zdoDevInd.IEEEAddr;
    	  //logMsg("new device announced: IEEE 0x" + zdoDevInd.IEEEAddr.ToString("X") + ", ShortAddr: 0x" + devaddr_Short.ToString("X"));
          gotDevAnn = true;
    	  	  
    	  logMsg("*************************************************");
          logMsg("NEW DEVICE announced: 0x" + devaddr_Short.ToString("X") + " (IEEE:0x" + devaddr_Long.ToString("X") + ")");
          logMsg("*************************************************");
          break;
        }
    
        case MESSAGE_ID.ZDO_STATE_CHANGE_IND:
        {
          var zdoStateInd : ZDO_STATE_CHANGE_IND = msg;
    
          // { DEV_END_DEVICE, DEV_ROUTER, DEV_ZB_COORD } : { 6, 7, 9 }
          if ((zdoStateInd.State == 6) || (zdoStateInd.State == 7) || (zdoStateInd.State == 9))
          {
            gotStateRsp = true;
            if (zdoStateInd.State == 6) logMsg("Albert:  network started as EndDevice after authentication!");
            if (zdoStateInd.State == 7) logMsg("Albert:  Device joined, authenticated and now working as Router!");
            if (zdoStateInd.State == 9) logMsg("Albert:  network started as Coordinator!"); 
          }
          break;
        }
    
        case MESSAGE_ID.AF_DATA_REQUEST_EXT_SRSP:
        {
          var afRegExtRsp : AF_DATA_REQUEST_EXT_SRSP = msg;
    
          if (afRegExtRsp.Status == SUCCESS)
          {
            gotAfReqExtRsp = true;
          }
          break;
        }
        
        case MESSAGE_ID.AF_DATA_REQUEST_SRSP:
        {
          var afRegRsp : AF_DATA_REQUEST_SRSP = msg;
    
          if (afRegRsp.Status == SUCCESS)
          {
            //gotAfReqRsp = true;
          }
          break;
        }
        
        case MESSAGE_ID.AF_DATA_CONFIRM:
        {
          var afDataCnf : AF_DATA_CONFIRM = msg;
    
          if (afDataCnf.Status == SUCCESS)
          {
            //wir könnten hier noch den Endpoint checken:  afDataCnf.Endpoint sowie afDataCnf.TransID
          }
          break;
        }
    
        case MESSAGE_ID.AF_DATA_STORE_SRSP:
        {
          var afStoreRsp : AF_DATA_STORE_SRSP = msg;
    
          if (afStoreRsp.Status == SUCCESS)
          {
            gotAfStoreRsp = true;
          }
          break;
        }
    
        case MESSAGE_ID.AF_INCOMING_MSG_EXT:
        {
          var afIncExt : AF_INCOMING_MSG_EXT = msg;
          afDataRetrieve(comm, msg);
          gotAfIncExt = true;
          break;
        }
    
        case MESSAGE_ID.AF_INCOMING_MSG:
        {
           var inMsgDat : AF_INCOMING_MSG = msg;
          imGroup = inMsgDat.GroupID;
          imCluster = inMsgDat.ClusterID;
          imSrcAddr = inMsgDat.SrcAddr;
          imSrcEndp = inMsgDat.SrcEndpoint;		//EP von Sender
          imDstEndp = inMsgDat.DstEndpoint;		//mein eigner EP
          imLen = inMsgDat.Len;
    	  //save APS Payload: ZCL Header and Payload
          for (var idx = 0; idx < imLen; idx++)
          {
              imData[idx] = inMsgDat.Data[idx];
          }
          logMsg("Albert, got AF_INCOMING_MSG for Endpoint 0x" + imDstEndp.ToString("X") + " and ClusterID 0x" + imCluster.ToString("X") );
    	  //logMsg("Albert, got AF_INCOMING_MSG with NWK-SeqNumber " + inMsgDat.TransSeqNumber +" ??stimmt glaub ich nicht, ist immer 0 ??!)");  //ToDo: check with Sniffer, da wird etwas anderes angezeigt!
          processIncomingZCLMsg(comm);
          break;
          
        }
    
        case MESSAGE_ID.AF_DATA_RETRIEVE_SRSP:
        {
          var afRetrieveRsp : AF_DATA_RETRIEVE_SRSP = msg;
    
          if (afRetrieveRsp.Status == SUCCESS)
          {
            var index = retrieveIdx;
    
            for (var idx = 0; idx < afRetrieveRsp.Length; idx++, index++)
            {
              retrieveBuf[index] = afRetrieveRsp.Data[idx];
            }
    
            gotAfRetrieveRsp = true;
          }
          break;
        }
    
        case MESSAGE_ID.APP_CNF_BDB_COMMISSIONING_NOTIFICATION:
        {
            var commissionRsp : APP_CNF_BDB_COMMISSIONING_NOTIFICATION = msg;
            if (commissionRsp.Status == SUCCESS)
            {
                gotBDBcommissioningSuccess = true;
                logMsg("Albert, got APP_CNF_BDB_COMMISSIONING_NOTIFICATION with Status " + commissionRsp.Status);
            }else{
                logMsg("Albert, got APP_CNF_BDB_COMMISSIONING_NOTIFICATION with Status " + commissionRsp.Status);
            }
            break;
        } 
        case MESSAGE_ID.ZDO_NODE_DESC_RSP:
        {
            var NodeDescRsp : ZDO_NODE_DESC_RSP = msg;
            logMsg("Albert, got ZDO_NODE_DESC_RSP from 0x" + NodeDescRsp.NwkAddr.ToString("X"));        
            break;
        }
        case MESSAGE_ID.ZDO_MGMT_PERMIT_JOIN_RSP:
        {
            var zdoMgmtPermitJoinRsp : ZDO_MGMT_PERMIT_JOIN_RSP = msg;
            logMsg("Albert, got ZDO_MGMT_PERMIT_JOIN_RSP from 0x" + zdoMgmtPermitJoinRsp.SrcAddr.ToString("X"));        
            break;
        }
        
        default:
        logMsg("Albert, received unhandled messageID: " + id + " with message:" + msg);
          break;
        }
      }
    //################################################################################################################  
    //############ END OF INCOMING MESSAGE HANDLER ###################################################################
    //################################################################################################################
    
      // Send a ZB_SYSTEM_RESET message until success.
      function sysReset(comm : String)
      {
        //var req : ZB_SYSTEM_RESET = new ZB_SYSTEM_RESET();  alter Befehl???
        var req : SYS_RESET = new SYS_RESET();
        gotRstRsp = false;
        while (!gotRstRsp)
        {
          //logMsg("ZB_SYSTEM_RESET  to " + comm);  alt
          //logMsg("SYS_RESET  to " + comm);
          ZEngine.Send(comm, req);
          ZEngine.Pause(800);
    
          // Sending SYS_STACK_TUNE as a way to get a 0x07 byte to the SBL before a 0xF8 byte.
          // An 0x07 byte forces the immediate run of valid code.
          //sysStackTune(comm, 7, 7);
          //ZEngine.Pause(300);
        }
        //logMsg("und aus...");
      }
    
      // Send a SYS_STACK_TUNE message.
      function sysStackTune(comm : String, Operation: Byte, Value: Byte)
      {
        var req : SYS_STACK_TUNE = new SYS_STACK_TUNE();
        req.Operation = Operation;
        req.Value = Value;
    
        logMsg("SYS_STACK_TUNE to " + comm);
        ZEngine.Send(comm, req);
      }
    
    
      // Send a SYS_OSAL_NV_WRITE message.
      // (alt: Send a ZB_WRITE_CONFIGURATION message.)
      function writeCfg(comm : String, cfgId : Byte, len : Byte,  value : Array )
      {
        var req : SYS_OSAL_NV_WRITE = new SYS_OSAL_NV_WRITE();
        //var req : ZB_WRITE_CONFIGURATION = new ZB_WRITE_CONFIGURATION();
        //req.ConfigId = cfgId;
        req.Id = cfgId;
        req.Len = len;
        req.Offset = 0; //hardcoded by Albert
        req.Value = new byte[len];
    
        for (var idx = 0; idx < len; idx++)
        {
          req.Value[idx] = value[idx];
        }
        gotCfgRsp = false;
        while (!gotCfgRsp)
        {
          //logMsg("ZB_WRITE_CONFIGURATION  to " + comm);
          logMsg("SYS_OSAL_NV_WRITE  to " + comm);
          ZEngine.Send(comm, req);
          ZEngine.Pause(200);
        }
      }
    
    
      // Send a ZB_AF_REGISTER_REQUEST message.  (für gleiches Verhalten wie bei zed_sampleswitch-example)
      function afRegisterRequest_FirstEndpoint(comm : String) // zuvor function afReg(comm : String)
      {
        var req : AF_REGISTER  = new AF_REGISTER ();
        req.EndPoint = sourceEndpoint_ep1; //self-defined by user
        req.AppProfID = ZCL_HA_PROFILE_ID; //zuvor profileId
        //req.AppDeviceId = ZCL_HA_DEVICEID_ON_OFF_LIGHT; 
        req.AppDeviceId = ZCL_HA_DEVICEID_ON_OFF_LIGHT_SWITCH;  //für Switch !!
        req.AppDevVer = 1;
     
        //set up clusters for switch (wie bei zed_sampleswitch-example)
        req.AppNumInClusters = inClusterCnt_ep1;
        inClusterList_ep1[0] = ZCL_CLUSTER_ID_GEN_BASIC; //0 //ZCL_CLUSTER_ID_GEN_BASIC,  see zcl.h
        inClusterList_ep1[1] = ZCL_CLUSTER_ID_GEN_IDENTIFY;
        
        req.AppNumOutClusters = outClusterCnt_ep1;
        outClusterList_ep1[0] = ZCL_CLUSTER_ID_GEN_IDENTIFY; // see zcl.h
        outClusterList_ep1[1] = ZCL_CLUSTER_ID_GEN_ON_OFF; 
        outClusterList_ep1[2] = ZCL_CLUSTER_ID_GEN_GROUPS; 
                         
        req.AppInClusterList = inClusterList_ep1;
        req.AppOutClusterList = outClusterList_ep1;
                         
        gotRegRsp = false;
        while (!gotRegRsp)
        {
          logMsg("ZB_AF_REGISTER_REQUEST to " + comm);
          ZEngine.Send(comm, req);
          ZEngine.Pause(200);
        }
      }
      
        // Send a ZB_AF_REGISTER_REQUEST message.  
      function afRegisterRequest_FirstEndpoint_PhilipsRWL021(comm : String) // zuvor function afReg(comm : String)
      {
        var req : AF_REGISTER  = new AF_REGISTER ();
        req.EndPoint = sourceEndpoint_ep1_PhilipsRWL021;
        req.AppProfID = ZCL_HA_PROFILE_ID; //zuvor profileId
        req.AppDeviceId = ZCL_HA_DEVICEID_ON_OFF_LIGHT;  //zuvor devId;
        req.AppDevVer = 0;
    
        //set up clusters for light
        // inClusterList[0] = 0; //ZCL_CLUSTER_ID_GEN_BASIC,  see zcl.h
        // inClusterList[1] = 3; //ZCL_CLUSTER_ID_GEN_IDENTIFY
        // inClusterList[2] = 4; //ZCL_CLUSTER_ID_GEN_GROUPS
        // inClusterList[3] = 5; //ZCL_CLUSTER_ID_GEN_SCENES
        // inClusterList[4] = 6; //ZCL_CLUSTER_ID_GEN_ON_OFF
    
        // outClusterList[0] = 0; //ZCL_CLUSTER_ID_GEN_BASIC, see zcl.h
        
        //set up clusters for switch (wie bei Philips Hue Dimmer)
        req.AppNumInClusters = inClusterCnt_ep1;
        inClusterList_ep1[0] = ZCL_CLUSTER_ID_GEN_BASIC; //0 //ZCL_CLUSTER_ID_GEN_BASIC,  see zcl.h
        
        req.AppNumOutClusters = outClusterCnt_ep1;
        outClusterList_ep1[0] = ZCL_CLUSTER_ID_GEN_BASIC; //ZCL_CLUSTER_ID_GEN_BASIC (0x0), see zcl.h
        outClusterList_ep1[1] = ZCL_CLUSTER_ID_GEN_IDENTIFY; //ZCL_CLUSTER_ID_GEN_IDENTIFY (0x3)
        outClusterList_ep1[2] = ZCL_CLUSTER_ID_GEN_GROUPS; //ZCL_CLUSTER_ID_GEN_GROUPS (0x4)
        outClusterList_ep1[3] = ZCL_CLUSTER_ID_GEN_ON_OFF; //ZCL_CLUSTER_ID_GEN_ON_OFF (0x6)
        outClusterList_ep1[4] = ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL; //ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL (0x8)
        outClusterList_ep1[5] = ZCL_CLUSTER_ID_GEN_SCENES; //ZCL_CLUSTER_ID_GEN_SCENES (0x5)
                         
        req.AppInClusterList = inClusterList_ep1;
        req.AppOutClusterList = outClusterList_ep1;
                         
        gotRegRsp = false;
        while (!gotRegRsp)
        {
          logMsg("ZB_AF_REGISTER_REQUEST to " + comm);
          ZEngine.Send(comm, req);
          ZEngine.Pause(200);
        }
      }
      
      function afRegisterRequest_SecondEndpoint_PhilipsRWL021(comm : String)
      {
        var req : AF_REGISTER  = new AF_REGISTER ();
        req.EndPoint = sourceEndpoint_ep2_PhilipsRWL021;
        req.AppProfID = ZCL_HA_PROFILE_ID;
        req.AppDeviceId = ZCL_HA_DEVICEID_SIMPLE_SENSOR; 
        req.AppDevVer = 0;
            
        //set up clusters for switch (wie bei Philips Hue Dimmer)
        req.AppNumInClusters = inClusterCnt_ep2; 
        inClusterList_ep2[0] = ZCL_CLUSTER_ID_GEN_BASIC; //ZCL_CLUSTER_ID_GEN_BASIC (0x0), see zcl.h
        inClusterList_ep2[1] = ZCL_CLUSTER_ID_GEN_POWER_CFG;
        inClusterList_ep2[2] = ZCL_CLUSTER_ID_GEN_IDENTIFY;
        inClusterList_ep2[3] = ZCL_CLUSTER_ID_GEN_BINARY_INPUT_BASIC;
        inClusterList_ep2[4] = 0xFC00; //reserved, siehe Sniffer-Log von echtem Hue Dimmer
        
        req.AppNumOutClusters = outClusterCnt_ep2;
        outClusterList_ep2[0] = ZCL_CLUSTER_ID_OTA; 
                
        req.AppInClusterList = inClusterList_ep2;
        req.AppOutClusterList = outClusterList_ep2;
        
        gotRegRsp = false;
        while (!gotRegRsp)
        {
          logMsg("ZB_AF_REGISTER_REQUEST to " + comm);
          ZEngine.Send(comm, req);
          ZEngine.Pause(200);
        }
      }
    
    
      // Send a ZDO_STARTUP_FROM_APP  message. ( old: Send a ZB_START_REQUEST message.)
      function startReq(comm : String)
      {
        var req : ZDO_STARTUP_FROM_APP  = new ZDO_STARTUP_FROM_APP(); //old: var req : ZB_START_REQUEST  = new ZB_START_REQUEST();
        gotStateRsp = false; //wird in callback ZDO_STATE_CHANGE_IND auf 1 gesetzt, falls z.B. zdoStateInd.State == 7 ist (als Router erfolgreich gejoined)
                            //ToDo Albert: wäre das auch mit Flag gotBDBcommissioningSuccess möglich???
        while (!gotStateRsp)
        {
          gotStartRsp = false;
          while (!gotStartRsp)
          {
            //alt: logMsg("ZB_START_REQUEST  to " + comm);
            logMsg("Albert, issue ZDO_STARTUP_FROM_APP");
            ZEngine.Send(comm, req);
            ZEngine.Pause(1000);
          }
          ZEngine.Pause(5000);  //wichtig, hier so lange warten damit erfolgreiches joinen möglich ist (gotStateRsp sollte idealerweise danach bereits auf 1 sein, sonst wird nocheinmal  ZDO_STARTUP_FROM_APP getriggert)
                                //äussere while-loop sollte wenn möglich nur 1x durchlaufen werden
                                //-> in der Zwischenzeit sollte normalerweise eine  APP_CNF_BDB_COMMISSIONING_NOTIFICATION empfangen worden sein
          
        }
      }
    
      
      
    
      /* Make a huge data request via an AF_DATA_REQUEST_EXT message and store the huge data.
       * Since the max MT payload is 250 & the store message header is 3, the max bytes per store
       * is 247. So to simplify the script just use 3 X 247 = 741.
       * Note that we are simultaneously proving the max capacity of 250 bytes per MT message here.
       */
      function afDataReqFrag(comm : String)
      {
        // var req : AF_DATA_REQUEST_EXT = new AF_DATA_REQUEST_EXT();
    
        // req.DstAddrMode = 2;  // Addr16Bit = 2
        // req.DstAddr[0] = 0; req.DstAddr[1] = 0;  // Short address 0x0000 is for ZC.
        // req.DstEndPoint = coord_endPoint;
        // req.DstPanId = 0;  // Zero signifies not Inter-PAN.
        // req.SrcEndpoint = coord_endPoint;
        // req.ClusterID = 1;  // Startup initialization makes cluster Id's 1,2,3... up to count.
        // req.TransID = 0;  // Trans Id is a don't care.
        // req.Options = 0;  // AF_TX_OPTIONS_NONE = 0
        // req.Radius = 15;  // AF_DEFAULT_RADIUS = 15
        // req.Len = retrieveTot;
    
        // gotAfReqExtRsp = false;
        // while (!gotAfReqExtRsp)
        // {
          // logMsg("AF_DATA_REQUEST_EXT to " + comm);
          // ZEngine.Send(comm, req);
          // ZEngine.Pause(3000);
        // }
    
        // var index : UInt16 = 0;
        // var fragLen : Byte = retrieveLen;
        // var fragBuf : Byte[] = new Byte[fragLen];
        // for (var idx = 0; idx < fragLen; idx++)
        // {
          // fragBuf[idx] = idx;
        // }
        // afDataStore(comm, index, fragLen, fragBuf);
        // index += fragLen;
    
        //Change the frag data to enhance verification reliability on Rx.
        // for (idx = 0; idx < fragLen; idx++)
        // {
          // fragBuf[idx]++;
        // }
        // afDataStore(comm, index, fragLen, fragBuf);
        // index += fragLen;
    
        //Change the frag data again to enhance verification reliability on Rx.
        // for (idx = 0; idx < fragLen; idx++)
        // {
          //Without a type-cast, the script promotes fragBuf[] to int at run-time.
          // fragBuf[idx] = (Byte)(idx * 2);
        // }
        // afDataStore(comm, index, fragLen, fragBuf);
    
        //A store of zero length indicates to send it OTA.
        // afDataStore(comm, 0, 0, fragBuf);
      }
    
    
      // Send a AF_DATA_STORE message.
      function afDataStore(comm : String, index : UInt16, len : Byte, buf : Byte[])
      {
        var req : AF_DATA_STORE = new AF_DATA_STORE();
    
        req.Index = index;
        req.Length = len;
    
        for (var idx = 0; idx < len; idx++)
        {
          req.Data[idx] = buf[idx];
        }
    
        gotAfStoreRsp = false;
        while (!gotAfStoreRsp)
        {
          logMsg("AF_DATA_STORE to " + comm);
          ZEngine.Send(comm, req);
          ZEngine.Pause(100);
        }
      }
    
    
      // Send a series of AF_DATA_RETRIEVE message(s) to get the data of an incoming huge message.
      function afDataRetrieve(comm : String, msgIn : AF_INCOMING_MSG_EXT)
      {
        var req : AF_DATA_RETRIEVE = new AF_DATA_RETRIEVE();
    
        req.Timestamp = msgIn.Timestamp;
        req.Length = retrieveLen;
    
        for (retrieveIdx = 0; retrieveIdx < msgIn.Len; retrieveIdx += retrieveLen)
        {
          req.Index = retrieveIdx;
    
          gotAfRetrieveRsp = false;
          while (!gotAfRetrieveRsp)
          {
            logMsg("AF_DATA_RETRIEVE to " + comm);
            ZEngine.Send(comm, req);
            ZEngine.Pause(100);
          }
        }
    
        /* Retrieve request with zero length indicates to flush the message and free the dynamic
         * memory. If this request fails, the device times out the incoming huge message buffer and
         * flushes it automatically, so no loop here.
         */
        req.Length = 0;
        logMsg("AF_DATA_RETRIEVE to " + comm);
        ZEngine.Send(comm, req);
        ZEngine.Pause(100);
      }
    
    
      // Verify the data in the global retrieveBuf[] according to what was sent in afDataReqFrag().
      function verifyMsgIn() : boolean
      {
        /* At first writing of this script, the afDataReqFrag() sent 741 bytes.
         * The first 247 bytes were 0-247; the next 247 bytes were 1-248; and the last 247 bytes were
         * calculated as twice the corresponding index.
         */
        var index = 0;
    
        for (var idx = 0; idx < retrieveLen; idx++, index++)
        {
          if (retrieveBuf[index] != idx)
          {
            break;
          }
        }
    
        for (var idx = 1; idx <= retrieveLen; idx++, index++)
        {
          if (retrieveBuf[index] != idx)
          {
            break;
          }
        }
    
        for (var idx = 0; idx < retrieveLen; idx++, index++)
        {
          if (retrieveBuf[index] != (Byte)(idx * 2))
          {
            break;
          }
        }
    
        if (index < retrieveTot)
        {
          return false;
        }
        else
        {
          return true;
        }
      }
    
    
      // Display a log message if log messages are enabled.
      function logMsg(theMsg : String)
      {
        if (showLogMsgs)
        {
          ZEngine.WriteLog(theMsg);  // Display the message.
        }
      }
    } // End of TheScript class.
    
    
    // The script engine will execute the following code.
    var script:TheScript = new TheScript();
    script.run();
    
    
    /**************************************************************************************************
    */