#include-once

; #INDEX# =======================================================================================================================
#region
; Title .........: LibNoDave
; AutoIt Version : 3.3.6.1
; Description ...: LibNoDave functions that have been translated to AutoIt functions.
; Author(s) .....: funkey, m-obi
; Dll ...........: libnodave.dll
#cs
LIBNODAVE provides a way to exchange data with Siemens PLCs of S7-200, 300 and 400 families.
It has also been successfully tested with a VIPA Speed7 CPU. It should also be useable with S7-compatible PLCs from SAIA.
Data exchange comprises all memory areas and variables you canaccess in your PLC programs, e.g. flags, data blocks,
input and output image memory, timers and counters.
Additionally, LIBNODAVE provides access to functions that are in the scope of programming software, e.g. reading diagnostic information,
read program blocks from a PLC and write them to a PLC, start and stop a PLC.

LIBNODAVE is free software under GPL and LGPL.

http://libnodave.sf.net/

#ce
#endregion
; #INDEX# =======================================================================================================================

; #VARIABLES# ===================================================================================================================
#region
Global $__ghLNDDll = 0
Global $__giLNDRef = 0
#endregion
; #VARIABLES# ===================================================================================================================

; #CONSTANTS# ===================================================================================================================
#region
Global Const $DLE = 0x10
Global Const $ETX = 0x03
Global Const $STX = 0x02
Global Const $SYN = 0x16
Global Const $NAK = 0x15
Global Const $EOT = 0x04						;  for S5
Global Const $ACK = 0x06						;  for S5

Global Const $LNDAVE_PROTO_MPI = 0				; MPI for S7 300/400
Global Const $LNDAVE_PROTO_MPI2	= 1				; MPI for S7 300/400, "Andrew's version" without STX
Global Const $LNDAVE_PROTO_MPI3	= 2				; MPI for S7 300/400, Step 7 Version, not yet implemented
Global Const $LNDAVE_PROTO_MPI4	= 3				; MPI for S7 300/400, "Andrew's version" with STX
Global Const $LNDAVE_PROTO_PPI = 10				; PPI for S7 200
Global Const $LNDAVE_PROTO_AS511 = 20			; S5 programming port protocol
Global Const $LNDAVE_PROTO_S7ONLINE = 50		; use s7onlinx.dll for transport
Global Const $LNDAVE_PROTO_ISOTCP = 122			; ISO over TCP
Global Const $LNDAVE_PROTO_ISOTCP243 = 123		; ISO over TCP with CP243
Global Const $LNDAVE_PROTO_ISOTCPR = 124		; ISO over TCP with Routing
Global Const $LNDAVE_PROTO_MPI_IBH = 223		; MPI with IBH NetLink MPI to ethernet gateway
Global Const $LNDAVE_PROTO_PPI_IBH = 224		; PPI with IBH NetLink PPI to ethernet gateway
Global Const $LNDAVE_PROTO_NLPRO = 230			; MPI with NetLink Pro MPI to ethernet gateway
Global Const $LNDAVE_PROTO_USERTRANSPORT = 255	; Libnodave will pass the PDUs of S7 Communication to user
												; defined call back functions.

;   ProfiBus speed constants:
Global Const $LNDAVE_SPEED_9K = 0
Global Const $LNDAVE_SPEED_19K = 1
Global Const $LNDAVE_SPEED_187K = 2
Global Const $LNDAVE_SPEED_500K = 3
Global Const $LNDAVE_SPEED_1500K = 4
Global Const $LNDAVE_SPEED_45K = 5
Global Const $LNDAVE_SPEED_93K = 6

;    Some MPI function codes (yet unused ones may be incorrect).
Global Const $LNDAVE_FUNC_OPENS7CONNECTION = 0xF0
Global Const $LNDAVE_FUNC_READ = 0x04
Global Const $LNDAVE_FUNC_WRITE = 0x05
Global Const $LNDAVE_FUNC_REQUESTDOWNLOAD = 0x1A
Global Const $LNDAVE_FUNC_DOWNLOADBLOCK = 0x1B
Global Const $LNDAVE_FUNC_DOWNLOADENDED = 0x1C
Global Const $LNDAVE_FUNC_STARTUPLOAD = 0x1D
Global Const $LNDAVE_FUNC_UPLOAD = 0x1E
Global Const $LNDAVE_FUNC_ENDUPLOAD = 0x1F
Global Const $LNDAVE_FUNC_INSERTBLOCK = 0x28

;    S7 specific constants:
Global Const $LNDAVE_BLOCKTYPE_OB = 56			; '8'
Global Const $LNDAVE_BLOCKTYPE_DB = 65			; 'A'
Global Const $LNDAVE_BLOCKTYPE_SDB = 66			; 'B'
Global Const $LNDAVE_BLOCKTYPE_FC = 67			; 'C'
Global Const $LNDAVE_BLOCKTYPE_SFC = 68			; 'D'
Global Const $LNDAVE_BLOCKTYPE_FB = 69			; 'E'
Global Const $LNDAVE_BLOCKTYPE_SFB = 70			; 'F'

Global Const $LNDAVE_S5BLOCKTYPE_DB = 0x01
Global Const $LNDAVE_S5BLOCKTYPE_SB = 0x02
Global Const $LNDAVE_S5BLOCKTYPE_PB = 0x04
Global Const $LNDAVE_S5BLOCKTYPE_FX = 0x05
Global Const $LNDAVE_S5BLOCKTYPE_FB = 0x08
Global Const $LNDAVE_S5BLOCKTYPE_DX = 0x0C
Global Const $LNDAVE_S5BLOCKTYPE_OB = 0x10

;    Use these constants for parameter "area" in daveReadBytes and daveWriteBytes
Global Const $LNDAVE_SYSINFO = 0x3				; System info of 200 family
Global Const $LNDAVE_SYSFLAGS = 0x5				; System flags of 200 family
Global Const $LNDAVE_ANAIN = 0x6				; analog inputs of 200 family
Global Const $LNDAVE_ANAOUT = 0x7				; analog outputs of 200 family

Global Const $LNDAVE_P = 0x80    				; direct peripheral access
Global Const $LNDAVE_INPUTS = 0x81
Global Const $LNDAVE_OUTPUTS = 0x82
Global Const $LNDAVE_FLAGS = 0x83
Global Const $LNDAVE_DB = 0x84					; data blocks
Global Const $LNDAVE_DI = 0x85					; instance data blocks
Global Const $LNDAVE_LOCAL = 0x86 				; not tested
Global Const $LNDAVE_V = 0x87					; don't know what it is
Global Const $LNDAVE_COUNTER = 28				; S7 counters
Global Const $LNDAVE_TIMER = 29					; S7 timers
Global Const $LNDAVE_COUNTER200 = 30			; IEC counters (200 family)
Global Const $LNDAVE_TIMER200 = 31				; IEC timers (200 family)
Global Const $LNDAVE_SYSDATAS5 = 0x86			; system data area ?
Global Const $LNDAVE_RAWMEMORYS5 = 0			; just the raw memory

