Registering for Callback

General

With the EtherNet adapter it is possible to register for a callback in the case of a noncyclical enquiry. If a noncyclical enquiry of the scanner is received by the EtherNet/IP adapter driver, the enquiry is first passed on to registered data areas.

Then, all registered user FB instances are called up which have been registered with the EtherNet/IP adapter by means of the interfaces IF_EIPEventHandler_AsyncGetAt­tributeAll, IF_EIPEventHandler_AsyncGetAttributeSingle and IF_EIPEventHandler_AsyncSetAttributeSingle. At the same time, the state of the automatic enquiry processing is transferred as well, so that possible problems can be responded to. The current status is then written into parameter iq_udiError.

NOTE: The RegisterAsyncClass() method has to be called up in order to obtain the callbacks of a certain class in the callback method.

In the example program SR_RegisterUserCallback, enquiries to class 102 are to be processed. Therefore, it might be necessary to manually call up ifEtherNetIP­Adapter.RegisterAsyncClass(102) in the registration process.

The example program for registering for a callback (SR_RegisterUserCallback) can be found here.

NOTE: If noncyclical data areas are registered, this method is automatically executed internally. In this case, you do not need to call up the RegisterAsyncClass() method manually. In the example program SR_RegisterInstances (see Example: Registration of noncyclical data areas), noncyclical data modules are registered to ClassId 105. Here, the RegisterAsyn­cClass() method does not have to be used.

A list of all relevant methods and the associated interfaces can be found under Relevant methods (Callback registration).

Relevant Methods (Callback Registration)

In the following, all relevant methods for the registration of the data areas of the IF_EtherNetI­PAdapter interface are listed:

Method

Description

IsRegisteredAsyncGetAttributeAll

Returns whether the transferred function block is already registered for the callback upon arrival of a GetAttributeAll enquiry.

IsRegisteredAsyncGetAttributeSingle

Returns whether the transferred function block is already registered for the callback upon arrival of a GetAttributeSingle enquiry.

IsRegisteredAsyncSetAttributeSingle

Returns whether the transferred function block is already registered for the callback upon arrival of a SetAttributeSingle enquiry.

RegisterAsyncGetAttributeAll

Registers the transferred function block for the callback in the case of GetAttributeAll enquiries.

RegisterAsyncGetAttributeSingle

Registers the transferred function block for the callback in the case of GetAttributeSingle enquiries.

RegisterAsyncSetAttributeSingle

Registers the transferred function block for the callback in the case of SetAttributeSingle enquiries.

UnregisterAsyncGetAttributeAll

Unregisters the transferred function block for the callback in the case of GetAttributeAll enquiries.

UnregisterAsyncGetAttributeSingle

Unregisters the transferred function block for the callback in the case of GetAttributeSingle enquiries.

UnregisterAsyncSetAttributeSingle

Unregisters the transferred function block for the callback in the case of SetAttributeSingle enquiries.

RegisterAsyncClass

Enables the callbacks for the transferred ClassId. Only when the callbacks for a certain ClassId have been activated, the code registered for the callbacks is called up.

Return value 0: The ClassId has been registered successfully.

Return value 1: The ClassId is already registered.

Return value 2: The ClassId is invalid.

Return value 3: The enquiry AsyncClassRegister REQ cannot be sent.

Return value 4: The enquiry AsyncClassRegister REQ was not correct.

Interface declaration

Method

Interface declaration

IsRegisteredAsyncGetAttributeAll

METHOD IsRegisteredAsyncGetAttributeAll : BOOL
VAR_INPUT
   i_ifAsyncGetAttributeAll : IF_AsyncG­etAttributeAll;
END_VAR

IsRegisteredAsyncGetAttributeSingle

METHOD IsRegisteredAsyncGetAttributeS­ingle : BOOL
VAR_INPUT
   i_ifAsyncGetAttributeSingle : IF­_AsyncGetAttributeSingle;
END_VAR

IsRegisteredAsyncSetAttributeSingle

METHOD IsRegisteredAsyncSetAttributeS­ingle : BOOL
VAR_INPUT
   i_ifAsyncSetAttributeSingle : IF­_AsyncSetAttributeSingle;
END_VAR

RegisterAsyncGetAttributeAll

METHOD RegisterAsyncGetAttributeAll : BOOL
VAR_INPUT
   i_ifAsyncGetAttributeAll : IF_AsyncG­etAttributeAll;
END_VAR

RegisterAsyncGetAttributeSingle

METHOD RegisterAsyncGetAttributeSingle : BOOL
VAR_INPUT
   i_ifAsyncRead : IF_AsyncRead;
END_VAR

RegisterAsyncSetAttributeSingle

METHOD RegisterAsyncSetAttributeSingle : BOOL
VAR_INPUT
   i_ifAsyncGetAttributeSingle : IF­_AsyncGetAttributeSingle;
END_VAR

UnregisterAsyncGetAttributeAll

METHOD UnregisterAsyncGetAttributeAll : BOOL
VAR_INPUT
   i_ifAsyncGetAttributeAll : IF_AsyncG­etAttributeAll;
END_VAR

UnregisterAsyncGetAttributeSingle

METHOD UnregisterAsyncGetAttributeSing­le : BOOL
VAR_INPUT
   i_ifAsyncGetAttributeSingle : IF­_AsyncGetAttributeSingle;
END_VAR

UnregisterAsyncSetAttributeSingle

METHOD UnregisterAsyncSetAttributeSing­le : BOOL
VAR_INPUT
   i_ifAsyncSetAttributeSingle : IF­_AsyncSetAttributeSingle;
END_VAR

RegisterAsyncClass

METHOD RegisterAsyncClass : UDINT
VAR_INPUT
   i_byClassId : BYTE;
END_VAR

Example: Registering a Callback

PROGRAM SR_RegisterUserCallback
VAR
   xAlreadyRegistered : BOOL := FALSE;
   fbUserCallback : FB_UserCallback;
   ifEtherNetIPAdapter : IF_EtherNetIP_Adapter := EtherNet_IP_Adapter;
   byIndex : BYTE := 0;
   udiResult : UDINT := 0;
   axResults : ARRAY[0..2] OF BOOL := [3(FALSE)];
END_VAR

IF (xAlreadyRegistered=FALSE) THEN
   // Set values of global array that is returned when class 102, instance 1 is requested
   FOR (byIndex:=0) TO (c_byDataLength1-1) DO
      G_abyDataTransfer1[byIndex] := byIndex+1;
   END_FOR
   // register async class 102 which should be used in user callback
   udiResult := ifEtherNetIPAdapter.RegisterAsyncClass(102);
   // Register for callback when Get_Attribute_All is requested
   axResults[0] := ifEtherNetIPAdapter.RegisterAsyncGetAttributeAll(fbUserCallback);
   // Register for callback when Get_Attribute_Single is requested
   axResults[1] := ifEtherNetIPAdapter.RegisterAsyncGetAttributeSingle(fbUserCallback);
   // Register for callback when Set_Attribute_Single is requested
   axResults[2] := ifEtherNetIPAdapter.RegisterAsyncSetAttributeSingle(fbUserCallback);
   xAlreadyRegistered := TRUE;
END_IF

Function block FB_UserCallback

FUNCTION_BLOCK FB_UserCallback IMPLEMENTS
   IF_AsyncGetAttributeAll,
   IF_AsyncGetAttributeSingle,
   IF_AsyncSetAttributeSingle
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
   udiAsyncGetAttributeAllCallbackCount : UDINT := 0;
   udiAsyncGetAttributeSingleCallbackCount : UDINT := 0;
   udiAsyncSetAttributeSingleCallbackCount : UDINT := 0;
END_VAR

Method AsyncGetAttributeAll

METHOD AsyncGetAttributeAll : UDINT
VAR_INPUT
   i_byClassId : BYTE;
   i_byInstanceId : BYTE;
END_VAR
VAR_IN_OUT
   iq_abyReadData : ARRAY [0..(Gc_EtherNetIPInstance_MaxSize - 1)] OF BYTE;
   (* Length of read data*)
   iq_byReadDataLen : BYTE;
   iq_udiError : UDINT;
END_VAR
VAR
   byIndex : BYTE := 0;
END_VAR

// You can write your own code here.
// The code is called by the callback when an Get_Attribute_All operation is requested.
THIS^.udiAsyncGetAttributeAllCallbackCount := THIS^.udiAsyncGetAttributeAllCallbackCount + 1;
// This method should give back the whole array
// G_abyDataTransfer[] when Get_Attribute_Allof class 102, instance 1 is requested.
IF (i_byClassId=102 AND i_byInstanceId=1) THEN
   FOR (byIndex:=0) TO (c_byDataLength1) DO
      // Return data
      iq_abyReadData[byIndex] := G_abyDataTransfer1[byIndex];
   END_FOR
   // Return read data length
   iq_byReadDataLen := c_byDataLength1;
   // Before this method is called, the device searches for registered data modules.
   // If no data module is registered for this class, instance, attribute combination
   // the value of iq_udiError can be <> 0.
   // Therefore it must be set to 0 => indicates that data was read
   iq_udiError := 0;
END_IF

Method AsyncGetAttributeSingle

METHOD AsyncGetAttributeSingle : UDINT
VAR_INPUT
   i_byClassId : BYTE;
   i_byInstanceId : BYTE;
   i_byAttributeId : BYTE;
END_VAR
VAR_IN_OUT
   iq_abyReadData : ARRAY [0..(Gc_EtherNetIPAttribute_MaxSize - 1)] OF BYTE;
   (* Length of read data*)
   iq_byReadDataLen : BYTE;
   iq_udiError : UDINT;
END_VAR

// You can write your own code here.
// The code is called by the callback when an Get_Attribute_Single operation is requested.
THIS^.udiAsyncGetAttributeSingleCallbackCount := THIS^.udiAsyncGetAttributeSingleCallbackCount + 1;
// This method should give back the value of G_abyDataTransfer[i_byAttributeId]
// when class 102, instance 1, attribute < Gc_byAttributeNumber is requested. IF (i_byClassId=102 AND i_byInstanceId=1) THEN
   IF (i_byAttributeId < c_byDataLength1) THEN
      // Return data
      iq_abyReadData[0] := G_abyDataTransfer1[i_byAttributeId];
      // Return read data length
      iq_byReadDataLen := 1;
      // Before this method is called, the device searches for registered data modules.
      // If no data module is registered for this class, instance,
      // attribute combination the value of iq_udiError can be <> 0.
      // Therefore it must be set to 0 => indicates that data was read
      iq_udiError := 0; ELSE // Error: Invalid attribute requested
      // iq_udiError <> 0 actuates a negative response.
      iq_udiError := 1;
   END_IF
END_IF

Method AsyncSetAttributeSingle

The noncyclical enquiry GetAttributeSingle of the master is processed in the slave by AsyncGetAttributeSingle(). In the example, processing is executed analogously to AsyncGetAttributeAll().