⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecinterface.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 3 页
字号:
	SUB_MALLOC( aInstance->itsAttributes, t_Attribute *, theAttributesCount*sizeof( t_Attribute ) );
	aInstance->itsAttributesCount = theAttributesCount;

	/* ! */
	RET(ECI_E_SUCCESS,0);
}

int EC_CreateClassAttribute( unsigned int theClassCode, unsigned char theAttributeCode, unsigned int theIsReadOnly, void *theDataPtr, int theDataSize ){
/*
** create a new Attribute in the Class identified by theClassCode
*/
t_Class     *aClass;
t_Attribute *aAttribute;

	/* ! find Class identified by theClassCode */
	if( (aClass=FindClass( theClassCode ))==NULL )
		RET(gECIError,-1);

	/* ! an AttributeCode of 0 returns the next free Attribute */
	if( (aAttribute=FindClassAttribute( aClass, 0 ))==NULL )
		RET(gECIError,-1);

	/* ! */
	aAttribute->itsAttributeCode = theAttributeCode;
	aAttribute->itsIsReadOnly    = theIsReadOnly;
	aAttribute->itsDataPtr       = theDataPtr;
	aAttribute->itsDataSize      = theDataSize;

	/* ! */
	RET(ECI_E_SUCCESS,0);
}

int EC_CreateInstanceAttribute( unsigned int theClassCode, unsigned int theInstanceCode, unsigned char theAttributeCode, unsigned int theIsReadOnly, void *theDataPtr, int theDataSize ){
/*
** create a new Attribute in the Instance identified by theClassCode and theInstanceCode
*/
t_Class     *aClass;
t_Instance  *aInstance;
t_Attribute *aAttribute;

	/* ! find Class */
	if( (aClass=FindClass( theClassCode ))==NULL )
		RET(gECIError,-1);

	/* ! find Instance */
	if( (aInstance=FindInstance( aClass, theInstanceCode ))==NULL )
		RET(gECIError,-1);

	/* ! an AttributeCode of 0 returns the next free Attribute */
	if( (aAttribute=FindInstanceAttribute( aInstance, 0 ))==NULL )
		RET(gECIError,-1);

	/* ! */
	aAttribute->itsAttributeCode = theAttributeCode;
	aAttribute->itsIsReadOnly    = theIsReadOnly;
	aAttribute->itsDataPtr       = theDataPtr;
	aAttribute->itsDataSize      = theDataSize;

	/* ! */
	RET(ECI_E_SUCCESS,0);
}



int EC_CheckIntegrity( void ){
/*
** ! test the data consistency of the UserDefined Objects
*/
unsigned int c,ia,ca,i;
t_Class     aClass;
t_Instance  aInstance;
#define TEST( item, invalid, err ) { if( (item)==(invalid) ) RET((err),-1); }
#define TEST_ATTRIBUTE(a){\
		TEST( (a).itsAttributeCode,   0, ECI_E_ATTRIBUTECODE_IS_EMPTY );  \
		TEST( (a).itsDataPtr,      NULL, ECI_E_DATAPTR_IS_NULL        );  \
		TEST( (a).itsDataSize,        0, ECI_E_DATASIZE_IS_0          );  \
	}

	/* ! check the user defined assembly object */
	if( gUserDefinedAssembly!=NULL )
		for( i=0; i<gUserDefinedAssembly->itsInstancesCount; i++ )
			TEST( gUserDefinedAssembly->itsInstances[i].itsInstanceNo, 0, ECI_E_USERDEFINEDASSEMBLY_IS_EMPTY );

	/* ! check the user defined objects */
	TEST( gUserDefined, NULL, ECI_E_USERDEFINED_IS_NULL );

	/* ! */
	for( c=0; c<gUserDefined->itsClassesCount; c++ ){

		/* ! */
		aClass = gUserDefined->itsClasses[c];
		TEST( aClass.itsClassCode, 0, ECI_E_CLASSCODE_IS_EMPTY);

		/* ! */
		for( ca=0; ca<aClass.itsAttributesCount; ca++ ){

			/* ! */
			TEST_ATTRIBUTE( aClass.itsAttributes[ca] );


			/* ! */
			for( i=0; i<aClass.itsInstancesCount; i++ ){

				/* ! */
				aInstance = aClass.itsInstances[i];
				TEST( aInstance.itsInstanceCode,   0, ECI_E_INSTANCECODE_IS_EMPTY );

				/* ! */
				for( ia=0; ia<aInstance.itsAttributesCount; ia++ )
					TEST_ATTRIBUTE( aInstance.itsAttributes[ia] );

			}

		}

	}

	/* ! */
	RET(ECI_E_SUCCESS,0);
}