;    Library specific:
#cs
    Result codes. Genarally, 0 means ok,
    >0 are results (also errors) reported by the PLC
    <0 means error reported by library code.
#ce
Global Const $LNDAVE_RES_OK = 0							; means all ok
Global Const $LNDAVE_RES_NOPERIPHERALATADDRESS = 1		; CPU tells there is no peripheral at address
Global Const $LNDAVE_RES_MULTIPLEBITSNOTSUPPORTED = 6 	; CPU tells it does not support to read a bit block with a
														; length other than 1 bit.
Global Const $LNDAVE_RES_ITEMNOTAVAILABLE200 = 3		; means a a piece of data is not available in the CPU, e.g.
														; when trying to read a non existing DB or bit bloc of length<>1
														; This code seems to be specific to 200 family.
Global Const $LNDAVE_RES_ITEMNOTAVAILABLE = 10			; means a a piece of data is not available in the CPU, e.g.
														; when trying to read a non existing DB
Global Const $DAVEADDRESSOUTOFRANGE = 5					; means the data address is beyond the CPUs address range
Global Const $DAVEWRITEDATASIZEMISMATCH = 7				; means the write data size doesn't fit item size
Global Const $LNDAVE_RES_CANNOTEVALUATEPDU = -123    	; PDU is not understood by libnodave
Global Const $LNDAVE_RES_CPUNODATA = -124
Global Const $LNDAVE_UNKNOWNERROR = -125
Global Const $LNDAVE_EMPTYRESULTERROR = -126
Global Const $LNDAVE_EMPTYRESULTSETERROR = -127
Global Const $LNDAVE_RES_UNEXPECTEDFUNC = -128
Global Const $LNDAVE_RES_UNKNOWNDATAUNITSIZE = -129
Global Const $LNDAVE_RES_NOBUFFER = -130
Global Const $LNDAVE_NOTAVAILABLEINS5 = -131
Global Const $LNDAVE_RES_INVALIDLENGTH = -132
Global Const $LNDAVE_RES_INVALIDPARAM = -133
Global Const $LNDAVE_RES_NOTYETIMPLEMENTED = -134
Global Const $LNDAVE_RES_SHORTPACKET = -1024
Global Const $LNDAVE_RES_TIMEOUT = -1025

#cs
	Max number of bytes in a single message.
    An upper limit for MPI over serial is:
    8		transport header
    +2*240	max PDU len *2 if every character were a DLE
    +3		DLE,ETX and BCC
    = 491

    Later I saw some programs offering up to 960 bytes in PDU size negotiation

    Max number of bytes in a single message.
    An upper limit for MPI over serial is:
    8		transport header
    +2*960	max PDU len *2 if every character were a DLE
    +3		DLE,ETX and BCC
    = 1931

    For now, we take the rounded max of all this to determine our buffer size. This is ok
    for PC systems, where one k less or more doesn't matter.
#ce
Global Const $LNDAVE_MAXRAWLEN = 2048

;    Some definitions for debugging:
Global Const $LNDAVE_DEBUG_RAWREAD = 0x01				; Show the single bytes received
Global Const $LNDAVE_DEBUG_SPECIALCHARS = 0x02			; Show when special chars are read
Global Const $LNDAVE_DEBUG_RAWWRITE	= 0x04				; Show the single bytes written
Global Const $LNDAVE_DEBUG_LISTREACHABLES = 0x08		; Show the steps when determine devices in MPI net
Global Const $LNDAVE_DEBUG_INITADAPTER = 0x10			; Show the steps when Initilizing the MPI adapter
Global Const $LNDAVE_DEBUG_CONNECT = 0x20				; Show the steps when connecting a PLC
Global Const $LNDAVE_DEBUG_PACKET = 0x40
Global Const $LNDAVE_DEBUG_BYTE = 0x80
Global Const $LNDAVE_DEBUG_COMPARE = 0x100
Global Const $LNDAVE_DEBUG_EXCHANGE = 0x200
Global Const $LNDAVE_DEBUG_PDU = 0x400					; debug PDU handling
Global Const $LNDAVE_DEBUG_UPLOAD = 0x800				; debug PDU loading program blocks from PLC
Global Const $LNDAVE_DEBUG_MPI = 0x1000
Global Const $LNDAVE_DEBUG_PRINTERRORS = 0x2000			; Print error messages
Global Const $LNDAVE_DEBUG_PASSIVE = 0x4000
Global Const $LNDAVE_DEBUG_ERRORREPORTING = 0x8000
Global Const $LNDAVE_DEBUG_OPEN = 0x10000  				; print messages in openSocket and setPort
Global Const $LNDAVE_DEBUG_ALL = 0x1ffff

;  IBH-NetLink packet types:
Global Const $LNDAVE_PT_EMPTY = -2
Global Const $LNDAVE_PT_MPIACK = -3
Global Const $LNDAVE_PT_UNKNOWNMPIFUNC = -4
Global Const $LNDAVE_PT_UNKNOWNPDUFUNC = -5
Global Const $LNDAVE_PT_READRESPONSE = 1
Global Const $LNDAVE_PT_WRITERESPONSE = 2

;    Some data types:
Global Const $tagUC = "byte"						; unsigned char
Global Const $tagUS = "ushort"
Global Const $tagU32 = "uint"

Global Const $tagPDU = _
		"ptr header;" & _
		"ptr param;" & _
		"ptr data;" & _
		"ptr udata;" & _
		"int hlen;" & _
		"int plen;" & _
		"int dlen;" & _
		"int udlen"

Global Const $tagLNDAVEOSSERIALTYPE = "HANDLE rfd; HANDLE wfd"

Global Const $tagLNDAVEINTERFACE = _
		"long timeout;" & _
		$tagLNDAVEOSSERIALTYPE & ";" & _
		"INT localMPI;" & _
		"int users;" & _
		"char name[20];" & _
		"INT protocol;" & _
		"INT speed;" & _
		"INT ackPos;" & _
		"INT nextConnection;" & _
		"INT_PTR initAdapter;" & _
		"INT_PTR connectPLC;" & _
		"INT_PTR disconnectPLC;" & _
		"INT_PTR disconnectAdapter;" & _
		"INT_PTR exchange;" & _
		"INT_PTR sendMessage;" & _
		"INT_PTR getResponse;" & _
		"INT_PTR listReachablePartners;" & _
		"char realName[20];" & _
		"INT_PTR ifread;" & _
		"INT_PTR ifwrite;" & _
		"INT seqNumber"

Global Const $tagLNDAVES5REAINFO = "int area;int DBnumber;int address;int len;ptr next"

Global Const $tagLNDAVES5CACHE = "int PAE;int PAA;int flags;int timers;int counters;int systemData;ptr first"

