1 (изменено: Alectric, 2022-08-31 19:57:47)

Тема: AHK: Class Snap7 Client

Класс для удобной работы с библиотекой Snap7 в режиме клиента.

В прикрепленном архиве: файл класса, файлы DLL, простенький скрипт для теста.

Тема для обсуждения.


/*

;Класс Snap7 - адаптация библиотеки Snap7 для Autohotkey.
;В классе реализованы все функции библиотеки в режиме клиента кроме асинхронных
;(смотри мануал для подробностей или комментарий рядом с нужной функцией)
;для работы класса требуются DLL файлы библиотеки snap7x64.dll, snap7x86.dll

;Как использовать:
;Необходимо создать объект
;Параметры создания объекта:	(IP="",Rack=0,Slot=3,ConnectionType=0x02,AutoReconnect=true,ReconnectTime=10000)
; IP	- указать IP контроллера к которому нужно подключиться
; Rack	- указать Rack прописаный в конфигураторе железа в Step7
; Slot	- указать Slot в котором стоит PLC
	;Таблица из мануала
	; 		Rack	Slot
	; S7 300 CPU	0	2	Always
	; S7 400 CPU	Not fixed	Follow the hardware configuration.
	; WinAC CPU	Not fixed	Follow the hardware configuration.
	; S7 1200 CPU	0	0	Or 0, 1
	; S7 1500 CPU	0	0	Or 0, 1
	; CP 343	0	0	Or follow Hardware configuration.
	; CP 443	Not fixed	Follow the hardware configuration.
	; WinAC IE	0	0	Or follow Hardware configuration.

; ConnectionType	- тип подключения
			; можно использовать переменные класса:
			; Snap7.PG
			; Snap7.OP
			; Snap7.S7_Basic[1] .. Snap7.S7_Basic[14]

; AutoReconnect		- использовать функцию автоматических попыток подключения в случае ошибок связи с PLC
; ReconnectTime		- период автоматических попыток в миллисекундах

; Пример
s7Obj:=new Snap7("192.168.0.15", 0, 3, Snap7.OP, true, 10000)

; далее обращаясь к этому классу можно вызывать функции как описано в мануале
; за исключением того что не нужно указывать первый параметр во всех функциях (S7Object Client) он уже прописан в классе Snap7.
; Например:
s7Obj.Cli_GetConnected(Var)
msgbox,% "Cli_GetConnected = " Var

; Добавленны свои функции для удобства работы в autohotkey.

Var:=s7Obj.Connected ; возвращает текущее состояние подключения. 0 - не подключен, любое значение - подключен
msgbox,% "Connected = " Var

; Можно отключить\включить функцию автоподключения в любой момент
s7Obj.AutoReconnect:=true
; Также изменить период
s7Obj.ReconnectTime:=5000

; Поумолчанию включено обображение ошибок в виде отдельного окна
; чтобы выключить:
s7Obj.ShowErrors:=false
; в этом случае придется обрабатывать ошибки самостоятельно
; для этого предусмотренны свойства класса:

Var:=s7Obj.LastError ; возвращает номер последней ошибки при выполнении функций
msgbox,% "LastError = " Var

Var:=s7Obj.LastErrors ; возвращает массив из 3х элементов - разделяет ошибку на состовляющие
msgbox,% "TCP_IP_Error = " Var[1] ; TCP_IP_Error
msgbox,% "ISO_TCP_Error = " Var[2] ; ISO_TCP_Error
msgbox,% "Client_Error = " Var[3] ; Client_Error

Var:=s7Obj.LastErrorText ; возвращает полный текст ошибки с подробным описанием
msgbox,% "LastErrorText = `n`n" Var

Var:=s7Obj.Cli_LastErrorText ; возвращает текст ошибки предоставляемый самой библиотекой
msgbox,% "Cli_LastErrorText = " Var

; данную функцию можно вызывать напрямую из класса Snap7 без создания объекта
Snap7.Msg("Текст сообщения") ; выводит отдельное окно сообщения с указанным текстом

info:=s7Obj.GetOrderCode() ; упрощеный вариант стандартной функции библиотеки Cli_GetOrderCode
msgbox,% "Code = " info.Code
msgbox,% "V1 = " info.V1
msgbox,% "V2 = " info.V2
msgbox,% "V3 = " info.V3
msgbox,% "Version = " info.Version

info:=s7Obj.GetCpuInfo() ; упрощеный вариант стандартной функции библиотеки Cli_GetCpuInfo
msgbox,% "ModuleTypeName = " info.ModuleTypeName
msgbox,% "SerialNumber = " info.SerialNumber
msgbox,% "ASName = " info.ASName
msgbox,% "Copyright = " info.Copyright
msgbox,% "ModuleName = " info.ModuleName

info:=s7Obj.GetCpInfo() ; упрощеный вариант стандартной функции библиотеки Cli_GetCpInfo
msgbox,% "MaxPduLengt = " info.MaxPduLengt
msgbox,% "MaxConnections = " info.MaxConnections
msgbox,% "MaxMpiRate = " info.MaxMpiRate
msgbox,% "MaxBusRate = " info.MaxBusRate

varsetcapacity(Data,20,0x30) ; подготовка переменной для демонстрации следующих функций
numput(0x31,Data,4,"uchar")
numput(0x32,Data,5,"uchar")
numput(0x33,Data,6,"uchar")
numput(0x34,Data,7,"uchar")

; данную функцию можно вызывать напрямую из класса Snap7 без создания объекта
var:=Snap7.GetStr(Data,2,8) ; возвращает ASCII строку из памяти по указанному смещению
				; Параметры (byref Data,Start,Size)
				; Data - переменная из памяти которой брать строку
				; Start - начальная позиция строки
				; Size - количество символов
msgbox,% "GetStr = " var

; данную функцию можно вызывать напрямую из класса Snap7 без создания объекта
Snap7.SwapData(Data,4,4) ; разворачивает чередование байтов в памяти переменной по указанным координатам
					; Параметры (byref pVar,Size,Offset=0)
					; pVar - переменная в которой необходимо развернуть байты
					; Size - размер в байтах
					; Offset - начальная позиция в памяти
var:=Snap7.GetStr(Data,2,8)
msgbox,% "GetStr swapped = " var

Var:=s7Obj.DBRead(1,0,"Real") ; читает из DB контроллера по указанному адресу указанный тип данных
						; Параметры (DBNumber,Start=0,DataType="Int")
						; DBNumber - номер DB из которого читать данные
						; Start - начальная позиция
						; DataType - тип данных
						; поддержываемые типы данных: Byte, Int, Word, DInt, DWord, Real
msgbox,% "DBRead = " var

Var:=s7Obj.DBWrite(12.34,1,0,"Real") ; пишет в DB контроллера по указанному адресу указанный тип данных
						; Параметры (Value,DBNumber,Start=0,DataType="Int")
						; Value - значение которое небходимо записать в DB
						; DBNumber - номер DB в который писать данные
						; Start - начальная позиция
						; DataType - тип данных
						; поддержываемые типы данных: Byte, Int, Word, DInt, DWord, Real
Var:=s7Obj.DBRead(1,0,"Real")
msgbox,% "DBRead after write = " var

*/








/*
	Snap7 Reference manual

Administrative functions
These functions allow controlling the behavior a Client Object.
Function		Purpose
Cli_Create		Creates a Client Object.
Cli_Destroy		Destroys a Client Object.
Cli_ConnectTo		Connects a Client Object to a PLC.
Cli_SetConnectionType	Sets the connection type (PG/OP/S7Basic)
Cli_ConnectionParamst	Sets Address, Local and Remote TSAP for the connection.
Cli_Connect		Connects a Client Object to a PLC with implicit parameters.
Cli_Disconnect		Disconnects a Client.
Cli_GetParam		Reads an internal Client parameter.
Cli_SetParam		Writes an internal Client Parameter.

Data I/O functions
These functions allow the Client to exchange data with a PLC.
Function		Purpose
Cli_ReadArea		Reads a data area from a PLC.
Cli_WriteArea		Writes a data area into a PLC.
Cli_DBRead		Reads a part of a DB from a PLC.
Cli_DBWrite		Writes a part of a DB into a PLC.
Cli_ABRead		Reads a part of IPU area from a PLC.
Cli_ABWrite		Writes a part of IPU area into a PLC.
Cli_EBRead		Reads a part of IPI area from a PLC.
Cli_EBWrite		Writes a part of IPI area into a PLC.
Cli_MBRead		Reads a part of Merkers area from a PLC.
Cli_MBWrite		Writes a part of Merkers area into a PLC.
Cli_TMRead		Reads timers from a PLC.
Cli_TMWrite		Write timers into a PLC.
Cli_CTRead		Reads counters from a PLC.
Cli_CTWrite		Write counters into a PLC.
Cli_ReadMultiVars	Reads different kind of variables from a PLC simultaneously.
Cli_WriteMultiVars	Writes different kind of variables into a PLC simultaneously.

Directory functions
These functions give you detailed information about the blocks present in a PLC.
Function		Purpose
Cli_ListBlocks		Returns the AG blocks amount divided by type.
Cli_ListBlocksOfType	Returns the AG blocks list of a given type.
Cli_GetAgBlockInfo	Returns detailed information about a block present in AG.
Cli_GetPgBlockInfo	Returns detailed information about a block loaded in memory.

Block oriented functions
Function		Purpose
Cli_FullUpload		Uploads a block from AG with Header and Footer infos.
Cli_Upload		Uploads a block from AG.
Cli_Download		Download a block into AG.
Cli_Delete		Delete a block into AG.
Cli_DBGet		Uploads a DB from AG using DBRead.
Cli_DBFill		Fills a DB in AG with a given byte.

Date/Time functions
These functions allow to read/modify the date and time of a PLC.
Imagine a production line in which each PLC saves the data with date/time field inside,
it is very important that the date be up to date.
Both CP X43 and internal PN allow to synchronize date and time but you need an NTP
server, and in some cases (old hardware or CP343-1 Lean or old firmware release)
this doesn’t work properly.
Snap7 Client, using the same method of S7 Manager, always works.
Function			Purpose
Cli_GetPlcDateTime		Returns the PLC date/time.
Cli_SetPlcDateTime		Sets the PLC date/time with a given value.
Cli_SetPlcSystemDateTime	Sets the PLC date/time with the host (PC) date/time.

System info functions
these functions access to SZL ( or SSL - System Status List) to give you all the same
information that you can get from S7 Manager.
Function		Purpose
Cli_ReadSZL		Reads a partial list of given ID and Index.
Cli_ReadSZLList		Reads the list of partial lists available in the CPU.
Cli_GetOrderCode	Returns the CPU order code.
Cli_GetCpuInfo		Returns some information about the AG.
Cli_GetCpInfo		Returns some information about the CP (communication processor).

PLC control functions
With these control function it’s possible to Start/Stop a CPU and perform some other
maintenance tasks.
Function		Purpose
Cli_PlcHotStart		Puts the CPU in RUN mode performing an HOT START.
Cli_PlcColdStart	Puts the CPU in RUN mode performing a COLD START.
Cli_PlcStop		Puts the CPU in STOP mode.
Cli_CopyRamToRom	Performs the Copy Ram to Rom action.
Cli_Compress		Performs the Compress action.
Cli_GetPlcStatus	Returns the CPU status (running/stopped).

Security functions
With these functions is possible to know the current protection level, and to set/clear
the current session password.
The correct name of the below functions Cli_SetSessionPassword and
Cli_ClearSessionPassword, would have to be Cli_Login and Cli_Logout to avoid
misunderstandings about their scope.
Especially because, if you look at the source code, there is an encoding function that
translates the plain password before send it to the PLC.
PASSWORD HACKING IS VERY FAR FROM THE AIM OF THIS PROJECT, MOREOVER
YOU NEED TO KNOW THE CORRECT PASSWORD TO MEET THE CPU SECURITY
LEVEL.
Detailed information about the protection level can be found in §33.19 of "System
Software for S7-300/400 System and Standard Functions".
Function			Purpose
Cli_SetSessionPassword		Send the password to the PLC to meet its security level.
Cli_ClearSessionPassword	Clears the password set for the current session (logout).
Cli_GetProtection		Gets the CPU protection level info.

Low level functions
Snap7 hides the IsoTCP underlying layer. With this function however, it’s possible to
exchange an IsoTCP telegram with a PLC.
Function		Purpose
Cli_IsoExchangeBuffer	Exchanges a given S7 PDU (protocol data unit) with the CPU.

Miscellaneous functions
These are utility functions.
Function		Purpose
Cli_GetExecTime		Returns the last job execution time in milliseconds.
Cli_GetLastError	Returns the last job result.
Cli_GetPduLength	Returns info about the PDU length (requested and negotiated).
Cli_ErrorText		Returns a textual explanation of a given error number.
Cli_GetConnected	Returns the connection status of the client.

Asynchronous functions
These functions are executed in a separate thread simultaneously to the execution of
the caller program.
Function		Purpose
Cli_AsReadArea		Reads a data area from a PLC.
Cli_AsWriteArea		Writes a data area into a PLC.
Cli_AsDBRead		Reads a part of a DB from a PLC.
Cli_AsDBWrite		Writes a part of a DB into a PLC.
Cli_AsABRead		Reads a part of IPU area from a PLC.
Cli_AsABWrite		Writes a part of IPU area into a PLC.
Cli_AsEBRead		Reads a part of IPI area from a PLC.
Cli_AsEBWrite		Writes a part of IPI area into a PLC.
Cli_AsMBRead		Reads a part of Merkers area from a PLC.
Cli_AsMBWrite		Writes a part of Merkers area into a PLC.
Cli_AsTMRead		Reads timers from a PLC.
Cli_AsTMWrite		Write timers into a PLC.
Cli_AsCTRead		Reads counters from a PLC.
Cli_AsCTWrite		Write counters into a PLC.
Cli_AsListBlocksOfType	Returns the AG blocks list of a given type.
Cli_AsReadSZL		Reads a partial list of given ID and Index.
Cli_AsReadSZLList	Reads the list of partial lists available in the CPU.
Cli_AsFullUpload	Uploads a block from AG with Header and Footer infos.
Cli_AsUpload		Uploads a block from AG.
Cli_AsDownload		Download a block into AG.
Cli_AsDBGet		Uploads a DB from AG using DBRead.
Cli_AsDBFill		Fills a DB in AG with a given byte.
Cli_AsCopyRamToRom	Performs the Copy Ram to Rom action.
Cli_AsCompress		Performs the Compress action.
*/



class Snap7
{
  static PG:=0x01
  static OP:=0x02
  static S7_Basic:=[0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10] ; 0x03..0x10

  ; Area
  static S7AreaPE:=0x81 ; Process Inputs.
  static S7AreaPA:=0x82 ; Process Outputs.
  static S7AreaMK:=0x83 ; Merkers.
  static S7AreaDB:=0x84 ; DB
  static S7AreaCT:=0x1C ; Counters.
  static S7AreaTM:=0x1D ; Timers
  static AreaList:=	{0x81:"Process Inputs"
			,0x82:"Process Outputs"
			,0x83:"Merkers"
			,0x84:"DB"
			,0x1C:"Counters"
			,0x1D:"Timers"}

  ; WordLen
  static S7WLBit:=0x01 ; Bit (inside a word)
  static S7WLByte:=0x02 ; Byte (8 bit)
  static S7WLWord:=0x04 ; Word (16 bit)
  static S7WLDWord:=0x06 ; Double Word (32 bit)
  static S7WLReal:=0x08 ; Real (32 bit float)
  static S7WLCounter:=0x1C ; Counter (16 bit)
  static S7WLTimer:=0x1D ; Timer (16 bit)
  static WordLenList:=	{0x01:"Bit (inside a word)"
			,0x02:"Byte (8 bit)"
			,0x04:"Word (16 bit)"
			,0x06:"Double Word (32 bit)"
			,0x08:"Real (32 bit float)"
			,0x1C:"Counter (16 bit)"
			,0x1D:"Timer (16 bit)"}
  static WordLen:=	{Snap7.S7WLBit:1
			,Snap7.S7WLByte:1
			,Snap7.S7WLWord:2
			,Snap7.S7WLDWord:4
			,Snap7.S7WLReal:4
			,Snap7.S7WLCounter:2
			,Snap7.S7WLTimer:2}

  ; BlockType
  static Block_OB:=0x38 ; OB
  static Block_DB:=0x41 ; DB
  static Block_SDB:=0x42 ; SDB
  static Block_FC:=0x43 ; FC
  static Block_SFC:=0x44 ; SFC
  static Block_FB:=0x45 ; FB
  static Block_SFB:=0x46 ; SFB
  static BlockTypeList:={0x38:"OB"
			,0x41:"DB"
			,0x42:"SDB"
			,0x43:"FC"
			,0x44:"SFC"
			,0x45:"FB"
			,0x46:"SFB"}

  static StatusList:=	{0x00:"The CPU status is unknown."
			,0x08:"The CPU is running."
			,0x04:"The CPU is stopped."}

  static dll:=a_scriptdir "\" (A_Is64bitOS ? "snap7x64.dll":"snap7x86.dll")
  static hModule:=Dllcall("LoadLibrary","Str",Snap7.dll,"Ptr")
  static hCli_Create:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Create","Ptr")
  static hCli_Destroy:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Destroy","Ptr")
  static hCli_SetConnectionType:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetConnectionType","Ptr")
  static hCli_ConnectTo:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ConnectTo","Ptr")
  static hCli_SetConnectionParams:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetConnectionParams","Ptr")
  static hCli_Connect:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Connect","Ptr")
  static hCli_Disconnect:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Disconnect","Ptr")
  static hCli_GetParam:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetParam","Ptr")
  static hCli_SetParam:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetParam","Ptr")
  static hCli_ReadArea:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ReadArea","Ptr")
  static hCli_WriteArea:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_WriteArea","Ptr")
  static hCli_DBRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_DBRead","Ptr")
  static hCli_DBWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_DBWrite","Ptr")
  static hCli_ABRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ABRead","Ptr")
  static hCli_ABWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ABWrite","Ptr")
  static hCli_EBRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_EBRead","Ptr")
  static hCli_EBWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_EBWrite","Ptr")
  static hCli_MBRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_MBRead","Ptr")
  static hCli_MBWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_MBWrite","Ptr")
  static hCli_TMRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_TMRead","Ptr")
  static hCli_TMWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_TMWrite","Ptr")
  static hCli_CTRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_CTRead","Ptr")
  static hCli_CTWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_CTWrite","Ptr")
  static hCli_ReadMultiVars:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ReadMultiVars","Ptr")
  static hCli_WriteMultiVars:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_WriteMultiVars","Ptr")
  static hCli_ListBlocks:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ListBlocks","Ptr")
  static hCli_ListBlocksOfType:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ListBlocksOfType","Ptr")
  static hCli_GetAgBlockInfo:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetAgBlockInfo","Ptr")
  static hCli_GetPgBlockInfo:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetPgBlockInfo","Ptr")
  static hCli_FullUpload:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_FullUpload","Ptr")
  static hCli_Upload:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Upload","Ptr")
  static hCli_Download:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Download","Ptr")
  static hCli_Delete:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Delete","Ptr")
  static hCli_DBGet:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_DBGet","Ptr")
  static hCli_DBFill:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_DBFill","Ptr")
  static hCli_GetPlcDateTime:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetPlcDateTime","Ptr")
  static hCli_SetPlcDateTime:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetPlcDateTime","Ptr")
  static hCli_SetPlcSystemDateTime:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetPlcSystemDateTime","Ptr")
  static hCli_ReadSZL:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ReadSZL","Ptr")
  static hCli_ReadSZLList:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ReadSZLList","Ptr")
  static hCli_GetOrderCode:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetOrderCode","Ptr")
  static hCli_GetCpuInfo:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetCpuInfo","Ptr")
  static hCli_GetCpInfo:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetCpInfo","Ptr")
  static hCli_PlcHotStart:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_PlcHotStart","Ptr")
  static hCli_PlcColdStart:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_PlcColdStart","Ptr")
  static hCli_PlcStop:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_PlcStop","Ptr")
  static hCli_CopyRamToRom:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_CopyRamToRom","Ptr")
  static hCli_Compress:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_Compress","Ptr")
  static hCli_GetPlcStatus:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetPlcStatus","Ptr")
  static hCli_SetSessionPassword:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetSessionPassword","Ptr")
  static hCli_ClearSessionPassword:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ClearSessionPassword","Ptr")
  static hCli_GetProtection:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetProtection","Ptr")
  static hCli_IsoExchangeBuffer:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_IsoExchangeBuffer","Ptr")
  static hCli_GetExecTime:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetExecTime","Ptr")
  static hCli_GetLastError:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetLastError","Ptr")
  static hCli_GetPduLength:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetPduLength","Ptr")
  static hCli_ErrorText:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_ErrorText","Ptr")
  static hCli_GetConnected:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_GetConnected","Ptr")
  static hCli_SetAsCallback:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_SetAsCallback","Ptr")
  static hCli_CheckAsCompletion:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_CheckAsCompletion","Ptr")
  static hCli_WaitAsCompletion:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_WaitAsCompletion","Ptr")
  static hCli_AsReadArea:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsReadArea","Ptr")
  static hCli_AsWriteArea:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsWriteArea","Ptr")
  static hCli_AsDBRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsDBRead","Ptr")
  static hCli_AsDBWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsDBWrite","Ptr")
  static hCli_AsABRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsABRead","Ptr")
  static hCli_AsABWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsABWrite","Ptr")
  static hCli_AsEBRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsEBRead","Ptr")
  static hCli_AsEBWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsEBWrite","Ptr")
  static hCli_AsMBRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsMBRead","Ptr")
  static hCli_AsMBWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsMBWrite","Ptr")
  static hCli_AsTMRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsTMRead","Ptr")
  static hCli_AsTMWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsTMWrite","Ptr")
  static hCli_AsCTRead:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsCTRead","Ptr")
  static hCli_AsCTWrite:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsCTWrite","Ptr")
  static hCli_AsListBlocksOfType:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsListBlocksOfType","Ptr")
  static hCli_AsReadSZL:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsReadSZL","Ptr")
  static hCli_AsReadSZLList:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsReadSZLList","Ptr")
  static hCli_AsFullUpload:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsFullUpload","Ptr")
  static hCli_AsUpload:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsUpload","Ptr")
  static hCli_AsDownload:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsDownload","Ptr")
  static hCli_AsDBGet:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsDBGet","Ptr")
  static hCli_AsDBFill:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsDBFill","Ptr")
  static hCli_AsCopyRamToRom:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsCopyRamToRom","Ptr")
  static hCli_AsCompress:=DllCall("GetProcAddress","Ptr",Snap7.hModule,"AStr","Cli_AsCompress","Ptr")

  static ISOTCPErrorTable:=	{0x1:"Iso Connection error."
				,0x2:"Iso Disconnection error."
				,0x3:"Malformatted PDU suppled."
				,0x4:"Bad Datasize passed to send/recv function."
				,0x5:"Null pointer supplied."
				,0x6:"A short packet received."
				,0x7:"Too many packets without EoT flag (>64)"
				,0x8:"The sum of fragments data exceeds the maximum packet size."
				,0x9:"An error occurred during send."
				,0xA:"An error occurred during recv."
				,0xB:"Invalid TSAP params supplied."
				,0xC:"Reserved (unused)"
				,0xD:"Reserved (unused)"
				,0xE:"Reserved (unused)"
				,0xF:"Reserved (unused)"}

  static ClientErrorsTable:=	{0x001:"Error during PDU negotiation."
				,0x002:"Invalid param(s) supplied to the current function."
				,0x003:"A Job is pending : there is an async function in progress."
				,0x004:"More than 20 items where passed to a MultiRead/Write area function."
				,0x005:"Invalid Wordlen param supplied to the current function."
				,0x006:"Partial data where written : The target area is smaller than the DataSize supplied."
				,0x007:"A MultiRead/MultiWrite function has datasize over the PDU size."
				,0x008:"Invalid answer from the PLC."
				,0x009:"An address out of range was specified."
				,0x00A:"Invalid Transportsize parameter was supplied to a Read/WriteArea function."
				,0x00B:"Invalid datasize parameter supplied to the current function."
				,0x00C:"Item requested was not found in the PLC."
				,0x00D:"Invalid value supplied to the current function."
				,0x00E:"PLC cannot be started."
				,0x00F:"PLC is already in RUN stare."
				,0x010:"PLC cannot be stopped."
				,0x011:"Cannot copy RAM to ROM : the PLC is running or doesn’t support this function."
				,0x012:"Cannot compress : the PLC is running or doesn’t support this function."
				,0x013:"PLC is already in STOP state."
				,0x014:"Function not available."
				,0x015:"Block upload sequence failed."
				,0x016:"Invalid data size received from the PLC."
				,0x017:"Invalid block type supplied to the current function."
				,0x018:"Invalid block supplied to the current function."
				,0x019:"Invalid block size supplied to the current function."
				,0x01A:"Block download sequence failed."
				,0x01B:"Insert command (implicit command sent after a block download) refused."
				,0x01C:"Delete command refused."
				,0x01D:"This operation is password protected."
				,0x01E:"Invalid password supplied."
				,0x01F:"There is no password to set or clear : the protection is OFF."
				,0x020:"Job timeout."
				,0x021:"Partial data where read : The source area is greater than the DataSize supplied."
				,0x022:"The buffer supplied is too small."
				,0x023:"Function refused by the PLC."
				,0x024:"Invalid param number suppilied to Get/SetParam."
				,0x025:"Cannot perform : the client is destroying."
				,0x026:"Cannot change parameter because connected."}

  LastError[]
  {
    get
    {
      return format("0x{:08x}",this.Err)
    }
    set
    {
      return this.Err:=value
    }
  }

  LastErrors[]
  {
    get
    {
      TCP_IP_Error:= format("0x{:04X}",(this.Err & 0x0000FFFF))
      ISO_TCP_Error:=format("0x{:01X}",(this.Err & 0x000F0000) >> 16)
      Client_Error:= format("0x{:03X}",(this.Err & 0xFFF00000) >> 20)
      return [TCP_IP_Error,ISO_TCP_Error,Client_Error]
    }
  }

  LastErrorText[]
  {
    get
    {
      TCP_IP_Error:= format("0x{:04X}",(this.Err & 0x0000FFFF))
      ISO_TCP_Error:=format("0x{:X}",(this.Err & 0x000F0000) >> 16)
      Client_Error:= format("0x{:03X}",(this.Err & 0xFFF00000) >> 20)
      txt.="IP " this.IP "`tRack " this.Rack "`tSlot " this.Slot "`n"
      txt.="Error`t" (this.Err=""?"NULL":(format("0x{:08X}",this.Err))) "`n`n"
      txt.="TCP/IP Error = " (TCP_IP_Error?TCP_IP_Error:"None") "`t"
      txt.=(TCP_IP_Error?"(" (format("{:u}",TCP_IP_Error)) ")":"") "`n"
      txt.="`t" (TCP_IP_Error?"For TCP/IP code please refer to your OS reference.":"") "`n"
      txt.="ISO TCP Error = " (ISO_TCP_Error?ISO_TCP_Error:"None") "`n"
      txt.="`t" (Snap7.ISOTCPErrorTable[ISO_TCP_Error]) "`n"
      txt.="Client Error = " (Client_Error?Client_Error:"None") "`n"
      txt.="`t" (Snap7.ClientErrorsTable[Client_Error]) "`n`n"
      txt.=this.MsgAddText
      return txt
    }
  }

  Cli_LastErrorText[]
  {
    get
    {
      this.Cli_ErrorText(this.LastError,Text)
      return Text
    }
  }

  Msg(Msg)
  {
    this.SaveDefaultGui:=A_DefaultGui
    try Gui,% this.hGui . ":Destroy"
    Gui,new:+HwndhGui -sysmenu +AlwaysOnTop
    this.hGui:=hGui
    try Gui,%hGui%:font,s10
    try Gui,%hGui%:add,text,,%Msg%
    try Gui,%hGui%:add,button,+hwndhOkB,Ok
    obm:=ObjBindMethod(this,"OkButton")
    try GuiControl,+g,% hOkB,% obm
    try Gui,%hGui%:show,% "noactivate x" a_screenwidth/3 " y" a_screenheight/3 ,Snap7
    try Gui,% this.SaveDefaultGui . ":Default"
  }
  OkButton()
  {
    try Gui,% this.hGui . ":Destroy"
  }

  _sub()
  {
    this.MsgAddText:=this.AddText
    this.AddText:=""
    if this.ShowErrors
      this.Msg(this.LastErrorText)
    Err:=this.LastErrors
    if Err[1]
      this.Cli_Disconnect()
    if this.AutoReconnect and Err[1] and !this.TryingConnect
    {
      this.TryingConnect:=true
      obm:=this.ReconnectTimer
      settimer,% obm,% this.ReconnectTime
    }
  }
  Reconnect()
  {
    this.Cli_Disconnect()
    this.Cli_Connect()
    if this.Connected
    {
      obm:=this.ReconnectTimer
      settimer,% obm,Off
      this.TryingConnect:=false
    }
  }

  __New(IP="",Rack=0,Slot=3,ConnectionType=0x02,AutoReconnect=true,ReconnectTime=10000)
  {
    this.Err:=0
    this.ShowErrors:=true
    this.IP:=IP
    this.Rack:=Rack
    this.Slot:=Slot
    this.ConnectionType:=ConnectionType
    this.AutoReconnect:=AutoReconnect
    this.ReconnectTime:=ReconnectTime
    this.ReconnectTimer:=ObjBindMethod(this,"Reconnect")
    if this.Cli_Create()
      return ""
    this.Cli_SetConnectionType(ConnectionType)
    if IP
      this.Cli_ConnectTo(IP,Rack,Slot)
  }

  __Delete()
  {
    this.Cli_Destroy()
    try Gui,% this.hGui . ":Destroy"
  }

; Creates a Client and returns its handle, which is the reference that you have to use
; every time you refer to that client.
; The maximum number of clients that you can create depends only on the system
; memory amount
  Cli_Create()
  {
    ; S7Object Cli_Create();
    this._obj:=DllCall(Snap7.hCli_Create,"Ptr")
    if !this._obj
    {
      this.Err:=-1
      this.Msg("No S7Object.`n`nDll are not found.")
    }
    return this.Err
  }

; Destroy a Client of given handle.
; Before destruction the client is automatically disconnected if it was.
  Cli_Destroy()
  {
    ; void Cli_Destroy( S7Object *Client );
    DllCall(Snap7.hCli_Destroy,"ptr",this._obj)
    this._obj:=""
  }

; Sets the connection resource type, i.e the way in which the Clients connects to a PLC.
; Connection Type Value
; PG 0x01
; OP 0x02
; S7 Basic 0x03..0x10
  Cli_SetConnectionType(ConnectionType)
  {
    this.ConnectionType:=ConnectionType
    if !this._obj
      return this.LastError
    ; int Cli_SetConnectionType(S7Object Client, word ConnectionType);
    this.Err:=DllCall(Snap7.hCli_SetConnectionType
  		,"Ptr",this._obj
  		,"Int",ConnectionType)
    if (this.Err!=0)
    {
      Text:=this.LastErrorText
      Text.="Cli_SetConnectionType function`n"
      if this.ShowErrors
        this.Msg(Text)
    }
    return this.Err
  }

; Connects the client to the hardware at (IP, Rack, Slot) Coordinates.
; Rack and Slot
; In addition to the IP Address, that we all understand, there are two other parameters
; that index the unit : Rack (0..7) and Slot (1..31) that you find into the hardware
; configuration of your project, for a physical component, or into the Station
; Configuration manager for WinAC.
; There is however some special cases for which those values are fixed or can work with
; a default as you can see in the next table.
; 		Rack	Slot
; S7 300 CPU	0	2	Always
; S7 400 CPU	Not fixed	Follow the hardware configuration.
; WinAC CPU	Not fixed	Follow the hardware configuration.
; S7 1200 CPU	0	0	Or 0, 1
; S7 1500 CPU	0	0	Or 0, 1
; CP 343	0	0	Or follow Hardware configuration.
; CP 443	Not fixed	Follow the hardware configuration.
; WinAC IE	0	0	Or follow Hardware configuration.
; In the worst case, if you know the IP address, run ClientDemo, set 0 as Rack and try
; to connect with different values of Slot (1..31).
  Cli_ConnectTo(Address,Rack,Slot)
  {
    this.IP:=Address
    this.Rack:=Rack
    this.Slot:=Slot
    this.Cli_Disconnect()
    if !this._obj
      return this.LastError
    VarSetCapacity(addr,40,0)
    loop,parse,Address
      numput(asc(a_loopfield),addr,a_index-1,"Char")
    ; int Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot);
    this.Err:=DllCall(Snap7.hCli_ConnectTo
    		,"ptr",this._obj
    		,"ptr",&addr
    		,"int",Rack
    		,"int",Slot)
    if (this.Err!=0)
    {
      Text:=this.LastErrorText
      Text.="Cli_ConnectTo function`n"
      if this.ShowErrors
        this.Msg(Text)
    }
    Err:=this.LastErrors
    if Err[1]
      this.Cli_Disconnect()
    if this.AutoReconnect and Err[1]
    {
      this.TryingConnect:=true
      obm:=this.ReconnectTimer
      settimer,% obm,% this.ReconnectTime
    }
    return this.Err
  }

    ;int Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP);

; Connects the client to the PLC with the parameters specified in the previous call of
; Cli_ConnectTo() or Cli_SetConnectionParams().
; Remarks
; This function can be called only after a previous of Cli_ConnectTo()or
; Cli_SetConnectionParams() which internally sets Address and TSAPs.
  Cli_Connect()
  {
    ; int Cli_Connect(S7Object Client);
    this.Err:=DllCall(Snap7.hCli_Connect
  		,"Ptr",this._obj)
    if (this.Err!=0)
    {
      Text:=this.LastErrorText
      Text.="Cli_Connect function`n"
      if this.ShowErrors
        this.Msg(Text)
    }
    return this.Err
  }

; Disconnects “gracefully” the Client from the PLC.
; Remarks
; If Client parameter is a valid handle, this function returns always 0, it can be called
; safely multiple times.
; This function is called internally by Cli_Destroy() too.
  Cli_Disconnect()
  {
    ; int Cli_Disconnect(S7Object Client);
    DllCall(Snap7.hCli_Disconnect
  		,"Ptr",this._obj)
;    if (this.Err!=0)
;    {
;      if this.ShowErrors
;        this.Msg(this.LastErrorText)
;    }
;    return this.Err
  }

    ;int Cli_GetParam(S7Object Client, int ParamNumber, void *pValue);
    ;int Cli_SetParam(S7Object Client, int ParamNumber, void *pValue);

; This is the main function to read data from a PLC.
; With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters.
; Area table
; 		Value	Mean
; S7AreaPE	0x81	Process Inputs.
; S7AreaPA	0x82	Process Outputs.
; S7AreaMK	0x83	Merkers.
; S7AreaDB	0x84	DB
; S7AreaCT	0x1C	Counters.
; S7AreaTM	0x1D	Timers
;
; WordLen table
; 		Value	Mean
; S7WLBit	0x01	Bit (inside a word)
; S7WLByte	0x02	Byte (8 bit)
; S7WLWord	0x04	Word (16 bit)
; S7WLDWord	0x06	Double Word (32 bit)
; S7WLReal	0x08	Real (32 bit float)
; S7WLCounter	0x1C	Counter (16 bit)
; S7WLTimer	0x1D	Timer (16 bit)
;
; Remarks
; As said, every data packet exchanged with a PLC must fit in a PDU, whose size is fixed
; and varies from 240 up to 960 bytes.
; This function completely hides this concept, the data that you can transfer in
; a single call depends only on the size available of the data area (i.e. obviously,
; you cannot read 1024 bytes from a DB whose size is 300 bytes).
; If this data size exceeds the PDU size, the packet is automatically split across more
; subsequent transfers.
; If either S7AreaCT or S7AreaTM is selected, WordLen must be either S7WLCounter
; or S7WLTimer (However no error is raised and the values are internally fixed).
; Your buffer should be large enough to receive the data.
; Particularly:
; Buffer size (byte) = Word size * Amount
; Where:
; Word		size
; S7WLBit	1
; S7WLByte	1
; S7WLWord	2
; S7WLDWord	4
; S7WLReal	4
; S7WLCounter	2
; S7WLTimer	2
; Notes
; If you need a large data transfer you may consider to use the asynchronous
; counterpart Cli_AsReadArea.
; (2) When WordLen=S7WLBit the Offset (Start) must be expressed in bits.
; Ex. The Start for DB4.DBX 10.3 is (10*8)+3 = 83.
  Cli_ReadArea(Area,DBNumber,Start,Amount,WordLen,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ; int Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_ReadArea
  		,"Ptr",this._obj
		,"Int",Area
		,"Int",DBNumber
		,"Int",Start
		,"Int",Amount
		,"Int",WordLen
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ReadArea function`n"
      this.AddText.="Area`t`t" Snap7.AreaList[Area] "`nDBNumber`t" DBNumber "`nStart`t`t" Start
      this.AddText.="`nAmount`t`t" Amount "`nWordLen`t" Snap7.WordLenList[WordLen]
      this._sub()
    }
    return this.Err
  }

; This is the main function to write data into a PLC. It’s the complementary function of
; Cli_ReadArea(), the parameters and their meanings are the same.
; The only difference is that the data is transferred from the buffer pointed by pUsrData
; into PLC.
; Remarks
; If you need a large data transfer you may consider to use the asynchronous
; counterpart Cli_AsWriteArea.
  Cli_WriteArea(Area,DBNumber,Start,Amount,WordLen,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ; int Cli_WriteArea( S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_WriteArea
  		,"Ptr",this._obj
		,"Int",Area
		,"Int",DBNumber
		,"Int",Start
		,"Int",Amount
		,"Int",WordLen
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_WriteArea function`n"
      this.AddText.="Area`t`t" Snap7.AreaList[Area] "`nDBNumber`t" DBNumber "`nStart`t`t" Start
      this.AddText.="`nAmount`t`t" Amount "`nWordLen`t" Snap7.WordLenList[WordLen]
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_ReadArea() to read PLC DB.
; It simply internally calls Cli_ReadArea() with
;  Area = S7AreaDB.
;  WordLen = S7WLBytes.
  Cli_DBRead(DBNumber,Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_DBRead( S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_DBRead
  		,"Ptr",this._obj
		,"Int",DBNumber
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_DBRead function`n"
      this.AddText.="DBNumber`t" DBNumber "`nStart`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_WriteArea() to Write PLC DB.
; It simply internally calls Cli_WriteArea() with
;  Area = S7AreaDB.
;  WordLen = S7WLBytes.
  Cli_DBWrite(DBNumber,Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_DBWrite( S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_DBWrite
  		,"Ptr",this._obj
		,"Int",DBNumber
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_DBWrite function`n"
      this.AddText.="DBNumber`t" DBNumber "`nStart`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_ReadArea() to read PLC process outputs .
; It simply internally calls Cli_ReadArea() with
;  Area = S7AreaPA.
;  WordLen = S7WLBytes.
  Cli_ABRead(Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ABRead( S7Object Client, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_ABRead
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ABRead function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_WriteArea() to Write PLC process outputs.
; It simply internally calls Cli_WriteArea() with
;  Area = S7AreaPA.
;  WordLen = S7WLBytes.
  Cli_ABWrite(Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ABWrite( S7Object Client, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_ABWrite
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ABWrite function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_ReadArea() to read PLC process inputs .
; It simply internally calls Cli_ReadArea() with
;  Area = S7AreaPE.
;  WordLen = S7WLBytes.
  Cli_EBRead(Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_EBRead( S7Object Client, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_EBRead
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_EBRead function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_WriteArea() to Write PLC process inputs .
; It simply internally calls Cli_WriteArea() with
;  Area = S7AreaPE.
;  WordLen = S7WLBytes.
  Cli_EBWrite(Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_EBWrite( S7Object Client, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_EBWrite
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_EBWrite function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_ReadArea() to read PLC Merkers .
; It simply internally calls Cli_ReadArea() with
;  Area = S7AreaMK.
;  WordLen = S7WLBytes.
  Cli_MBRead(Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_MBRead
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_MBRead function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_WriteArea() to Write PLC Merkers.
; It simply internally calls Cli_WriteArea() with
;  Area = S7AreaMK.
;  WordLen = S7WLBytes.
  Cli_MBWrite(Start,Size,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_MBWrite
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Size
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_MBWrite function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nSize`t`t" Size
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_ReadArea() to read PLC Timers .
; It simply internally calls Cli_ReadArea() with
;  Area = S7AreaTM.
;  WordLen = S7WLTimer.
; Buffer size (bytes) needed is Amount * 2.
  Cli_TMRead(Start,Amount,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_TMRead
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Amount
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_TMRead function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nAmount`t`t" Amount
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_WriteArea() to Write PLC Timers .
; It simply internally calls Cli_WriteArea() with
;  Area = S7AreaTM.
;  WordLen = S7WLTimer.
; Buffer size (bytes) needed is Amount * 2.
  Cli_TMWrite(Start,Amount,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_TMWrite
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Amount
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_TMWrite function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nAmount`t`t" Amount
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_ReadArea() to read PLC Counters.
; It simply internally calls Cli_ReadArea() with
;  Area = S7AreaCT.
;  WordLen = S7WLCounter.
; Buffer size (bytes) needed is Amount * 2.
  Cli_CTRead(Start,Amount,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_CTRead
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Amount
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_CTRead function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nAmount`t`t" Amount
      this._sub()
    }
    return this.Err
  }

; This is a lean function of Cli_WriteArea() to Write PLC Counters.
; It simply internally calls Cli_WriteArea() with
;  Area = S7AreaCT.
;  WordLen = S7WLCounter.
; Buffer size (bytes) needed is Amount * 2.
  Cli_CTWrite(Start,Amount,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData);
    this.Err:=DllCall(Snap7.hCli_CTWrite
  		,"Ptr",this._obj
		,"Int",Start
		,"Int",Amount
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_CTWrite function`n"
      this.AddText.="Start`t`t" Start
      this.AddText.="`nAmount`t`t" Amount
      this._sub()
    }
    return this.Err
  }

; This is function allows to read different kind of variables from a PLC in a single call.
; With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters.
; PS7DataItem struct
; 		Type		Dir.
; Area		integer 32	In	Area identifier.
; Wordlen	integer 32	In	Word size
; Result	integer 32	Out	Item operation result (2)
; DBNumber	integer 32	In	DB Number if Area = S7AreaDB, otherwise is ignored.
; Start		integer 32	In	Offset to start
; Amount	integer 32	In	Amount of words to read (1)
; pData		Pointer		In	Address of user buffer.
; (1) Note the use of the parameter name “amount”, it means quantity of words, not byte size.
; Remarks
; Due the different kind of variables involved , there is no split feature available for this
; function, so the maximum data size must not exceed the PDU size. Thus there
; isn't an asynchronous counterpart of this function.
; The advantage of this function becomes big when you have many small noncontiguous
; variables to be read.
  Cli_ReadMultiVars(byref Item,ItemsCount)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);
    this.Err:=DllCall(Snap7.hCli_ReadMultiVars
  		,"Ptr",this._obj
		,"Ptr",&Item
		,"Int",ItemsCount)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ReadMultiVars function`n"
      this.AddText.="ItemsCount`t" ItemsCount "`n"
      this._sub()
    }
    return this.Err
  }

; This is function allows to write different kind of variables into a PLC in a single call.
; With it you can write DB, Inputs, Outputs, Merkers, Timers and Counters.
; It’s the complementary function of Cli_ReadMultiVars(), the parameters and their
; meanings are the same.
; See Cli_ReadMultiVars() for parameters and remarks.
  Cli_WriteMultiVars(Item,ItemsCount)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);
    this.Err:=DllCall(Snap7.hCli_WriteMultiVars
  		,"Ptr",this._obj
		,"Ptr",&Item
		,"Int",ItemsCount)
    if (this.Err!=0)
    {
      this.AddText.="Cli_WriteMultiVars function`n"
      this.AddText.="ItemsCount`t" ItemsCount "`n"
      this._sub()
    }
    return this.Err
  }

; This function returns the AG blocks amount divided by type.
; TS7BlocksList struct
; 		Type		Dir.
; OBCount	integer 32	Out	OB amount in AG
; FBCount	integer 32	Out	FB amount in AG
; FCCount	integer 32	Out	FC amount in AG
; SFBCount	integer 32	Out	SFB amount in AG
; SFCCount	integer 32	Out	SFC amount in AG
; DBCount	integer 32	Out	DB amount in AG
; SDBCount	integer 32	Out	SDB amount in AG
  Cli_ListBlocks(byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData);
    this.Err:=DllCall(Snap7.hCli_ListBlocks
  		,"Ptr",this._obj
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ListBlocks function`n"
      this._sub()
    }
    return this.Err
  }

; This function returns the AG list of a specified block type.
; BlockType values
; 		Value	Type
; Block_OB	0x38	OB
; Block_DB	0x41	DB
; Block_SDB	0x42	SDB
; Block_FC	0x43	FC
; Block_SFC	0x44	SFC
; Block_FB	0x45	FB
; Block_SFB	0x46	SFB
; TS7BlocksOfType, by default, is defined as a packed array of 8192 16-bit word.
; typedef word TS7BlocksOfType[0x2000];
; 8192 is the maximum number of blocks that a CPU S7417-4 can hold.
; ItemsCount
; In input indicates the user buffer capacity, in output how many items were found.
; The function reads the list into the internal buffer, if ItemsCount is smaller than the
; data uploaded, only ItemsCount elements are copied into the user buffer and
; errCliPartialDataRead is returned.
; The minimum expected value for ItemsCount is 1, otherwise
; errCliInvalidBlockSize error is returned.

  Cli_ListBlocksofType(BlockType,byref pUsrData,ItemsCount)
  {
    if !this.Connected
      return this.LastError
    varsetcapacity(pItemsCount,8)
    numput(ItemsCount,pItemsCount,0,"Int")
    ;int Cli_ListBlocksofType (S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);
    this.Err:=DllCall(Snap7.hCli_ListBlocksofType
  		,"Ptr",this._obj
		,"Int",BlockType
		,"Ptr",&pUsrData
		,"Ptr",&pItemsCount)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ListBlocksofType function`nBlockType`t" Snap7.BlockTypeList[BlockType]
      this._sub()
    }
    return this.Err
  }

; Returns detailed information about an AG given block.
; This function is very useful if you need to read or write data in a DB which you do not
; know the size in advance (see MC7Size field)
; This function is used internally by Cli_DBGet().
; BlockType values
; 		Value	Type
; Block_OB	0x38	OB
; Block_DB	0x41	DB
; Block_SDB	0x42	SDB
; Block_FC	0x43	FC
; Block_SFC	0x44	SFC
; Block_FB	0x45	FB
; Block_SFB	0x46	SFB

  Cli_GetAgBlockInfo(BlockType,BlockNum,byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData);
    this.Err:=DllCall(Snap7.hCli_GetAgBlockInfo
  		,"Ptr",this._obj
		,"Int",BlockType
		,"Int",BlockNum
		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetAgBlockInfo function`nBlockType`t" Snap7.BlockTypeList[BlockType] "`nBlockNum`t" BlockNum
      this._sub()
    }
    return this.Err
  }

; Returns detailed information about a block present in a user buffer.
; This function is usually used in conjunction with Cli_FullUpload().
; An uploaded a block saved to disk, could be loaded in a user buffer and checked with
; this function.
; Remarks
; For a detailed description of TS7BlockInfo see Cli_GetAgBlockInfo
; With this function in conjunction with block oriented functions it’s possible to create a
; “backup manager”.
; The rich demo ClientDemo shows how to upload/download/delete and get detailed
; block information.
  Cli_GetPgBlockInfo(byref pBlock,byref pUsrData, size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int size);
    this.Err:=DllCall(Snap7.hCli_GetPgBlockInfo
  		,"Ptr",this._obj
		,"Ptr",&pBlock
		,"Ptr",&pUsrData
		,"Int",size)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetPgBlockInfo function`nsize`t" size
      this._sub()
    }
    return this.Err
  }

; Uploads a block from AG.
; The whole block (including header and footer) is copied into the user buffer.
; BlockType values
; 		Value	Type
; Block_OB	0x38	OB
; Block_DB	0x41	DB
; Block_SDB	0x42	SDB
; Block_FC	0x43	FC
; Block_SFC	0x44	SFC
; Block_FB	0x45	FB
; Block_SFB	0x46	SFB
; The function is performed into the internal buffer, if size is smaller than the data
; uploaded, only size bytes are copied and errCliPartialDataRead is returned.
  Cli_FullUpload(BlockType,BlockNum,byref pUsrData,byref Size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_FullUpload( S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
    this.Err:=DllCall(Snap7.hCli_FullUpload
  		,"Ptr",this._obj
		,"Int",BlockType
		,"Int",BlockNum
		,"Ptr",&pUsrData
		,"Ptr",&Size)
    Size:=numget(Size,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_FullUpload function`nBlockType`t" Snap7.BlockTypeList[BlockType] "`nBlockNum`t" BlockNum "`nSize" Size
      this._sub()
    }
    return this.Err
  }

; Uploads a block body from AG.
; Only the block body (but header and footer) is copied into the user buffer.
; BlockType values
; 		Value	Type
; Block_OB	0x38	OB
; Block_DB	0x41	DB
; Block_SDB	0x42	SDB
; Block_FC	0x43	FC
; Block_SFC	0x44	SFC
; Block_FB	0x45	FB
; Block_SFB	0x46	SFB
; The function reads the block data into the internal buffer, if size is smaller than the
; data uploaded, only size bytes are copied into the user buffer and
; errCliPartialDataRead is returned.
  Cli_Upload(BlockType,BlockNum,byref pUsrData,byref Size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_Upload( S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
    this.Err:=DllCall(Snap7.hCli_Upload
  		,"Ptr",this._obj
		,"Int",BlockType
		,"Int",BlockNum
		,"Ptr",&pUsrData
		,"Ptr",&Size)
    Size:=numget(Size,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_Upload function`nBlockType`t" Snap7.BlockTypeList[BlockType] "`nBlockNum`t" BlockNum "`nSize" Size
      this._sub()
    }
    return this.Err
  }

; Downloads a block into AG.
; A whole block (including header and footer) must be available into the user buffer.
; Remarks
; A block ready to be downloaded already contains info about block type and block
; number.
; If the parameter BlockNum is -1, the block number is not changed used else the block
; is downloaded with a different number (just like a “Download As…”).
  Cli_Download(BlockNum,byref pUsrData,Size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_Download( S7Object Client, int BlockNum, void *pUsrData, int *Size);
    this.Err:=DllCall(Snap7.hCli_Download
  		,"Ptr",this._obj
		,"Int",BlockNum
		,"Ptr",&pUsrData
		,"Ptr",Size)
    if (this.Err!=0)
    {
      this.AddText.="Cli_Download function`nBlockNum`t" BlockNum "`nSize" Size
      this._sub()
    }
    return this.Err
  }

; Deletes a block into AG.
; BlockType values
; 		Value	Type
; Block_OB	0x38	OB
; Block_DB	0x41	DB
; Block_SDB	0x42	SDB
; Block_FC	0x43	FC
; Block_SFC	0x44	SFC
; Block_FB	0x45	FB
; Block_SFB	0x46	SFB
  Cli_Delete(BlockType,BlockNum)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_Delete( S7Object Client, int BlockType, int BlockNum);
    this.Err:=DllCall(Snap7.hCli_Delete
  		,"Ptr",this._obj
		,"Int",BlockType
		,"Int",BlockNum)
    if (this.Err!=0)
    {
      this.AddText.="Cli_Delete function`nBlockType`t" Snap7.BlockTypeList[BlockType] "`nBlockNum`t" BlockNum
      this._sub()
    }
    return this.Err
  }

; Uploads a DB from AG.
; This function is equivalent to Cli_Upload() with BlockType = Block_DB but it uses a
; different approach so it’s not subject to the security level set.
; Only data is uploaded.
; Remarks
; This function first gathers the DB size via Cli_GetAgBlockInfo then calls Cli_DBRead.
  Cli_DBGet(DBNumber,byref pUsrData,byref Size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_DBGet( S7Object Client, int DBNumber, void *pUsrData, int *Size);
    this.Err:=DllCall(Snap7.hCli_DBGet
  		,"Ptr",this._obj
		,"Int",DBNumber
		,"Ptr",&pUsrData
		,"Ptr",&Size)
    Size:=numget(Size,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_DBGet function`nDBNumber`t" DBNumber "`nSize" Size
      this._sub()
    }
    return this.Err
  }

; Fills a DB in AG with a given byte without the need of specifying its size.
; Remarks
; Fillchar is an integer for efficiency reasons, only the lowest byte is used.
  Cli_DBFill(DBNumber,FillChar)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_DBFill( S7Object Client, int DBNumber, int FillChar);
    this.Err:=DllCall(Snap7.hCli_DBFill
  		,"Ptr",this._obj
		,"Int",DBNumber
		,"Int",FillChar)
    if (this.Err!=0)
    {
      this.AddText.="Cli_DBFill function`nDBNumber`t" DBNumber "`nFillChar" FillChar
      this._sub()
    }
    return this.Err
  }

; Reads PLC date and time.
; Struct tm is C++ specific, if you use the wrappers provided, you don’t need to care
; about it, since tm is internally converted to the native date/time format.
  Cli_GetPlcDateTime(byref DateTime)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetPlcDateTime(S7Object Client, tm *DateTime);
    this.Err:=DllCall(Snap7.hCli_GetPlcDateTime
  		,"Ptr",this._obj
		,"Ptr",&DateTime)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetPlcDateTime function`n"
      this._sub()
    }
    return this.Err
  }

; Sets the PLC date and time.
; Struct tm is C++ specific, if you use the wrappers provided, you don’t need to care
; about it, since tm is internally converted to the native date/time format.
  Cli_SetPlcDateTime(byref DateTime)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_SetPlcDateTime(S7Object Client, tm *DateTime);
    this.Err:=DllCall(Snap7.hCli_SetPlcDateTime
  		,"Ptr",this._obj
		,"Ptr",&DateTime)
    if (this.Err!=0)
    {
      this.AddText.="Cli_SetPlcDateTime function`n"
      this._sub()
    }
    return this.Err
  }

; Sets the PLC date and time in accord to the PC system Date/Time.
  Cli_SetPlcSystemDateTime()
  {
    if !this.Connected
      return this.LastError
    ;int Cli_SetPlcSystemDateTime(S7Object Client);
    this.Err:=DllCall(Snap7.hCli_SetPlcSystemDateTime
  		,"Ptr",this._obj)
    if (this.Err!=0)
    {
      this.AddText.="Cli_SetPlcSystemDateTime function`n"
      this._sub()
    }
    return this.Err
  }

; Reads a partial list of given ID and INDEX.
; The function is performed into the internal buffer, if size is smaller than the data
; uploaded, only size bytes are copied and errCliPartialDataRead is returned.
; Remarks
; LENTHDR and N_DR are HI-LOW order swapped, the data buffer is unchanged.
; TS7SZL struct
; // See §33.1 of "System Software for S7-300/400 System and
; // Standard Functions"
; // and see SFC51 description too
; typedef struct {
; word LENTHDR;
; word N_DR;
; } SZL_HEADER, *PSZL_HEADER;
; typedef struct {
; SZL_HEADER Header;
; byte Data[0x4000-4];
; } TS7SZL, *PS7SZL;
;
;	 	Type			Dir.	Mean
; LENTHDR	unsigned Integer 16	Out	Length of a data record of the partial list in bytes
; N_DR		unsigned Integer 16	Out	Number of data records contained in the partial list.

  Cli_ReadSZL(ID,Index,byref pUsrData,byref Size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ReadSZL( S7Object Client, int ID, int Index, TS7SZL *pUsrData, int *Size);
    this.Err:=DllCall(Snap7.hCli_ReadSZL
  		,"Ptr",this._obj
  		,"Int",ID
  		,"Int",Index
  		,"Ptr",&pUsrData
  		,"Ptr",&Size)
    Size:=numget(Size,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_ReadSZL function`nID" ID "`nIndex`t" Index "`nSize`t" Size
      this._sub()
    }
    return this.Err
  }

; Reads the directory of the partial lists.
; TS7SZLList struct
; // See §33.1 of "System Software for S7-300/400 System and
; // Standard Functions"
; // and see SFC51 description too
; typedef struct {
; word LENTHDR;
; word N_DR;
; } SZL_HEADER, *PSZL_HEADER;
; typedef struct {
; SZL_HEADER Header;
; word List[0x2000-2]; // HI-LO Swapped
; } TS7SZLList, *PS7SZLList;
;
; 		Type			Dir.
; LENTHDR	unsigned Integer 16	Out	Length of a data record of the partial list in bytes
; N_DR		unsigned Integer 16	Out	Number of data records contained in the partial list.
  Cli_ReadSZLList(byref pUsrData,byref ItemsCount)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ReadSZLList( S7Object Client, TS7SZLList *pUsrData, int *ItemsCount);
    this.Err:=DllCall(Snap7.hCli_ReadSZLList
  		,"Ptr",this._obj
  		,"Ptr",&pUsrData
  		,"Ptr",&ItemsCount)
    ItemsCount:=numget(ItemsCount,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_ReadSZLList function`nItemsCount`t" ItemsCount
      this._sub()
    }
    return this.Err
  }

; Gets CPU order code and version info.
; TS7OrderCode struct
; typedef struct {
; char Code[21]; // Order Code
; byte V1; // Version V1.V2.V3
; byte V2;
; byte V3;
; } TS7OrderCode, *PS7OrderCode;
  Cli_GetOrderCode(byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetOrderCode( S7Object Client, TS7OrderCode *pUsrData);
    this.Err:=DllCall(Snap7.hCli_GetOrderCode
  		,"Ptr",this._obj
  		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetOrderCode function`n"
      this._sub()
    }
    return this.Err
  }
  GetOrderCode()
  {
    varsetcapacity(pUsrData,25)
    Err:=this.Cli_GetOrderCode(pUsrData)
    if (Err!=0)
      return
    Code:=Snap7.GetStr(pUsrData,0,21)
    V1:=numget(pUsrData,21,"UChar")
    V2:=numget(pUsrData,22,"UChar")
    V3:=numget(pUsrData,23,"UChar")
    return {Code:Code,V1:V1,V2:V2,V3:V3,Version:(V1 "." V2 "." V3)}
  }

; Gets CPU module name, serial number and other info.
; TS7CpuInfo struct
; typedef struct {
; char ModuleTypeName[33];
; char SerialNumber[25];
; char ASName[25];
; char Copyright[27];
; char ModuleName[25];
; } TS7CpuInfo, *PS7CpuInfo;
  Cli_GetCpuInfo(byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetCpuInfo( S7Object Client, TS7CpuInfo *pUsrData);
    this.Err:=DllCall(Snap7.hCli_GetCpuInfo
  		,"Ptr",this._obj
  		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetCpuInfo function`n"
      this._sub()
    }
    return this.Err
  }
  GetCpuInfo()
  {
    varsetcapacity(pUsrData,33+25+25+27+25)
    Err:=this.Cli_GetCpuInfo(pUsrData)
    if (Err!=0)
      return
    ModuleTypeName:=Snap7.GetStr(pUsrData,0,33)
    SerialNumber:=Snap7.GetStr(pUsrData,33,25)
    ASName:=Snap7.GetStr(pUsrData,33+25,25)
    Copyright:=Snap7.GetStr(pUsrData,33+25+25,27)
    ModuleName:=Snap7.GetStr(pUsrData,33+25+25+27,25)
    return {ModuleTypeName:ModuleTypeName,SerialNumber:SerialNumber,ASName:ASName,Copyright:Copyright,ModuleName:ModuleName}
  }

; Gets CP (communication processor) info.
; TS7CpInfo struct
; typedef struct {
; int MaxPduLengt;
; int MaxConnections;
; int MaxMpiRate;
; int MaxBusRate;
; } TS7CpInfo, *PS7CpInfo;
  Cli_GetCpInfo(byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetCpInfo( S7Object Client, TS7CpInfo *pUsrData);
    this.Err:=DllCall(Snap7.hCli_GetCpInfo
  		,"Ptr",this._obj
  		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetCpInfo function`n"
      this._sub()
    }
    return this.Err
  }
  GetCpInfo()
  {
    varsetcapacity(pUsrData,4*4)
    Err:=this.Cli_GetCpInfo(pUsrData)
    if (Err!=0)
      return
    MaxPduLengt:=numget(pUsrData,0,"Int")
    MaxConnections:=numget(pUsrData,4,"Int")
    MaxMpiRate:=numget(pUsrData,8,"Int")
    MaxBusRate:=numget(pUsrData,12,"Int")
    return {MaxPduLengt:MaxPduLengt,MaxConnections:MaxConnections,MaxMpiRate:MaxMpiRate,MaxBusRate:MaxBusRate}
  }

; Puts the CPU in RUN mode performing an HOT START.
; Remarks
; This function is subject to the security level set.
  Cli_PlcHotStart()
  {
    if !this.Connected
      return this.LastError
    ;int Cli_PlcHotStart( S7Object Client);
    this.Err:=DllCall(Snap7.hCli_PlcHotStart
  		,"Ptr",this._obj)
    if (this.Err!=0)
    {
      this.AddText.="Cli_PlcHotStart function`n"
      this._sub()
    }
    return this.Err
  }

; Puts the CPU in RUN mode performing a COLD START.
; Remarks
; This function is subject to the security level set.
  Cli_PlcColdStart()
  {
    if !this.Connected
      return this.LastError
    ;int Cli_PlcColdStart( S7Object Client);
    this.Err:=DllCall(Snap7.hCli_PlcColdStart
  		,"Ptr",this._obj)
    if (this.Err!=0)
    {
      this.AddText.="Cli_PlcColdStart function`n"
      this._sub()
    }
    return this.Err
  }

; Puts the CPU in STOP mode.
; Remarks
; This function is subject to the security level set.
  Cli_PlcStop()
  {
    if !this.Connected
      return this.LastError
    ;int Cli_PlcStop( S7Object Client);
    this.Err:=DllCall(Snap7.hCli_PlcStop
  		,"Ptr",this._obj)
    if (this.Err!=0)
    {
      this.AddText.="Cli_PlcStop function`n"
      this._sub()
    }
    return this.Err
  }

; Performs the Copy Ram to Rom action.
; Remarks
; Not all CPUs support this operation.
; The CPU must be in STOP mode.
  Cli_CopyRamToRom(Timeout)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_CopyRamToRom(S7Object Client, int Timeout);
    this.Err:=DllCall(Snap7.hCli_CopyRamToRom
  		,"Ptr",this._obj
  		,"Int",Timeout)
    if (this.Err!=0)
    {
      this.AddText.="Cli_CopyRamToRom function`nTimeout`t" Timeout
      this._sub()
    }
    return this.Err
  }

; Performs the Memory compress action.
; Remarks
; Not all CPUs support this operation.
; The CPU must be in STOP mode.
  Cli_Compress(Timeout)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_Compress(S7Object Client, int Timeout);
    this.Err:=DllCall(Snap7.hCli_Compress
  		,"Ptr",this._obj
  		,"Int",Timeout)
    if (this.Err!=0)
    {
      this.AddText.="Cli_Compress function`nTimeout`t" Timeout
      this._sub()
    }
    return this.Err
  }

; Returns the CPU status (running/stopped).
; Status values
; 			Value
; S7CpuStatusUnknown	0x00	The CPU status is unknown.
; S7CpuStatusRun	0x08	The CPU is running.
; S7CpuStatusStop	0x04	The CPU is stopped.
  Cli_GetPlcStatus(byref Status)
  {
    if !this.Connected
      return this.LastError
    VarSetCapacity(Status,8,0)
    ;int Cli_GetPlcStatus(S7Object Client, int *Status);
    this.Err:=DllCall(Snap7.hCli_GetPlcStatus
  		,"Ptr",this._obj
  		,"Ptr",&Status)
    Status:=numget(Status,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetPlcStatus function`n"
      this._sub()
    }
    return this.Err
  }

; Send the password to the PLC to meet its security level.
; Remarks
; A password accepted by a PLC is an 8 chars string, a greater password will be
; trimmed, and a smaller one will be "right space padded".
  Cli_SetSessionPassword(Password)
  {
    if !this.Connected
      return this.LastError
    StringLeft,Password,Password,8
    VarSetCapacity(Pass,8,0)
    loop,parse,Password
      numput(asc(a_loopfield),Pass,a_index-1,"Char")
    ;int Cli_SetSessionPassword(S7Object Client, char *Password);
    this.Err:=DllCall(Snap7.hCli_SetSessionPassword
  		,"Ptr",this._obj
  		,"Ptr",&Pass)
    if (this.Err!=0)
    {
      this.AddText.="Cli_SetSessionPassword function`n"
      this._sub()
    }
    return this.Err
  }

; Clears the password set for the current session (logout).
  Cli_ClearSessionPassword(Password)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_ClearSessionPassword(S7Object Client);
    this.Err:=DllCall(Snap7.hCli_ClearSessionPassword
  		,"Ptr",this._obj)
    if (this.Err!=0)
    {
      this.AddText.="Cli_ClearSessionPassword function`n"
      this._sub()
    }
    return this.Err
  }

; Gets the CPU protection level info.
; TS7Protection struct
; typedef struct {
; word sch_schal;
; word sch_par;
; word sch_rel;
; word bart_sch;
; word anl_sch;
; } TS7Protection, *PS7Protection;
;
; S7Protection Values
; 		Values
; sch_schal	1, 2, 3		Protection level set with the mode selector.
; sch_par	0, 1, 2, 3	Password level, 0 : no password
; sch_rel	0, 1, 2, 3	Valid protection level of the CPU
; bart_sch	1, 2, 3, 4	Mode selector setting (1:RUN, 2:RUN-P, 3:STOP, 4:MRES, 0:undefined or cannot be determined)
; anl_sch	0, 1, 2		Startup switch setting (1:CRST, 2:WRST, 0:undefined, does not exist of cannot be determined)
  Cli_GetProtection(byref pUsrData)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetProtection( S7Object Client, TS7Protection *pUsrData);
    this.Err:=DllCall(Snap7.hCli_GetProtection
  		,"Ptr",this._obj
  		,"Ptr",&pUsrData)
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetProtection function`n"
      this._sub()
    }
    return this.Err
  }

; Exchanges a given S7 PDU (protocol data unit) with the CPU.
; Remarks
; The S7 PDU supplied is encapsulated into an IsoTCP telegram then is sent to the CPU.
; Finally, the S7 PDU is extracted from the reply telegram and is copied into the user
; buffer.
; Look at S7_types.h for more info about S7 PDU.
; No size check is performed : use a large enough buffer.
  Cli_IsoExchangeBuffer(byref pUsrData,byref Size)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int *Size);
    this.Err:=DllCall(Snap7.hCli_IsoExchangeBuffer
  		,"Ptr",this._obj
  		,"Ptr",&pUsrData
  		,"Ptr",&Size)
    Size:=numget(Size,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_IsoExchangeBuffer function`nSize`t" Size
      this._sub()
    }
    return this.Err
  }

; Returns the last job execution time in milliseconds.
  Cli_GetExecTime(byref Time)
  {
    if !this.Connected
      return this.LastError
    ;int Cli_GetExecTime(S7Object Client, int *Time);
    this.Err:=DllCall(Snap7.hCli_GetExecTime
  		,"Ptr",this._obj
  		,"Ptr",&Time)
    Time:=numget(Time,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetExecTime function`nTime`t" Time
      this._sub()
    }
    return this.Err
  }

; Returns the last job result.
  Cli_GetLastError(byref LastError)
  {
    ;int Cli_GetLastError(S7Object Client, int *LastError);
    varsetcapacity(LastError,8)
    DllCall(Snap7.hCli_GetLastError
  		,"Ptr",this._obj
  		,"Ptr",&LastError)
    LastError:=numget(LastError,0,"Int")
;    if (this.Err!=0)
;    {
;      this.AddText.="Cli_GetLastError function`n"
;      if this.ShowErrors
;        this.Msg(this.LastErrorText)
;    }
;    return this.Err
  }

; Returns info about the PDU length.
; Remarks
; During the S7 connection Client and Server (the PLC) negotiate the PDU length.
; PDU requested can be modified with Cli_SetParam().
; It’s useful to know the PDU negotiated when we need to call Cli_ReadMultivar() or
; Cli_WriteMultiVar().
; All other data transfer functions handle by themselves this information and split
; automatically the telegrams if needed.
  Cli_GetPduLength(byref Requested,byref Negotiated)
  {
    ;int Cli_GetPduLength(S7Object Client, int *Requested, int *Negotiated);
    this.Err:=DllCall(Snap7.hCli_GetPduLength
  		,"Ptr",this._obj
  		,"Ptr",&Requested
  		,"Ptr",&Negotiated)
    Requested:=numget(Requested,0,"Int")
    Negotiated:=numget(Negotiated,0,"Int")
    if (this.Err!=0)
    {
      this.AddText.="Cli_GetPduLength function`n"
      if this.ShowErrors
        this.Msg(this.LastErrorText)
    }
    return this.Err
  }

; Returns a textual explanation of a given error number.
; Remarks
; This is a translation function, so there is no need of a client handle.
; The messages are in (internet) English, all they are in s7_text.cpp.
  Cli_ErrorText(Error,byref Text)
  {
    ;int Cli_ErrorText(int Error, char *Text, int TextLen);
    VarSetCapacity(Text,1024)
    DllCall(Snap7.hCli_ErrorText
  		,"Int",Error
  		,"Ptr",&Text
  		,"Int",1024)
    while(code:=numget(Text,a_index-1,"char"))
      tmpText.=Chr(code)
    Text:=tmpText
;    if (this.Err!=0)
;    {
;      this.AddText.="Cli_ErrorText function`n"
;      if this.ShowErrors
;        this.Msg(this.LastErrorText)
;    }
;    return this.Err
  }

; Returns the connection status
; Remarks
; IsConnected is 0 if the client is not connected otherwise contains an integer !=0.
  Cli_GetConnected(byref IsConnected)
  {
    ;int Cli_GetConnected(S7Object Client, int *IsConnected);
    varsetcapacity(IsConnected,8)
    DllCall(Snap7.hCli_GetConnected
  		,"Ptr",this._obj
  		,"Ptr",&IsConnected)
    IsConnected:=numget(IsConnected,0,"Int")
;    if (this.Err!=0)
;    {
;      this.MsgAddText:="Cli_GetPduLength function`n"
;      if this.ShowErrors
;        this.Msg(this.LastErrorText)
;      Err:=this.LastErrors
;      if Err[1]
;        this.Cli_Disconnect()
;    }
;    return this.Err
  }
  Connected[]
  {
    get
    {
      this.Cli_GetConnected(state)
      return state
    }
  }

    ;int Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr);
    ;int Cli_CheckAsCompletion(S7Object Client, int *opResult);
    ;int Cli_WaitAsCompletion(S7Object Client, int Timeout);
    ;int Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
    ;int Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
    ;int Cli_AsDBRead( S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
    ;int Cli_AsDBWrite( S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
    ;int Cli_AsABRead( S7Object Client, int Start, int Size, void *pUsrData);
    ;int Cli_AsABWrite( S7Object Client, int Start, int Size, void *pUsrData);
    ;int Cli_AsEBRead( S7Object Client, int Start, int Size, void *pUsrData);
    ;int Cli_AsEBWrite( S7Object Client, int Start, int Size, void *pUsrData);
    ;int Cli_AsMBRead( S7Object Client, int Start, int Size, void *pUsrData);
    ;int Cli_AsMBWrite( S7Object Client, int Start, int Size, void *pUsrData);
    ;int Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData);
    ;int Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData);
    ;int Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData);
    ;int Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData);
    ;int Cli_AsListBlocksofType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);
    ;int Cli_AsReadSZL( S7Object Client, int ID, int Index, TS7SZL *pUsrData, int *Size);
    ;int Cli_AsReadSZLList( S7Object Client, TS7SZLList *pUsrData, int *ItemsCount);
    ;int Cli_AsFullUpload( S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
    ;int Cli_AsUpload( S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
    ;int Cli_AsDownload( S7Object Client, int BlockNum, void *pUsrData, int *Size);
    ;int Cli_AsDBGet( S7Object Client, int DBNumber, void *pUsrData, int *Size);
    ;int Cli_AsDBFill( S7Object Client, int DBNumber, int FillChar);
    ;int Cli_AsCopyRamToRom(S7Object Client, int Timeout);
    ;int Cli_AsCompress(S7Object Client, int Timeout);

  GetStr(byref Data,Start,Size)
  {
    loop,% Size
      str.=Chr(numget(&Data,Start+a_index-1,"Char"))
    return str
  }

  SwapData(byref pVar,Size,Offset=0)
  {
    varsetcapacity(tmpvar,Size+Offset)
    loop,% Size
      numput(numget(&pVar,Offset+a_index-1,"uchar"),tmpvar,Offset+Size-a_index,"uchar")
    loop,% Size
      numput(numget(tmpvar,Offset+a_index-1,"uchar"),&pVar,Offset+a_index-1,"uchar")
  }

  DBRead(DBNumber,Start=0,DataType="Int")
  {
    switch DataType
    {
    case "Byte":
      Amount:=2
      aType:="UChar"
    case "Int":
      Amount:=2
      aType:="Short"
    case "Word":
      Amount:=2
      aType:="UShort"
    case "DInt":
      Amount:=4
      aType:="Int"
    case "DWord":
      Amount:=4
      aType:="UInt"
    case "Real":
      Amount:=4
      aType:="Float"
    default: ; Int
      Amount:=2
      aType:="Short"
    }
    VarSetCapacity(UsrData,Amount)
    Err:=this.Cli_ReadArea(Snap7.S7AreaDB,DBNumber,Start,Amount,Snap7.S7WLByte,UsrData)
    if (Err!=0)
      return
    Snap7.SwapData(UsrData,Amount)
    return NumGet(UsrData,0,aType)
  }

  DBWrite(Value,DBNumber,Start=0,DataType="Int")
  {
    switch DataType
    {
    case "Byte":
      Amount:=2
      aType:="UChar"
    case "Int":
      Amount:=2
      aType:="Short"
    case "Word":
      Amount:=2
      aType:="UShort"
    case "DInt":
      Amount:=4
      aType:="Int"
    case "DWord":
      Amount:=4
      aType:="UInt"
    case "Real":
      Amount:=4
      aType:="Float"
    default: ; Int
      Amount:=2
      aType:="Short"
    }
    VarSetCapacity(UsrData,Amount)
    NumPut(Value,UsrData,0,aType)
    Snap7.SwapData(UsrData,Amount)
    Err:=this.Cli_WriteArea(Snap7.S7AreaDB,DBNumber,Start,Amount,Snap7.S7WLByte,UsrData)
    return Err
  }
}
Post's attachments

snap7 AHK.zip 522.06 kb, 1 downloads since 2022-08-31 

You don't have the permssions to download the attachments of this post.
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.