#include "libnodave.au3"
#include <Array.au3>

Opt("GUIOnEventMode", 1)

_DaveInit()
If @error Then
	MsgBox(16, "Error", "Error opening DLL file!")
	Exit 1
EndIf

OnAutoItExitRegister("_DeInit")

Global $IniFile = StringLeft(@ScriptFullPath, StringInStr(@ScriptFullPath, ".", 0, -1)) & "ini"

Global $Name, $Desc, $Protocol, $CPURack, $CPUSlot, $COMPort, $Baud, $IPAddress, $Timeout, $Interval, $MPISpeed, $MPILocal, $MPIRemote
Global $hSocket, $fds, $p_di, $p_dc
Global $bStarted = 0, $ProgressPercent = 0
Global $CycleTimeLimit, $Multiplier
Global $ah_ListViewItems[1]

If Not FileExists($IniFile) Then _CreateNewIni()
Global $aConnections = IniReadSection($IniFile, "Connections")

Global $Width = 440
Global $hGui = GUICreate("LibNoDave Demo Gui for Autoit", $Width, 400)
GUISetOnEvent(-3, "_Exit")

GUICtrlCreateLabel("Connection:", 10, 10, 60, 20, 0x201)
Global $hConnection = GUICtrlCreateCombo("", 80, 10, 120, 70, 0x003)
For $i = $aConnections[0][0] To 1 Step -1
	GUICtrlSetData(-1, $aConnections[$i][0], $aConnections[$i][0])
Next
	
GUICtrlCreateButton("Edit", 210, 10, 50, 20)
GUICtrlSetOnEvent(-1, "_ShowConfigGuiEdit")
GUICtrlCreateButton("New", 270, 10, 50, 20)
GUICtrlSetOnEvent(-1, "_ShowConfigGuiNew")
GUICtrlCreateLabel("", 0, 40, $Width, 2, 0x1000)

Global $hListView = GUICtrlCreateListView("Address|Value", 10, 50, 200, 340)
GUICtrlSendMsg(-1, 0x1000 + 30, 0, 100)
GUICtrlSendMsg(-1, 0x1000 + 30, 1, -2)

GUICtrlCreateLabel("Area:", 230, 50, 60, 20, 0x200)
GUICtrlCreateLabel("DB:", 230, 80, 60, 20, 0x200)
GUICtrlCreateLabel("Type:", 230, 110, 60, 20, 0x200)
GUICtrlCreateLabel("Offset:", 230, 140, 60, 20, 0x200)
GUICtrlCreateLabel("Count:", 230, 170, 60, 20, 0x200)

Global $hArea = GUICtrlCreateCombo("", 300, 50, 120, 70, 0x003)
GUICtrlSetData(-1, "Flags|Inputs|Outputs|Datablocks|Counter|Timer", "Datablocks")
Global $hDB = GUICtrlCreateInput("1", 300, 80, 120, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 9999, 1)
Global $hType = GUICtrlCreateCombo("", 300, 110, 120, 70, 0x003)
GUICtrlSetData(-1, "BYTE|WORD|INT|DWORD|DINT|REAL", "BYTE")
Global $hOffset = GUICtrlCreateInput("0", 300, 140, 120, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 9000, 0)
Global $hCount = GUICtrlCreateInput("1", 300, 170, 120, 20, 0)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 999, 1)

Global $hAccept = GUICtrlCreateButton("Accept", 230, 220, 190, 20)
GUICtrlSetOnEvent(-1, "_Accept")
GUICtrlCreateButton("Start", 230, 250, 90, 20)
GUICtrlSetOnEvent(-1, "_Start")
GUICtrlCreateButton("Stop", 330, 250, 90, 20)
GUICtrlSetOnEvent(-1, "_Stop")