unsigned int GetAttributeByteSize( t_Attribute *theAttribute ){
/*
** return the size of the attribute data in bytes
*/
	/* ! */
	return theAttribute->itsDataSize;
}

unsigned int GetClassAttributesByteSize( t_Class *theClass ){
/*
** return the size of all class attribute data in bytes
*/
unsigned int i;
unsigned int aByteSize;

	/* ! */
	aByteSize = 0;
	for(i=0; i<theClass->itsAttributesCount; i++ )
		aByteSize += theClass->itsAttributes[i].itsDataSize;

	/* ! */
	return aByteSize;
}

void GetSetClassAttributes( int thefGet, unsigned char *theBuf, t_Class *theClass ){
/*
** copy all attribute data betweeen the class and the buffer
*/
unsigned int i, aByteSize;

	/* ! */
	for( i=0; i<theClass->itsAttributesCount; i++ ){
		aByteSize = GetAttributeByteSize( &theClass->itsAttributes[i] );
		if( thefGet )
			memcpy( theBuf, theClass->itsAttributes[i].itsDataPtr, aByteSize );
		else
			memcpy( theClass->itsAttributes[i].itsDataPtr, theBuf, aByteSize );
		theBuf += aByteSize;
	}
}
void    GetClassAttributes(              unsigned char *theBuf, t_Class *theClass ){ GetSetClassAttributes( 1, theBuf, theClass ); }
void    SetClassAttributes(              unsigned char *theBuf, t_Class *theClass ){ GetSetClassAttributes( 0, theBuf, theClass ); }


unsigned int GetInstanceAttributesByteSize( t_Instance *theInstance ){
/*
** return the size of all instance attribute data in bytes
*/
unsigned int i;
unsigned int aByteSize;

	/* ! */
	aByteSize = 0;
	for(i=0; i<theInstance->itsAttributesCount; i++ )
		aByteSize += GetAttributeByteSize( &theInstance->itsAttributes[i] );

	/* ! */
	return aByteSize;
}

void GetSetInstanceAttributes( int thefGet, unsigned char *theBuf, t_Instance *theInstance ){
/*
** copy all attribute data from the Instance to the buffer
*/
unsigned int i, aByteSize;

	/* ! */
	for(i=0; i<theInstance->itsAttributesCount; i++ ){
		aByteSize = GetAttributeByteSize( &theInstance->itsAttributes[i] );
		if( thefGet )
			memcpy( theBuf, theInstance->itsAttributes[i].itsDataPtr, aByteSize );
		else
			memcpy( theInstance->itsAttributes[i].itsDataPtr, theBuf, aByteSize );
		theBuf += aByteSize;
	}
}
void    GetInstanceAttributes(              unsigned char *theBuf, t_Instance *theInstance ){ GetSetInstanceAttributes( 1, theBuf, theInstance ); }
void    SetInstanceAttributes(              unsigned char *theBuf, t_Instance *theInstance ){ GetSetInstanceAttributes( 0, theBuf, theInstance ); }

t_Attribute *GetClassAttribute( t_Class *theClass, unsigned char theAttributeCode ){
/*
** get the attribute of theClasss identified by theAttributeCode
*/
unsigned int i;

	/* ! */
	for( i=0; i<theClass->itsAttributesCount; i++ )
		if( theClass->itsAttributes[i].itsAttributeCode==theAttributeCode )
			return &theClass->itsAttributes[i];

	/* ! */
	return NULL;
}

t_Attribute *GetInstanceAttribute( t_Instance *theInstance, unsigned char theAttributeCode ){
/*
** get the attribute of theInstance identified by theAttributeCode
*/
unsigned int i;

	/* ! */
	for( i=0; i<theInstance->itsAttributesCount; i++ )
		if( theInstance->itsAttributes[i].itsAttributeCode==theAttributeCode )
			return &theInstance->itsAttributes[i];

	/* ! */
	return NULL;
}

/*
** Function to let the user send a Request. Copied from: void en_cd_TxFixedTagPacket(CD_PacketTrrblType * pTrrbl)
*/
 extern OE_Q_ID MngOutgoingEncapQueue;
 extern ENCAP_OBJ_TARGET list_target_data;
