Part Number: AM2434
Hello,
I'm having issue with callback for assembly set. Assembly is configurated to have 32bit Run/Idle header to detect Idle state. During run state callback is handled without issue and I can handle data I got from PLC. But during idle state, callback is called once and never again even if I switch to run and back to idle. As I tryed to understand code for discrete IO example, I didn't see any flags to clead or special methods to call for Idle handling. Could you point me in right direction to make callback being called during Idle state?
Here is my assembly creation:
static uint32_t createAsmOutput(EI_API_CIP_NODE_T* pCipNode) {
uint32_t errCode = EI_API_CIP_eERR_OK;
uint16_t len;
EI_API_CIP_SAssemCustomMap_t assembCustomMapCfg = {0};
errCode = EI_API_CIP_createAssembly(pCipNode, DEVICE_asmCfgParam.asmOutputInst, EI_API_CIP_eAR_GET_AND_SET);
if (errCode != EI_API_CIP_eERR_OK) {
OSAL_printf("Error: %s:%d ErrCode:0x%08X\r\n", __FILE__, __LINE__, errCode);
return errCode;
}
errCode = EI_API_CIP_setAssemblyFormat(pCipNode, DEVICE_asmCfgParam.asmOutputInst, ASSEMB_FORMAT_32BITHEADER);
if (errCode != EI_API_CIP_eERR_OK) {
OSAL_printf("Error: %s:%d ErrCode:0x%08X\r\n", __FILE__, __LINE__, errCode);
return errCode;
}
assembCustomMapCfg.assemblyMemberLength =DEVICE_asmCfgParam.asmOutputLen;
assembCustomMapCfg.mappedClassId = DEVICE_PROFILE_CIP_CLASS_ID_SOLENOID;
assembCustomMapCfg.mappedInstanceId = DEVICE_PROFILE_CIP_INSTANCE_ID_01;
assembCustomMapCfg.mappedAttributeId = k_INST_ATTR_ID_SOLENOID_VALUE;
assembCustomMapCfg.fuCustomGet = cbGetCustomMapAsmOut;
assembCustomMapCfg.fuCustomSet = cbSetCustomMapAsmOut;
errCode = EI_API_CIP_addAssemblyMemberCustomMapped(pCipNode, DEVICE_asmCfgParam.asmOutputInst, &assembCustomMapCfg);
if (errCode != EI_API_CIP_eERR_OK) {
OSAL_printf("Error: %s:%d ErrCode:0x%08X\r\n", __FILE__, __LINE__, errCode);
return errCode;
}
EI_API_CIP_getAssemblySize(pCipNode, DEVICE_asmCfgParam.asmOutputInst, &len);
if (len != DEVICE_asmCfgParam.asmOutputLen) {
OSAL_printf("Wrong assembly output length!\r\n");
return -1;
}
return errCode;
}
and here is handling of set callback:
static EI_API_CIP_EAssemb_Return_Code_t cbSetCustomMapAsmOut(EI_API_CIP_SAssemMapData_t* pAttrMapData, const EI_API_CIP_STransferBuffer_t* pConsumeBuffer) {
EI_API_CIP_EAssemb_Return_Code_t retValue = ASSEMB_SERVICE_NO_RESPONSE;
uint16_t dataLen;
OSAL_printf("ASM data set\r\n");
if (DEVICE_PROFILE_CIP_CLASS_ID_SOLENOID != pAttrMapData->classId) {
return retValue;
}
if (pAttrMapData->instanceId > 0) {
if (k_INST_ATTR_ID_SOLENOID_VALUE == pAttrMapData->attributeId)
{
OSAL_printf("ASM data set\r\n");
if(pConsumeBuffer->p8uDataBuf[0] == 0) //Idle state
{
OSAL_printf("Idle Detected\r\n");
if(ConnectionIdle == false)
{
// change state from run to idle
DEVICE_receiveConnectionEvent(pAttrMapData->attributeId, DEVICE_CONNECTION_DELETED);
}
ConnectionIdle = true;
retValue = ASSEMB_SERVICE_RESPONSE_OK;
}
else
{
if(ConnectionIdle == true)
{
// change state from idle to run
DEVICE_receiveConnectionEvent(pAttrMapData->attributeId, DEVICE_CONNECTION_ESTABLISHED_IO);
}
ConnectionIdle = false;
dataLen = pConsumeBuffer->u16uMaxData;
if (dataLen > MAX_SOLENOID_BYTES) {
dataLen = MAX_SOLENOID_BYTES;
}
OSAL_MEMORY_memcpy(ab_BitMapSolenoidValue, pConsumeBuffer->p8uDataBuf + 4, dataLen); // +4 for header
retValue = ASSEMB_SERVICE_RESPONSE_OK;
}
}
}
return retValue;
}
DEVICE_receiveConnectionEvent only change state machite to determine which values should by used for output to either Run or Idle.
Thank you for help.
Best regards,
Jan



