Request-Respond commnication of Jennic WSN.
1. Register Simple Description with one Input Cluster at the Receiver point.
2. Use afdeDataRequest with transaction.uFrame.sKvp.eCommandTypeID = SET_ACKNOWLEDGMENT, ACKNOWLEDGED_TRANSMISSION(OR with APS_TXOPTION_NONE) param and at the Sender point.
3. Make sure JZA_bAfKvpObject return TRUE, at the Receiver point.
When the KVP message which the Sender sent, arrived the Receiver point, a response message will be send to the Sender by the protocol stack automatically, to tell the Sender the KVP message has been received by the Receiver.
--------------------------------------------------------------Code---------------------------------------------------------------------------------------------
Sender point:
PRIVATE
void
vSendFrame(
void
)
{
uint8 u8SrcEP = ROUTE_ENDPOINT;
APS_Addrmode_e eAddrMode;
uint16 u16DestAddr;
uint8 u8DestEndpoint;
uint8 transCount = 1;
int i = 0;
PRIVATE AF_Transaction_s Transaction;
PRIVATE uint8 au8Afdu[10];
/**//*for (i = 0; i < 10; i++)
{
au8Afdu[i] = i;
}*/
for (i = 10; i > 0; i--)
{
au8Afdu[10-i] = i;
}
/**//* specify destination node short address and endpoint */
eAddrMode = APS_ADDRMODE_SHORT;
u16DestAddr = 0x0000;
u8DestEndpoint = COORDINATOR_ENDPOINT;
/**//* specify the transaction sequence number */
Transaction.u8SequenceNum = 0;
/**//* We want to send data to an input, so use the SET command type */
Transaction.uFrame.sKvp.eCommandTypeID = SET_ACKNOWLEDGMENT;
Transaction.uFrame.sKvp.eAttributeDataType = KVP_CHARACTER_STRING;
/**//* use the DATA attribute for a Data cluster, as specified in the
profile defined for this application */
Transaction.uFrame.sKvp.u16AttributeID = CLUSTERIDT_DATA;
Transaction.uFrame.sKvp.eErrorCode = KVP_SUCCESS;
memcpy(&Transaction.uFrame.sKvp.uAttributeData.CharacterString.au8CharacterData, au8Afdu, 10);
Transaction.uFrame.sKvp.uAttributeData.CharacterString.u8CharacterCount = 10;
/**//* send KVP data request */
afdeDataRequest(eAddrMode,
u16DestAddr,
u8DestEndpoint,
u8SrcEP,
PROFILE_ID,
CLUSTERID,
AF_KVP,
transCount,
&Transaction,
ACKNOWLEDGED_TRANSMISSION, //APS_TXOPTION_NONE,
ENABLE_ROUTE_DISCOVERY,
0);
static bool bSendSigned = TRUE;
vLedControl(1, bSendSigned);
bSendSigned = !bSendSigned;
return;
}
Get the Respond:
/**/
/****************************************************************************
*
* NAME: JZA_vAfKvpResponse
*
* DESCRIPTION:
* Called after a KVP transaction with acknowledgement request, when the
* acknowledgement arrives. *
* PARAMETERS: Name RW Usage
* srcAddressMod R Address of sender device
* transactionSequenceNum R KVP transaction number
* commandTypeIdentifier R KVP command type
* dstEndPoint R Endpoint at receiver
* clusterID R Cluster ID
* attributeIdentifier R KVP attribute ID
* errorCode R Result code
* afduLength R Length of payload data
* pAfdu R Payload data array
*
****************************************************************************/
PUBLIC
void
JZA_vAfKvpResponse(
APS_Addrmode_e eAddrMode,
uint16 u16AddrSrc,
uint8 u8SrcEP,
uint8 u8LQI,
uint8 u8DstEP,
uint8 u8ClusterID,
AF_Transaction_s
*
puTransactionInd)
{
static bool bResponseSigned = TRUE;
vLedControl(0, bResponseSigned);
bResponseSigned = !bResponseSigned;
return;
}
Receiver point:
Register simple description.
PRIVATE
void
vAddDesc(
void
)
{
/**//* Controller has 1 endpoints, with 1 input and 1 output clusters */
uint8 u8DeviceVer = 0x00;
uint8 u8Flags = 0x00;
uint8 u8EndPoint = COORDINATOR_ENDPOINT;
uint16 u16DeviceId = 0x0000;
/**//* use the same cluster ID for the input and output clusters. This means
that the output cluster from one node will match the input cluster of the
other node */
uint8 u8InputClusterCnt = 1;
uint8 au8InputClusterList[] = {CLUSTERID};
uint8 u8OutputClusterCnt = 0;
uint8 au8OutputClusterList[] = {};//{CLUSTERID};
(void)afmeAddSimpleDesc(u8EndPoint, PROFILE_ID, u16DeviceId,
u8DeviceVer, u8Flags, u8InputClusterCnt,
au8InputClusterList, u8OutputClusterCnt,
au8OutputClusterList);
}
Recv KVP message:
/**/
/****************************************************************************
*
* NAME: JZA_eAfKvpObject
*
* DESCRIPTION:
* Called when a KVP transaction has been received with a matching endpoint.
*
* PARAMETERS: Name RW Usage
* afSrcAddr R Address of sender device
* u8DstEndpoint R Endpoint at receiver
* pu8ClusterId R Pointer to cluster ID
* eCommandTypeId R KVP command type
* u16AttributeId R KVP attribute ID
* pu8AfduLength R Pointer to length of data
* pu8Afdu R Data array
*
* RETURNS:
* AF_ERROR_CODE
*
****************************************************************************/
PUBLIC bool_t JZA_bAfKvpObject(APS_Addrmode_e eAddrMode,
uint16 u16AddrSrc,
uint8 u8SrcEP,
uint8 u8LQI,
uint8 u8DstEP,
uint8 u8ClusterId,
uint8
*
pu8ClusterIDRsp,
AF_Transaction_s
*
puTransactionInd,
AF_Transaction_s
*
puTransactionRsp)
{
uint8 u8Length;
uint8 *pu8Afdu;
static bool bRecvFlag = TRUE;
bool_t bReturnVal = FALSE;
if (puTransactionInd->uFrame.sKvp.eCommandTypeID == SET_ACKNOWLEDGMENT)
{
bReturnVal = TRUE;
}
// check command frame is valid and for correct endpoint
if ( (eAddrMode != APS_ADDRMODE_SHORT)
|| (u8DstEP != COORDINATOR_ENDPOINT))
{
puTransactionRsp->uFrame.sKvp.eErrorCode = KVP_INVALID_ENDPOINT;
return bReturnVal;
}
// only accept SET commands
if ( (puTransactionInd->uFrame.sKvp.eCommandTypeID != SET)
&& (puTransactionInd->uFrame.sKvp.eCommandTypeID != SET_ACKNOWLEDGMENT))
{
puTransactionRsp->uFrame.sKvp.eErrorCode = KVP_INVALID_COMMAND_TYPE;
return bReturnVal;
}
u8Length = puTransactionInd->uFrame.sKvp.uAttributeData.CharacterString.u8CharacterCount;
pu8Afdu = puTransactionInd->uFrame.sKvp.uAttributeData.CharacterString.au8CharacterData;
// Extract data and send to UART
if (puTransactionInd->uFrame.sKvp.u16AttributeID == CLUSTERIDT_DATA)
{
vLedControl(1, bRecvFlag);
bRecvFlag = !bRecvFlag;
vSerial_Send(pu8Afdu, u8Length);
puTransactionRsp->uFrame.sKvp.eErrorCode = KVP_SUCCESS;
}
else
{
puTransactionRsp->uFrame.sKvp.eErrorCode = KVP_UNSUPPORTED_ATTRIBUTE;
}
return bReturnVal;
}
--------------------------------------------------
Fine day!