Global $hCycleTime = GUICtrlCreateLabel("not connected", 230, 280, 190, 20, 0x201)
Global $hQuestiontime = GUICtrlCreateLabel("", 230, 370, 190, 20, 0x201)
Global $hCPUInfo = GUICtrlCreateLabel("", 230, 340, 190, 20, 0x201)
Global $hProgressBar = GUICtrlCreateProgress(230, 310, 190, 20)

GUISetState()

Global $hConfigGui = GUICreate("Edit Connection", 470, 200)
GUISetOnEvent(-3, "_CancelConfigGui")

GUICtrlCreateLabel("Name:", 10, 10, 60, 20, 0x200)
GUICtrlCreateLabel("Protocol:", 210, 10, 60, 20, 0x200)
GUICtrlCreateLabel("Description:", 10, 40, 60, 20, 0x200)
GUICtrlCreateLabel("CPU-Rack:", 10, 70, 60, 20, 0x200)
GUICtrlCreateLabel("Slot:", 170, 70, 60, 20, 0x200)
GUICtrlCreateLabel("COM-Port:", 260, 70, 60, 20, 0x200)
GUICtrlCreateLabel("IP-Address:", 10, 100, 60, 20, 0x200)
GUICtrlCreateLabel("MPI-Speed:", 260, 100, 60, 20, 0x200)
GUICtrlCreateLabel("Timeout:", 10, 130, 60, 20, 0x200)
GUICtrlCreateLabel("Interval:", 140, 130, 60, 20, 0x200)
GUICtrlCreateLabel("MPI-Local:", 260, 130, 60, 20, 0x200)
GUICtrlCreateLabel("Remote:", 375, 130, 60, 20, 0x200)

Global $hName = GUICtrlCreateInput("", 75, 10, 100, 20)
Global $hProtocol = GUICtrlCreateCombo("", 270, 10, 190, 20, 0x0003)
GUICtrlSetData(-1, "MPI-Protocol|MPI-Protocol (Andrew's Version without STX)|MPI-Protocol (Step7 Version)|"& _
					"MPI-Protocol (Andrew's Version with STX)|PPI-Protocol|ISO over TCP|ISO over TCP (CP-243)|" & _
					"IBH-Link|IBH-Link (PPI)|S7onlinx.dll|AS-511|Deltalogic NetLink PRO")
Global $hDesc = GUICtrlCreateInput("", 75, 40, 385, 20)
Global $hCPURack = GUICtrlCreateInput("", 75, 70, 40, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 9, 0)
Global $hCPUSlot = GUICtrlCreateInput("", 200, 70, 40, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 32, 0)
Global $hCOMPort = GUICtrlCreateCombo("", 320, 70, 60, 20, 0x0003)
GUICtrlSetData(-1, "COM1|COM2|COM3|COM4|COM5|COM6|COM7|COM8")
Global $hBaud = GUICtrlCreateCombo("", 400, 70, 60, 20, 0x0003)
GUICtrlSetData(-1, "115200|57600|38400|19200|9600|4800|2400|1200|600|300")
Global $hIPAddress = GUICtrlCreateInput("", 75, 100, 165, 20)
Global $hMPISpeed = GUICtrlCreateCombo("", 320, 100, 140, 80, 0x0003)
GUICtrlSetData(-1, "9.6 kBit/s|19.2 kBit/s|187.5 kBit/s|500 kBit/s|1.5 kBit/s|45.45 kBit/s|93.75 kBit/s")
Global $hTimeout = GUICtrlCreateInput("", 75, 130, 60, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 10000, 100)
Global $hInterval = GUICtrlCreateInput("", 180, 130, 60, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 30000, 200)
Global $hMPILocal = GUICtrlCreateInput("", 320, 130, 40, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 32, 0)
Global $hMPIRemote = GUICtrlCreateInput("", 420, 130, 40, 20)
GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 32, 0)

GUICtrlCreateButton("OK", 280, 170, 80, 20)
GUICtrlSetOnEvent(-1, "_SaveConfigGui")
GUICtrlCreateButton("Cancel", 370, 170, 80, 20)
GUICtrlSetOnEvent(-1, "_CancelConfigGui")


While 1
	Sleep(20000)
WEnd

Func _ShowConfigGuiEdit()
	GUICtrlSetState($hName, 128)
	Local $Section = GUICtrlRead($hConnection)
	GUICtrlSetData($hName, $Section)
	GUICtrlSetData($hProtocol, IniRead($IniFile, $Section, "Protocol", ""))
	GUICtrlSetData($hDesc, IniRead($IniFile, "Connections", $Section, ""))
	GUICtrlSetData($hCPURack, IniRead($IniFile, $Section, "CPURack", ""))
	GUICtrlSetData($hCPUSlot, IniRead($IniFile, $Section, "CPUSlot", ""))
	GUICtrlSetData($hCOMPort, IniRead($IniFile, $Section, "COMPort", ""))
	GUICtrlSetData($hBaud, IniRead($IniFile, $Section, "Baud", ""))
	GUICtrlSetData($hIPAddress, IniRead($IniFile, $Section, "IPAddress", ""))
	GUICtrlSetData($hMPISpeed, IniRead($IniFile, $Section, "MPISpeed", ""))
	GUICtrlSetData($hTimeout, IniRead($IniFile, $Section, "Timeout", ""))
	GUICtrlSetData($hInterval, IniRead($IniFile, $Section, "Interval", ""))
	GUICtrlSetData($hMPILocal, IniRead($IniFile, $Section, "MPILocal", ""))
	GUICtrlSetData($hMPIRemote, IniRead($IniFile, $Section, "MPIRemote", ""))
	GUISetState(@SW_SHOW, $hConfigGui)
EndFunc

Func _ShowConfigGuiNew()
	GUICtrlSetState($hName, 64)
	GUICtrlSetData($hName, "")
	GUISetState(@SW_SHOW, $hConfigGui)
EndFunc

Func _SaveConfigGui()
	GUISetState(@SW_HIDE, $hConfigGui)
	Local $Section = GUICtrlRead($hName)
	GUICtrlSetData($hConnection, $Section, $Section)
	IniWrite($iniFile, "Connections", $Section, GUICtrlRead($hDesc))

	IniWrite($iniFile, $Section, "Protocol", GUICtrlRead($hProtocol))
	IniWrite($iniFile, $Section, "CPURack", GUICtrlRead($hCPURack))
	IniWrite($iniFile, $Section, "CPUSlot", GUICtrlRead($hCPUSlot))
	IniWrite($iniFile, $Section, "COMPort", GUICtrlRead($hCOMPort))
	IniWrite($iniFile, $Section, "Baud", GUICtrlRead($hBaud))
	IniWrite($iniFile, $Section, "IPAddress", GUICtrlRead($hIPAddress))
	IniWrite($iniFile, $Section, "Timeout", GUICtrlRead($hTimeout))
	IniWrite($iniFile, $Section, "Interval", GUICtrlRead($hInterval))
	IniWrite($iniFile, $Section, "MPISpeed", GUICtrlRead($hMPISpeed))
	IniWrite($iniFile, $Section, "MPILocal", GUICtrlRead($hMPILocal))
	IniWrite($iniFile, $Section, "MPIRemote", GUICtrlRead($hMPIRemote))	
EndFunc

Func _CancelConfigGui()
	GUISetState(@SW_HIDE, $hConfigGui)
EndFunc

Func _Start()
	If $bStarted Then Return
	$Name = GUICtrlRead($hConnection)
	$Desc = IniRead($IniFile, "Connections", $Name, "")
	$Protocol = IniRead($IniFile, $Name, "Protocol", "")
	$CPURack = IniRead($IniFile, $Name, "CPURack", "")
	$CPUSlot = IniRead($IniFile, $Name, "CPUSlot", "")
	$COMPort = IniRead($IniFile, $Name, "COMPort", "")
	$Baud = IniRead($IniFile, $Name, "Baud", "")
	$IPAddress = IniRead($IniFile, $Name, "IPAddress", "")
	$Timeout = IniRead($IniFile, $Name, "Timeout", "")
	$Interval = IniRead($IniFile, $Name, "Interval", "")
	$MPISpeed = IniRead($IniFile, $Name, "MPISpeed", "")
	$MPILocal = IniRead($IniFile, $Name, "MPILocal", "")
	$MPIRemote = IniRead($IniFile, $Name, "MPIRemote", "")
	
	_StartConnection()
	If @error Then Return
	GUICtrlSetData($hCPUInfo, _daveGetOrderCode($p_dc))
	$CycleTimeLimit = _daveGetCycleTimeLimit($p_dc)
	AdlibRegister("_Adlib", $Interval)
	$bStarted = 1
	GUICtrlSetState($hAccept, 128)
	GUICtrlSetState($hArea, 128)
	GUICtrlSetState($hDB, 128)
	GUICtrlSetState($hType, 128)
	GUICtrlSetState($hOffset, 128)
	GUICtrlSetState($hCount, 128)
	_Adlib()
EndFunc

Func _Stop()
	If Not $bStarted Then Return
	$bStarted = 0
EndFunc

Func _StartConnection()
	Local $ProtocolType = _ProtocolIsSerial($Protocol)
	If $ProtocolType = 1 Then
		$hSocket = _setPort($COMPort, $Baud, "o")
	ElseIf $Protocol = "Deltalogic NetLink PRO" Then
		$hSocket = _openSocket($IPAddress, 1099)
	ElseIf $ProtocolType = 2 Then
		$hSocket = _openS7online()
	Else
		$hSocket = _openSocket($IPAddress, 102)
	EndIf
	If @error Then
		ConsoleWrite("$hSocket = " & $hSocket & @CR)
		GUICtrlSetData($hCycleTime, "Error opening port!")
		Return SetError(1)
	EndIf
	$fds = DllStructCreate($_daveOSserialType)
	DllStructSetData($fds, "rfd", $hSocket)
	DllStructSetData($fds, "wfd", $hSocket)

	$p_di = _daveNewInterface($fds, $Name, $MPILocal, _getProtocol($Protocol), _getMPISpeed($MPISpeed))
	If @error Then
		ConsoleWrite("$p_di = " & $p_di & @CR)
		GUICtrlSetData($hCycleTime, "Error creating interface!")
		
		If $ProtocolType = 1 Then
			_closePort($hSocket)
		ElseIf $ProtocolType = 2 Then
			_closeS7online($hSocket)
		Else
			_closeSocket($hSocket)
		EndIf
		Return SetError(2)
	EndIf
	_daveInitAdapter($p_di)
	
	$p_dc = _daveNewConnection($p_di, $CPUSlot, $MPIRemote, $CPURack)
	If @error Then
		ConsoleWrite("$p_dc = " & $p_dc & @CR)
		GUICtrlSetData($hCycleTime, "Error creating connection!")
		_daveDisconnectAdapter($DLL, $p_di)
		Return SetError(3)
	EndIf
	If _daveConnectPLC($p_dc) <> 0 Then
		ConsoleWrite("$p_dc = " & $p_dc & @CR)
		GUICtrlSetData($hCycleTime, "Error connecting PLC!")
		_daveDisconnectAdapter($p_di)
		If $ProtocolType = 1  Then
			_closePort($hSocket)
		ElseIf $ProtocolType = 2 Then
			_closeS7online($hSocket)
		Else
			_closeSocket($hSocket)
		EndIf
		Return SetError(4)
	EndIf
EndFunc

Func _StopConnection()
	Local $ProtocolType = _ProtocolIsSerial($Protocol)
	_daveDisconnectPLC($p_dc)
	_daveDisconnectAdapter($p_di)
	
	If $ProtocolType = 1 Then
		_closePort($hSocket)
	ElseIf $ProtocolType = 2 Then
		_closeS7online($hSocket)
	Else
		_closeSocket($hSocket)
	EndIf
EndFunc

Func _Adlib()
	Local $start = TimerInit()
	Local $aBytes
	If $bStarted = 1 Then
		Local $Cycletime = _daveGetCycleTime($p_dc)
		If GUICtrlSendMsg($hListView, 0x1004, 0, 0) Then
			_daveReadManyBytes($p_dc, _getArea(GUICtrlRead($hArea)), GUICtrlRead($hDB), GUICtrlRead($hOffset), GUICtrlRead($hCount) * $Multiplier)
			For $i = 0 To UBound($ah_ListViewItems) - 1
				GUICtrlSetData($ah_ListViewItems[$i], "|" & Call("_daveGet" & _getFuncName(), $p_dc))
			Next
		EndIf
		
		$ProgressPercent += 5
		If $ProgressPercent >= 105 Then $ProgressPercent = 0
		GUICtrlSetData($hProgressBar, $ProgressPercent)
		GUICtrlSetData($hCycleTime, StringFormat("CycleTime: %s msec / %s msec", $Cycletime,  $CycletimeLimit))
		GUICtrlSetData($hQuestiontime, StringFormat("%3.0f msec", TimerDiff($start)))
	Else
		AdlibUnRegister("_Adlib")
		$ProgressPercent = 0
		GUICtrlSetData($hProgressBar, 0)
		GUICtrlSetData($hCycleTime, "closing connection")
		_StopConnection()
		GUICtrlSetData($hCycleTime, "not connected")
		GUICtrlSetData($hCPUInfo, "")
		GUICtrlSetData($hQuestiontime, "")
		GUICtrlSetState($hAccept, 64)
		GUICtrlSetState($hArea, 64)
		GUICtrlSetState($hDB, 64)
		GUICtrlSetState($hType, 64)
		GUICtrlSetState($hOffset, 64)
		GUICtrlSetState($hCount, 64)
		If $bStarted = -1 Then Exit
	EndIf	
EndFunc

Func _Accept()
	$Multiplier = _getMultiplier(GUICtrlRead($hType))
	GUICtrlSendMsg($hListView, 0x1000 + 9, 0, 0)
	Local $iOffset = GUICtrlRead($hOffset)
	Local $sSyntax = _getSyntax()
	Local $j = 0
	ReDim $ah_ListViewItems[GUICtrlRead($hCount)]
	For $i = $iOffset To $iOffset + (GUICtrlRead($hCount) - 1) * $Multiplier Step $Multiplier
		$ah_ListViewItems[$j] = GUICtrlCreateListViewItem($sSyntax & $i & "|?", $hListView)
		$j += 1
	Next
;~ 	If $sSyntax = "C" Or $sSyntax = "T" Then $Multiplier = 2
EndFunc

Func _getMultiplier($sType)
	Switch GUICtrlRead($hArea)
		Case "Counter", "Timer"
			Return 1
	EndSwitch
	Switch($sType)
		Case "BYTE"
			Return 1
		Case "WORD", "INT"
			Return 2
		Case "DWORD", "DINT", "REAL"
			Return 4
	EndSwitch
EndFunc

Func _getSyntax()
	Local $sRet
	Switch GUICtrlRead($hArea)
		Case "Flags"
			$sRet = "M"
		Case "Inputs"
			$sRet = "I"
		Case "Outputs"
			$sRet = "O"
		Case "Datablocks"
			$sRet = "DB" & GUICtrlRead($hDB) & ".DB"
		Case "Counter"
			Return "C"
		Case "Timer"
			Return "T"
	EndSwitch
	Switch 	GUICtrlRead($hType)
		Case "Byte"
			$sRet &= "B"
		Case "Word", "Int"
			$sRet &= "W"
		Case "DWord", "DInt", "Real"
			$sRet &= "D"
	EndSwitch
	Return $sRet
EndFunc

Func _getFuncName()
	Switch GUICtrlRead($hArea)
		Case "Counter"
			Return "CounterValue"
		Case "Timer"
			Return "Seconds"
	EndSwitch
	Switch GUICtrlRead($hType)
		Case "Byte"
			Return "S8"
		Case "Word"
			Return "U16"
		Case "Int"
			Return "S16"
		Case "DWord"
			Return "U32"
		Case "DInt"
			Return "S32"
		Case "Real"
			Return "Float"
	EndSwitch
EndFunc

Func _getArea($sArea)
	Switch $sArea
		Case "Flags"
			Return $daveFlags
		Case "Inputs"
			Return $daveInputs
		Case "Outputs"
			Return $daveOutputs
		Case "Datablocks"
			Return $daveDB
		Case "Counter"
			Return $daveCounter
		Case "Timer"
			Return $daveTimer
	EndSwitch
EndFunc


Func _getProtocol($sProtocol)
	Switch $sProtocol
		Case "MPI-Protocol"
			Return $daveProtoMPI
		Case "MPI-Protocol (Andrew's Version without STX)"
			Return $daveProtoMPI2
		Case "MPI-Protocol (Step7 Version)"
			Return $daveProtoMPI3
		Case "MPI-Protocol (Andrew's Version with STX)"
			Return $daveProtoMPI4
		Case "PPI-Protocol"
			Return $daveProtoPPI
		Case "ISO over TCP"
			Return $daveProtoISOTCP
		Case "ISO over TCP (CP-243)"
			Return $daveProtoISOTCP243
		Case "IBH-Link"
			Return $daveProtoMPI_IBH
		Case "IBH-Link (PPI)"
			Return $daveProtoPPI_IBH
		Case "S7onlinx.dll"
			Return $daveProtoS7online
		Case "AS-511"
			Return $daveProtoAS511
		Case "Deltalogic NetLink PRO"
			Return $daveProtoNLpro
	EndSwitch
EndFunc

Func _ProtocolIsSerial($sProtocol)
	Switch _getProtocol($sProtocol)
		Case $daveProtoMPI, $daveProtoPPI, $daveProtoAS511
			Return 1
		Case $daveProtoS7online
			Return 2
		Case Else
			Return 0
	EndSwitch
EndFunc
			
Func _getMPISpeed($sMPISpeed)
	Switch $sMPISpeed
		Case "9.6 kBit/s"
			Return $daveSpeed9k
		Case "19.2 kBit/s"
			Return $daveSpeed19k
		Case "187.5 kBit/s"
			Return $daveSpeed187k
		Case "500 kBit/s"
			Return $daveSpeed500k
		Case "1.5 kBit/s"
			Return $daveSpeed1500k
		Case "45.45 kBit/s"
			Return $daveSpeed45k
		Case "93.75 kBit/s"
			Return $daveSpeed93k
	EndSwitch	
EndFunc

Func _CreateNewIni()
	IniWrite($iniFile, "Connections", "Demo", "")

	IniWrite($iniFile, "Demo", "Protocol", "MPI-Protocol")
	IniWrite($iniFile, "Demo", "CPURack", "0")
	IniWrite($iniFile, "Demo", "CPUSlot", "2")
	IniWrite($iniFile, "Demo", "COMPort", "COM1")
	IniWrite($iniFile, "Demo", "Baud", "38400")
	IniWrite($iniFile, "Demo", "IPAddress", "192.168.3.1")
	IniWrite($iniFile, "Demo", "Timeout", "1000")
	IniWrite($iniFile, "Demo", "Interval", "1000")
	IniWrite($iniFile, "Demo", "MPISpeed", "187.5 kBit/s")
	IniWrite($iniFile, "Demo", "MPILocal", "0")
	IniWrite($iniFile, "Demo", "MPIRemote", "2")	
EndFunc

Func _Exit()
	If $bStarted = 0 Then Exit
	$bStarted = -1
EndFunc

Func _DeInit()
	_DaveInit()
EndFunc
