cancel
Showing results for 
Search instead for 
Did you mean: 
SOLVED

CXA_DataLayer how to read flatbuffer type? Is there an example?

CXA_DataLayer how to read flatbuffer type? Is there an example?

zhenhui
Established Member

Hello,

How to read flatbuffer types and parse flatbuffer types to simple type by CXA_DataLayer lib? Is there some example for this topic?

5 REPLIES 5

CodeShepherd
Community Moderator
Community Moderator

See an example I made for reading a safe area:

Declaration:

 

PROGRAM POU
VAR
	bRead: BOOL;
	fbDL_ReadNodeValue: DL_ReadNodeValue;
	DataRead: CXA_Datalayer.DL_NodeValue;
	strNodePath : STRING;
	bExecute: BOOL;
	bDone: BOOL;
	bActive: BOOL;
	bError: BOOL;
	ErrorID: CXA_Datalayer.ERROR_CODE;
	ErrorIdent: CXA_Datalayer.ERROR_STRUCT;
	strName : STRING := 'Zone_1';
	fbAreas_Read: CXA_MotionCore_fbs.motion_core_fbtypes_SysCfgSafeArea;
	Read_CoordSys: STRING;
	Read_Name: STRING;
	Read_Type: CXA_MotionCore_fbs.motion_core_fbtypes_SafeAreaType;
	Read_Boxes_length: UDINT;
	Read_Boxes: POINTER TO CXA_MotionCore_fbs.motion_core_fbtypes_SysCfgSafeAreaBox;
	Read_Boxes_Int: CXA_MotionCore_fbs.motion_core_fbtypes_SysCfgSafeAreaBox;
	arRead_Active: ARRAY [0..2] OF BOOL;
	arRead_Max:ARRAY [0..2] OF LREAL;
	arRead_Min: ARRAY [0..2] OF LREAL;
	arRead_Unit: ARRAY [0..2] OF STRING;
	i: INT;
END_VAR

 

Implementation:

 

IF bRead THEN
	bRead := FALSE;
	strNodePath := CONCAT('motion/cfg/safe-areas/',strName);
	bExecute := TRUE;
END_IF
	
IF fbDL_ReadNodeValue.Done THEN	
	fbAreas_Read.getRootAsSysCfgSafeArea(data:= DataRead.GetData(), size:= DataRead.GetSize());
	Read_CoordSys := fbAreas_Read.getCoordSystem();
	Read_Name := fbAreas_Read.getName();
	Read_Type := fbAreas_Read.getType();
	Read_Boxes_length := fbAreas_Read.getBoxLength();

	FOR i := 0 TO TO_INT(Read_Boxes_length)-1 BY 1 DO		
        	Read_Boxes := fbAreas_Read.getBox(i);
		Read_Boxes_Int := Read_Boxes^;
		arRead_Active[i] := Read_Boxes_Int.getActive();
		arRead_Max[i] := Read_Boxes_Int.getMax();
		arRead_Min[i] := Read_Boxes_Int.getMin();
		arRead_Unit[i] := Read_Boxes_Int.getUnit();	
	END_FOR
	bExecute := FALSE;
END_IF

fbDL_ReadNodeValue(
	Execute:= bExecute, 
	Done=> bDone, 
	Active=> bActive, 
	Error=> bError, 
	ErrorID=> ErrorID, 
	ErrorIdent=> ErrorIdent, 
	ClientId:= , 
	NodeName:= strNodePath, 
	NodeValue:= DataRead);

 

 

Hello,

Thanks a lot for your sample. It's pretty helpful.

I'm reading fbs script_manager_fbtypes_DiagInfo which inculdes string type and array of string type, there are sitll some problems for me:

1. When trying to parse array of string, I can get a valid value of pointer to string by getLasetErrTrace method, but when convert it to string type,  I always get invalid result.

2. Besides, I can always get a value(not zero) by method strPtr := fbsDiag_Read.getLastErrTrace(idx), even though idx is bigger than count. 

 

count := fbsDiag_Read.getLastErrTraceLength();

FOR idx := 0 TO count - 1 DO
   strPtr := fbsDiag_Read.getLastErrTrace(idx);
   IF strPtr <>0 THEN
      Stu.StrCpyA(pBuffer:=ADR(testStr), iBufferSize := SIZEOF(testStr), pStr := strPtr);
   END_IF
END_FOR

 

 

3. When trying to read a string longer than 80 length, it's limited to 80(default string length in codesys). For some case, it's not enough to get a string with wrong length.

 

ErrorStr := fbsDiag_Read.getLastErrText();

 

 

CodeShepherd
Community Moderator
Community Moderator

I do not get all of your points. Please see my version that works as I expected:

Declaration:

PROGRAM script_manager_fbtypes_DiagInfo
VAR
 	strMyInstancename : STRING := 'MyInstance';
	bRead: BOOL;
	bExecute: BOOL;
	strNodePath: STRING(255);
	fbDL_ReadNodeValue: DL_ReadNodeValue;
	bDone: BOOL;
	bActive: BOOL;
	bError: BOOL;
	ErrorID: CXA_Datalayer.ERROR_CODE;
	ErrorIdent: CXA_Datalayer.ERROR_STRUCT;
	DataRead: CXA_Datalayer.DL_NodeValue;	
	fbDiagInfo: cxa_automationcore_fbs.script_manager_fbtypes_DiagInfo;
	udiLastMainDiag: UDINT;
	udiLastDetailDiag: UDINT;
	strLastErrText: STRING(255);
	udiLastErrTraceLength: UDINT;
	i: INT;
	arstrLastErrTrace: ARRAY [0..99] OF STRING;
	pLastErrTrace: POINTER TO STRING;