// EXTFUNC ETHERNETIPEXAMPLECODE_API int ListIndentify(void)
// {
// 	
// 	UINT16          iSize;
// 	PKTBUF         *msg;
// 	EnCdMessageType EnCdMessage;    /* Message to be sent out via tcpip */
// 	UINT32          Status;
// 
// 	CB_ComBufType *aCbDestHost;
// 	CB_ComBufType *aCbData;
// 
// 	/* ! Reset ResponseData */
// 	gResponseDataSize = 0;
// 	memset( &gResponseAddrIn, 0, sizeof(gResponseAddrIn));
// 
// 	/*
// 	** Message is originating on this board.  Allocate message dynamically
// 	*/
// 	if( ( msg=PktBufAlloc() )==NULL)
// 		return ECI_E_OUT_OF_MEMORY;
// 
// 	/* ! */
// 	if( (NULL==(aCbDestHost=CB_NewComBuf( strlen( theHostName ) )) ) )
// 		return ECI_E_OUT_OF_MEMORY;
// 
// 	/* ! */
// 	if( (NULL==(aCbData=CB_NewComBuf( theDataLen )) ) )
// 	{
// 		CB_DeleteComBuf( aCbDestHost );
// 		return ECI_E_OUT_OF_MEMORY;
// 	}
// 
// 
// 	/* ! */
// 	CB_PrependComBuf( aCbDestHost, theHostName, strlen( theHostName ) );
// 	CB_PrependComBuf( aCbData, theData, theDataLen );
// 
// 
// 	/*
// 	** Transfer host name in case we need to connect. Send this message on to the management task.
// 	** Depending on whether this host has a session set up or not, we may need to do a lot of pre-processing.
// 	*/
// 
// 	EnCdMessage.pcbDestHost = aCbDestHost; /* pTrrbl->pCbDestHost; */
// 	msg->sOutputQ = MngOutgoingEncapQueue;
// 
// 	/* ! Header */
// 	msg->sEncap.sHdr.iEncaph_command = ENCAP_CMD_LISTIDENTITY;
// 	msg->sEncap.sHdr.lEncaph_session = 0;
// 	msg->sEncap.sHdr.lEncaph_status = 0;
// 	msg->sEncap.sHdr.lEncaph_opt = 0;
// 
// 	/* ! Data transfer field */
// 	msg->sEncap.sDt_hdr.lDt_target = 0;
// 	msg->sEncap.sDt_hdr.iDt_timeout = 0;
// 	msg->sEncap.lValid = PKTBUF_ENCAPV_DT;
// 
// 	/*
// 	** Decided not to save the Cd Packet tribble handle in the context.  This would have
// 	** required us to save the tribble, and then create some way of recovering the tribbles
// 	** should the return message not be sent.  Instead we will only save the xUmHandle in the
// 	** context and let the UCMM worry about how to handle unreturned responses
// 	*/
// 	msg->sEncap.sHdr.alEncaph_context[ 1 ] = 0; /* Number, who is not recognized by the EC */
// 
// 	/*
// 	** Encode our IP address into the 0 context field.  This will help
// 	** determine that the incoming message is a reply to us and not an
// 	** illegal request from an originator coming in on the wrong socket.
// 	*/
// 	msg->sEncap.sHdr.alEncaph_context[ 0 ] = list_target_data.sS.s_sock.lSin_addr;
// 
// 	msg->pData = &msg->abData[0]; /* used by en_cd_SetSocketAddresses() */
// 	msg->lLength = 0;             /* used by en_cd_SetSocketAddresses() */
// 
// 
// 	/*
// 	** setup the SockAddr Info Data types in the packet addenda if needed
// 	*/
// 	en_cd_SetSocketAddresses( msg, &msg->sEce.sSa );
// 
// 
// 	/*
// 	** msg should still have the original command, and options (both in host order) in it.
// 	** Context is also preserved, though the order was never changed
// 	*/
// 
// 	iSize                                 = CB_GetDataSizeComBuf( aCbData ); /* CB_GetDataSizeComBuf(pTrrbl->pComBuf); */
// 	msg->sEncap.sPkt_tag.sTag.iTag_length = iSize;
// 	msg->lLength                          = iSize;
// 
// 	/*
// 	** Instead of copying the data to a new buffer, just attach the combuff and send it to the
// 	** transmission task
// 	*/
// 	msg->pData            = aCbData->pData;    /* pTrrbl->pComBuf->pData; /* point the datapointer to the combuffer */
// 	msg->pCb              = aCbData;           /* pTrrbl->pComBuf; */
// 	EnCdMessage.Command   = SENDCOMMBUF;                                  /* Send the attached message using a combuf */
// 	EnCdMessage.PacketBuf = msg;                                          /* Tcpip message to be sent.  It will be deleted by the send task */
// 
// 	/*
// 	** Send to queue the message at the send task, or the management task depending on connection state
// 	*/
// 	Status = OE_MsgQSend(msg->sOutputQ,
// 		(char *) &EnCdMessage.Command,
// 		sizeof EnCdMessage,
// 		WAIT_FOREVER,
// 		MSG_PRI_NORMAL);
// 
// 	/*
// 	** Send failed, we need to delete the packet here lest we loose it
// 	*/
// 	if (Status == OE_ERROR)
// 	{
// 		CB_DeleteComBuf( aCbDestHost );
// 		CB_DeleteComBuf( msg->pCb );
// 		PktBufFree(msg);
// 		return ECI_E_SEND_SOME_DATA_FAILED;
// 	}
// 
// 	/* ! */
// 	return ECI_E_SUCCESS;
//}