Global Const $tagLNDAVECONNECTION = _
		"int AnswLen;" & _
		"ptr resultPointer;" & _
		"int maxPDUlength;" & _
		"int MPIAdr;" & _
		"ptr iface;" & _
		"int needAckNumber;" & _
		"int PDUnumber;" & _
		"int ibhSrcConn;" & _
		"int ibhDstConn;" & _
		"byte msgIn[" & $LNDAVE_MAXRAWLEN & "];" & _
		"byte msgOut[" & $LNDAVE_MAXRAWLEN & "];" & _
		"ptr _resultPointer;" & _
		"int PDUstartO;" & _
		"int PDUstartI;" & _
		"int rack;" & _
		"int slot;" & _
		"int connectionNumber;" & _
		"int connectionNumber2;" & _
		"byte messageNumber;" & _
		"byte packetNumber;" & _
		"ptr hook;" & _
		"ptr cache"

Global Const $tagLNDAVEBLOCKTYPEENTRY = "byte type[2];ushort count"

Global Const $tagLNDAVEBLOCKENTRY = "ushort number;byte type[2]"

Global Const $tagLNDAVEBLOCKINFO = _
		"byte type[2];" & _
		"byte x1[2];" & _
		"byte w1[2];" & _
		"char pp[2];" & _
		"byte x2[4];" & _
		"ushort number;" & _
		"byte x3[26];" & _
		"ushort length;" & _
		"byte x4[16];" & _
		"byte name[8];" & _
		"byte x5[12]"

Global Const $tagLNDAVERESULT = "int error;int length;ptr bytes"

Global Const $tagLNDAVERESULTSET = "int numResults;ptr results"
#endregion
; #CONSTANTS# ===================================================================================================================

; #CURRENT# =====================================================================================================================
#region

#endregion
; #CURRENT# =====================================================================================================================