END_VAR

Implementation:

IF bRead THEN
	bRead := FALSE;
	strNodePath := CONCAT('script/instances/',strMyInstancename);
	strNodePath := CONCAT(strNodePath,'/diag');
	bExecute := TRUE;
END_IF
	
IF fbDL_ReadNodeValue.Done THEN	
	fbDiagInfo.getRootAsDiagInfo(data:= DataRead.GetData(), size:= DataRead.GetSize());
	udiLastMainDiag := fbDiagInfo.getLastMainDiag();
	udiLastDetailDiag := fbDiagInfo.getLastDetailDiag();
	strLastErrText := fbDiagInfo.getLastErrText();
	udiLastErrTraceLength := fbDiagInfo.getLastErrTraceLength();
	FOR i := 0 TO TO_INT(udiLastErrTraceLength)-1 BY 1 DO
		pLastErrTrace := fbDiagInfo.getLastErrTrace(i);
		arstrLastErrTrace[i] := pLastErrTrace^;		
	END_FOR
	bExecute := FALSE;
END_IF

fbDL_ReadNodeValue(
	Execute:= bExecute, 
	Done=> bDone, 
	Active=> bActive, 
	Error=> bError, 
	ErrorID=> ErrorID, 
	ErrorIdent=> ErrorIdent, 
	ClientId:= , 
	NodeName:= strNodePath, 
	NodeValue:= DataRead);

Picture:

CodeShepherd_0-1633082148367.png

 

hello,

about how to read array of string type in the datalayer, I follow your example to read the data as below.

I am planed to read the offset-xyz value and offset-xyz-units.it is works to read array of LREAL type, but the array of string is always empty, although the  length is corrent.

2022-08-09_11h09_19.png2022-08-09_11h08_05.png

see my program code:

Declaration:

FUNCTION_BLOCK ReadSets
VAR_INPUT
	strName : STRING;	
END_VAR
VAR_OUTPUT
END_VAR
VAR
    bRead : BOOL;
	fbDL_ReadNodeValue: DL_ReadNodeValue;
	DataRead: CXA_Datalayer.DL_NodeValue;
	strNodePath : STRING;
	fbSysCfgPcsSet_Read: motion_core_fbtypes_SysCfgPcsSet;

	OffsetXYZ_length : UDINT;
	Orientation_Length : UDINT;
	OffsetAux_Length : UDINT;
	OffsetXYZUnits_Length : UDINT;

    pOffsetXYZ : POINTER TO  LREAL;
    pOrientation : POINTER TO  LREAL;	
    pOffsetAux : POINTER TO  LREAL;	
	pOffsetXYZUnits : 	POINTER TO STRING;
	
	arOffsetXYZ: ARRAY [0..2] OF  LREAL;
	arOrientation: ARRAY [0..2] OF  LREAL;	
	arOffsetAux: ARRAY [0..9] OF  LREAL;	
	arOffsetXYZUnits: ARRAY [0..2] OF  STRING;	
	i: UDINT;		
END_VAR

Implementation:

	
IF fbDL_ReadNodeValue.Done THEN	
	fbSysCfgPcsSet_Read.getRootAsSysCfgPcsSet(data:= DataRead.GetData(), size:= DataRead.GetSize());
	OffsetXYZ_length := fbSysCfgPcsSet_Read.getOffsetXYZLength();
    Orientation_Length := fbSysCfgPcsSet_Read.getOrientationLength();
    OffsetAux_Length := fbSysCfgPcsSet_Read.getOffsetAuxLength();	
	OffsetXYZUnits_Length := fbSysCfgPcsSet_Read.getOffsetXYZUnitsLength();
	
	//OffsetXYZ
	FOR i := 0 TO TO_INT(OffsetXYZ_length)-1 BY 1 DO		
        pOffsetXYZ := fbSysCfgPcsSet_Read.getOffsetXYZ(i);
		arOffsetXYZ[i] := pOffsetXYZ^;
	END_FOR
	//Offset Orientation
	FOR i := 0 TO TO_INT(Orientation_Length)-1 BY 1 DO		
        pOrientation := fbSysCfgPcsSet_Read.getOrientation(i);
		arOrientation[i] := pOrientation^;
	END_FOR	
	//OffsetAux
	FOR i := 0 TO TO_INT(OffsetAux_Length)-1 BY 1 DO		
        pOffsetAux := fbSysCfgPcsSet_Read.getOffsetAux(i);
		arOffsetAux[i] := pOffsetAux^;
	END_FOR			
	//OffsetXYZUnits  example faild	
	FOR i := 0 TO OffsetXYZUnits_Length-1 BY 1 DO		
        pOffsetXYZUnits := fbSysCfgPcsSet_Read.getOffsetXYZUnits(i);
		arOffsetXYZUnits[i] := pOffsetXYZUnits^;
	END_FOR			
	bRead := FALSE;
END_IF

//motion/cfg/coord-systems/pcs/sets
strNodePath := CONCAT('motion/cfg/coord-systems/pcs/sets/',strName);
fbDL_ReadNodeValue(
	Execute:= bRead, 
	NodeName:= strNodePath, 
	NodeValue:= DataRead);
	
	
	

 

CodeShepherd
Community Moderator
Community Moderator

@leo1 your example is working fine at my side with a small change. In line 24 in my code I also added the unit conversion and declared "i" as integer:

ctrlX PLC Engineering read PCS setctrlX PLC Engineering read PCS set

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist