[r5]: / trunk / d-logg / d-logg.library  Maximize  Restore  History

Download this file

792 lines (638 with data), 777.8 kB

-------------------------------------------------------------------------------
DLogg
-------------------------------------------------------------------------------


FUNCTION_BLOCK DLogg

VAR_INPUT
    udtInput: IoDrvInput;
    udtConfig: IoDrvConfig;
END_VAR

VAR_OUTPUT
    udtOutput: IoDrvOutput;
END_VAR

VAR
    stream: SerialStream;
    i: LINT;
    byByte: BYTE;
    nRead: UDINT;
    nWrote: ULINT;
    dwState: DWORD;
    udiNumDL: UDINT;
    audtSensor: ARRAY [..] OF ;
    audtSolar1: ARRAY [..] OF ;
    audtSolar2: ARRAY [..] OF ;
    byChecksum: BYTE;
    Delay: TON;
END_VAR
// Execute the FB only every second
// Quicker sampling is not supported by the logger
Delay(IN:=TRUE, PT:=T#1S);
IF NOT(Delay.Q) THEN
	RETURN;
END_IF
Delay(IN:=FALSE);

// Start with the state machine
CASE dwState OF
	0:	stream.Open(1, 115200);
		next();
	// Read number of data loggers
	1: 	nWrote := stream.WriteByte(16#81);
		IF nWrote = 1 THEN	
			next();
		END_IF
	2:	IF stream.Length >= 1 THEN
			stream.Read(ADR(byByte), 1);
			CASE byByte OF
				16#A8: udiNumDL := 1;
				16#D1: udiNumDL := 2;
			END_CASE
			next();
		END_IF
	// Read Data-Logger Type (also polls for new data)
	3: 	nWrote := stream.WriteByte(16#AB);
		IF nWrote = 1 THEN	
			next();
		END_IF
	4:	IF stream.Length >= 1 THEN
			byByte := stream.ReadByte();
			CASE byByte OF
				16#AB: reset(); // no new data
				16#80: next(); // UVR1611
				16#90: next(); // UVR61-3
			END_CASE
		END_IF
	// Read sensor data
	5:	IF stream.Length >= (39 + 16 + 1) * udiNumDL THEN
			FOR i:=0 TO udiNumDL-1 DO
				stream.Read(ADR(audtSensor[i]), 39);
				stream.Read(ADR(audtSolar1[i]), 8);
				stream.Read(ADR(audtSolar2[i]), 8);
				byChecksum := stream.ReadByte();
 			END_FOR
			next();
		END_IF
	// Convert RAW data to temperatures and boolean actor data
	6:	udtInput.C0_S1  := THIS^.raw2temp(audtSensor[0].auiTemperature[0]);
		udtInput.C0_S2  := THIS^.raw2temp(audtSensor[0].auiTemperature[1]);
		udtInput.C0_S3  := THIS^.raw2temp(audtSensor[0].auiTemperature[2]);
		udtInput.C0_S4  := THIS^.raw2temp(audtSensor[0].auiTemperature[3]);
		udtInput.C0_S5  := THIS^.raw2temp(audtSensor[0].auiTemperature[4]);
		udtInput.C0_S6  := THIS^.raw2temp(audtSensor[0].auiTemperature[5]);
		udtInput.C0_S7  := THIS^.raw2temp(audtSensor[0].auiTemperature[6]);
		udtInput.C0_S8  := THIS^.raw2temp(audtSensor[0].auiTemperature[7]);
		udtInput.C0_S9  := THIS^.raw2temp(audtSensor[0].auiTemperature[8]);
		udtInput.C0_S10 := THIS^.raw2temp(audtSensor[0].auiTemperature[9]);
		udtInput.C0_S11 := THIS^.raw2temp(audtSensor[0].auiTemperature[10]);
		udtInput.C0_S12 := THIS^.raw2temp(audtSensor[0].auiTemperature[11]);
		udtInput.C0_S13 := THIS^.raw2temp(audtSensor[0].auiTemperature[12]);
		udtInput.C0_S14 := THIS^.raw2temp(audtSensor[0].auiTemperature[13]);
		udtInput.C0_S15 := THIS^.raw2temp(audtSensor[0].auiTemperature[14]);
		udtInput.C0_S16 := THIS^.raw2temp(audtSensor[0].auiTemperature[15]);
		udtInput.C1_S1  := THIS^.raw2temp(audtSensor[1].auiTemperature[0]);
		udtInput.C1_S2  := THIS^.raw2temp(audtSensor[1].auiTemperature[1]);
		udtInput.C1_S3  := THIS^.raw2temp(audtSensor[1].auiTemperature[2]);
		udtInput.C1_S4  := THIS^.raw2temp(audtSensor[1].auiTemperature[3]);
		udtInput.C1_S5  := THIS^.raw2temp(audtSensor[1].auiTemperature[4]);
		udtInput.C1_S6  := THIS^.raw2temp(audtSensor[1].auiTemperature[5]);
		udtInput.C1_S7  := THIS^.raw2temp(audtSensor[1].auiTemperature[6]);
		udtInput.C1_S8  := THIS^.raw2temp(audtSensor[1].auiTemperature[7]);
		udtInput.C1_S9  := THIS^.raw2temp(audtSensor[1].auiTemperature[8]);
		udtInput.C1_S10 := THIS^.raw2temp(audtSensor[1].auiTemperature[9]);
		udtInput.C1_S11 := THIS^.raw2temp(audtSensor[1].auiTemperature[10]);
		udtInput.C1_S12 := THIS^.raw2temp(audtSensor[1].auiTemperature[11]);
		udtInput.C1_S13 := THIS^.raw2temp(audtSensor[1].auiTemperature[12]);
		udtInput.C1_S14 := THIS^.raw2temp(audtSensor[1].auiTemperature[13]);
		udtInput.C1_S15 := THIS^.raw2analog(audtSensor[1].auiTemperature[14]);
		udtInput.C1_S16 := THIS^.raw2analog(audtSensor[1].auiTemperature[15]);
		
		udtInput.C0_A0 := audtSensor[0].abyDOUT[0];
		udtInput.C0_A1 := audtSensor[0].abyDOUT[1];
		udtInput.C1_A0 := audtSensor[1].abyDOUT[0];
		udtInput.C1_A1 := audtSensor[1].abyDOUT[1];
		
		next();
	// End
	7:	reset();
			
END_CASE

-------------------------------------------------------------------------------
raw2temp
-------------------------------------------------------------------------------


METHOD raw2temp: REAL

VAR_INPUT
    raw: WORD;
END_VAR

VAR
    tmp: INT;
END_VAR
tmp := WORD_TO_INT(raw AND 16#8000);
tmp := SHR(tmp, 3);
tmp := UINT_TO_INT(WORD_TO_UINT(raw AND 16#0FFF) OR INT_TO_UINT(tmp));
raw2temp := tmp / 10;

-------------------------------------------------------------------------------
raw2analog
-------------------------------------------------------------------------------


METHOD raw2analog: DWORD

VAR_INPUT
    raw: WORD;
END_VAR
raw2analog := raw AND 16#0FFF;

-------------------------------------------------------------------------------
IoDrvFB
-------------------------------------------------------------------------------


FUNCTION_BLOCK IoDrvFB EXTENDS IoDrvBase

VAR
    _IIoDrv: ICmpIoDrv;
    _IIoDrvParameter: ICmpIoDrvParameter;
    _instance: DLogg;
END_VAR

-------------------------------------------------------------------------------
FB_Init
-------------------------------------------------------------------------------


METHOD FB_Init: BOOL

VAR_INPUT
    bInitRetains: BOOL;
    bInCopyCode: BOOL;
END_VAR

VAR
    Result: UDINT;
END_VAR
m_Info.szDriverName := cDriverName;
m_Info.szVendorName := cVendorName;
m_info.szDeviceName := cDeviceName;
m_Info.wModuleType := cModuleType;

_IIoDrv := THIS^;
_IIoDrvParameter := THIS^;

m_IBaseItf := THIS^;
m_hInterface := IoMgrRegisterInstance2(dwClassId:=cClassID, pItf:=m_IBaseItf, pResult:=ADR(Result));
FB_Init := TRUE;
-------------------------------------------------------------------------------
Initialize
-------------------------------------------------------------------------------


METHOD Initialize: UDINT

VAR_INPUT
    wModuleType: UINT;
    dwInstance: UDINT;
    pConnector: pointer;
END_VAR
Initialize_Count := Initialize_Count + 1;

m_wModuleType := wModuleType;
m_dwInstance := dwInstance;
m_Info.wModuleType := wModuleType;

Initialize := CmpErrors.Errors.ERR_OK;
-------------------------------------------------------------------------------
QueryInterface
-------------------------------------------------------------------------------


METHOD QueryInterface: pointer

VAR_INPUT
    iid: DWORD;
    pResult: pointer;
END_VAR
IF iid = ITFID_ICmpIoDrv THEN
	QueryInterface := ADR(_IIoDrv);
	AddRef();
	IF (pResult <> 0) THEN
		pResult^ := Errors.ERR_OK;
	END_IF
	RETURN;	
ELSIF iid = ITFID_ICmpIoDrvParameter THEN
	QueryInterface := ADR(_IIoDrvParameter);
	AddRef();
	IF (pResult <> 0) THEN
		pResult^ := Errors.ERR_OK;
	END_IF	
	RETURN;	
ELSE
	QueryInterface := SUPER^.QueryInterface(iid, pResult);
END_IF

-------------------------------------------------------------------------------
IoDrvReadInputs
-------------------------------------------------------------------------------


METHOD IoDrvReadInputs: UDINT

VAR_INPUT
    pConnectorMapList: pointer;
    nCount: DINT;
END_VAR

VAR
    i: DINT;
    j: DINT;
END_VAR
IF pConnectorMapList = 0 OR nCount = 0 THEN
	IoDrvReadInputs := Errors.ERR_PARAMETER;
	RETURN;
END_IF

FOR i:=0 TO nCount - 1 DO
	IF (pConnectorMapList[i].dwNumOfChannels = 0) THEN
		CONTINUE;
	END_IF
	FOR j:= 0 TO UDINT_TO_UINT(pConnectorMapList[i].dwNumOfChannels) - 1 DO	
		IoMgrCopyInputLE(ADR(pConnectorMapList[i].pChannelMapList[j]), pConnectorMapList[i].pChannelMapList[j].pParameter^.dwDriverSpecific);
	END_FOR
END_FOR

IoDrvReadInputs := Errors.ERR_OK;
-------------------------------------------------------------------------------
IoDrvStartBusCycle
-------------------------------------------------------------------------------


METHOD IoDrvStartBusCycle: UDINT

VAR_INPUT
    pConnector: pointer;
END_VAR
_instance();

IoDrvStartBusCycle := Errors.ERR_OK;
-------------------------------------------------------------------------------
IoDrvUpdateConfiguration
-------------------------------------------------------------------------------


METHOD IoDrvUpdateConfiguration: UDINT

VAR_INPUT
    pConnectorList: pointer;
    nCount: DINT;
END_VAR

VAR
    pParameter: pointer;
    Result: RTS_IEC_RESULT;
    pudtConfig: pointer;
END_VAR
IoDrvUpdateConfiguration_Count := IoDrvUpdateConfiguration_Count + 1;
IoDrvUpdateConfiguration := Errors.ERR_OK;

IF (pConnectorList = 0) THEN
	RETURN;
END_IF

m_pConnector := IoMgrConfigGetConnector(pConnectorList, ADR(nCount), m_wModuleType, m_dwInstance);

IF m_pConnector = 0 THEN
	IoDrvUpdateConfiguration := ERRORS.ERR_PARAMETER;
	RETURN;
END_IF

//check if device is enabled in the device tree
IF (m_pConnector^.dwFlags AND ConnectorFlags.CF_ENABLE) = 0 THEN
	IoDrvUpdateConfiguration := Errors.ERR_OK;
	RETURN;
END_IF

IF m_pConnector^.hIoDrv = 0 THEN
	m_pConnector^.hIoDrv := m_hInterface;
	m_pConnector^.pFather^.hIoDrv := m_hInterface;
	
	{IF defined (pou:IoMgrConfigSetDiagnosis)}
	IoMgrConfigSetDiagnosis(m_pConnector,
							ConnectorFlags.CF_DRIVER_AVAILABLE OR
							ConnectorFlags.CF_CONNECTOR_FOUND OR
							ConnectorFlags.CF_CONNECTOR_CONFIGURED OR
							ConnectorFlags.CF_CONNECTOR_ACTIVE);
	{END_IF}
	
	{IF defined (pou:IoMgrConfigSetDiagnosis)}
	IoMgrConfigSetDiagnosis(m_pConnector^.pFather,
							ConnectorFlags.CF_DRIVER_AVAILABLE OR
							ConnectorFlags.CF_CONNECTOR_FOUND OR
							ConnectorFlags.CF_CONNECTOR_CONFIGURED OR
							ConnectorFlags.CF_CONNECTOR_ACTIVE);
	{END_IF}

	{IF defined (pou:IoMgrSetDriverProperties)}			
		IoMgrSetDriverProperties(m_hInterface, DRVPROP_CONSISTENCY OR DRVPROP_BACKGROUND_GETDIAG);
	{END_IF}										

	// Map config-, input- and output parameters
	pParameter := IoMgrConfigGetParameter(m_pConnector, 1000);
	IF (pParameter <> 0) THEN
		pParameter^.dwDriverSpecific := ADR(_instance.udtInput);
	END_IF

	pParameter := IoMgrConfigGetParameter(m_pConnector, 2000);
	IF (pParameter <> 0) THEN
		pParameter^.dwDriverSpecific := ADR(_instance.udtOutput);
	END_IF

	pParameter := IoMgrConfigGetParameter(m_pConnector, 3000);
	IF (pParameter <> 0) THEN
		pudtConfig := IoStandard.ConfigGetParameterValuePointer(pParameter, ADR(Result));
		_instance.udtConfig := pudtConfig^;
	END_IF
END_IF
-------------------------------------------------------------------------------
IoDrvWriteOutputs
-------------------------------------------------------------------------------


METHOD IoDrvWriteOutputs: UDINT

VAR_INPUT
    pConnectorMapList: pointer;
    nCount: DINT;
END_VAR

VAR
    i: DINT;
    j: DINT;
END_VAR
IF pConnectorMapList = 0 OR nCount = 0 THEN
	IoDrvWriteOutputs := Errors.ERR_PARAMETER;
	RETURN;
END_IF

FOR i:=0 TO nCount - 1 DO
	IF (pConnectorMapList[i].dwNumOfChannels = 0) THEN
		CONTINUE;
	END_IF
	FOR j:= 0 TO UDINT_TO_UINT(pConnectorMapList[i].dwNumOfChannels) - 1 DO	
		IoMgrCopyOutputLE(ADR(pConnectorMapList[i].pChannelMapList[j]), pConnectorMapList[i].pChannelMapList[j].pParameter^.dwDriverSpecific);
	END_FOR
END_FOR
-------------------------------------------------------------------------------
IoDrvReadParameter
-------------------------------------------------------------------------------


METHOD IoDrvReadParameter: UDINT

VAR_INPUT
    pConnector: pointer;
    pParameter: pointer;
    pData: pointer;
    dwBitSize: DWORD;
    dwBitOffset: DWORD;
END_VAR
IF 	pConnector = 0 OR pParameter = 0 OR pData = 0 THEN
	IoDrvReadParameter := Errors.ERR_PARAMETER;
	RETURN;	
END_IF

// All standard parameters of our device are handled by the IO-manager!
IoDrvReadParameter := Errors.ERR_FAILED;

-------------------------------------------------------------------------------
IoDrvWriteParameter
-------------------------------------------------------------------------------


METHOD IoDrvWriteParameter: UDINT

VAR_INPUT
    pConnector: pointer;
    pParameter: pointer;
    pData: pointer;
    dwBitSize: DWORD;
    dwBitOffset: DWORD;
END_VAR

VAR
    pParam: pointer;
    pstDiagString: pointer;
END_VAR
IF pConnector = 0 OR pParameter = 0 OR pData = 0 THEN
	IoDrvWriteParameter := Errors.ERR_PARAMETER;
	RETURN;	
END_IF

IoDrvWriteParameter := Errors.ERR_FAILED;
-------------------------------------------------------------------------------
DumpJSON
-------------------------------------------------------------------------------


METHOD DumpJSON: BOOL

VAR_INPUT
    filename: REFERENCE TO STRING;
END_VAR

VAR
    hJSON: RTS_IEC_HANDLE;
    timestamp: UDINT;
    Result: RTS_IEC_RESULT;
END_VAR
hJSON := SysFile.SysFileOpen(filename, SysFile.ACCESS_MODE.AM_WRITE, 0);
IF hJSON <> SysTypes.RTS_INVALID_HANDLE THEN
	timestamp := SysTimeRtc.SysTimeRtcGet(Result);
	puts(hJSON, '{');
	putval(hJSON, 'Timestamp', UDINT_TO_STRING(timestamp));
	putval(hJSON, 'C1_S1',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S1));
	putval(hJSON, 'C1_S2',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S2));
	putval(hJSON, 'C1_S3',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S3));
	putval(hJSON, 'C1_S4',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S4));
	putval(hJSON, 'C1_S5',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S5));
	putval(hJSON, 'C1_S6',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S6));
	putval(hJSON, 'C1_S7',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S7));
	putval(hJSON, 'C1_S8',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S8));
	putval(hJSON, 'C1_S9',  REAL_TO_STRING(THIS^._instance.udtInput.C0_S9));
	putval(hJSON, 'C1_S10', REAL_TO_STRING(THIS^._instance.udtInput.C0_S10));
	putval(hJSON, 'C1_S11', REAL_TO_STRING(THIS^._instance.udtInput.C0_S11));
	putval(hJSON, 'C1_S12', REAL_TO_STRING(THIS^._instance.udtInput.C0_S12));
	putval(hJSON, 'C1_S13', REAL_TO_STRING(THIS^._instance.udtInput.C0_S13));
	putval(hJSON, 'C1_S14', REAL_TO_STRING(THIS^._instance.udtInput.C0_S14));
	putval(hJSON, 'C1_S15', REAL_TO_STRING(THIS^._instance.udtInput.C0_S15));
	putval(hJSON, 'C1_S16', REAL_TO_STRING(THIS^._instance.udtInput.C0_S16));

	putval(hJSON, 'C2_S1',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S1));
	putval(hJSON, 'C2_S2',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S2));
	putval(hJSON, 'C2_S3',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S3));
	putval(hJSON, 'C2_S4',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S4));
	putval(hJSON, 'C2_S5',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S5));
	putval(hJSON, 'C2_S6',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S6));
	putval(hJSON, 'C2_S7',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S7));
	putval(hJSON, 'C2_S8',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S8));
	putval(hJSON, 'C2_S9',  REAL_TO_STRING(THIS^._instance.udtInput.C1_S9));
	putval(hJSON, 'C2_S10', REAL_TO_STRING(THIS^._instance.udtInput.C1_S10));
	putval(hJSON, 'C2_S11', REAL_TO_STRING(THIS^._instance.udtInput.C1_S11));
	putval(hJSON, 'C2_S12', REAL_TO_STRING(THIS^._instance.udtInput.C1_S12));
	putval(hJSON, 'C2_S13', REAL_TO_STRING(THIS^._instance.udtInput.C1_S13));
	putval(hJSON, 'C2_S14', REAL_TO_STRING(THIS^._instance.udtInput.C1_S14));
	putval(hJSON, 'C2_S15', DWORD_TO_STRING(THIS^._instance.udtInput.C1_S15));
	putval(hJSON, 'C2_S16', DWORD_TO_STRING(THIS^._instance.udtInput.C1_S16));

	putval(hJSON, 'C1_A1',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#01) <> 0)));
	putval(hJSON, 'C1_A2',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#02) <> 0)));
	putval(hJSON, 'C1_A3',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#04) <> 0)));
	putval(hJSON, 'C1_A4',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#08) <> 0)));
	putval(hJSON, 'C1_A5',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#10) <> 0)));
	putval(hJSON, 'C1_A6',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#20) <> 0)));
	putval(hJSON, 'C1_A7',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#40) <> 0)));
	putval(hJSON, 'C1_A8',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A0 AND 16#80) <> 0)));
	putval(hJSON, 'C1_A9',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#01) <> 0)));
	putval(hJSON, 'C1_A10', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#02) <> 0)));
	putval(hJSON, 'C1_A11', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#04) <> 0)));
	putval(hJSON, 'C1_A12', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#08) <> 0)));
	putval(hJSON, 'C1_A13', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#10) <> 0)));
	putval(hJSON, 'C1_A14', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#20) <> 0)));
	putval(hJSON, 'C1_A15', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#40) <> 0)));
	putval(hJSON, 'C1_A16', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C0_A1 AND 16#80) <> 0)));

	putval(hJSON, 'C2_A1',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#01) <> 0)));
	putval(hJSON, 'C2_A2',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#02) <> 0)));
	putval(hJSON, 'C2_A3',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#04) <> 0)));
	putval(hJSON, 'C2_A4',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#08) <> 0)));
	putval(hJSON, 'C2_A5',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#10) <> 0)));
	putval(hJSON, 'C2_A6',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#20) <> 0)));
	putval(hJSON, 'C2_A7',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#40) <> 0)));
	putval(hJSON, 'C2_A8',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A0 AND 16#80) <> 0)));
	putval(hJSON, 'C2_A9',  INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#01) <> 0)));
	putval(hJSON, 'C2_A10', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#02) <> 0)));
	putval(hJSON, 'C2_A11', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#04) <> 0)));
	putval(hJSON, 'C2_A12', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#08) <> 0)));
	putval(hJSON, 'C2_A13', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#10) <> 0)));
	putval(hJSON, 'C2_A14', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#20) <> 0)));
	putval(hJSON, 'C2_A15', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#40) <> 0)));
	putval(hJSON, 'C2_A16', INT_TO_STRING(BOOL_TO_INT((THIS^._instance.udtInput.C1_A1 AND 16#80) <> 0)));
	puts(hJSON, '"":0}');
	SysFile.SysFileClose(hJSON);
END_IF
-------------------------------------------------------------------------------
puts
-------------------------------------------------------------------------------


METHOD puts: 

VAR_INPUT
    h: SysTypes.RTS_IEC_HANDLE;
    str: string;
END_VAR
SysFile.SysFileWrite(h, ADR(str), LEN(str), 0);

-------------------------------------------------------------------------------
putval
-------------------------------------------------------------------------------


METHOD putval: 

VAR_INPUT
    h: SysTypes.RTS_IEC_HANDLE;
    key: string;
    val: string;
END_VAR
puts(h, '"');
puts(h, key);
puts(h, '": ');
puts(h, val);
puts(h, ',$n');
-------------------------------------------------------------------------------
PRG_RUNTEST
-------------------------------------------------------------------------------


PROGRAM PRG_RUNTEST

VAR
    xError: BOOL;
    xReady: BOOL;
    szMessage: string;
END_VAR
xError := FALSE;
xReady := TRUE;
szMessage := 'Output...';

-------------------------------------------------------------------------------
SerialStream
-------------------------------------------------------------------------------


FUNCTION_BLOCK SerialStream

VAR
    hPort: SysCom.SysTypes.RTS_IEC_HANDLE;
    abyBuffer: ARRAY [..] OF ;
    udiBufferLength: UDINT;
    udiBufferWritePos: UDINT;
    udiBufferReadPos: UDINT;
END_VAR

VAR
    cBufferSize: UDINT;
END_VAR

-------------------------------------------------------------------------------
Close
-------------------------------------------------------------------------------


METHOD Close: BYTE
IF hPort <> SysCom.SysTypes.RTS_INVALID_HANDLE THEN
	SysCom.SysComClose(hCom := hPort);
END_IF

-------------------------------------------------------------------------------
FB_EXIT
-------------------------------------------------------------------------------


METHOD FB_EXIT: BYTE

VAR_INPUT
    bInCopyCode: BOOL;
END_VAR
THIS^.Close();

-------------------------------------------------------------------------------
Open
-------------------------------------------------------------------------------


METHOD Open: BYTE

VAR_INPUT
    iPortNr: INT;
    dwBaudrate: DWORD;
END_VAR

VAR
    udtComSettings: SysCom.COM_Settings;
    Result: SysCom.SysTypes.RTS_IEC_RESULT;
END_VAR
(* Default settings *)
udtComSettings.byParity := SysCom.COM_Parity.SYS_NOPARITY;
udtComSettings.byStopBits := SysCom.COM_StopBits.SYS_ONESTOPBIT;
udtComSettings.ulBufferSize := 1024 * 1024; // not used on most systems, but if, we don't want to make it too small
udtComSettings.ulTimeout := 100; // This timeout is nonsense, as a timeout is passed to each read / write operation

(* User settings *)
udtComSettings.ulBaudrate := dwBaudrate;
udtComSettings.sPort := iPortNr;

hPort := SysCom.SysComOpen2(pSettings := ADR(udtComSettings), pSettingsEx := 0, pResult := ADR(Result));
//iPortNr := SysCom.SYS_COMPORT1;

//hPort := SysCom.SysComOpen(iPortNr, ADR(Result));
-------------------------------------------------------------------------------
Read
-------------------------------------------------------------------------------


METHOD Read: UDINT

VAR_INPUT
    pbyBuffer: pointer;
    udiSize: UDINT;
END_VAR

VAR
    i: UDINT;
    Result: SysCom.SysTypes.RTS_IEC_RESULT;
END_VAR
THIS^.ReadAhead();

i := 0;
IF hPort <> SysCom.SysTypes.RTS_INVALID_HANDLE THEN
	WHILE (udiBufferReadPos MOD cBufferSize) <> udiBufferWritePos AND i < udiSize DO
		pbyBuffer[i] := abyBuffer[udiBufferReadPos];
		udiBufferReadPos := (udiBufferReadPos + 1) MOD cBufferSize;
		i := i + 1;
	END_WHILE
	udiBufferLength := udiBufferLength - i;
END_IF
Read := i;
-------------------------------------------------------------------------------
ReadAhead
-------------------------------------------------------------------------------


METHOD ReadAhead: UDINT

VAR
    udiSize: UDINT;
    Result: SysCom.SysTypes.RTS_IEC_RESULT;
END_VAR
IF hPort <> SysCom.SysTypes.RTS_INVALID_HANDLE THEN
	// Read from current write position to the end of the buffer
	udiSize := cBufferSize - udiBufferWritePos;
	ReadAhead := SysCom.SysComRead(hCom := hPort, pbyBuffer := ADR(abyBuffer[udiBufferWritePos]), ulSize := udiSize, ulTimeout := 10, pResult := ADR(Result));
	udiBufferWritePos := (udiBufferWritePos + ReadAhead) MOD cBufferSize;
	udiBufferLength := udiBufferLength + ReadAhead;
	
	IF ReadAhead = udiSize THEN
		// Read from 0 to the current read position
		udiSize := udiBufferReadPos;
		ReadAhead := SysCom.SysComRead(hCom := hPort, pbyBuffer := ADR(abyBuffer[0]), ulSize := udiSize, ulTimeout := 10, pResult := ADR(Result));
		udiBufferWritePos := (udiBufferWritePos + ReadAhead) MOD cBufferSize;
		udiBufferLength := udiBufferLength + ReadAhead;
	END_IF
END_IF
-------------------------------------------------------------------------------
ReadByte
-------------------------------------------------------------------------------


METHOD ReadByte: BYTE
THIS^.Read(ADR(Readbyte), 1);

-------------------------------------------------------------------------------
Write
-------------------------------------------------------------------------------


METHOD Write: UDINT

VAR_INPUT
    pbyBuffer: pointer;
    udiSize: UDINT;
END_VAR

VAR
    Result: SysCom.SysTypes.RTS_IEC_RESULT;
END_VAR
IF hPort <> SysCom.SysTypes.RTS_INVALID_HANDLE THEN
	Write := SysCom.SysComWrite(hCom := hPort, pbyBuffer := pbyBuffer, ulSize := udiSize, ulTimeout := 100, pResult := ADR(Result));
END_IF


-------------------------------------------------------------------------------
WriteByte
-------------------------------------------------------------------------------


METHOD WriteByte: ULINT

VAR_INPUT
    byByte: BYTE;
END_VAR
WriteByte := THIS^.Write(ADR(byByte), 1);
VAR_GLOBAL
    cClassID: DWORD;
    cDriverName: string;
    cDeviceName: string;
    cVendorName: string;
    cModuleType: WORD;
END_VAR

-------------------------------------------------------------------------------
Read
-------------------------------------------------------------------------------


METHOD Read: UDINT

VAR_INPUT
    pbyBuffer: pointer;
    udiSize: UDINT;
END_VAR

-------------------------------------------------------------------------------
ReadByte
-------------------------------------------------------------------------------


METHOD ReadByte: BYTE

-------------------------------------------------------------------------------
Write
-------------------------------------------------------------------------------


METHOD Write: UDINT

VAR_INPUT
    pbyBuffer: pointer;
    udiSize: UDINT;
END_VAR

-------------------------------------------------------------------------------
WriteByte
-------------------------------------------------------------------------------


METHOD WriteByte: ULINT

VAR_INPUT
    byByte: BYTE;
END_VAR