1.5.3 Using the AL Module
The following code shows a basic example on how to use Meters And More AL:
// ***************************************************************************** // ***************************************************************************** // Section: Global Data Definitions // ***************************************************************************** // ***************************************************************************** static const uint8_t appDataTxDataBuffer[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; APP_DATA appData; // ***************************************************************************** // ***************************************************************************** // Section: Application Callback Functions // ***************************************************************************** // ***************************************************************************** static void APP_AL_DataIndication_callback(AL_DATA_IND_PARAMS *indParams) { AL_IB_VALUE ibValue; SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AL_DATA_INDICATION: DSAP=0x%02X, ECC=0x%02X, SrcAddr=0x%02X%02X%02X%02X%02X%02X, ATTR=%hhu, APDU=0x", indParams->dsap, indParams->ecc, indParams->srcAddress.address[0], indParams->srcAddress.address[1], indParams->srcAddress.address[2], indParams->srcAddress.address[3], indParams->srcAddress.address[4], indParams->srcAddress.address[5], indParams->attr); for (uint8_t i = 0; i < indParams->apduLen; i++) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "%02X", indParams->apdu[i]); } SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "\r\n"); if (indParams->dsap == DLL_DSAP_APPLICATION_FRAME) { if (indParams->rxStatus == AL_RX_STATUS_ERROR_BAD_TMAC) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "TMAC Error\r\n"); } else if (indParams->rxStatus == AL_RX_STATUS_ERROR_AES_NO_KEY) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Error No Decryption Key\r\n"); } else if (indParams->rxStatus == AL_RX_STATUS_ERROR_AES_DECRYPT) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Decryption Error\r\n"); } else if (indParams->rxStatus == AL_RX_STATUS_ERROR_AES_CMAC) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Authentication Error\r\n"); } else if (indParams->rxStatus == AL_RX_STATUS_ERROR_BAD_LEN) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Error Bad Length\r\n"); } else { /* Update LMON to received value */ appData.drParams.lmon = indParams->lmon; if ((indParams->attr == AL_MSG_READ_RESP) || (indParams->attr == AL_MSG_READ_RESP_AUTH)) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Read Response Frame received\r\n"); } else { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Application Frame command not recognized\r\n"); } } } else if (indParams->dsap == DLL_DSAP_NETWORK_MANAGEMENT) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Network Management Frame: "); if (indParams->attr == AL_MSG_ADDRESS_RESP) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "ADDRESS RESPONSE\r\n"); } else if (indParams->attr == AL_MSG_REQADDR_RESP) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "REQ ADDRESS RESPONSE\r\n"); } else { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Command not recognized\r\n"); } } else { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "DSAP not recognized\r\n"); } } static void APP_AL_DataConfirm_callback(AL_DATA_CONFIRM_PARAMS *cfmParams) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AL_DATA_CONFIRM: Result=%hhu DSAP=0x%02X, ECC=0x%02X, DestAddr=0x%02X%02X%02X%02X%02X%02X\r\n", cfmParams->txStatus, cfmParams->dsap, cfmParams->ecc, cfmParams->dstAddress.address[0], cfmParams->dstAddress.address[1], cfmParams->dstAddress.address[2], cfmParams->dstAddress.address[3], cfmParams->dstAddress.address[4], cfmParams->dstAddress.address[5]); } static void APP_AL_EventIndication_callback(AL_EVENT_IND_PARAMS *indParams) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AL_EVENT_INDICATION: Id=0x%02X, Value=0x", indParams->eventId); for (uint8_t i = 0; i < indParams->eventValue.length; i++) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "%02X", indParams->eventValue.value[i]); } SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "\r\n"); } // ***************************************************************************** // ***************************************************************************** // Section: Application Initialization and State Machine Functions // ***************************************************************************** // ***************************************************************************** void APP_Initialize ( void ) { /* IDLE state is used to signal when application is started */ appData.state = APP_STATE_INIT; /* Init Timer handler */ appData.tmr1Handle = SYS_TIME_HANDLE_INVALID; appData.tmr2Handle = SYS_TIME_HANDLE_INVALID; appData.tmr1Expired = false; appData.tmr2Expired = false; /* Configure DLL Data Request parameters */ appData.drParams.ecc = DLL_ECC_AES_CTR_READ_KEY; appData.drParams.lmon = 0ULL; appData.drParams.apdu = (uint8_t *)appDataTxDataBuffer; appData.drParams.apduLen = sizeof(appDataTxDataBuffer); appData.drParams.dsap = DLL_DSAP_APPLICATION_FRAME; appData.drParams.serviceClass = SERVICE_CLASS_S; appData.drParams.attr = AL_MSG_COMMAND_AUTH; appData.drParams.dstAddress.routeSize = 1; /* First Address in the route */ appData.drParams.dstAddress.macAddress[0].address[0] = 0x11; appData.drParams.dstAddress.macAddress[0].address[1] = 0x22; appData.drParams.dstAddress.macAddress[0].address[2] = 0x33; appData.drParams.dstAddress.macAddress[0].address[3] = 0x44; appData.drParams.dstAddress.macAddress[0].address[4] = 0x55; appData.drParams.dstAddress.macAddress[0].address[5] = 0x66; } void APP_Tasks ( void ) { /* Refresh WDG */ CLEAR_WATCHDOG(); /* Check the application's current state. */ switch ( appData.state ) { case APP_STATE_INIT: { AL_DataIndicationCallbackRegister(APP_AL_DataIndication_callback); AL_DataConfirmCallbackRegister(APP_AL_DataConfirm_callback); AL_EventIndicationCallbackRegister(APP_AL_EventIndication_callback); /* Set MAC address */ const AL_IB_VALUE value = { .length = 6, .value = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00} }; AL_SetRequest(AL_MAC_ACA_ADDRESS_IB, 0, &value); #if defined(TEST_USE_ENCRYPTION) /* Set Keys */ const AL_IB_VALUE valueK1 = { .length = 16, .value = {0x64, 0x25, 0x77, 0xB3, 0x98, 0x2E, 0x43, 0xAA, 0xF5, 0x35, 0x33, 0x59, 0x74, 0x4D, 0x06, 0x1D} }; AL_SetRequest(AL_AUTH_WRITE_KEY_K1_IB, 0, &valueK1); const AL_IB_VALUE valueK2 = { .length = 16, .value = {0xA0, 0xEE, 0x4C, 0xED, 0x9A, 0x01, 0x59, 0x3C, 0x5C, 0xA7, 0x78, 0xA2, 0xDD, 0x13, 0x34, 0xD2} }; AL_SetRequest(AL_AUTH_READ_KEY_K2_IB, 0, &valueK2); #endif appData.state = APP_STATE_WAIT_AL_READY; break; } case APP_STATE_WAIT_AL_READY: { if (AL_GetStatus() == SYS_STATUS_READY) { appData.state = APP_STATE_TX_FRAME; appData.txTimeCount = SYS_TIME_Counter64Get() + SYS_TIME_USToCount(APP_TX_DELAY_US); } break; } case APP_STATE_TX_FRAME: { if (SYS_TIME_Counter64Get() >= appData.txTimeCount) { AL_IB_VALUE valueDestACA = { .length = 6, .value = {0x00} }; /* Reverse ACA for Auth IB */ valueDestACA.value[0] = appData.drParams.dstAddress.macAddress[0].address[5]; valueDestACA.value[1] = appData.drParams.dstAddress.macAddress[0].address[4]; valueDestACA.value[2] = appData.drParams.dstAddress.macAddress[0].address[3]; valueDestACA.value[3] = appData.drParams.dstAddress.macAddress[0].address[2]; valueDestACA.value[4] = appData.drParams.dstAddress.macAddress[0].address[1]; valueDestACA.value[5] = appData.drParams.dstAddress.macAddress[0].address[0]; AL_SetRequest(AL_AUTH_DESTINATION_NODE_ACA_IB, 0, &valueDestACA); SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AL_DATA_REQUEST ATTR=%hhu, APDU=0x", appData.drParams.attr); for (uint8_t i = 0; i < appData.drParams.apduLen; i++) { SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "%02X", appData.drParams.apdu[i]); } SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "\r\n"); AL_DataRequest(&appData.drParams); appData.state = APP_STATE_WAITING; } break; } case APP_STATE_WAITING: { break; } /* The default state should never be executed. */ default: { break; } } }