Func _LibNoDave_ClosePort($_hPort)
	Local $_aRet = DllCall($__ghLNDDll, "int", "closePort", "handle", $_hPort)
	If @error Then Return SetError(1, @error, 0)
	If $_aRet[0] < 0 Then Return SetError(2, $_aRet[0], 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_CloseS7online($_hWnd)
	Local $_aRet = DllCall($__ghLNDDll, "handle", "closeS7online", "int", $_hWnd)
	If @error Then Return SetError(1, @error, 0)
	If $_aRet[0] <= 0 Then Return SetError(2, $_aRet[0], 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_CloseSocket($_iSocket)
	Local $_aRet = DllCall($__ghLNDDll, "int", "closeSocket", "int", $_iSocket)
	If @error Then Return SetError(1, @error, 0)
	If $_aRet[0] < 0 Then Return SetError(2, $_aRet[0], 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_Deinit()
	If $__ghLNDDll = 0 Then Return SetError(1, 0, False)

	$__giLNDRef -= 1
	If $__giLNDRef = 0 Then
		DllClose($__ghLNDDll)
		$__ghLNDDll = 0
	EndIf
	Return True
EndFunc


Func _LibNoDave_Free($_pConnection)
	DllCall($__ghLNDDll, "none", "daveFree", "ptr", $_pConnection)
	If @error Then Return SetError(@error, 0, False)
	Return True
EndFunc


Func _LibNoDave_GetDebug()
	Local $_aRet = DllCall($__ghLNDDll, "int", "daveGetDebug")
	If @error Then Return SetError(@error, 0, 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_GetTimeout(ByRef $_pInterface)
	Local $_aRet = DllCall($__ghLNDDll, "int", "daveGetTimeout", "ptr", $_pInterface)
	If @error Then Return SetError(@error, 0, 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_Init($_sDll = "libnodave.dll")
	$__giLNDRef += 1
	If $__giLNDRef > 1 Then Return True

	$__ghLNDDll = DllOpen($_sDll)
	If $__ghLNDDll = -1 Then Return SetError(1, 0, False)
	Return True
EndFunc


Func _LibNoDave_MPIConnect($_sPort, $_sBaud, ByRef $_hPort, ByRef $_hInterface, ByRef $_hConnection, $_iCPURack = 0, $_iCPUSlot = 2, $_sName = "SPS")
	If Not $__ghLNDDll Then _LibNoDave_Init()
	$_hPort = _LibNoDave_SetPort($_sPort, $_sBaud, "o")
	If @error Then Return SetError(1, 0, 0)
	Local $_tFDS = DllStructCreate($tagLNDAVEOSSERIALTYPE)
	DllStructSetData($_tFDS, "rfd", $_hPort)
	DllStructSetData($_tFDS, "wfd", $_hPort)
	$_hInterface = _LibNoDave_NewInterface($_tFDS, $_sName, 0, $LNDAVE_PROTO_MPI)
	If @error Then
		_LibNoDave_MPIDisconnect($_hPort, $_hInterface, $_hConnection)
		Return SetError(2, 0, 0)
	EndIf
	_LibNoDave_InitAdapter($_hInterface)
	$_hConnection = _LibNoDave_NewConnection($_hInterface, $_iCPUSlot, 0, $_iCPURack)
	If @error Then
		_LibNoDave_MPIDisconnect($_hPort, $_hInterface, $_hConnection)
		Return SetError(3, 0, 0)
	EndIf
	Return _LibNoDave_ConnectPLC($_hConnection)
EndFunc


Func _LibNoDave_MPIDisconnect(ByRef $_hPort, ByRef $_hInterface, ByRef $_hConnection)
	If $_hConnection Then
		_LibNoDave_DisconnectPLC($_hConnection)
		_LibNoDave_Free($_hConnection)
	EndIf
	If $_hInterface Then
		_LibNoDave_DisconnectAdapter($_hInterface)
		_LibNoDave_Free($_hInterface)
	EndIf
	If $_hPort Then _LibNoDave_ClosePort($_hPort)
	Return True
EndFunc


Func _LibNoDave_OpenS7online($_sAccessPoint= "S7online", $_hWnd = "")
	If $_hWnd = "" Then $_hWnd = __GetHwndFromPID()
	Local $_aRet = DllCall($__ghLNDDll, "handle", "openS7online", "str", $_sAccessPoint, "hwnd", $_hWnd)
	If @error Then Return SetError(1, @error, 0)
	If $_aRet[0] <= 0 Then Return SetError(2, $_aRet[0], 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_OpenSocket($_sIP, $_iPort = 102)
	Local $_aRet = DllCall($__ghLNDDll, "int", "openSocket", "int", $_iPort, "str", $_sIP)
	If @error Then Return SetError(1, @error, 0)
	If $_aRet[0] <= 0 Then Return SetError(2, $_aRet[0], 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_ReadBytes(ByRef $_hConnection, $_iArea, $_iDB, $_iStart, $_iLen)
	;reads max. 224 Bytes!!	<-- PDU from CPU 315 = 240 Bytes
	Local $_iLenCount = 1
	If $_iArea = $LNDAVE_COUNTER Or $_iArea = $LNDAVE_TIMER Then $_iLenCount = 2
	Local $_tBuffer = DLLStructCreate("byte buffer[" & $_iLen * $_iLenCount & "]")
	Local $_aRet = DllCall($__ghLNDDll, "int", "daveReadBytes", "ptr", $_hConnection, "int", $_iArea, "int", $_iDB, "int", $_iStart, "int", $_iLen, "ptr", DllStructGetPtr($_tBuffer, "buffer"))
	If @error Then Return SetError(@error, 0, 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_S5Connect($_sPort, ByRef $_hPort, ByRef $_hInterface, ByRef $_hConnection, $_sName = "SPS")
	If Not $__ghLNDDll Then _LibNoDave_Init()
	$_hPort = _LibNoDave_SetPort($_sPort, 9600, "e")
	If @error Then Return SetError(1, 0, 0)
	Local $_tFDS = DllStructCreate($tagLNDAVEOSSERIALTYPE)
	DllStructSetData($_tFDS, "rfd", $_hPort)
	DllStructSetData($_tFDS, "wfd", $_hPort)
	$_hInterface = _LibNoDave_NewInterface($_tFDS, $_sName, 0, $LNDAVE_PROTO_AS511)
	If @error Then
		_LibNoDave_S5Disconnect($_hPort, $_hInterface, $_hConnection)
		Return SetError(2, 0, 0)
	EndIf
	_LibNoDave_SetTimeout($_hInterface, 100000)
	_LibNoDave_InitAdapter($_hInterface)
	$_hConnection = _LibNoDave_NewConnection($_hInterface, 2, 0, 0)
	If @error Then
		_LibNoDave_S5Disconnect($_hPort, $_hInterface, $_hConnection)
		Return SetError(3, 0, 0)
	EndIf
	Local $_iResult = _LibNoDave_ConnectPLC($_hConnection)
	If $_iResult <> 0 Then
		_LibNoDave_S5Disconnect($_hPort, $_hInterface, $_hConnection)
		Return SetError(4, $_iResult, 0)
	EndIf
	Return $_iResult
EndFunc


Func _LibNoDave_S5Disconnect(ByRef $_hPort, ByRef $_hInterface, ByRef $_hConnection)
	If $_hConnection Then
		_LibNoDave_DisconnectPLC($_hConnection)
		_LibNoDave_Free($_hConnection)
	EndIf
	If $_hInterface Then
		_LibNoDave_DisconnectAdapter($_hInterface)
		_LibNoDave_Free($_hInterface)
	EndIf
	If $_hPort Then _LibNoDave_ClosePort($_hPort)
	Return True
EndFunc


Func _LibNoDave_SetDebug($_iDebug)
	DllCall($__ghLNDDll, "none", "daveSetDebug", "int", $_iDebug)
	If @error Then Return SetError(@error, 0, False)
	Return True
EndFunc


Func _LibNoDave_SetPort($_sPort, $_sBaud, $_sParity)
	Local $_tParity = DllStructCreate("wchar parity")
	DllStructSetData($_tParity, "parity", AscW($_sParity))
	Local $_aRet = DllCall($__ghLNDDll, "int", "setPort", "str", $_sPort, "str", $_sBaud, "ptr", DllStructGetPtr($_tParity))
	If @error Then Return SetError(1, @error, 0)
	If $_aRet[0] < 0 Then Return SetError(2, $_aRet[0], 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_SetTimeout(ByRef $_pInterface, $_iTimeout)
	DllCall($__ghLNDDll, "none", "daveSetTimeout", "ptr", $_pInterface, "int", $_iTimeout)
	If @error Then Return SetError(@error, 0, False)
	Return True
EndFunc


Func _LibNoDave_Strerror($_iError)
	Local $_aRet = DllCall($__ghLNDDll, "str", "daveStrerror", "int", $_iError)
	If @error Then Return SetError(@error, 0, 0)
	Return $_aRet[0]
EndFunc


Func _LibNoDave_TCPConnect($_sIP, ByRef $_iSocket, ByRef $_hInterface, ByRef $_hConnection, $_iCPURack = 0, $_iCPUSlot = 2, $_sName = "SPS")
	If $__ghLNDDll = 0 Then _LibNoDave_Init()
	If @error Then Return SetError(1, 0, 0)
	$_iSocket = _LibNoDave_OpenSocket($_sIP)
	If @error Then Return SetError(2, 0, 0)
	Local $_tFDS = DllStructCreate($tagLNDAVEOSSERIALTYPE)
	DllStructSetData($_tFDS, "rfd", $_iSocket)
	DllStructSetData($_tFDS, "wfd", $_iSocket)
	$_hInterface = _LibNoDave_NewInterface($_tFDS, $_sName, 0, $LNDAVE_PROTO_ISOTCP)
	If @error Then
		_LibNoDave_TCPDisconnect($_iSocket, $_hInterface, $_hConnection)
		Return SetError(3, 0, 0)
	EndIf
	_LibNoDave_InitAdapter($_hInterface)
	$_hConnection = _LibNoDave_NewConnection($_hInterface, $_iCPUSlot, 0, $_iCPURack)
	If @error Then
		_LibNoDave_TCPDisconnect($_iSocket, $_hInterface, $_hConnection)
		Return SetError(4, 0, 0)
	EndIf
	Return _LibNoDave_ConnectPLC($_hConnection)
EndFunc


Func _LibNoDave_TCPDisconnect(ByRef $_iSocket, ByRef $_hInterface, ByRef $_hConnection)
	If $_hConnection Then
		_LibNoDave_DisconnectPLC($_hConnection)
		_LibNoDave_Free($_hConnection)
	EndIf
	If $_hInterface Then
		_LibNoDave_DisconnectAdapter($_hInterface)
		_LibNoDave_Free($_hInterface)
	EndIf
	If $_iSocket Then _LibNoDave_CloseSocket($_iSocket)
	Return True
EndFunc






Func _LibNoDave_GetOrderCode(ByRef $_pConnection)
	Local $_tBuffer = DLLStructCreate("char buffer[21]")
	DllCall($__ghLNDDll, "int", "daveGetOrderCode", "ptr", $_pConnection, "ptr", DllStructGetPtr($_tBuffer, "buffer"))
	Return DllStructGetData($_tBuffer, "buffer")
EndFunc


Func _LibNoDave_NewInterface($fds, $nname = "IF1", $localMPI = 0, $protocol = $LNDAVE_PROTO_ISOTCP, $speed = $LNDAVE_SPEED_187K)
    If IsPtr($fds) Then
        Local $i_fds = $fds
    Else
        Local $i_fds = DllStructGetPtr($fds)
    EndIf
    Local $di = DllCall($__ghLNDDll, "HANDLE", "davePascalNewInterface", "ptr", $i_fds, "str", $nname, "int", $localMPI, "int", $protocol, "int", $speed)
    If @error Then Return SetError(1,@error,0)
    Return $di[0]
EndFunc


Func _LibNoDave_InitAdapter($di)
    Local $ret = DllCall($__ghLNDDll, "int", "daveInitAdapter", "ptr", $di)
	Return $ret[0]
EndFunc


Func _LibNoDave_NewConnection($di, $iSlot = 2, $iMPI_Address = 2, $iRack = 0)
    Local $ret = DllCall($__ghLNDDll, "ptr", "daveNewConnection", "ptr", $di, "int", $iMPI_Address, "int", $iRack, "int", $iSlot)
	Return $ret[0]
EndFunc


Func _LibNoDave_ConnectPLC($dc)
    Local $ret = DllCall($__ghLNDDll, "int", "daveConnectPLC", "ptr", $dc)
	Return $ret[0]
EndFunc


Func _LibNoDave_DisconnectPLC($dc)
    Local $ret = DllCall($__ghLNDDll, "int", "daveDisconnectPLC", "ptr", $dc)
	Return $ret[0]
EndFunc


Func _LibNoDave_DisconnectAdapter($di)
    Local $ret = DllCall($__ghLNDDll, "int", "daveDisconnectAdapter", "ptr", $di)
	Return $ret[0]
EndFunc


Func _setTimeOut($di, $iTime)
    DllCall($__ghLNDDll, "none", "setTimeOut", "ptr", $di, "int", $iTime)
EndFunc

Func _LibNoDave_ReadSZL(ByRef $dc, $iID = 0, $iIndex = 0, $iAnzahl = 1000)
	Local $Buffer = DLLStructCreate("byte buffer["&$iAnzahl&"]"), $Werte[$iAnzahl]
	$aRet = DllCall($__ghLNDDll, "int", "daveReadSZL", "ptr", $dc, "int", $iID, "int", $iIndex, "ptr", DllStructGetPtr($Buffer, 'buffer'), "int", $iAnzahl)
	For $i = 1 To $iAnzahl
		$Werte[$i-1] = DllStructGetData($Buffer, 'buffer', $i)
	Next
	Return $Werte
EndFunc

Func _LibNoDave_GetCycleTimeMin(ByRef $dc)
	Local $aInfo = _LibNoDave_ReadSZL($dc, 0x222, 1, 20)
	Return BitShift($aInfo[16], -8) +  $aInfo[17]
EndFunc

Func _LibNoDave_GetCycleTimeMax(ByRef $dc)
	Local $aInfo = _LibNoDave_ReadSZL($dc, 0x222, 1, 20)
	Return BitShift($aInfo[18], -8) +  $aInfo[19]
EndFunc

Func _LibNoDave_GetCycleTime(ByRef $dc)
	Local $aInfo = _LibNoDave_ReadSZL($dc, 0x222, 1, 20)
	Return BitShift($aInfo[14], -8) +  $aInfo[15]
EndFunc

Func _LibNoDave_GetCycleTimeLimit(ByRef $dc)
	Local $aInfo = _LibNoDave_ReadSZL($dc, 0x222, 80, 20)
	Return BitShift($aInfo[18], -8) +  $aInfo[19]
EndFunc

Func _LibNoDave_GetBlockInfo(ByRef $dc, $type, $iNumber)
	Local $db_info = DllStructCreate($tagLNDAVEBLOCKINFO)
	Local $p_dbi = DllStructGetPtr($db_info)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetBlockInfo", "ptr", $dc, "ptr", $p_dbi, "byte", $type, "int", $iNumber)
	Return SetError(@error, $aRet[0], DllStructGetData($db_info, "length"))
EndFunc


Func _LibNoDave_ReadManyBytes(ByRef $_pConnection, $_iArea, $_iDB, $_iStart, $_iLen)
	Local $_iLenCount = 1
	If $_iArea = $LNDAVE_COUNTER Or $_iArea = $LNDAVE_TIMER Then $_iLenCount = 2
	Local $Buffer = DLLStructCreate("byte buffer[" & $_iLen * $_iLenCount & "]")
	Local $_aRet = DllCall($__ghLNDDll, "int", "daveReadManyBytes", "ptr", $_pConnection, "int", $_iArea, "int", $_iDB, "int", $_iStart, "int", $_iLen, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	Return $_aRet[0]
EndFunc

Func _LibNoDave_ReadPEW(ByRef $dc, $iStart, $iCount)
	Local $aPEW[$iCount]
	Local $Res = _LibNoDave_ReadBytes($dc, $LNDAVE_P, 0, $iStart, $iCount * 2)
	If $Res Then Return SetError(1)
	For $i = 0 To $iCount - 1
		$aPEW[$i] = _LibNoDave_GetS16($dc)
	Next
	Return $aPEW
EndFunc

Func _LibNoDave_ReadBits(ByRef $dc, $iArea, $iDB, $iStart, $iLen = 1)
	Local $Buffer = DLLStructCreate("BYTE buffer["&$iLen&"]")
	Local $aBits[$iLen]
	$aRet = DllCall($__ghLNDDll, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	For $i = 1 To $iLen
		$aBits[$i - 1] = DllStructGetData($Buffer, 1, $i)
	Next
	Return SetError($aRet[0], 0, $aBits)
EndFunc

Func _LibNoDave_ReadBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
	Local $Buffer = DLLStructCreate("BYTE buffer[1]")
	Local $_aRet = DllCall($__ghLNDDll, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte * 8 + $iBit, "int", 1, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	If @error Then Return SetError(1, @error, False)
	If $_aRet[0] < 0 Then Return SetError(2, $_aRet[0], False)
	Return DllStructGetData($Buffer, 1, 1) = 1
EndFunc

Func _LibNoDave_ReadReal($dc, $iArea, $iDB, $iStart, $iLen)
	;reads max. 56 floats! --> 224 Bytes!!	<-- PDU from CPU 315 = 240 Bytes
	Local $Werte[$iLen]
	$aRet = DllCall($__ghLNDDll, "int", "daveReadBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen * 4, "ptr", 0)
	For $i = 1 To $iLen
		$Werte[$i-1] = _LibNoDave_GetFloat($dc)
	Next
	Return SetError($aRet[0], 0, $Werte)
EndFunc

Func _LibNoDave_ReadManyReal($dc, $iArea, $iDB, $iStart, $iLen)
	Local $Werte[$iLen]
	$aRet = DllCall($__ghLNDDll, "int", "daveReadManyBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen * 4, "ptr", 0)
	For $i = 1 To $iLen
		$Werte[$i-1] = _LibNoDave_GetFloat($dc)
	Next
	Return SetError($aRet[0], 0, $Werte)
EndFunc

Func _LibNoDave_GetS8(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS8", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU8(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetU8", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS16(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS16", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU16(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetU16", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS32(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS32", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU32(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "uint", "daveGetU32", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetFloat(ByRef $dc)
	$aRet = DllCall($__ghLNDDll, "float", "daveGetFloat", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS8from(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS8from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU8from(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetU8from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS16from(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS16from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU16from(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetU16from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS32from(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS32from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU32from(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "uint", "daveGetU32from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetFloatfrom(ByRef $b)
	$aRet = DllCall($__ghLNDDll, "float", "daveGetFloatfrom", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS8At(ByRef $dc, $iPos)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS8At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU8At(ByRef $dc, $iPos)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetU8At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS16At(ByRef $dc, $iPos)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetS16At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU16At(ByRef $dc, $iPos)
	$aRet = DllCall($__ghLNDDll, "int", "daveGetU16At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetS32At(ByRef $dc, $iPos)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetS32At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetU32At(ByRef $dc, $iPos)
	Local $aRet = DllCall($__ghLNDDll, "uint", "daveGetU32At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetFloatAt(ByRef $dc, $iPos)
	Local $aRet = DllCall($__ghLNDDll, "float", "daveGetFloatAt", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetSeconds(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "float", "daveGetSeconds", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetSecondsAt(ByRef $dc, $iPos)
	Local $aRet = DllCall($__ghLNDDll, "float", "daveGetSecondsAt", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetCounterValue(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetCounterValue", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetCounterValueAt(ByRef $dc, $iPos)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetCounterValueAt", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _LibNoDave_Put8(ByRef $p, $Byte)
	Local $aRet = DllCall($__ghLNDDll, "ptr", "davePut8", "ptr", $p, "int", $Byte)
	$p = $aRet[0]
EndFunc

Func _LibNoDave_Put16(ByRef $p, $Word)
	Local $aRet = DllCall($__ghLNDDll, "ptr", "davePut16", "ptr", $p, "int", $Word)
	$p = $aRet[0]
EndFunc

Func _LibNoDave_Put32(ByRef $p, $DWord)
	Local $aRet = DllCall($__ghLNDDll, "ptr", "davePut32", "ptr", $p, "int", $DWord)
	Return $aRet[0]
EndFunc

Func _LibNoDave_PutFloat(ByRef $p, $Float)
	Local $aRet = DllCall($__ghLNDDll, "ptr", "davePutFloat", "ptr", $p, "float", $Float)
	$p = $aRet[0]
EndFunc

Func _LibNoDave_PutKG(ByRef $p, $KG)
	Local $aRet = DllCall($__ghLNDDll, "ptr", "davePutKG", "ptr", $p, "float", $KG)
	Return $aRet[0]
EndFunc

Func _LibNoDave_Put8At(ByRef $p, $iPos, $Byte)
	Local $aRet = DllCall($__ghLNDDll, "none", "davePut8At", "ptr", $p, "int", $iPos, "int", $Byte)
	Return $aRet[0]
EndFunc

Func _LibNoDave_Put16At(ByRef $p, $iPos, $Word)
	Local $aRet = DllCall($__ghLNDDll, "none", "davePut16At", "ptr", $p, "int", $iPos, "int", $Word)
	Return $aRet[0]
EndFunc

Func _LibNoDave_Put32At(ByRef $p, $iPos, $DWord)
	Local $aRet = DllCall($__ghLNDDll, "none", "davePut32At", "ptr", $p, "int", $iPos, "int", $DWord)
	Return $aRet[0]
EndFunc

Func _LibNoDave_PutFloatAt(ByRef $p, $iPos, $Float)
	Local $aRet = DllCall($__ghLNDDll, "none", "davePutFloatAt", "ptr", $p, "int", $iPos, "float", $Float)
	Return $aRet[0]
EndFunc

Func _LibNoDave_PutKGAt(ByRef $p, $iPos, $KG)
	Local $aRet = DllCall($__ghLNDDll, "none", "davePutKGAt", "ptr", $p, "int", $iPos, "float", $KG)
	Return $aRet[0]
EndFunc

Func _LibNoDave_WriteBytes(ByRef $dc, $iArea, $iDB, $iByte, $iLen, $Value)
	Local $Buf = DllStructCreate("byte[" & $iLen & "]")
	For $i = 1 To $iLen
		DllStructSetData($Buf, 1, BitShift(Int($Value), ($i - 1) * 8), $iLen - ($i - 1))
	Next
	DllCall($__ghLNDDll, "int", "daveWriteBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte, "int", $iLen, "ptr", DllStructGetPtr($Buf))
EndFunc

Func _LibNoDave_WriteBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit, $Value)
	Local $Buf = DllStructCreate("byte")
	DllStructSetData($Buf, 1, Int($Value))
	DllCall($__ghLNDDll, "int", "daveWriteBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte*8+$iBit, "int", 1, "ptr", DllStructGetPtr($Buf))
EndFunc

Func _LibNoDave_SetBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
	DllCall($__ghLNDDll, "int", "daveSetBit", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte, "int", $iBit)
EndFunc

Func _LibNoDave_ClrBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
	DllCall($__ghLNDDll, "int", "daveClrBit", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte, "int", $iBit)
EndFunc

Func _LibNoDave_GetMPIAdr(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetMPIAdr", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetAnswLen(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetAnswLen", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetMaxPDULen(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetMaxPDULen", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_Start(ByRef $_pConnection)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveStart", "ptr", $_pConnection)
	If @error Then Return SetError(@error, 0, 0)
	Return $aRet[0]
EndFunc

Func _LibNoDave_Stop($_pConnection)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveStop", "ptr", $_pConnection)
	If @error Then Return SetError(@error, 0, 0)
	Return $aRet[0]
EndFunc

Func _LibNoDave_CopyRAMtoROM(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveCopyRAMtoROM", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_FromBCD($int)
	Local $aRet = DllCall($__ghLNDDll, "byte", "daveFromBCD", "byte", $int)
	Return $aRet[0]
EndFunc

Func _LibNoDave_ToBCD($int)
	Local $aRet = DllCall($__ghLNDDll, "byte", "daveToBCD", "byte", $int)
	Return $aRet[0]
EndFunc

Func _LibNoDave_SetPLCTimeToSystime(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveSetPLCTimeToSystime", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_GetResponse(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetResponse", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _LibNoDave_PrepareReadRequest(ByRef $dc, ByRef $p)
	DllCall($__ghLNDDll, "none", "davePrepareReadRequest", "ptr", $dc, "ptr", $p)
EndFunc

Func _LibNoDave_AddVarToReadRequest(ByRef $p, $iArea, $iDB, $iStart, $iLen)
	DllCall($__ghLNDDll, "none", "daveAddVarToReadRequest", "ptr", $p, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen)
EndFunc

Func _LibNoDave_ExecReadRequest(ByRef $dc, ByRef $p, ByRef $res)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveExecReadRequest", "ptr", $dc, "ptr", $p, "ptr", $res)
	Return $aRet[0]
EndFunc

Func _LibNoDave_UseResult(ByRef $dc, ByRef $rs, $n)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveUseResult", "ptr", $dc, "ptr", $rs, "int", $n)
	Return $aRet[0]
EndFunc

Func _LibNoDave_FreeResults(ByRef $rs)
	DllCall($__ghLNDDll, "none", "daveFreeResults", "ptr", $rs)
EndFunc

Func _LibNoDave_AddBitVarToReadRequest(ByRef $p, $iArea, $iDB, $iStart, $iLen)
	DllCall($__ghLNDDll, "none", "daveAddBitVarToReadRequest", "ptr", $p, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen)
EndFunc

Func _LibNoDave_PrepareMultipleRead(ByRef $dc, ByRef $a_p, $aResList)
	_LibNoDave_PrepareReadRequest($dc, $a_p[0])
	For $i = 0 To UBound($aResList, 1) -1
		_LibNoDave_AddVarToReadRequest($a_p[0], $aResList[$i][0], $aResList[$i][1], $aResList[$i][2], $aResList[$i][3])
	Next
EndFunc

Func _LibNoDave_MultipleRead(ByRef $dc, ByRef $a_p, $aResList)
	Local $iUbound = _LibNoDave_GetResultSum($aResList)
	Local $iRes = @extended
	Local $ByteArray[$iUbound], $n = 0
	Local $err = _LibNoDave_ExecReadRequest($dc, $a_p[0], $a_p[1])
	If $err Then
		ConsoleWrite("daveExecReadRequest: - " & _LibNoDave_Strerror($err) & @cr)
		Return SetError(1)
	EndIf
	For $i = 0 To UBound($aResList, 1) -1
		$err = _LibNoDave_UseResult($dc, $a_p[1], $i)
		For $j = 0 To ($aResList[$i][3] - 1) / $aResList[$i][5]
			$ByteArray[$n] = Call("_LibNoDave_Get" & $aResList[$i][4], $dc)
			$n += 1
		Next
	Next
	 _LibNoDave_FreeResults($a_p[1])
	 Return $ByteArray
EndFunc

Func _LibNoDave_ReadMultiple(ByRef $dc, $aResList)
	Local $pdu1 = DllStructCreate($tagPDU)
	Local $rs1 = DllStructCreate($tagLNDAVERESULTSET)
	Local $a_p[2] = [DllStructGetPtr($pdu1), DllStructGetPtr($rs1)]
	_LibNoDave_PrepareReadRequest($dc, $a_p[0])
	For $i = 0 To UBound($aResList, 1) -1
		_LibNoDave_AddVarToReadRequest($a_p[0], $aResList[$i][0], $aResList[$i][1], $aResList[$i][2], $aResList[$i][3])
	Next
	Local $iUbound = _LibNoDave_GetResultSum($aResList)
	Local $iRes = @extended
	Local $ByteArray[$iUbound], $n = 0
	Local $err = _LibNoDave_ExecReadRequest($dc, $a_p[0], $a_p[1])
	If $err Then
		ConsoleWrite("daveExecReadRequest: - " & _LibNoDave_Strerror($err) & @cr)
		Return SetError(1)
	EndIf
	For $i = 0 To UBound($aResList, 1) -1
		$err = _LibNoDave_UseResult($dc, $a_p[1], $i)
		For $j = 0 To ($aResList[$i][3] - 1) / $aResList[$i][5]
			$ByteArray[$n] = Call("_LibNoDave_Get" & $aResList[$i][4], $dc)
			$n += 1
		Next
	Next
	 _LibNoDave_FreeResults($a_p[1])
	 Return $ByteArray
EndFunc

Func _LibNoDave_GetResultSum($a)
	Local $Sum = 0, $SumExt = 0
	For $i = 0 To UBound($a) - 1
			$Sum += $a[$i][3] / $a[$i][5]
			$SumExt += $a[$i][3]
	Next
	Return SetExtended($SumExt, $Sum)
EndFunc

Func _LibNoDave_ReadPLCTime(ByRef $dc)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveReadPLCTime", "ptr", $dc)
	If $aRet[0] <> 0 Then Return SetError(1)
	Local $aTime[10]
	For $i = 0 To 9
		$aTime[$i] = _LibNoDave_FromBCD(_LibNoDave_GetU8($dc))
	Next
	Return $aTime
EndFunc

#cs
Byte 0: ist wohl Reserve
Byte 1: ist wohl immer &h19
Byte 1, Jahreszahl von 90 ...89, d.h. die Jahre von 1990 bis 2089
Byte 3: Monat
Byte 4: Tag
Byte 5: Stunde
Byte 6: Minute
Byte 7: Sekunde
Byte 8: Hunderter und Zehner der Millisekunden
Byte 9: oberes Nibbel: Einer der Millisekunden
unteres Nibbel: Wochentag 1 ... 7 (1=Sonntag)
#ce

Func _LibNoDave_GetPLCTimeString(ByRef $dc)
	Local $aTime = _LibNoDave_ReadPLCTime($dc)
	Local $sTime, $Year, $WDay
	If $aTime[2] > 89 Then
		$Year = "19" & $aTime[2]
	Else
		$Year = "20" & $aTime[2]
	EndIf
	Local $iHelper = $aTime[8] * 100 + $aTime[9]
	$WDay = __Locale_DayName(Mod($iHelper, 10) - 1)
	Return StringFormat("%s, %02s.%02s.%04s %02s:%02s:%02s.%03s", $WDay, $aTime[4], $aTime[3], $Year, $aTime[5], $aTime[6], $aTime[7], Floor($iHelper / 10))
EndFunc

Func _LibNoDave_ListBlocks(ByRef $dc)
	Local $tStruct = "byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort"
	Local $dbte = DllStructCreate($tStruct)
	Local $p_dbte = DllStructGetPtr($dbte)

	DllCall($__ghLNDDll, "int", "daveListBlocks", "ptr", $dc, "ptr", $p_dbte)

	Local $aRes[7][2]
	For $i = 0 To 6
		$aRes[$i][0] = DllStructGetData($dbte, 2*$i + 1, 2)
		$aRes[$i][1] = DllStructGetData($dbte, 2*$i + 2)
	Next
	Return $aRes
EndFunc

#cs
Das zweite Byte ist die Sprache des Bausteins:

0x00, "Not defined"
0x01, "AWL"
0x02, "KOP"
0x03, "FUP"
0x04, "SCL"
0x05, "DB"
0x06, "GRAPH"
#ce

Func _LibNoDave_ListBlocksOfType(ByRef $dc, $type)
	Local $MaxBlockNumber = _LibNoDave_GetMaxBlockNumber($dc, $type)
	Local $aStruct = "byte type["&4*$MaxBlockNumber&"]"
	Local $dbe = DllStructCreate($aStruct)
	;Es wird ein Array des Structs erwartet!
	Local $p_dbe = DllStructGetPtr($dbe)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveListBlocksOfType", "ptr", $dc, "byte", $type, "ptr", $p_dbe)

	Local $aRes[$MaxBlockNumber][2]
	For $i = 0 To $MaxBlockNumber - 1
		$aRes[$i][0] = BitShift(DllStructGetData($dbe, "type", 4*$i+2), -8) +  DllStructGetData($dbe, "type", 4*$i+1)
;~ 		$aRes[$i][1] = DllStructGetData($dbe, "type", 4*$i+3)
		$aRes[$i][1] = DllStructGetData($dbe, "type", 4*$i+4)
	Next
	Return $aRes
EndFunc

Func _LibNoDave_GetMaxBlockNumber(ByRef $dc, $type)
	Local $aList = _LibNoDave_ListBlocks($dc)
	For $i = 0 To UBound($aList, 1)
		If $aList[$i][0] = $type Then Return $aList[$i][1]
	Next
	Return SetError(1)
EndFunc

Func _LibNoDave_BlockName($bn)
	Local $aRet = DllCall($__ghLNDDll, "str", "daveBlockName", "byte", $bn)
	Return $aRet[0]
EndFunc

Func _LibNoDave_AreaName($n)
	Local $aRet = DllCall($__ghLNDDll, "str", "daveAreaName", "byte", $n)
	Return $aRet[0]
EndFunc

;#############################################################################
; internal functions
Func __GetHwndFromPID($PID = @AutoItPID)
    Local $hWnd = 0, $stPID = DllStructCreate("int")
	Local $winlist = WinList()
	For $i = 1 To $winlist[0][0]
		If $winlist[$i][0] <> "" Then
			DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", $winlist[$i][1], "ptr", DllStructGetPtr($stPID))
			If DllStructGetData($stPID, 1) = $PID Then
				$hWnd = $winlist[$i][1]
				ExitLoop
			EndIf
		EndIf
	Next
    Return $hWnd
EndFunc ;==>__GetHwndFromPID

Func __Locale_DayName($WDay, $Abbrev = False)
    Local Const $LOCALE_USER_DEFAULT = 0x0400
    Local Const $LOCALE_SDAYNAME = 0x29
    Local Const $LOCALE_SABBREVDAYNAME = 0x30
    Local $LCType = $LOCALE_SDAYNAME
    If $Abbrev Then $LCType = $LOCALE_SABBREVDAYNAME
    If Not StringIsInt($WDay) Or $WDay < 1 Or $WDay > 7 Then Return False
    Local $aResult = DllCall("Kernel32.dll", "Int", "GetLocaleInfoA", _
                            "UInt", $LOCALE_USER_DEFAULT, _
                            "UInt", $LCType + $WDay, _
                            "Str", "", _
                            "Int", 80)
    If @error Or $aResult[0] = 0 Then Return False
    Return $aResult[3]
EndFunc

Func __StructArrayToArray($tStruct, $Teiler = 4, $MaxLen = 0)
	Local $Len = $MaxLen
	If $MaxLen = 0 Then $Len = DllStructGetSize($tStruct) / $Teiler
	Local $array[$Len]
	For $i = 1 To $Len
		$array[$i - 1] = DllStructGetData($tStruct, 1, $i)
	Next
	Return $array
EndFunc

;#############################################################################
; noch nicht fertige und nicht richtig funktionierende Funktionen

Func _initUpload($dc, $BlockType, $BlockNumber)
	Local $UploadID = DllStructCreate("int"), $p_UploadID = DllStructGetPtr($UploadID)
	Local $aRet = DllCall($__ghLNDDll, "int", "initUpload", "ptr", $dc, "byte", $BlockType, "int", $BlockNumber, "ptr", $p_UploadID)
	Return SetError($aRet[0], 0, DllStructGetData($UploadID, 1))
EndFunc

Func _doUpload($dc, ByRef $p_Buffer, $UploadID)
	Local $More = DllStructCreate("int"), $p_More = DllStructGetPtr($More)
	Local $Len = DllStructCreate("int"), $p_Len = DllStructGetPtr($Len)

	Local $aRet = DllCall($__ghLNDDll, "int", "doUpload", "ptr", $dc, "ptr", $p_More, "ptr", $p_Buffer, "ptr", $p_Len, "int", $UploadID)
	Return SetError($aRet[0], DllStructGetData($More, 1), DllStructGetData($Len, 1))
EndFunc

Func _endUpload($dc, $UploadID)
	Local $aRet = DllCall($__ghLNDDll, "int", "endUpload", "ptr", $dc, "int", $UploadID)
	Return SetError($aRet[0], 0, $aRet[0])
EndFunc

Func _readProgramBlockDummy(ByRef $dc, $BlockType, $BlockNumber)
	Local $bb = DllStructCreate("byte[20000]"), $p_bb = DllStructGetPtr($bb)
	$ID = _initUpload($dc, $BlockType, $BlockNumber)
	Local $Size = 0
	Do
		$Size += _doUpload($dc, $p_bb, $ID)
	Until @extended = 0
	_endUpload($dc, $ID)
	Local $aBlock = _LibNoDave_GetProgramBlock($dc, $BlockType, $BlockNumber, $Size)
	Return $aBlock
EndFunc


Func _readProgramBlock(ByRef $dc, $BlockType, $BlockNumber)
	Local $bb = DllStructCreate("byte[20000]"), $p_bb = DllStructGetPtr($bb)
	$ID = _initUpload($dc, $BlockType, $BlockNumber)
	Local $Buffer = DllStructCreate("byte[20000]"), $p_Buffer = DllStructGetPtr($Buffer)
	Local $Size = 0, $Size_now = 0, $aBuffer[1], $extended_save
	Do
		$Size_now = _doUpload($dc, $p_bb, $ID)
		$extended_save = @extended
		$Size += $Size_now
		ReDim $aBuffer[$Size]
		ConsoleWrite($Size & " / " & $Size_now & @cr)
		For $i = 1 To $Size_now
;~ 			$aBuffer[$Size - $Size_now + $i - 1] = Hex(DllStructGetData($Buffer, 1, $i), 2)
			$aBuffer[$Size - $Size_now + $i - 1] = DllStructGetData($bb, 1, $i)
		Next

;~ 		ConsoleWrite($Count & @cr)
;~ 		$Count += 1

	Until $extended_save = 0

	_endUpload($dc, $ID)

	ConsoleWrite($Size & @cr)

;~ 	Local $aBuffer[$Size], $sBuffer
;~ 	For $i = 1 To $Size
;~ 		$aBuffer[$i - 1] = Hex(DllStructGetData($Buffer, 1, $i), 2)
;~ 		$sBuffer &= $aBuffer[$i - 1]
;~ 	Next
	Return $aBuffer
EndFunc


Func _LibNoDave_GetProgramBlock(ByRef $dc, $BlockType, $BlockNumber, $Len)
	Local $Buffer = DllStructCreate("byte["&$Len&"]"), $Length = DllStructCreate("int")
	Local $p_Buffer = DllStructGetPtr($Buffer), $p_Length = DllStructGetPtr($Length)
	Local $aRet = DllCall($__ghLNDDll, "int", "daveGetProgramBlock", "ptr", $dc, "int", $BlockType, "int", $BlockNumber, "ptr", $p_Buffer, "ptr", $p_Length)
;~ 	ConsoleWrite($aRet[0] & @cr)
;~ Local $Size = DllStructGetData($Length, 1)
	Local $aBuffer[$Len], $sBuffer
	For $i = 1 To $Len
		$aBuffer[$i - 1] = BinaryToString("0x" & Hex(DllStructGetData($Buffer, 1, $i), 2))
		$sBuffer &= $aBuffer[$i - 1]
	Next
	Return $aBuffer
EndFunc


#cs

;    PLC program read functions:

EXPORTSPEC int DECL2 initUpload(daveConnection * dc, char blockType, int blockNr, int * uploadID); // char or uc,to decide
EXPORTSPEC int DECL2 doUpload(daveConnection*dc, int * more, uc**buffer, int*len, int uploadID);
EXPORTSPEC int DECL2 endUpload(daveConnection*dc, int uploadID);


;    Functions to load blocks from PLC:

EXPORTSPEC void DECL2 _daveConstructUpload(PDU *p, char blockType, int blockNr); // char or uc,to decide
EXPORTSPEC void DECL2 _daveConstructDoUpload(PDU * p, int uploadID);
EXPORTSPEC void DECL2 _daveConstructEndUpload(PDU * p, int uploadID);

;	Program Block from PLC:

EXPORTSPEC int DECL2 daveGetProgramBlock(daveConnection * dc, int blockType, int number, char* buffer, int * length);

#ce

;#############################################################################