EXTFUNC ETHERNETIPEXAMPLECODE_API int EC_Request( char *theHostName, unsigned char *theData, int theDataLen )
{
/*
** Send the CIP Message (theData,theDataLen) to the TCP/IP Address (theHostName)
**
** Example: Get Attribute Single: Class 1, Instance 1, Attribute 1
**
** 02 00 00 00 00 00 B2 00 08 00 0E 03 20 01 24 01 30 06
** |     |     |     |     |     |  |  |     |     30 06 Loical Segment, Attribute ID, 8-bit
** |     |     |     |     |     |  |  |     24 01       Logical Segment, Instance ID, 8-bit
** |     |     |     |     |     |  |  20 01             Logical Segment, Class ID, 8-bit
** |     |     |     |     |     |  03                   Number of 16 bit words in the following Request_Path field
** |     |     |     |     |     0E                      Service Code of the Request: Get Attribute Single
** |     |     |     |     08 00                         Item Length in Bytes
** |     |     |     B2 00                               Item Code: unconnected message
** |     |     00 00                                     Address Item: Item Length 
** |     00 00                                           Address Item: Item Code 
** 02 00                                                 Item Count
*/
UINT16          iSize;
PKTBUF         *msg;
EnCdMessageType EnCdMessage;    /* Message to be sent out via tcpip */
UINT32          Status;

CB_ComBufType *aCbDestHost;
CB_ComBufType *aCbData;

	/* ! Reset ResponseData */
	gResponseDataSize = 0;
	memset( &gResponseAddrIn, 0, sizeof(gResponseAddrIn));
	
	/*
	** Message is originating on this board.  Allocate message dynamically
	*/
	if( ( msg=PktBufAlloc() )==NULL)
		return ECI_E_OUT_OF_MEMORY;

	/* ! */
	if( (NULL==(aCbDestHost=CB_NewComBuf( strlen( theHostName ) )) ) )
		return ECI_E_OUT_OF_MEMORY;

	/* ! */
	if( (NULL==(aCbData=CB_NewComBuf( theDataLen )) ) ){
		CB_DeleteComBuf( aCbDestHost );
		return ECI_E_OUT_OF_MEMORY;
	}

	/* ! */
	CB_PrependComBuf( aCbDestHost, theHostName, strlen( theHostName ) );
	CB_PrependComBuf( aCbData, theData, theDataLen );


	/*
	** Transfer host name in case we need to connect. Send this message on to the management task.
	** Depending on whether this host has a session set up or not, we may need to do a lot of pre-processing.
	*/

	EnCdMessage.pcbDestHost = aCbDestHost; /* pTrrbl->pCbDestHost; */
	msg->sOutputQ = MngOutgoingEncapQueue;

	/* ! Header */
	msg->sEncap.sHdr.iEncaph_command = ENCAP_CMD_SEND_RRDATA;
	msg->sEncap.sHdr.lEncaph_session = 0;
	msg->sEncap.sHdr.lEncaph_status = 0;
	msg->sEncap.sHdr.lEncaph_opt = 0;

	/* ! Data transfer field */
	msg->sEncap.sDt_hdr.lDt_target = 0;
	msg->sEncap.sDt_hdr.iDt_timeout = 0;
	msg->sEncap.lValid = PKTBUF_ENCAPV_DT;

	/*
	** Decided not to save the Cd Packet tribble handle in the context.  This would have
	** required us to save the tribble, and then create some way of recovering the tribbles
	** should the return message not be sent.  Instead we will only save the xUmHandle in the
	** context and let the UCMM worry about how to handle unreturned responses
	*/
	msg->sEncap.sHdr.alEncaph_context[ 1 ] = 0; /* Number, who is not recognized by the EC */

	/*
	** Encode our IP address into the 0 context field.  This will help
	** determine that the incoming message is a reply to us and not an
	** illegal request from an originator coming in on the wrong socket.
	*/
	msg->sEncap.sHdr.alEncaph_context[ 0 ] = list_target_data.sS.s_sock.lSin_addr;
	
	msg->pData = &msg->abData[0]; /* used by en_cd_SetSocketAddresses() */
	msg->lLength = 0;             /* used by en_cd_SetSocketAddresses() */


   /*
   ** setup the SockAddr Info Data types in the packet addenda if needed
   */
   en_cd_SetSocketAddresses( msg, &msg->sEce.sSa );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -