Snap7 communication library for Siemens PLC

Just starting out? Need help? Post your questions and find answers here.
filip
New User
New User
Posts: 4
Joined: Sat Aug 11, 2018 7:31 pm

Snap7 communication library for Siemens PLC

Post by filip »

Hi,

I'm a newbie with Purebasic.
Is-there any way to use the snap7 with Purebasic ?

http://snap7.sourceforge.net/
It's a multi-platform Ethernet communication suite for interfacing natively with Siemens S7 PLCs.

Could someone give me some advice ?
I have no idea how to start...

Thanks
Filip
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Snap7 communication library for Siemens PLC

Post by mk-soft »

The Snap7 package looks very good. Is also a wrapper included to easily integrate it into Purebasic like at "C".
The snap7.h file still has to be converted into purebasic and the import of the lib has to be written.

Let's see when I have time to test them with the S7 controllers. I'm on vacation, though.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
- chris -
New User
New User
Posts: 9
Joined: Sun Jun 06, 2010 10:43 am

Re: Snap7 communication library for Siemens PLC

Post by - chris - »

Here is my snap7 include:

Code: Select all


;-TOP
; Kommentar     : snap7 include
; Author        : 
; Second Author : 
; Datei         : snap7.pbi
; Version       : 1.4.2
; Erstellt      : 12.10.2013
; Geändert      : 28.12.2016

; http://snap7.sourceforge.net/

; ------------------------------------------------------------------------------
;                                  COMMON
; ------------------------------------------------------------------------------

;- COMMON

Structure tm
  tm_sec.l   ; seconds of minutes from 0 to 59
  tm_min.l   ; minutes of hour from 0 to 59
  tm_hour.l  ; hours of day from 0 to 23
  tm_mday.l  ; day of month from 1 to 31
  tm_mon.l   ; month of year from 0 to 11
  tm_year.l  ; year since 1900
  tm_wday.l  ; days since sunday
  tm_yday.l  ; days since January 1st
  tm_isdst.l ; hours of daylight savings time    
EndStructure  

#TextLen = 1024

#errLibInvalidParam  = -1
#errLibInvalidObject = -2

; CPU status
#S7CpuStatusUnknown = $00
#S7CpuStatusRun     = $08
#S7CpuStatusStop    = $04

; ISO Errors
#errIsoConnect          = $00010000 ; Connection error
#errIsoDisconnect       = $00020000 ; Disconnect error
#errIsoInvalidPDU       = $00030000 ; Bad format
#errIsoInvalidDataSize  = $00040000 ; Bad Datasize passed to send/recv buffer is invalid
#errIsoNullPointer      = $00050000 ; Null passed as pointer
#errIsoShortPacket      = $00060000 ; A short packet received
#errIsoTooManyFragments = $00070000 ; Too many packets without EoT flag
#errIsoPduOverflow      = $00080000 ; The sum of fragments data exceded maximum packet size
#errIsoSendPacket       = $00090000 ; An error occurred during send
#errIsoRecvPacket       = $000A0000 ; An error occurred during recv
#errIsoInvalidParams    = $000B0000 ; Invalid TSAP params
#errIsoResvd_1          = $000C0000 ; Unassigned
#errIsoResvd_2          = $000D0000 ; Unassigned
#errIsoResvd_3          = $000E0000 ; Unassigned
#errIsoResvd_4          = $000F0000 ; Unassigned

; Tag Struct
Structure TS7Tag
  Area.l
  DBNumber.l
  Start.l
  Size.l
  WordLen.l  
EndStructure  

; ------------------------------------------------------------------------------
;                                  PARAMS LIST
; ------------------------------------------------------------------------------

;- PARAMS LIST

#p_u16_LocalPort     = 1
#p_u16_RemotePort    = 2
#p_i32_PingTimeout   = 3
#p_i32_SendTimeout   = 4
#p_i32_RecvTimeout   = 5
#p_i32_WorkInterval  = 6
#p_u16_SrcRef        = 7
#p_u16_DstRef        = 8
#p_u16_SrcTSap       = 9
#p_i32_PDURequest    = 10
#p_i32_MaxClients    = 11
#p_i32_BSendTimeout  = 12
#p_i32_BRecvTimeout  = 13
#p_u32_RecoveryTime  = 14
#p_u32_KeepAliveTime = 15

; Client/Partner Job status
#JobComplete = 0
#JobPending  = 1

;******************************************************************************
;                                   CLIENT
;******************************************************************************

;- CLIENT

; Error codes
#errNegotiatingPDU            = $00100000
#errCliInvalidParams          = $00200000
#errCliJobPending             = $00300000
#errCliTooManyItems           = $00400000
#errCliInvalidWordLen         = $00500000
#errCliPartialDataWritten     = $00600000
#errCliSizeOverPDU            = $00700000
#errCliInvalidPlcAnswer       = $00800000
#errCliAddressOutOfRange      = $00900000
#errCliInvalidTransportSize   = $00A00000
#errCliWriteDataSizeMismatch  = $00B00000
#errCliItemNotAvailable       = $00C00000
#errCliInvalidValue           = $00D00000
#errCliCannotStartPLC         = $00E00000
#errCliAlreadyRun             = $00F00000
#errCliCannotStopPLC          = $01000000
#errCliCannotCopyRamToRom     = $01100000
#errCliCannotCompress         = $01200000
#errCliAlreadyStop            = $01300000
#errCliFunNotAvailable        = $01400000
#errCliUploadSequenceFailed   = $01500000
#errCliInvalidDataSizeRecvd   = $01600000
#errCliInvalidBlockType       = $01700000
#errCliInvalidBlockNumber     = $01800000
#errCliInvalidBlockSize       = $01900000
#errCliDownloadSequenceFailed = $01A00000
#errCliInsertRefused          = $01B00000
#errCliDeleteRefused          = $01C00000
#errCliNeedPassword           = $01D00000
#errCliInvalidPassword        = $01E00000
#errCliNoPasswordToSetOrClear = $01F00000
#errCliJobTimeout             = $02000000
#errCliPartialDataRead        = $02100000
#errCliBufferTooSmall         = $02200000
#errCliFunctionRefused        = $02300000
#errCliDestroying             = $02400000
#errCliInvalidParamNumber     = $02500000
#errCliCannotChangeParam      = $02600000

#MaxVars = 20 ; Max vars that can be transferred with MultiRead/MultiWrite

; Client Connection Type
#CONNTYPE_PG    = $0001 ; Connect to the PLC as a PG
#CONNTYPE_OP    = $0002 ; Connect to the PLC as an OP
#CONNTYPE_BASIC = $0003 ; Basic connection

; Area ID
#S7AreaPE = $81
#S7AreaPA = $82
#S7AreaMK = $83
#S7AreaDB = $84
#S7AreaCT = $1C
#S7AreaTM = $1D

; Word Length
#S7WLBit     = $01
#S7WLByte    = $02
#S7WLWord    = $04
#S7WLDWord   = $06
#S7WLReal    = $08
#S7WLCounter = $1C
#S7WLTimer   = $1D

; Block type
#Block_OB  = $38
#Block_DB  = $41
#Block_SDB = $42
#Block_FC  = $43
#Block_SFC = $44
#Block_FB  = $45
#Block_SFB = $46

; Sub Block Type
#SubBlk_OB  = $08
#SubBlk_DB  = $0A
#SubBlk_SDB = $0B
#SubBlk_FC  = $0C
#SubBlk_SFC = $0D
#SubBlk_FB  = $0E
#SubBlk_SFB = $0F

; Block languages
#BlockLangAWL   = $01
#BlockLangKOP   = $02
#BlockLangFUP   = $03
#BlockLangSCL   = $04
#BlockLangDB    = $05
#BlockLangGRAPH = $06

; Read/Write Multivars
Structure TS7DataItem
  Area.l
  WordLen.l
  Result.l
  DBNumber.l
  Start.l
  Amount.l
  *pdata
EndStructure

; List Blocks
Structure TS7BlocksList
  OBCount.l
  FBCount.l
  FCCount.l
  SFBCount.l
  SFCCount.l
  DBCount.l
  SDBCount.l
EndStructure

; Blocks info
Structure TS7BlockInfo
  BlkType.l       ; Block Type (OB, DB) 
  BlkNumber.l     ; Block number
  BlkLang.l       ; Block Language
  BlkFlags.l      ; Block flags
  MC7Size.l       ; The real size in bytes
  LoadSize.l      ; Load memory size
  LocalData.l     ; Local data
  SBBLength.l     ; SBB Length
  CheckSum.l      ; Checksum
  Version.l       ; Block version
  ; Chars info
  CodeDate.a[11]  ; Code date
  IntfDate.a[11]  ; Interface date 
  Author.a[9]     ; Author
  Family.a[9]     ; Family
  Header.a[9]     ; Header    
EndStructure  

; Order code
Structure TS7OrderCode
  Code.a[21]
  V1.b
  V2.b
  V3.b  
EndStructure  

; CPU Info
Structure TS7CpuInfo
  ModuleTypeName.a[33]
  SerialNumber.a[25]
  ASName.a[25]
  Copyright.a[27]
  ModuleName.a[25]
EndStructure  

; CP Info
Structure TS7CpInfo
  MaxPduLengt.l
  MaxConnections.l
  MaxMpiRate.l
  MaxBusRate.l  
EndStructure  

; See §33.1 of "System Software for S7-300/400 System and Standard Functions"
; and see SFC51 description too
Structure SZL_HEADER
  LENTHDR.u
  N_DR.u
EndStructure  

Structure TS7SZL
  Header.SZL_HEADER
  Data_SZL.a[$4000-4]
EndStructure  

; SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted
Structure TS7SZLList
  Header.SZL_HEADER
  List_SZL.u[$2000-2]
EndStructure  

; See §33.19 of "System Software for S7-300/400 System and Standard Functions"
Structure TS7Protection
  sch_schal.u
  sch_par.u
  sch_rel.u
  bart_sch.u
  anl_sch.u  
EndStructure  

;******************************************************************************
;                                   SERVER
;******************************************************************************

;- SERVER

#OperationRead  = 0
#OperationWrite = 1

#mkEvent = 0
#mkLog   = 1

; Server Area ID  (use with Register/unregister - Lock/unlock Area)
#srvAreaPE = 0
#srvAreaPA = 1
#srvAreaMK = 2
#srvAreaCT = 3
#srvAreaTM = 4
#srvAreaDB = 5

; Errors
#errSrvCannotStart        = $00100000 ; Server cannot start
#errSrvDBNullPointer      = $00200000 ; Passed null as PData
#errSrvAreaAlreadyExists  = $00300000 ; Area Re-registration
#errSrvUnknownArea        = $00400000 ; Unknown area
#errSrvInvalidParams      = $00500000 ; Invalid param(s) supplied
#errSrvTooManyDB          = $00600000 ; Cannot register DB
#errSrvInvalidParamNumber = $00700000 ; Invalid param (srv_get/set_param)
#errSrvCannotChangeParam  = $00800000 ; Cannot change because running

; TCP Server Event codes
#evcServerStarted       = $00000001
#evcServerStopped       = $00000002
#evcListenerCannotStart = $00000004
#evcClientAdded         = $00000008
#evcClientRejected      = $00000010
#evcClientNoRoom        = $00000020
#evcClientException     = $00000040
#evcClientDisconnected  = $00000080
#evcClientTerminated    = $00000100
#evcClientsDropped      = $00000200
#evcReserved_00000400   = $00000400 ; actually unused
#evcReserved_00000800   = $00000800 ; actually unused
#evcReserved_00001000   = $00001000 ; actually unused
#evcReserved_00002000   = $00002000 ; actually unused
#evcReserved_00004000   = $00004000 ; actually unused
#evcReserved_00008000   = $00008000 ; actually unused

; S7 Server Event Code
#evcPDUincoming       = $00010000
#evcDataRead          = $00020000
#evcDataWrite         = $00040000
#evcNegotiatePDU      = $00080000
#evcReadSZL           = $00100000
#evcClock             = $00200000
#evcUpload            = $00400000
#evcDownload          = $00800000
#evcDirectory         = $01000000
#evcSecurity          = $02000000
#evcControl           = $04000000
#evcReserved_08000000 = $08000000 ; actually unused
#evcReserved_10000000 = $10000000 ; actually unused
#evcReserved_20000000 = $20000000 ; actually unused
#evcReserved_40000000 = $40000000 ; actually unused
#evcReserved_80000000 = $80000000 ; actually unused

; Masks to enable/disable all events
#evcAll  = $FFFFFFFF
#evcNone = $00000000

; Event SubCodes
#evsUnknown       = $0000
#evsStartUpload   = $0001
#evsStartDownload = $0001
#evsGetBlockList  = $0001
#evsStartListBoT  = $0002
#evsListBoT       = $0003
#evsGetBlockInfo  = $0004
#evsGetClock      = $0001
#evsSetClock      = $0002
#evsSetPassword   = $0001
#evsClrPassword   = $0002

; Event Params : functions group
#grProgrammer = $0041
#grCyclicData = $0042
#grBlocksInfo = $0043
#grSZL        = $0044
#grPassword   = $0045
#grBSend      = $0046
#grClock      = $0047
#grSecurity   = $0045

; Event Params : control codes
#CodeControlUnknown   = $0000
#CodeControlColdStart = $0001
#CodeControlWarmStart = $0002
#CodeControlStop      = $0003
#CodeControlCompress  = $0004
#CodeControlCpyRamRom = $0005
#CodeControlInsDel    = $0006

; Event Result
#evrNoError           = $0000
#evrFragmentRejected  = $0001
#evrMalformedPDU      = $0002
#evrSparseBytes       = $0003
#evrCannotHandlePDU   = $0004
#evrNotImplemented    = $0005
#evrErrException      = $0006
#evrErrAreaNotFound   = $0007
#evrErrOutOfRange     = $0008
#evrErrOverPDU        = $0009
#evrErrTransportSize  = $000A
#evrInvalidGroupUData = $000B
#evrInvalidSZL        = $000C
#evrDataSizeMismatch  = $000D
#evrCannotUpload      = $000E
#evrCannotDownload    = $000F
#evrUploadInvalidID   = $0010
#evrResNotFound       = $0011

Structure TSrvEvent
  EvtTime.l    ; Timestamp
  EvtSender.l  ; Sender
  EvtCode.l    ; Event code
  EvtRetCode.u ; Event result
  EvtParam1.u  ; Param 1 (if available)
  EvtParam2.u  ; Param 2 (if available)
  EvtParam3.u  ; Param 3 (if available)
  EvtParam4.u  ; Param 4 (if available)    
EndStructure  

;******************************************************************************
;                                   PARTNER
;******************************************************************************

;- PARTNER

; Status
#par_stopped    = 0 ; stopped
#par_connecting = 1 ; running and active connecting
#par_waiting    = 2 ; running and waiting for a connection
#par_linked     = 3 ; running and connected : linked
#par_sending    = 4 ; sending data
#par_receiving  = 5 ; receiving data
#par_binderror  = 6 ; error starting passive server

; Errors
#errParAddressInUse       = $00200000
#errParNoRoom             = $00300000
#errServerNoRoom          = $00400000
#errParInvalidParams      = $00500000
#errParNotLinked          = $00600000
#errParBusy               = $00700000
#errParFrameTimeout       = $00800000
#errParInvalidPDU         = $00900000
#errParSendTimeout        = $00A00000
#errParRecvTimeout        = $00B00000
#errParSendRefused        = $00C00000
#errParNegotiatingPDU     = $00D00000
#errParSendingBlock       = $00E00000
#errParRecvingBlock       = $00F00000
#errParBindError          = $01000000
#errParDestroying         = $01100000
#errParInvalidParamNumber = $01200000 ; Invalid param (par_get/set_param)
#errParCannotChangeParam  = $01300000 ; Cannot change because running
#errParBufferTooSmall     = $01400000 ; Raised by LabVIEW wrapper

;- Global
Global snap7_hDLL.i

;- Client Prototype
Prototype.i Cli_ABRead(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_ABWrite(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsABRead(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsABWrite(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsCTRead(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_AsCTWrite(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_AsCompress(Client.i, Timeout.i)
Prototype.i Cli_AsCopyRamToRom(Client.i, Timeout.i)
Prototype.i Cli_AsDBFill(Client.i, DBNumber.i, FillChar.i)
Prototype.i Cli_AsDBGet(Client.i, DBNumber.i, *pUsrData, *Size)
Prototype.i Cli_AsDBRead(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsDBWrite(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsDownload(Client.i, BlockNum.i, *pUsrData, Size.i)
Prototype.i Cli_AsEBRead(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsEBWrite(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsFullUpload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
Prototype.i Cli_AsListBlocksOfType(Client.i, BlockType.i, *pUsrData, *ItemsCount)
Prototype.i Cli_AsMBRead(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsMBWrite(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_AsReadArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
Prototype.i Cli_AsReadSZL(Client.i, ID.i, Index.i, *pUsrData, *Size)
Prototype.i Cli_AsReadSZLList(Client.i, *pUsrData, *ItemsCount)
Prototype.i Cli_AsTMRead(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_AsTMWrite(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_AsUpload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
Prototype.i Cli_AsWriteArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
Prototype.i Cli_CTRead(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_CTWrite(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_CheckAsCompletion(Client.i, *opResult)
Prototype.i Cli_ClearSessionPassword(Client)
Prototype.i Cli_Compress(Client.i, Timeout.i)
Prototype.i Cli_Connect(Client)
Prototype.i Cli_ConnectTo(Client.i, Address.p-ascii, Rack.i, Slot.i)
Prototype.i Cli_CopyRamToRom(Client.i, Timeout.i)
Prototype.i Cli_Create()
Prototype.i Cli_DBFill(Client.i, DBNumber.i, FillChar.i)
Prototype.i Cli_DBGet(Client.i, DBNumber.i, *pUsrData, *Size)
Prototype.i Cli_DBRead(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_DBWrite(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_Delete(Client.i, BlockType.i, BlockNum.i)
Prototype.i Cli_Destroy(*Client)
Prototype.i Cli_Disconnect(Client.i)
Prototype.i Cli_Download(Client.i, BlockNum.i, *pUsrData, Size.i)
Prototype.i Cli_EBRead(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_EBWrite(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_ErrorText(Error.i, *Text, TextLen.i)
Prototype.i Cli_FullUpload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
Prototype.i Cli_GetAgBlockInfo(Client.i, BlockType.i, BlockNum.i, *pUsrData)
Prototype.i Cli_GetConnected(Client.i, *Connected)
Prototype.i Cli_GetCpInfo(Client.i, *pUsrData)
Prototype.i Cli_GetCpuInfo(Client.i, *pUsrData)
Prototype.i Cli_GetExecTime(Client.i, *Time)
Prototype.i Cli_GetLastError(Client.i, *LastError)
Prototype.i Cli_GetOrderCode(Client.i, *pUsrData)
Prototype.i Cli_GetParam(Client.i, ParamNumber.i, *pValue)
Prototype.i Cli_GetPduLength(Client.i, *Requested, *Negotiated)
Prototype.i Cli_GetPgBlockInfo(Client.i, *pBlock, *pUsrData, Size.i)
Prototype.i Cli_GetPlcDateTime(Client, *DateTime)
Prototype.i Cli_GetPlcStatus(Client.i, *Status)
Prototype.i Cli_GetProtection(Client.i, *pUsrData)
Prototype.i Cli_IsoExchangeBuffer(Client.i, *pUsrData, *Size)
Prototype.i Cli_ListBlocks(Client.i, *pUsrData)
Prototype.i Cli_ListBlocksOfType(Client.i, BlockType.i, *pUsrData, *ItemsCount)
Prototype.i Cli_MBRead(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_MBWrite(Client.i, Start.i, Size.i, *pUsrData)
Prototype.i Cli_PlcColdStart(Client.i)
Prototype.i Cli_PlcHotStart(Client.i)
Prototype.i Cli_PlcStop(Client.i)
Prototype.i Cli_ReadArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
Prototype.i Cli_ReadMultiVars(Client.i, Item.i, ItemsCount.i)
Prototype.i Cli_ReadSZL(Client.i, ID.i, Index.i, *pUsrData, *Size)
Prototype.i Cli_ReadSZLList(Client.i, *pUsrData, *ItemsCount)
Prototype.i Cli_SetAsCallback(Client.i, *pCompletion, *usrPtr)
Prototype.i Cli_SetConnectionParams(Client.i, Address.p-ascii, LocalTSAP.u, RemoteTSAP.u)
Prototype.i Cli_SetConnectionType(Client.i, ConnectionType.u)
Prototype.i Cli_SetParam(Client.i, ParamNumber.i, *pValue)
Prototype.i Cli_SetPlcDateTime(Client.i, *DateTime)
Prototype.i Cli_SetPlcSystemDateTime(Client.i)
Prototype.i Cli_SetSessionPassword(Client.i, *Password)
Prototype.i Cli_TMRead(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_TMWrite(Client.i, Start.i, Amount.i, *pUsrData)
Prototype.i Cli_Upload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
Prototype.i Cli_WaitAsCompletion(Client.i, Timeout.i)
Prototype.i Cli_WriteArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
Prototype.i Cli_WriteMultiVars(Client.i, Item.i, ItemsCount.i)

;- Server Prototype
Prototype.i Srv_ClearEvents(Server)
Prototype.i Srv_Create()
Prototype.i Srv_Destroy(*Server)
Prototype.i Srv_ErrorText(Error.i, *Text, TextLen.i)
Prototype.i Srv_EventText(*Event, *Text, TextLen.i)
Prototype.i Srv_GetMask(Server.i, MaskKind.i, *Mask)
Prototype.i Srv_GetParam(Server.i, ParamNumber.i, *pValue)
Prototype.i Srv_GetStatus(Server.i, *ServerStatus, *CpuStatus, *ClientsCount)
Prototype.i Srv_LockArea(Server.i, AreaCode.i, Index.u)
Prototype.i Srv_PickEvent(Server.i, *pEvent, *EvtReady)
Prototype.i Srv_RegisterArea(Server.i, AreaCode.i, Index.u, *pUsrData, Size.i)
Prototype.i Srv_SetCpuStatus(Server.i, CpuStatus.i)
Prototype.i Srv_SetEventsCallback(Server.i, *pCallback, *usrPtr)
Prototype.i Srv_SetMask(Server.i, MaskKind.i, Mask.l)
Prototype.i Srv_SetParam(Server.i, ParamNumber.i, *pValue)
Prototype.i Srv_SetRWAreaCallback(Server.i, *pCallback, *usrPtr)
Prototype.i Srv_SetReadEventsCallback(Server.i, *pCallback, *usrPtr)
Prototype.i Srv_Start(Server.i)
Prototype.i Srv_StartTo(Server, Address.p-ascii)
Prototype.i Srv_Stop(Server.i)
Prototype.i Srv_UnlockArea(Server.i, AreaCode.i, Index.u)
Prototype.i Srv_UnregisterArea(Server.i, AreaCode.i, Index.u)

;- Partner Prototype
Prototype.i Par_AsBSend(Partner.i, R_ID.l, *pUsrData, Size.i)
Prototype.i Par_BRecv(Partner.i, *R_ID, *pData, *Size, Timeout.l)
Prototype.i Par_BSend(Partner.i, R_ID.l, *pUsrData, Size.i)
Prototype.i Par_CheckAsBRecvCompletion(Partner.i, *opResult, *R_ID, *pData, *Size)
Prototype.i Par_CheckAsBSendCompletion(Partner.i, *opResult)
Prototype.i Par_Create(Active.i)
Prototype.i Par_Destroy(*Partner)
Prototype.i Par_ErrorText(Error.i, *Text, TextLen.i)
Prototype.i Par_GetLastError(Partner.i, *LastError)
Prototype.i Par_GetParam(Partner.i, ParamNumber.i, *pValue)
Prototype.i Par_GetStats(Partner.i, *BytesSent, *BytesRecv, *SendErrors, *RecvErrors)
Prototype.i Par_GetStatus(Partner.i, *Status)
Prototype.i Par_GetTimes(Partner.i, *SendTime, *RecvTime)
Prototype.i Par_SetParam(Partner.i, ParamNumber.i, *pValue)
Prototype.i Par_SetRecvCallback(Partner.i, *pCompletion, *usrPtr)
Prototype.i Par_SetSendCallback(Partner.i, *pCompletion, *usrPtr)
Prototype.i Par_Start(Partner.i)
Prototype.i Par_StartTo(Partner.i, LocalAddress.p-ascii, RemoteAddress.p-ascii, LocTsap.u, RemTsap.u)
Prototype.i Par_Stop(Partner.i)
Prototype.i Par_WaitAsBSendCompletion(Partner.i, Timeout.l)

Procedure snap7_CloseDLL()
  If snap7_hDLL <> 0
    If IsLibrary(snap7_hDLL)
      CloseLibrary(snap7_hDLL)
    EndIf
    snap7_hDLL = 0
  EndIf
EndProcedure

Procedure snap7_OpenDLL()

  snap7_hDLL = OpenLibrary(#PB_Any, "snap7.dll")
  If snap7_hDLL = 0
    ProcedureReturn #False
  EndIf

  Global Cli_ABRead.Cli_ABRead=GetFunction(snap7_hDLL,"Cli_ABRead")
  Global Cli_ABWrite.Cli_ABWrite=GetFunction(snap7_hDLL,"Cli_ABWrite")
  Global Cli_AsABRead.Cli_AsABRead=GetFunction(snap7_hDLL,"Cli_AsABRead")
  Global Cli_AsABWrite.Cli_AsABWrite=GetFunction(snap7_hDLL,"Cli_AsABWrite")
  Global Cli_AsCTRead.Cli_AsCTRead=GetFunction(snap7_hDLL,"Cli_AsCTRead")
  Global Cli_AsCTWrite.Cli_AsCTWrite=GetFunction(snap7_hDLL,"Cli_AsCTWrite")
  Global Cli_AsCompress.Cli_AsCompress=GetFunction(snap7_hDLL,"Cli_AsCompress")
  Global Cli_AsCopyRamToRom.Cli_AsCopyRamToRom=GetFunction(snap7_hDLL,"Cli_AsCopyRamToRom")
  Global Cli_AsDBFill.Cli_AsDBFill=GetFunction(snap7_hDLL,"Cli_AsDBFill")
  Global Cli_AsDBGet.Cli_AsDBGet=GetFunction(snap7_hDLL,"Cli_AsDBGet")
  Global Cli_AsDBRead.Cli_AsDBRead=GetFunction(snap7_hDLL,"Cli_AsDBRead")
  Global Cli_AsDBWrite.Cli_AsDBWrite=GetFunction(snap7_hDLL,"Cli_AsDBWrite")
  Global Cli_AsDownload.Cli_AsDownload=GetFunction(snap7_hDLL,"Cli_AsDownload")
  Global Cli_AsEBRead.Cli_AsEBRead=GetFunction(snap7_hDLL,"Cli_AsEBRead")
  Global Cli_AsEBWrite.Cli_AsEBWrite=GetFunction(snap7_hDLL,"Cli_AsEBWrite")
  Global Cli_AsFullUpload.Cli_AsFullUpload=GetFunction(snap7_hDLL,"Cli_AsFullUpload")
  Global Cli_AsListBlocksOfType.Cli_AsListBlocksOfType=GetFunction(snap7_hDLL,"Cli_AsListBlocksOfType")
  Global Cli_AsMBRead.Cli_AsMBRead=GetFunction(snap7_hDLL,"Cli_AsMBRead")
  Global Cli_AsMBWrite.Cli_AsMBWrite=GetFunction(snap7_hDLL,"Cli_AsMBWrite")
  Global Cli_AsReadArea.Cli_AsReadArea=GetFunction(snap7_hDLL,"Cli_AsReadArea")
  Global Cli_AsReadSZL.Cli_AsReadSZL=GetFunction(snap7_hDLL,"Cli_AsReadSZL")
  Global Cli_AsReadSZLList.Cli_AsReadSZLList=GetFunction(snap7_hDLL,"Cli_AsReadSZLList")
  Global Cli_AsTMRead.Cli_AsTMRead=GetFunction(snap7_hDLL,"Cli_AsTMRead")
  Global Cli_AsTMWrite.Cli_AsTMWrite=GetFunction(snap7_hDLL,"Cli_AsTMWrite")
  Global Cli_AsUpload.Cli_AsUpload=GetFunction(snap7_hDLL,"Cli_AsUpload")
  Global Cli_AsWriteArea.Cli_AsWriteArea=GetFunction(snap7_hDLL,"Cli_AsWriteArea")
  Global Cli_CTRead.Cli_CTRead=GetFunction(snap7_hDLL,"Cli_CTRead")
  Global Cli_CTWrite.Cli_CTWrite=GetFunction(snap7_hDLL,"Cli_CTWrite")
  Global Cli_CheckAsCompletion.Cli_CheckAsCompletion=GetFunction(snap7_hDLL,"Cli_CheckAsCompletion")
  Global Cli_ClearSessionPassword.Cli_ClearSessionPassword=GetFunction(snap7_hDLL,"Cli_ClearSessionPassword")
  Global Cli_Compress.Cli_Compress=GetFunction(snap7_hDLL,"Cli_Compress")
  Global Cli_Connect.Cli_Connect=GetFunction(snap7_hDLL,"Cli_Connect")
  Global Cli_ConnectTo.Cli_ConnectTo=GetFunction(snap7_hDLL,"Cli_ConnectTo")
  Global Cli_CopyRamToRom.Cli_CopyRamToRom=GetFunction(snap7_hDLL,"Cli_CopyRamToRom")
  Global Cli_Create.Cli_Create=GetFunction(snap7_hDLL,"Cli_Create")
  Global Cli_DBFill.Cli_DBFill=GetFunction(snap7_hDLL,"Cli_DBFill")
  Global Cli_DBGet.Cli_DBGet=GetFunction(snap7_hDLL,"Cli_DBGet")
  Global Cli_DBRead.Cli_DBRead=GetFunction(snap7_hDLL,"Cli_DBRead")
  Global Cli_DBWrite.Cli_DBWrite=GetFunction(snap7_hDLL,"Cli_DBWrite")
  Global Cli_Delete.Cli_Delete=GetFunction(snap7_hDLL,"Cli_Delete")
  Global Cli_Destroy.Cli_Destroy=GetFunction(snap7_hDLL,"Cli_Destroy")
  Global Cli_Disconnect.Cli_Disconnect=GetFunction(snap7_hDLL,"Cli_Disconnect")
  Global Cli_Download.Cli_Download=GetFunction(snap7_hDLL,"Cli_Download")
  Global Cli_EBRead.Cli_EBRead=GetFunction(snap7_hDLL,"Cli_EBRead")
  Global Cli_EBWrite.Cli_EBWrite=GetFunction(snap7_hDLL,"Cli_EBWrite")
  Global Cli_ErrorText.Cli_ErrorText=GetFunction(snap7_hDLL,"Cli_ErrorText")
  Global Cli_FullUpload.Cli_FullUpload=GetFunction(snap7_hDLL,"Cli_FullUpload")
  Global Cli_GetAgBlockInfo.Cli_GetAgBlockInfo=GetFunction(snap7_hDLL,"Cli_GetAgBlockInfo")
  Global Cli_GetConnected.Cli_GetConnected=GetFunction(snap7_hDLL,"Cli_GetConnected")
  Global Cli_GetCpInfo.Cli_GetCpInfo=GetFunction(snap7_hDLL,"Cli_GetCpInfo")
  Global Cli_GetCpuInfo.Cli_GetCpuInfo=GetFunction(snap7_hDLL,"Cli_GetCpuInfo")
  Global Cli_GetExecTime.Cli_GetExecTime=GetFunction(snap7_hDLL,"Cli_GetExecTime")
  Global Cli_GetLastError.Cli_GetLastError=GetFunction(snap7_hDLL,"Cli_GetLastError")
  Global Cli_GetOrderCode.Cli_GetOrderCode=GetFunction(snap7_hDLL,"Cli_GetOrderCode")
  Global Cli_GetParam.Cli_GetParam=GetFunction(snap7_hDLL,"Cli_GetParam")
  Global Cli_GetPduLength.Cli_GetPduLength=GetFunction(snap7_hDLL,"Cli_GetPduLength")
  Global Cli_GetPgBlockInfo.Cli_GetPgBlockInfo=GetFunction(snap7_hDLL,"Cli_GetPgBlockInfo")
  Global Cli_GetPlcDateTime.Cli_GetPlcDateTime=GetFunction(snap7_hDLL,"Cli_GetPlcDateTime")
  Global Cli_GetPlcStatus.Cli_GetPlcStatus=GetFunction(snap7_hDLL,"Cli_GetPlcStatus")
  Global Cli_GetProtection.Cli_GetProtection=GetFunction(snap7_hDLL,"Cli_GetProtection")
  Global Cli_IsoExchangeBuffer.Cli_IsoExchangeBuffer=GetFunction(snap7_hDLL,"Cli_IsoExchangeBuffer")
  Global Cli_ListBlocks.Cli_ListBlocks=GetFunction(snap7_hDLL,"Cli_ListBlocks")
  Global Cli_ListBlocksOfType.Cli_ListBlocksOfType=GetFunction(snap7_hDLL,"Cli_ListBlocksOfType")
  Global Cli_MBRead.Cli_MBRead=GetFunction(snap7_hDLL,"Cli_MBRead")
  Global Cli_MBWrite.Cli_MBWrite=GetFunction(snap7_hDLL,"Cli_MBWrite")
  Global Cli_PlcColdStart.Cli_PlcColdStart=GetFunction(snap7_hDLL,"Cli_PlcColdStart")
  Global Cli_PlcHotStart.Cli_PlcHotStart=GetFunction(snap7_hDLL,"Cli_PlcHotStart")
  Global Cli_PlcStop.Cli_PlcStop=GetFunction(snap7_hDLL,"Cli_PlcStop")
  Global Cli_ReadArea.Cli_ReadArea=GetFunction(snap7_hDLL,"Cli_ReadArea")
  Global Cli_ReadMultiVars.Cli_ReadMultiVars=GetFunction(snap7_hDLL,"Cli_ReadMultiVars")
  Global Cli_ReadSZL.Cli_ReadSZL=GetFunction(snap7_hDLL,"Cli_ReadSZL")
  Global Cli_ReadSZLList.Cli_ReadSZLList=GetFunction(snap7_hDLL,"Cli_ReadSZLList")
  Global Cli_SetAsCallback.Cli_SetAsCallback=GetFunction(snap7_hDLL,"Cli_SetAsCallback")
  Global Cli_SetConnectionParams.Cli_SetConnectionParams=GetFunction(snap7_hDLL,"Cli_SetConnectionParams")
  Global Cli_SetConnectionType.Cli_SetConnectionType=GetFunction(snap7_hDLL,"Cli_SetConnectionType")
  Global Cli_SetParam.Cli_SetParam=GetFunction(snap7_hDLL,"Cli_SetParam")
  Global Cli_SetPlcDateTime.Cli_SetPlcDateTime=GetFunction(snap7_hDLL,"Cli_SetPlcDateTime")
  Global Cli_SetPlcSystemDateTime.Cli_SetPlcSystemDateTime=GetFunction(snap7_hDLL,"Cli_SetPlcSystemDateTime")
  Global Cli_SetSessionPassword.Cli_SetSessionPassword=GetFunction(snap7_hDLL,"Cli_SetSessionPassword")
  Global Cli_TMRead.Cli_TMRead=GetFunction(snap7_hDLL,"Cli_TMRead")
  Global Cli_TMWrite.Cli_TMWrite=GetFunction(snap7_hDLL,"Cli_TMWrite")
  Global Cli_Upload.Cli_Upload=GetFunction(snap7_hDLL,"Cli_Upload")
  Global Cli_WaitAsCompletion.Cli_WaitAsCompletion=GetFunction(snap7_hDLL,"Cli_WaitAsCompletion")
  Global Cli_WriteArea.Cli_WriteArea=GetFunction(snap7_hDLL,"Cli_WriteArea")
  Global Cli_WriteMultiVars.Cli_WriteMultiVars=GetFunction(snap7_hDLL,"Cli_WriteMultiVars")
  
  Global Srv_ClearEvents.Srv_ClearEvents=GetFunction(snap7_hDLL,"Srv_ClearEvents")
  Global Srv_Create.Srv_Create=GetFunction(snap7_hDLL,"Srv_Create")
  Global Srv_Destroy.Srv_Destroy=GetFunction(snap7_hDLL,"Srv_Destroy")
  Global Srv_ErrorText.Srv_ErrorText=GetFunction(snap7_hDLL,"Srv_ErrorText")
  Global Srv_EventText.Srv_EventText=GetFunction(snap7_hDLL,"Srv_EventText")
  Global Srv_GetMask.Srv_GetMask=GetFunction(snap7_hDLL,"Srv_GetMask")
  Global Srv_GetParam.Srv_GetParam=GetFunction(snap7_hDLL,"Srv_GetParam")
  Global Srv_GetStatus.Srv_GetStatus=GetFunction(snap7_hDLL,"Srv_GetStatus")
  Global Srv_LockArea.Srv_LockArea=GetFunction(snap7_hDLL,"Srv_LockArea")
  Global Srv_PickEvent.Srv_PickEvent=GetFunction(snap7_hDLL,"Srv_PickEvent")
  Global Srv_RegisterArea.Srv_RegisterArea=GetFunction(snap7_hDLL,"Srv_RegisterArea")
  Global Srv_SetCpuStatus.Srv_SetCpuStatus=GetFunction(snap7_hDLL,"Srv_SetCpuStatus")
  Global Srv_SetEventsCallback.Srv_SetEventsCallback=GetFunction(snap7_hDLL,"Srv_SetEventsCallback")
  Global Srv_SetMask.Srv_SetMask=GetFunction(snap7_hDLL,"Srv_SetMask")
  Global Srv_SetParam.Srv_SetParam=GetFunction(snap7_hDLL,"Srv_SetParam")
  Global Srv_SetRWAreaCallback.Srv_SetRWAreaCallback=GetFunction(snap7_hDLL,"Srv_SetRWAreaCallback")
  Global Srv_SetReadEventsCallback.Srv_SetReadEventsCallback=GetFunction(snap7_hDLL,"Srv_SetReadEventsCallback")
  Global Srv_Start.Srv_Start=GetFunction(snap7_hDLL,"Srv_Start")
  Global Srv_StartTo.Srv_StartTo=GetFunction(snap7_hDLL,"Srv_StartTo")
  Global Srv_Stop.Srv_Stop=GetFunction(snap7_hDLL,"Srv_Stop")
  Global Srv_UnlockArea.Srv_UnlockArea=GetFunction(snap7_hDLL,"Srv_UnlockArea")
  Global Srv_UnregisterArea.Srv_UnregisterArea=GetFunction(snap7_hDLL,"Srv_UnregisterArea")  
  
  Global Par_AsBSend.Par_AsBSend=GetFunction(snap7_hDLL,"Par_AsBSend")
  Global Par_BRecv.Par_BRecv=GetFunction(snap7_hDLL,"Par_BRecv")
  Global Par_BSend.Par_BSend=GetFunction(snap7_hDLL,"Par_BSend")
  Global Par_CheckAsBRecvCompletion.Par_CheckAsBRecvCompletion=GetFunction(snap7_hDLL,"Par_CheckAsBRecvCompletion")
  Global Par_CheckAsBSendCompletion.Par_CheckAsBSendCompletion=GetFunction(snap7_hDLL,"Par_CheckAsBSendCompletion")
  Global Par_Create.Par_Create=GetFunction(snap7_hDLL,"Par_Create")
  Global Par_Destroy.Par_Destroy=GetFunction(snap7_hDLL,"Par_Destroy")
  Global Par_ErrorText.Par_ErrorText=GetFunction(snap7_hDLL,"Par_ErrorText")
  Global Par_GetLastError.Par_GetLastError=GetFunction(snap7_hDLL,"Par_GetLastError")
  Global Par_GetParam.Par_GetParam=GetFunction(snap7_hDLL,"Par_GetParam")
  Global Par_GetStats.Par_GetStats=GetFunction(snap7_hDLL,"Par_GetStats")
  Global Par_GetStatus.Par_GetStatus=GetFunction(snap7_hDLL,"Par_GetStatus")
  Global Par_GetTimes.Par_GetTimes=GetFunction(snap7_hDLL,"Par_GetTimes")
  Global Par_SetParam.Par_SetParam=GetFunction(snap7_hDLL,"Par_SetParam")
  Global Par_SetRecvCallback.Par_SetRecvCallback=GetFunction(snap7_hDLL,"Par_SetRecvCallback")
  Global Par_SetSendCallback.Par_SetSendCallback=GetFunction(snap7_hDLL,"Par_SetSendCallback")
  Global Par_Start.Par_Start=GetFunction(snap7_hDLL,"Par_Start")
  Global Par_StartTo.Par_StartTo=GetFunction(snap7_hDLL,"Par_StartTo")
  Global Par_Stop.Par_Stop=GetFunction(snap7_hDLL,"Par_Stop")
  Global Par_WaitAsBSendCompletion.Par_WaitAsBSendCompletion=GetFunction(snap7_hDLL,"Par_WaitAsBSendCompletion")  
  
  ProcedureReturn #True
EndProcedure

;- Text routines

Procedure.s CliErrorText(Error.i)
  
  Dim text.a(#TextLen - 1)
  
  Cli_ErrorText(Error, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii) 
EndProcedure  

Procedure.s SrvErrorText(Error.i)
  
  Dim text.a(#TextLen - 1)
  
  Srv_ErrorText(Error, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii) 
EndProcedure  

Procedure.s ParErrorText(Error.i)
  
  Dim text.a(#TextLen - 1)
  
  Par_ErrorText(Error, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii) 
EndProcedure  

Procedure.s SrvEventText(*Event)
  
  Dim text.a(#TextLen - 1)
  
  Srv_EventText(*Event, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii)  
EndProcedure

;******************************************************************************
;                           HELPER DATA ACCESS FUNCTIONS
;******************************************************************************

;- Helper data access functions

; GET

Procedure.i GetBitAt(*Buffer, Pos.i, Bit.i)

  Protected value.i

  If *Buffer
    If Pos >= 0
      If Bit >= 0 And Bit <= 7
        If PeekA(*Buffer + Pos) & (1 << Bit)
          value = 1
        Else
          value = 0
        EndIf
      EndIf
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.a GetByteAt(*Buffer, Pos.i)

  Protected value.a

  If *Buffer
    If Pos >= 0
      value = PeekA(*Buffer + Pos)
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.u GetWordAt(*Buffer, Pos.i)

  Protected value.u

  If *Buffer
    If Pos >= 0
      PokeA(@value + 0, PeekA(*Buffer + Pos + 1))
      PokeA(@value + 1, PeekA(*Buffer + Pos + 0))
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.w GetIntAt(*Buffer, Pos.i)

  Protected value.w

  If *Buffer
    If Pos >= 0
      PokeA(@value + 0, PeekA(*Buffer + Pos + 1))
      PokeA(@value + 1, PeekA(*Buffer + Pos + 0))
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.q GetDWordAt(*Buffer, Pos.i)

  Protected value.q

  If *buffer
    If Pos >= 0
      PokeA(@value + 0, PeekA(*Buffer + Pos + 3))
      PokeA(@value + 1, PeekA(*Buffer + Pos + 2))
      PokeA(@value + 2, PeekA(*Buffer + Pos + 1))
      PokeA(@value + 3, PeekA(*Buffer + Pos + 0))
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.l GetDIntAt(*Buffer, Pos.i)

  Protected value.l

  If *buffer
    If Pos >= 0
      PokeA(@value + 0, PeekA(*Buffer + Pos + 3))
      PokeA(@value + 1, PeekA(*Buffer + Pos + 2))
      PokeA(@value + 2, PeekA(*Buffer + Pos + 1))
      PokeA(@value + 3, PeekA(*Buffer + Pos + 0))
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.f GetRealAt(*Buffer, Pos.i)

  Protected value.f

  If *Buffer
    If Pos >= 0
      PokeA(@Value + 0, PeekA(*Buffer + Pos + 3))
      PokeA(@Value + 1, PeekA(*Buffer + Pos + 2))
      PokeA(@Value + 2, PeekA(*Buffer + Pos + 1))
      PokeA(@Value + 3, PeekA(*Buffer + Pos + 0))
    EndIf
  EndIf

  ProcedureReturn value
EndProcedure

Procedure.a BCDtoByte(B.a)
  
  ProcedureReturn ((B >> 4) * 10) + (B & $0F)
  
EndProcedure  

Procedure GetDateTimeAt(*Buffer, Pos.i, *DateTime.tm)
  
  Protected DateTime.tm, y.l
  
  If *Buffer
    If Pos >= 0
      If *DateTime
      
        y = BCDtoByte(PeekA(*Buffer + Pos + 0))
        
        If y >= 90 And y <= 99
          y = y + 1900
        ElseIf y >= 0 And y <= 89
          y = y + 2000        
        EndIf  
        
        *DateTime\tm_year = y
        
        *DateTime\tm_mon = BCDtoByte(PeekA(*Buffer + Pos + 1))
        *DateTime\tm_mday = BCDtoByte(PeekA(*Buffer + Pos + 2))
        *DateTime\tm_hour = BCDtoByte(PeekA(*Buffer + Pos + 3))
        *DateTime\tm_min = BCDtoByte(PeekA(*Buffer + Pos + 4))
        *DateTime\tm_sec = BCDtoByte(PeekA(*Buffer + Pos + 5))
        
        *DateTime\tm_wday = BCDtoByte(PeekA(*Buffer + Pos + 7) & $0F)
      
      EndIf
    EndIf  
  EndIf  
  
EndProcedure  

; SET

Procedure SetBitAt(*Buffer, Pos.i, Bit.i, Value.i)

  If *Buffer
    If Pos >= 0
      If Bit >= 0 And Bit <= 7
        If Value = 1
          PokeA(*Buffer + Pos, PeekA(*Buffer + Pos) | (1 << Bit))
        ElseIf Value = 0
          PokeA(*Buffer + Pos, PeekA(*Buffer + Pos) & ~(1 << Bit))
        EndIf
      EndIf
    EndIf
  EndIf

EndProcedure

Procedure SetByteAt(*Buffer, Pos.i, Value.a)

  If *Buffer
    If Pos >= 0
      PokeA(*Buffer + Pos, Value)
    EndIf
  EndIf

EndProcedure

Procedure SetWordAt(*Buffer, Pos.i, Value.u)

  If *Buffer
    If Pos >= 0
      PokeA(*Buffer + Pos + 0, PeekA(@Value + 1))
      PokeA(*Buffer + Pos + 1, PeekA(@Value + 0))
    EndIf
  EndIf

EndProcedure

Procedure SetIntAt(*Buffer, Pos.i, Value.w)

  If *Buffer
    If Pos >= 0
      PokeA(*buffer + Pos + 0, PeekA(@Value + 1))
      PokeA(*buffer + Pos + 1, PeekA(@Value + 0))
    EndIf
  EndIf

EndProcedure

Procedure SetDWordAt(*Buffer, Pos.i, Value.l)

  If *Buffer
    If Pos >= 0
      PokeA(*Buffer + Pos + 0, PeekA(@Value + 3))
      PokeA(*Buffer + Pos + 1, PeekA(@Value + 2))
      PokeA(*Buffer + Pos + 2, PeekA(@Value + 1))
      PokeA(*Buffer + Pos + 3, PeekA(@Value + 0))
    EndIf
  EndIf

EndProcedure

Procedure SetDIntAt(*Buffer, Pos.i, Value.l)

  If *Buffer
    If Pos >= 0
      PokeA(*buffer + Pos + 0, PeekA(@Value + 3))
      PokeA(*buffer + Pos + 1, PeekA(@Value + 2))
      PokeA(*buffer + Pos + 2, PeekA(@Value + 1))
      PokeA(*buffer + Pos + 3, PeekA(@Value + 0))
    EndIf
  EndIf

EndProcedure

Procedure SetRealAt(*Buffer, Pos.i, Value.f)

  If *Buffer
    If Pos >= 0
      PokeA(*Buffer + Pos + 0, PeekA(@Value + 3))
      PokeA(*Buffer + Pos + 1, PeekA(@Value + 2))
      PokeA(*Buffer + Pos + 2, PeekA(@Value + 1))
      PokeA(*Buffer + Pos + 3, PeekA(@Value + 0))
    EndIf
  EndIf

EndProcedure

Procedure.a WordToBCD(Value.u)
  
  ProcedureReturn ((Value / 10) << 4) | (Value % 10)
  
EndProcedure  

Procedure SetDateTimeAt(*Buffer, Pos.i, *DateTime.tm)
  
  Protected y.l
  
  If *Buffer
    If Pos >= 0
      If *DateTime
        
        y = *DateTime\tm_year
        
        If y >= 1990 And y <= 1999
          y = y - 1900
        ElseIf y >= 2000 And y <= 2089
          y = y - 2000          
        EndIf  
        
        PokeA(*Buffer + Pos + 0, WordToBCD(y))
        PokeA(*Buffer + Pos + 1, WordToBCD(*DateTime\tm_mon))
        PokeA(*Buffer + Pos + 2, WordToBCD(*DateTime\tm_mday))
        PokeA(*Buffer + Pos + 3, WordToBCD(*DateTime\tm_hour))
        PokeA(*Buffer + Pos + 4, WordToBCD(*DateTime\tm_min))
        PokeA(*Buffer + Pos + 5, WordToBCD(*DateTime\tm_sec))
        PokeA(*Buffer + Pos + 6, 0)
        PokeA(*Buffer + Pos + 7, WordToBCD(*DateTime\tm_wday))
        
      EndIf
    EndIf  
  EndIf          
    
EndProcedure

example:

Code: Select all


EnableExplicit

IncludeFile "snap7.pbi"

Define MyClient.i, n.i

Dim MyDB32.b(255)

If snap7_OpenDLL()

  MyClient = Cli_Create()
    
  Cli_ConnectTo(MyClient, "192.168.1.111", 0, 2)
    
  Cli_DBRead(MyClient, 32, 0, 16, @MyDB32())
  
  For n = 0 To 15
    Debug MyDB32(n)    
  Next n  
  
  Cli_Disconnect(MyClient)
  
  Cli_Destroy(@MyClient)

  snap7_CloseDLL()

EndIf

End

PB v5.62 x86/x64
Windows 10 Pro
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Snap7 communication library for Siemens PLC

Post by mk-soft »

@chris

Thank you so much.
I know it's a lot of work. :D


@filip
Please remember that incorrect writing of the data into the PLC can lead to unpredictable consequences for the machine or man.


P.S.
With the DateTime format, the byte sequence in the PLC 1500 is reversed.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
filip
New User
New User
Posts: 4
Joined: Sat Aug 11, 2018 7:31 pm

Re: Snap7 communication library for Siemens PLC

Post by filip »

It's amazing, thank you Chris for your BIG job :D !!!!

As a new user, I see that Purebasic has an active and great community
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Snap7 communication library for Siemens PLC

Post by mk-soft »

I have optimized the "snap7.pbi" for processor type X64 and X86 because of the byte notation with assembler code.

Added reading and writing S7 strings via the buffer.
Added reading and writing of TIA-PLC Long Integer (8 Bytes) and TIA-PLC Double.
Additional parameter for reading and writing of types DateAndTime for TIA-PLC (the byte sequence is the other way around)
With TIA controllers, the data block must not be optimized and S7 Get/Put must be allowed in the safety setting of the PLC.

Update v1.4.4
- Bugfix SetLIntAt(...)

Update v2.01.2
- Added C-Backend support (Must be work with Raspberry)
- Optimize code

Only for trained and educated personnel with the handling of PLC controls and machines.

Code: Select all

;-TOP
; Comment       : snap7 include
; Author        : chris
; Second Author : mk-soft
; File          : snap7_include.pbi
; Version       : v2.01.2
; Create        : 12.10.2013
; Update        : 23.07.2022

; http://snap7.sourceforge.net/

; ------------------------------------------------------------------------------

; License
;
; Permission is hereby granted, free of charge, To any person obtaining
; a copy of this software And associated documentation files (the
; "Software"), To deal in the Software without restriction, including
; without limitation the rights To use, copy, modify, merge, publish,
; distribute, sublicense, And/Or sell copies of the Software, And To
; permit persons To whom the Software is furnished To do so, subject To
; the following conditions:
; 
; The above copyright notice And this permission notice shall be included
; in all copies Or substantial portions of the Software.
; 
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
; EXPRESS Or IMPLIED, INCLUDING BUT Not LIMITED To THE WARRANTIES OF
; MERCHANTABILITY, FITNESS For A PARTICULAR PURPOSE And NONINFRINGEMENT.
; IN NO EVENT SHALL THE AUTHORS Or COPYRIGHT HOLDERS BE LIABLE For ANY
; CLAIM, DAMAGES Or OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
; TORT Or OTHERWISE, ARISING FROM, OUT OF Or IN CONNECTION With THE
; SOFTWARE Or THE USE Or OTHER DEALINGS IN THE SOFTWARE.

; ------------------------------------------------------------------------------
;                                  COMMON
; ------------------------------------------------------------------------------

;- COMMON

Structure tm
  tm_sec.l   ; seconds of minutes from 0 to 59
  tm_min.l   ; minutes of hour from 0 to 59
  tm_hour.l  ; hours of day from 0 to 23
  tm_mday.l  ; day of month from 1 to 31
  tm_mon.l   ; month of year from 0 to 11
  tm_year.l  ; year since 1900
  tm_wday.l  ; days since sunday
  tm_yday.l  ; days since January 1st
  tm_isdst.l ; hours of daylight savings time    
EndStructure  

#TextLen = 1024

#errLibInvalidParam  = -1
#errLibInvalidObject = -2

; CPU status
#S7CpuStatusUnknown = $00
#S7CpuStatusRun     = $08
#S7CpuStatusStop    = $04

; ISO Errors
#errIsoConnect          = $00010000 ; Connection error
#errIsoDisconnect       = $00020000 ; Disconnect error
#errIsoInvalidPDU       = $00030000 ; Bad format
#errIsoInvalidDataSize  = $00040000 ; Bad Datasize passed to send/recv buffer is invalid
#errIsoNullPointer      = $00050000 ; Null passed as pointer
#errIsoShortPacket      = $00060000 ; A short packet received
#errIsoTooManyFragments = $00070000 ; Too many packets without EoT flag
#errIsoPduOverflow      = $00080000 ; The sum of fragments data exceded maximum packet size
#errIsoSendPacket       = $00090000 ; An error occurred during send
#errIsoRecvPacket       = $000A0000 ; An error occurred during recv
#errIsoInvalidParams    = $000B0000 ; Invalid TSAP params
#errIsoResvd_1          = $000C0000 ; Unassigned
#errIsoResvd_2          = $000D0000 ; Unassigned
#errIsoResvd_3          = $000E0000 ; Unassigned
#errIsoResvd_4          = $000F0000 ; Unassigned

;- Structures

;-- Tag Struct
Structure TS7Tag
  Area.l
  DBNumber.l
  Start.l
  Size.l
  WordLen.l  
EndStructure  

;-- Read/Write Multivars
Structure TS7DataItem
  Area.l
  WordLen.l
  Result.l
  DBNumber.l
  Start.l
  Amount.l
  *pdata
EndStructure

;-- List Blocks
Structure TS7BlocksList
  OBCount.l
  FBCount.l
  FCCount.l
  SFBCount.l
  SFCCount.l
  DBCount.l
  SDBCount.l
EndStructure


; ------------------------------------------------------------------------------
;                                  PARAMS LIST
; ------------------------------------------------------------------------------

;- PARAMS LIST

#p_u16_LocalPort     = 1
#p_u16_RemotePort    = 2
#p_i32_PingTimeout   = 3
#p_i32_SendTimeout   = 4
#p_i32_RecvTimeout   = 5
#p_i32_WorkInterval  = 6
#p_u16_SrcRef        = 7
#p_u16_DstRef        = 8
#p_u16_SrcTSap       = 9
#p_i32_PDURequest    = 10
#p_i32_MaxClients    = 11
#p_i32_BSendTimeout  = 12
#p_i32_BRecvTimeout  = 13
#p_u32_RecoveryTime  = 14
#p_u32_KeepAliveTime = 15

; Client/Partner Job status
#JobComplete = 0
#JobPending  = 1

;******************************************************************************
;                                   CLIENT
;******************************************************************************

;- CLIENT

; Error codes
#errNegotiatingPDU            = $00100000
#errCliInvalidParams          = $00200000
#errCliJobPending             = $00300000
#errCliTooManyItems           = $00400000
#errCliInvalidWordLen         = $00500000
#errCliPartialDataWritten     = $00600000
#errCliSizeOverPDU            = $00700000
#errCliInvalidPlcAnswer       = $00800000
#errCliAddressOutOfRange      = $00900000
#errCliInvalidTransportSize   = $00A00000
#errCliWriteDataSizeMismatch  = $00B00000
#errCliItemNotAvailable       = $00C00000
#errCliInvalidValue           = $00D00000
#errCliCannotStartPLC         = $00E00000
#errCliAlreadyRun             = $00F00000
#errCliCannotStopPLC          = $01000000
#errCliCannotCopyRamToRom     = $01100000
#errCliCannotCompress         = $01200000
#errCliAlreadyStop            = $01300000
#errCliFunNotAvailable        = $01400000
#errCliUploadSequenceFailed   = $01500000
#errCliInvalidDataSizeRecvd   = $01600000
#errCliInvalidBlockType       = $01700000
#errCliInvalidBlockNumber     = $01800000
#errCliInvalidBlockSize       = $01900000
#errCliDownloadSequenceFailed = $01A00000
#errCliInsertRefused          = $01B00000
#errCliDeleteRefused          = $01C00000
#errCliNeedPassword           = $01D00000
#errCliInvalidPassword        = $01E00000
#errCliNoPasswordToSetOrClear = $01F00000
#errCliJobTimeout             = $02000000
#errCliPartialDataRead        = $02100000
#errCliBufferTooSmall         = $02200000
#errCliFunctionRefused        = $02300000
#errCliDestroying             = $02400000
#errCliInvalidParamNumber     = $02500000
#errCliCannotChangeParam      = $02600000

#MaxVars = 20 ; Max vars that can be transferred with MultiRead/MultiWrite

; Client Connection Type
#CONNTYPE_PG    = $0001 ; Connect to the PLC as a PG
#CONNTYPE_OP    = $0002 ; Connect to the PLC as an OP
#CONNTYPE_BASIC = $0003 ; Basic connection

; Area ID
#Cli_S7AreaPE = $81
#Cli_S7AreaPA = $82
#Cli_S7AreaMK = $83
#Cli_S7AreaDB = $84
#Cli_S7AreaCT = $1C
#Cli_S7AreaTM = $1D

#Srv_S7AreaPE = $00
#Srv_S7AreaPA = $01
#Srv_S7AreaMK = $02
#Srv_S7AreaCT = $03
#Srv_S7AreaTM = $04
#Srv_S7AreaDB = $05

; Word Length
#S7WLBit     = $01
#S7WLByte    = $02
#S7WLWord    = $04
#S7WLDWord   = $06
#S7WLReal    = $08
#S7WLCounter = $1C
#S7WLTimer   = $1D

; Block type
#Block_OB  = $38
#Block_DB  = $41
#Block_SDB = $42
#Block_FC  = $43
#Block_SFC = $44
#Block_FB  = $45
#Block_SFB = $46

; Sub Block Type
#SubBlk_OB  = $08
#SubBlk_DB  = $0A
#SubBlk_SDB = $0B
#SubBlk_FC  = $0C
#SubBlk_SFC = $0D
#SubBlk_FB  = $0E
#SubBlk_SFB = $0F

; Block languages
#BlockLangAWL   = $01
#BlockLangKOP   = $02
#BlockLangFUP   = $03
#BlockLangSCL   = $04
#BlockLangDB    = $05
#BlockLangGRAPH = $06

;-- Blocks of Type
Structure TS7BlocksOfType
  w.w[$2000]
EndStructure

Structure PS7BlocksOfType
  w.w[0]
EndStructure

;-- Blocks info
Structure TS7BlockInfo
  BlkType.l       ; Block Type (OB, DB) 
  BlkNumber.l     ; Block number
  BlkLang.l       ; Block Language
  BlkFlags.l      ; Block flags
  MC7Size.l       ; The real size in bytes
  LoadSize.l      ; Load memory size
  LocalData.l     ; Local data
  SBBLength.l     ; SBB Length
  CheckSum.l      ; Checksum
  Version.l       ; Block version
                  ; Chars info
  CodeDate.a[11]  ; Code date
  IntfDate.a[11]  ; Interface date 
  Author.a[9]     ; Author
  Family.a[9]     ; Family
  Header.a[9]     ; Header    
EndStructure  

;-- Order code
Structure TS7OrderCode
  Code.a[21]
  V1.b
  V2.b
  V3.b  
EndStructure  

;-- CPU Info
Structure TS7CpuInfo
  ModuleTypeName.a[33]
  SerialNumber.a[25]
  ASName.a[25]
  Copyright.a[27]
  ModuleName.a[25]
EndStructure  

;-- CP Info
Structure TS7CpInfo
  MaxPduLengt.l
  MaxConnections.l
  MaxMpiRate.l
  MaxBusRate.l  
EndStructure  

;-- SZL

; See §33.1 of "System Software for S7-300/400 System and Standard Functions"
; and see SFC51 description too
Structure SZL_HEADER
  LENTHDR.u
  N_DR.u
EndStructure  

Structure TS7SZL
  Header.SZL_HEADER
  Data_SZL.a[$4000-4]
EndStructure  

; SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted
Structure TS7SZLList
  Header.SZL_HEADER
  List_SZL.u[$2000-2]
EndStructure  

; See §33.19 of "System Software for S7-300/400 System and Standard Functions"
Structure TS7Protection
  sch_schal.u
  sch_par.u
  sch_rel.u
  bart_sch.u
  anl_sch.u  
EndStructure  

;******************************************************************************
;                                   SERVER
;******************************************************************************

;- SERVER

#OperationRead  = 0
#OperationWrite = 1

#mkEvent = 0
#mkLog   = 1

; Server Area ID  (use with Register/unregister - Lock/unlock Area)
#srvAreaPE = 0
#srvAreaPA = 1
#srvAreaMK = 2
#srvAreaCT = 3
#srvAreaTM = 4
#srvAreaDB = 5

; Errors
#errSrvCannotStart        = $00100000 ; Server cannot start
#errSrvDBNullPointer      = $00200000 ; Passed null as PData
#errSrvAreaAlreadyExists  = $00300000 ; Area Re-registration
#errSrvUnknownArea        = $00400000 ; Unknown area
#errSrvInvalidParams      = $00500000 ; Invalid param(s) supplied
#errSrvTooManyDB          = $00600000 ; Cannot register DB
#errSrvInvalidParamNumber = $00700000 ; Invalid param (srv_get/set_param)
#errSrvCannotChangeParam  = $00800000 ; Cannot change because running

; TCP Server Event codes
#evcServerStarted       = $00000001
#evcServerStopped       = $00000002
#evcListenerCannotStart = $00000004
#evcClientAdded         = $00000008
#evcClientRejected      = $00000010
#evcClientNoRoom        = $00000020
#evcClientException     = $00000040
#evcClientDisconnected  = $00000080
#evcClientTerminated    = $00000100
#evcClientsDropped      = $00000200
#evcReserved_00000400   = $00000400 ; actually unused
#evcReserved_00000800   = $00000800 ; actually unused
#evcReserved_00001000   = $00001000 ; actually unused
#evcReserved_00002000   = $00002000 ; actually unused
#evcReserved_00004000   = $00004000 ; actually unused
#evcReserved_00008000   = $00008000 ; actually unused

; S7 Server Event Code
#evcPDUincoming       = $00010000
#evcDataRead          = $00020000
#evcDataWrite         = $00040000
#evcNegotiatePDU      = $00080000
#evcReadSZL           = $00100000
#evcClock             = $00200000
#evcUpload            = $00400000
#evcDownload          = $00800000
#evcDirectory         = $01000000
#evcSecurity          = $02000000
#evcControl           = $04000000
#evcReserved_08000000 = $08000000 ; actually unused
#evcReserved_10000000 = $10000000 ; actually unused
#evcReserved_20000000 = $20000000 ; actually unused
#evcReserved_40000000 = $40000000 ; actually unused
#evcReserved_80000000 = $80000000 ; actually unused

; Masks to enable/disable all events
#evcAll  = $FFFFFFFF
#evcNone = $00000000

; Event SubCodes
#evsUnknown       = $0000
#evsStartUpload   = $0001
#evsStartDownload = $0001
#evsGetBlockList  = $0001
#evsStartListBoT  = $0002
#evsListBoT       = $0003
#evsGetBlockInfo  = $0004
#evsGetClock      = $0001
#evsSetClock      = $0002
#evsSetPassword   = $0001
#evsClrPassword   = $0002

; Event Params : functions group
#grProgrammer = $0041
#grCyclicData = $0042
#grBlocksInfo = $0043
#grSZL        = $0044
#grPassword   = $0045
#grBSend      = $0046
#grClock      = $0047
#grSecurity   = $0045

; Event Params : control codes
#CodeControlUnknown   = $0000
#CodeControlColdStart = $0001
#CodeControlWarmStart = $0002
#CodeControlStop      = $0003
#CodeControlCompress  = $0004
#CodeControlCpyRamRom = $0005
#CodeControlInsDel    = $0006

; Event Result
#evrNoError           = $0000
#evrFragmentRejected  = $0001
#evrMalformedPDU      = $0002
#evrSparseBytes       = $0003
#evrCannotHandlePDU   = $0004
#evrNotImplemented    = $0005
#evrErrException      = $0006
#evrErrAreaNotFound   = $0007
#evrErrOutOfRange     = $0008
#evrErrOverPDU        = $0009
#evrErrTransportSize  = $000A
#evrInvalidGroupUData = $000B
#evrInvalidSZL        = $000C
#evrDataSizeMismatch  = $000D
#evrCannotUpload      = $000E
#evrCannotDownload    = $000F
#evrUploadInvalidID   = $0010
#evrResNotFound       = $0011

Structure TSrvEvent
  EvtTime.l    ; Timestamp
  EvtSender.l  ; Sender
  EvtCode.l    ; Event code
  EvtRetCode.u ; Event result
  EvtParam1.u  ; Param 1 (if available)
  EvtParam2.u  ; Param 2 (if available)
  EvtParam3.u  ; Param 3 (if available)
  EvtParam4.u  ; Param 4 (if available)    
EndStructure  

;******************************************************************************
;                                   PARTNER
;******************************************************************************

;- PARTNER

; Status
#par_stopped    = 0 ; stopped
#par_connecting = 1 ; running and active connecting
#par_waiting    = 2 ; running and waiting for a connection
#par_linked     = 3 ; running and connected : linked
#par_sending    = 4 ; sending data
#par_receiving  = 5 ; receiving data
#par_binderror  = 6 ; error starting passive server

; Errors
#errParAddressInUse       = $00200000
#errParNoRoom             = $00300000
#errServerNoRoom          = $00400000
#errParInvalidParams      = $00500000
#errParNotLinked          = $00600000
#errParBusy               = $00700000
#errParFrameTimeout       = $00800000
#errParInvalidPDU         = $00900000
#errParSendTimeout        = $00A00000
#errParRecvTimeout        = $00B00000
#errParSendRefused        = $00C00000
#errParNegotiatingPDU     = $00D00000
#errParSendingBlock       = $00E00000
#errParRecvingBlock       = $00F00000
#errParBindError          = $01000000
#errParDestroying         = $01100000
#errParInvalidParamNumber = $01200000 ; Invalid param (par_get/set_param)
#errParCannotChangeParam  = $01300000 ; Cannot change because running
#errParBufferTooSmall     = $01400000 ; Raised by LabVIEW wrapper

;- Global
Global snap7_hDLL.i

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Macro PrototypeX
    Prototype
  EndMacro
CompilerElse
  Macro PrototypeX
    PrototypeC
  EndMacro
CompilerEndIf

;- Client Prototype
PrototypeX.i Cli_ABRead(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_ABWrite(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsABRead(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsABWrite(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsCTRead(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_AsCTWrite(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_AsCompress(Client.i, Timeout.i)
PrototypeX.i Cli_AsCopyRamToRom(Client.i, Timeout.i)
PrototypeX.i Cli_AsDBFill(Client.i, DBNumber.i, FillChar.i)
PrototypeX.i Cli_AsDBGet(Client.i, DBNumber.i, *pUsrData, *Size)
PrototypeX.i Cli_AsDBRead(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsDBWrite(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsDownload(Client.i, BlockNum.i, *pUsrData, Size.i)
PrototypeX.i Cli_AsEBRead(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsEBWrite(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsFullUpload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
PrototypeX.i Cli_AsListBlocksOfType(Client.i, BlockType.i, *pUsrData, *ItemsCount)
PrototypeX.i Cli_AsMBRead(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsMBWrite(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_AsReadArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
PrototypeX.i Cli_AsReadSZL(Client.i, ID.i, Index.i, *pUsrData, *Size)
PrototypeX.i Cli_AsReadSZLList(Client.i, *pUsrData, *ItemsCount)
PrototypeX.i Cli_AsTMRead(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_AsTMWrite(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_AsUpload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
PrototypeX.i Cli_AsWriteArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
PrototypeX.i Cli_CTRead(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_CTWrite(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_CheckAsCompletion(Client.i, *opResult)
PrototypeX.i Cli_ClearSessionPassword(Client)
PrototypeX.i Cli_Compress(Client.i, Timeout.i)
PrototypeX.i Cli_Connect(Client)
PrototypeX.i Cli_ConnectTo(Client.i, Address.p-ascii, Rack.i, Slot.i)
PrototypeX.i Cli_CopyRamToRom(Client.i, Timeout.i)
PrototypeX.i Cli_Create()
PrototypeX.i Cli_DBFill(Client.i, DBNumber.i, FillChar.i)
PrototypeX.i Cli_DBGet(Client.i, DBNumber.i, *pUsrData, *Size)
PrototypeX.i Cli_DBRead(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_DBWrite(Client.i, DBNumber.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_Delete(Client.i, BlockType.i, BlockNum.i)
PrototypeX.i Cli_Destroy(*Client)
PrototypeX.i Cli_Disconnect(Client.i)
PrototypeX.i Cli_Download(Client.i, BlockNum.i, *pUsrData, Size.i)
PrototypeX.i Cli_EBRead(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_EBWrite(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_ErrorText(Error.i, *Text, TextLen.i)
PrototypeX.i Cli_FullUpload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
PrototypeX.i Cli_GetAgBlockInfo(Client.i, BlockType.i, BlockNum.i, *pUsrData)
PrototypeX.i Cli_GetConnected(Client.i, *Connected)
PrototypeX.i Cli_GetCpInfo(Client.i, *pUsrData)
PrototypeX.i Cli_GetCpuInfo(Client.i, *pUsrData)
PrototypeX.i Cli_GetExecTime(Client.i, *Time)
PrototypeX.i Cli_GetLastError(Client.i, *LastError)
PrototypeX.i Cli_GetOrderCode(Client.i, *pUsrData)
PrototypeX.i Cli_GetParam(Client.i, ParamNumber.i, *pValue)
PrototypeX.i Cli_GetPduLength(Client.i, *Requested, *Negotiated)
PrototypeX.i Cli_GetPgBlockInfo(Client.i, *pBlock, *pUsrData, Size.i)
PrototypeX.i Cli_GetPlcDateTime(Client, *DateTime)
PrototypeX.i Cli_GetPlcStatus(Client.i, *Status)
PrototypeX.i Cli_GetProtection(Client.i, *pUsrData)
PrototypeX.i Cli_IsoExchangeBuffer(Client.i, *pUsrData, *Size)
PrototypeX.i Cli_ListBlocks(Client.i, *pUsrData)
PrototypeX.i Cli_ListBlocksOfType(Client.i, BlockType.i, *pUsrData, *ItemsCount)
PrototypeX.i Cli_MBRead(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_MBWrite(Client.i, Start.i, Size.i, *pUsrData)
PrototypeX.i Cli_PlcColdStart(Client.i)
PrototypeX.i Cli_PlcHotStart(Client.i)
PrototypeX.i Cli_PlcStop(Client.i)
PrototypeX.i Cli_ReadArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
PrototypeX.i Cli_ReadMultiVars(Client.i, Item.i, ItemsCount.i)
PrototypeX.i Cli_ReadSZL(Client.i, ID.i, Index.i, *pUsrData, *Size)
PrototypeX.i Cli_ReadSZLList(Client.i, *pUsrData, *ItemsCount)
PrototypeX.i Cli_SetAsCallback(Client.i, *pCompletion, *usrPtr)
PrototypeX.i Cli_SetConnectionParams(Client.i, Address.p-ascii, LocalTSAP.u, RemoteTSAP.u)
PrototypeX.i Cli_SetConnectionType(Client.i, ConnectionType.u)
PrototypeX.i Cli_SetParam(Client.i, ParamNumber.i, *pValue)
PrototypeX.i Cli_SetPlcDateTime(Client.i, *DateTime)
PrototypeX.i Cli_SetPlcSystemDateTime(Client.i)
PrototypeX.i Cli_SetSessionPassword(Client.i, *Password)
PrototypeX.i Cli_TMRead(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_TMWrite(Client.i, Start.i, Amount.i, *pUsrData)
PrototypeX.i Cli_Upload(Client.i, BlockType.i, BlockNum.i, *pUsrData, *Size)
PrototypeX.i Cli_WaitAsCompletion(Client.i, Timeout.i)
PrototypeX.i Cli_WriteArea(Client.i, Area.i, DBNumber.i, Start.i, Amount.i, WordLen.i, *pUsrData)
PrototypeX.i Cli_WriteMultiVars(Client.i, Item.i, ItemsCount.i)

;- Server Prototype
PrototypeX.i Srv_ClearEvents(Server)
PrototypeX.i Srv_Create()
PrototypeX.i Srv_Destroy(Server.i)
PrototypeX.i Srv_ErrorText(Error.i, *Text, TextLen.i)
PrototypeX.i Srv_EventText(*Event, *Text, TextLen.i)
PrototypeX.i Srv_GetMask(Server.i, MaskKind.i, *Mask)
PrototypeX.i Srv_GetParam(Server.i, ParamNumber.i, *pValue)
PrototypeX.i Srv_GetStatus(Server.i, *ServerStatus, *CpuStatus, *ClientsCount)
PrototypeX.i Srv_LockArea(Server.i, AreaCode.i, Index.u)
PrototypeX.i Srv_PickEvent(Server.i, *pEvent, *EvtReady)
PrototypeX.i Srv_RegisterArea(Server.i, AreaCode.i, Index.u, *pUsrData, Size.i)
PrototypeX.i Srv_SetCpuStatus(Server.i, CpuStatus.i)
PrototypeX.i Srv_SetEventsCallback(Server.i, *pCallback, *usrPtr)
PrototypeX.i Srv_SetMask(Server.i, MaskKind.i, Mask.l)
PrototypeX.i Srv_SetParam(Server.i, ParamNumber.i, *pValue)
PrototypeX.i Srv_SetRWAreaCallback(Server.i, *pCallback, *usrPtr)
PrototypeX.i Srv_SetReadEventsCallback(Server.i, *pCallback, *usrPtr)
PrototypeX.i Srv_Start(Server.i)
PrototypeX.i Srv_StartTo(Server, Address.p-ascii)
PrototypeX.i Srv_Stop(Server.i)
PrototypeX.i Srv_UnlockArea(Server.i, AreaCode.i, Index.u)
PrototypeX.i Srv_UnregisterArea(Server.i, AreaCode.i, Index.u)

;- Partner Prototype
PrototypeX.i Par_AsBSend(Partner.i, R_ID.l, *pUsrData, Size.i)
PrototypeX.i Par_BRecv(Partner.i, *R_ID, *pData, *Size, Timeout.l)
PrototypeX.i Par_BSend(Partner.i, R_ID.l, *pUsrData, Size.i)
PrototypeX.i Par_CheckAsBRecvCompletion(Partner.i, *opResult, *R_ID, *pData, *Size)
PrototypeX.i Par_CheckAsBSendCompletion(Partner.i, *opResult)
PrototypeX.i Par_Create(Active.i)
PrototypeX.i Par_Destroy(*Partner)
PrototypeX.i Par_ErrorText(Error.i, *Text, TextLen.i)
PrototypeX.i Par_GetLastError(Partner.i, *LastError)
PrototypeX.i Par_GetParam(Partner.i, ParamNumber.i, *pValue)
PrototypeX.i Par_GetStats(Partner.i, *BytesSent, *BytesRecv, *SendErrors, *RecvErrors)
PrototypeX.i Par_GetStatus(Partner.i, *Status)
PrototypeX.i Par_GetTimes(Partner.i, *SendTime, *RecvTime)
PrototypeX.i Par_SetParam(Partner.i, ParamNumber.i, *pValue)
PrototypeX.i Par_SetRecvCallback(Partner.i, *pCompletion, *usrPtr)
PrototypeX.i Par_SetSendCallback(Partner.i, *pCompletion, *usrPtr)
PrototypeX.i Par_Start(Partner.i)
PrototypeX.i Par_StartTo(Partner.i, LocalAddress.p-ascii, RemoteAddress.p-ascii, LocTsap.u, RemTsap.u)
PrototypeX.i Par_Stop(Partner.i)
PrototypeX.i Par_WaitAsBSendCompletion(Partner.i, Timeout.l)

Procedure snap7_CloseDLL()
  If snap7_hDLL <> 0
    If IsLibrary(snap7_hDLL)
      CloseLibrary(snap7_hDLL)
    EndIf
    snap7_hDLL = 0
  EndIf
EndProcedure

Procedure snap7_OpenDLL()
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      snap7_hDLL = OpenLibrary(#PB_Any, "snap7.dll")
    CompilerCase #PB_OS_Linux
      snap7_hDLL = OpenLibrary(#PB_Any, "libsnap7.so")
    CompilerCase #PB_OS_MacOS
      snap7_hDLL = OpenLibrary(#PB_Any, "libsnap7.dylib")
  CompilerEndSelect
  
  If snap7_hDLL = 0
    ProcedureReturn #False
  EndIf
  
  Global Cli_ABRead.Cli_ABRead=GetFunction(snap7_hDLL,"Cli_ABRead")
  Global Cli_ABWrite.Cli_ABWrite=GetFunction(snap7_hDLL,"Cli_ABWrite")
  Global Cli_AsABRead.Cli_AsABRead=GetFunction(snap7_hDLL,"Cli_AsABRead")
  Global Cli_AsABWrite.Cli_AsABWrite=GetFunction(snap7_hDLL,"Cli_AsABWrite")
  Global Cli_AsCTRead.Cli_AsCTRead=GetFunction(snap7_hDLL,"Cli_AsCTRead")
  Global Cli_AsCTWrite.Cli_AsCTWrite=GetFunction(snap7_hDLL,"Cli_AsCTWrite")
  Global Cli_AsCompress.Cli_AsCompress=GetFunction(snap7_hDLL,"Cli_AsCompress")
  Global Cli_AsCopyRamToRom.Cli_AsCopyRamToRom=GetFunction(snap7_hDLL,"Cli_AsCopyRamToRom")
  Global Cli_AsDBFill.Cli_AsDBFill=GetFunction(snap7_hDLL,"Cli_AsDBFill")
  Global Cli_AsDBGet.Cli_AsDBGet=GetFunction(snap7_hDLL,"Cli_AsDBGet")
  Global Cli_AsDBRead.Cli_AsDBRead=GetFunction(snap7_hDLL,"Cli_AsDBRead")
  Global Cli_AsDBWrite.Cli_AsDBWrite=GetFunction(snap7_hDLL,"Cli_AsDBWrite")
  Global Cli_AsDownload.Cli_AsDownload=GetFunction(snap7_hDLL,"Cli_AsDownload")
  Global Cli_AsEBRead.Cli_AsEBRead=GetFunction(snap7_hDLL,"Cli_AsEBRead")
  Global Cli_AsEBWrite.Cli_AsEBWrite=GetFunction(snap7_hDLL,"Cli_AsEBWrite")
  Global Cli_AsFullUpload.Cli_AsFullUpload=GetFunction(snap7_hDLL,"Cli_AsFullUpload")
  Global Cli_AsListBlocksOfType.Cli_AsListBlocksOfType=GetFunction(snap7_hDLL,"Cli_AsListBlocksOfType")
  Global Cli_AsMBRead.Cli_AsMBRead=GetFunction(snap7_hDLL,"Cli_AsMBRead")
  Global Cli_AsMBWrite.Cli_AsMBWrite=GetFunction(snap7_hDLL,"Cli_AsMBWrite")
  Global Cli_AsReadArea.Cli_AsReadArea=GetFunction(snap7_hDLL,"Cli_AsReadArea")
  Global Cli_AsReadSZL.Cli_AsReadSZL=GetFunction(snap7_hDLL,"Cli_AsReadSZL")
  Global Cli_AsReadSZLList.Cli_AsReadSZLList=GetFunction(snap7_hDLL,"Cli_AsReadSZLList")
  Global Cli_AsTMRead.Cli_AsTMRead=GetFunction(snap7_hDLL,"Cli_AsTMRead")
  Global Cli_AsTMWrite.Cli_AsTMWrite=GetFunction(snap7_hDLL,"Cli_AsTMWrite")
  Global Cli_AsUpload.Cli_AsUpload=GetFunction(snap7_hDLL,"Cli_AsUpload")
  Global Cli_AsWriteArea.Cli_AsWriteArea=GetFunction(snap7_hDLL,"Cli_AsWriteArea")
  Global Cli_CTRead.Cli_CTRead=GetFunction(snap7_hDLL,"Cli_CTRead")
  Global Cli_CTWrite.Cli_CTWrite=GetFunction(snap7_hDLL,"Cli_CTWrite")
  Global Cli_CheckAsCompletion.Cli_CheckAsCompletion=GetFunction(snap7_hDLL,"Cli_CheckAsCompletion")
  Global Cli_ClearSessionPassword.Cli_ClearSessionPassword=GetFunction(snap7_hDLL,"Cli_ClearSessionPassword")
  Global Cli_Compress.Cli_Compress=GetFunction(snap7_hDLL,"Cli_Compress")
  Global Cli_Connect.Cli_Connect=GetFunction(snap7_hDLL,"Cli_Connect")
  Global Cli_ConnectTo.Cli_ConnectTo=GetFunction(snap7_hDLL,"Cli_ConnectTo")
  Global Cli_CopyRamToRom.Cli_CopyRamToRom=GetFunction(snap7_hDLL,"Cli_CopyRamToRom")
  Global Cli_Create.Cli_Create=GetFunction(snap7_hDLL,"Cli_Create")
  Global Cli_DBFill.Cli_DBFill=GetFunction(snap7_hDLL,"Cli_DBFill")
  Global Cli_DBGet.Cli_DBGet=GetFunction(snap7_hDLL,"Cli_DBGet")
  Global Cli_DBRead.Cli_DBRead=GetFunction(snap7_hDLL,"Cli_DBRead")
  Global Cli_DBWrite.Cli_DBWrite=GetFunction(snap7_hDLL,"Cli_DBWrite")
  Global Cli_Delete.Cli_Delete=GetFunction(snap7_hDLL,"Cli_Delete")
  Global Cli_Destroy.Cli_Destroy=GetFunction(snap7_hDLL,"Cli_Destroy")
  Global Cli_Disconnect.Cli_Disconnect=GetFunction(snap7_hDLL,"Cli_Disconnect")
  Global Cli_Download.Cli_Download=GetFunction(snap7_hDLL,"Cli_Download")
  Global Cli_EBRead.Cli_EBRead=GetFunction(snap7_hDLL,"Cli_EBRead")
  Global Cli_EBWrite.Cli_EBWrite=GetFunction(snap7_hDLL,"Cli_EBWrite")
  Global Cli_ErrorText.Cli_ErrorText=GetFunction(snap7_hDLL,"Cli_ErrorText")
  Global Cli_FullUpload.Cli_FullUpload=GetFunction(snap7_hDLL,"Cli_FullUpload")
  Global Cli_GetAgBlockInfo.Cli_GetAgBlockInfo=GetFunction(snap7_hDLL,"Cli_GetAgBlockInfo")
  Global Cli_GetConnected.Cli_GetConnected=GetFunction(snap7_hDLL,"Cli_GetConnected")
  Global Cli_GetCpInfo.Cli_GetCpInfo=GetFunction(snap7_hDLL,"Cli_GetCpInfo")
  Global Cli_GetCpuInfo.Cli_GetCpuInfo=GetFunction(snap7_hDLL,"Cli_GetCpuInfo")
  Global Cli_GetExecTime.Cli_GetExecTime=GetFunction(snap7_hDLL,"Cli_GetExecTime")
  Global Cli_GetLastError.Cli_GetLastError=GetFunction(snap7_hDLL,"Cli_GetLastError")
  Global Cli_GetOrderCode.Cli_GetOrderCode=GetFunction(snap7_hDLL,"Cli_GetOrderCode")
  Global Cli_GetParam.Cli_GetParam=GetFunction(snap7_hDLL,"Cli_GetParam")
  Global Cli_GetPduLength.Cli_GetPduLength=GetFunction(snap7_hDLL,"Cli_GetPduLength")
  Global Cli_GetPgBlockInfo.Cli_GetPgBlockInfo=GetFunction(snap7_hDLL,"Cli_GetPgBlockInfo")
  Global Cli_GetPlcDateTime.Cli_GetPlcDateTime=GetFunction(snap7_hDLL,"Cli_GetPlcDateTime")
  Global Cli_GetPlcStatus.Cli_GetPlcStatus=GetFunction(snap7_hDLL,"Cli_GetPlcStatus")
  Global Cli_GetProtection.Cli_GetProtection=GetFunction(snap7_hDLL,"Cli_GetProtection")
  Global Cli_IsoExchangeBuffer.Cli_IsoExchangeBuffer=GetFunction(snap7_hDLL,"Cli_IsoExchangeBuffer")
  Global Cli_ListBlocks.Cli_ListBlocks=GetFunction(snap7_hDLL,"Cli_ListBlocks")
  Global Cli_ListBlocksOfType.Cli_ListBlocksOfType=GetFunction(snap7_hDLL,"Cli_ListBlocksOfType")
  Global Cli_MBRead.Cli_MBRead=GetFunction(snap7_hDLL,"Cli_MBRead")
  Global Cli_MBWrite.Cli_MBWrite=GetFunction(snap7_hDLL,"Cli_MBWrite")
  Global Cli_PlcColdStart.Cli_PlcColdStart=GetFunction(snap7_hDLL,"Cli_PlcColdStart")
  Global Cli_PlcHotStart.Cli_PlcHotStart=GetFunction(snap7_hDLL,"Cli_PlcHotStart")
  Global Cli_PlcStop.Cli_PlcStop=GetFunction(snap7_hDLL,"Cli_PlcStop")
  Global Cli_ReadArea.Cli_ReadArea=GetFunction(snap7_hDLL,"Cli_ReadArea")
  Global Cli_ReadMultiVars.Cli_ReadMultiVars=GetFunction(snap7_hDLL,"Cli_ReadMultiVars")
  Global Cli_ReadSZL.Cli_ReadSZL=GetFunction(snap7_hDLL,"Cli_ReadSZL")
  Global Cli_ReadSZLList.Cli_ReadSZLList=GetFunction(snap7_hDLL,"Cli_ReadSZLList")
  Global Cli_SetAsCallback.Cli_SetAsCallback=GetFunction(snap7_hDLL,"Cli_SetAsCallback")
  Global Cli_SetConnectionParams.Cli_SetConnectionParams=GetFunction(snap7_hDLL,"Cli_SetConnectionParams")
  Global Cli_SetConnectionType.Cli_SetConnectionType=GetFunction(snap7_hDLL,"Cli_SetConnectionType")
  Global Cli_SetParam.Cli_SetParam=GetFunction(snap7_hDLL,"Cli_SetParam")
  Global Cli_SetPlcDateTime.Cli_SetPlcDateTime=GetFunction(snap7_hDLL,"Cli_SetPlcDateTime")
  Global Cli_SetPlcSystemDateTime.Cli_SetPlcSystemDateTime=GetFunction(snap7_hDLL,"Cli_SetPlcSystemDateTime")
  Global Cli_SetSessionPassword.Cli_SetSessionPassword=GetFunction(snap7_hDLL,"Cli_SetSessionPassword")
  Global Cli_TMRead.Cli_TMRead=GetFunction(snap7_hDLL,"Cli_TMRead")
  Global Cli_TMWrite.Cli_TMWrite=GetFunction(snap7_hDLL,"Cli_TMWrite")
  Global Cli_Upload.Cli_Upload=GetFunction(snap7_hDLL,"Cli_Upload")
  Global Cli_WaitAsCompletion.Cli_WaitAsCompletion=GetFunction(snap7_hDLL,"Cli_WaitAsCompletion")
  Global Cli_WriteArea.Cli_WriteArea=GetFunction(snap7_hDLL,"Cli_WriteArea")
  Global Cli_WriteMultiVars.Cli_WriteMultiVars=GetFunction(snap7_hDLL,"Cli_WriteMultiVars")
  
  Global Srv_ClearEvents.Srv_ClearEvents=GetFunction(snap7_hDLL,"Srv_ClearEvents")
  Global Srv_Create.Srv_Create=GetFunction(snap7_hDLL,"Srv_Create")
  Global Srv_Destroy.Srv_Destroy=GetFunction(snap7_hDLL,"Srv_Destroy")
  Global Srv_ErrorText.Srv_ErrorText=GetFunction(snap7_hDLL,"Srv_ErrorText")
  Global Srv_EventText.Srv_EventText=GetFunction(snap7_hDLL,"Srv_EventText")
  Global Srv_GetMask.Srv_GetMask=GetFunction(snap7_hDLL,"Srv_GetMask")
  Global Srv_GetParam.Srv_GetParam=GetFunction(snap7_hDLL,"Srv_GetParam")
  Global Srv_GetStatus.Srv_GetStatus=GetFunction(snap7_hDLL,"Srv_GetStatus")
  Global Srv_LockArea.Srv_LockArea=GetFunction(snap7_hDLL,"Srv_LockArea")
  Global Srv_PickEvent.Srv_PickEvent=GetFunction(snap7_hDLL,"Srv_PickEvent")
  Global Srv_RegisterArea.Srv_RegisterArea=GetFunction(snap7_hDLL,"Srv_RegisterArea")
  Global Srv_SetCpuStatus.Srv_SetCpuStatus=GetFunction(snap7_hDLL,"Srv_SetCpuStatus")
  Global Srv_SetEventsCallback.Srv_SetEventsCallback=GetFunction(snap7_hDLL,"Srv_SetEventsCallback")
  Global Srv_SetMask.Srv_SetMask=GetFunction(snap7_hDLL,"Srv_SetMask")
  Global Srv_SetParam.Srv_SetParam=GetFunction(snap7_hDLL,"Srv_SetParam")
  Global Srv_SetRWAreaCallback.Srv_SetRWAreaCallback=GetFunction(snap7_hDLL,"Srv_SetRWAreaCallback")
  Global Srv_SetReadEventsCallback.Srv_SetReadEventsCallback=GetFunction(snap7_hDLL,"Srv_SetReadEventsCallback")
  Global Srv_Start.Srv_Start=GetFunction(snap7_hDLL,"Srv_Start")
  Global Srv_StartTo.Srv_StartTo=GetFunction(snap7_hDLL,"Srv_StartTo")
  Global Srv_Stop.Srv_Stop=GetFunction(snap7_hDLL,"Srv_Stop")
  Global Srv_UnlockArea.Srv_UnlockArea=GetFunction(snap7_hDLL,"Srv_UnlockArea")
  Global Srv_UnregisterArea.Srv_UnregisterArea=GetFunction(snap7_hDLL,"Srv_UnregisterArea")  
  
  Global Par_AsBSend.Par_AsBSend=GetFunction(snap7_hDLL,"Par_AsBSend")
  Global Par_BRecv.Par_BRecv=GetFunction(snap7_hDLL,"Par_BRecv")
  Global Par_BSend.Par_BSend=GetFunction(snap7_hDLL,"Par_BSend")
  Global Par_CheckAsBRecvCompletion.Par_CheckAsBRecvCompletion=GetFunction(snap7_hDLL,"Par_CheckAsBRecvCompletion")
  Global Par_CheckAsBSendCompletion.Par_CheckAsBSendCompletion=GetFunction(snap7_hDLL,"Par_CheckAsBSendCompletion")
  Global Par_Create.Par_Create=GetFunction(snap7_hDLL,"Par_Create")
  Global Par_Destroy.Par_Destroy=GetFunction(snap7_hDLL,"Par_Destroy")
  Global Par_ErrorText.Par_ErrorText=GetFunction(snap7_hDLL,"Par_ErrorText")
  Global Par_GetLastError.Par_GetLastError=GetFunction(snap7_hDLL,"Par_GetLastError")
  Global Par_GetParam.Par_GetParam=GetFunction(snap7_hDLL,"Par_GetParam")
  Global Par_GetStats.Par_GetStats=GetFunction(snap7_hDLL,"Par_GetStats")
  Global Par_GetStatus.Par_GetStatus=GetFunction(snap7_hDLL,"Par_GetStatus")
  Global Par_GetTimes.Par_GetTimes=GetFunction(snap7_hDLL,"Par_GetTimes")
  Global Par_SetParam.Par_SetParam=GetFunction(snap7_hDLL,"Par_SetParam")
  Global Par_SetRecvCallback.Par_SetRecvCallback=GetFunction(snap7_hDLL,"Par_SetRecvCallback")
  Global Par_SetSendCallback.Par_SetSendCallback=GetFunction(snap7_hDLL,"Par_SetSendCallback")
  Global Par_Start.Par_Start=GetFunction(snap7_hDLL,"Par_Start")
  Global Par_StartTo.Par_StartTo=GetFunction(snap7_hDLL,"Par_StartTo")
  Global Par_Stop.Par_Stop=GetFunction(snap7_hDLL,"Par_Stop")
  Global Par_WaitAsBSendCompletion.Par_WaitAsBSendCompletion=GetFunction(snap7_hDLL,"Par_WaitAsBSendCompletion")  
  
  ProcedureReturn #True
EndProcedure

;- Text routines

Procedure.s CliErrorText(Error.i)
  
  Dim text.a(#TextLen - 1)
  
  Cli_ErrorText(Error, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii) 
EndProcedure  

Procedure.s SrvErrorText(Error.i)
  
  Dim text.a(#TextLen - 1)
  
  Srv_ErrorText(Error, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii) 
EndProcedure  

Procedure.s ParErrorText(Error.i)
  
  Dim text.a(#TextLen - 1)
  
  Par_ErrorText(Error, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii) 
EndProcedure  

Procedure.s SrvEventText(*Event)
  
  Dim text.a(#TextLen - 1)
  
  Srv_EventText(*Event, @text(), #TextLen)
  
  ProcedureReturn PeekS(@text(), -1, #PB_Ascii)  
EndProcedure

;******************************************************************************
;                           HELPER DATA ACCESS FUNCTIONS
;******************************************************************************

;- Helper data access functions

Structure byteArray
  a.a[0]
  b.b[0]
EndStructure

Structure TS7String
  Max.a ; Max string len
  Len.a ; Act string len
  Char.a[255]
EndStructure

Structure PS7String
  Max.a ; Max string len
  Len.a ; Act string len
  Char.a[0]
EndStructure

Structure udtFloat
  StructureUnion
    fltVal.f
    lVal.l
  EndStructureUnion
EndStructure

Structure udtDouble
  StructureUnion
    dblVal.d
    llVal.q
  EndStructureUnion
EndStructure

CompilerIf #PB_Compiler_Version < 600
  #PB_Backend_Asm = 0
  #PB_Backend_C = 1
  #PB_Compiler_Backend = 0
CompilerEndIf

Procedure bswap16(value.u)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap16(v_value);
  CompilerElse
    !xor eax,eax
    !mov ax, word [p.v_value]
    !rol ax, 8
    ProcedureReturn
  CompilerEndIf
EndProcedure

Procedure bswap32(value.l)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap32(v_value);
  CompilerElse
    !mov eax, dword [p.v_value]
    !bswap eax
    ProcedureReturn
  CompilerEndIf
EndProcedure

Procedure.q bswap64(value.q)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap64(v_value);
  CompilerElse
    CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !mov rax, qword [p.v_value]
      !bswap rax
    CompilerElse
      !mov edx, dword [p.v_value]
      !mov eax, dword [p.v_value + 4]
      !bswap edx
      !bswap eax
    CompilerEndIf
    ProcedureReturn
  CompilerEndIf
EndProcedure

; ----

;- GET Function

Procedure.i GetBitAt(*Buffer.byteArray, Offset.i, Bit.i)
  Protected value.i
  
  If *Buffer
    If Bit >= 0 And Bit <= 7
      If *Buffer\a[Offset] & (1 << Bit)
        value = 1
      Else
        value = 0
      EndIf
    EndIf
  EndIf
  ProcedureReturn value
EndProcedure

; ----

Procedure GetByteAt(*Buffer.byteArray, Offset.i)
  Protected value.a
  
  If *Buffer
    value = *Buffer\a[Offset]
  EndIf
  ProcedureReturn value
EndProcedure

; ----

Procedure GetWordAt(*Buffer.unicode, Offset.i)
  If *Buffer
    *Buffer + Offset
    ProcedureReturn bswap16(*Buffer\u)
  EndIf
EndProcedure

; ----

Procedure GetIntAt(*Buffer.word, Offset.i)
  If *Buffer
    *Buffer + Offset
    ProcedureReturn bswap16(*Buffer\w)
  EndIf
EndProcedure

; ----

Procedure GetDWordAt(*Buffer.long, Offset.i)
  If *Buffer
    *Buffer + Offset
    ProcedureReturn bswap32(*Buffer\l)
  EndIf
EndProcedure

; ----

Procedure GetDIntAt(*Buffer.long, Offset.i)
  If *Buffer
    *Buffer + Offset
    ProcedureReturn bswap32(*Buffer\l)
  EndIf
EndProcedure

; ----

Procedure GetLIntAt(*Buffer.quad, Offset.i) ; TIA Long Integer (8 Byte)
  If *Buffer
    *Buffer + Offset
    ProcedureReturn bswap64(*Buffer\q)
  EndIf
EndProcedure

; ----

Procedure.f GetRealAt(*Buffer.long, Offset.i)
  Protected value.udtFloat
  If *Buffer
    *Buffer + Offset
    value\lVal = bswap32(*Buffer\l)
  EndIf
  ProcedureReturn value\fltVal
EndProcedure

; ----

Procedure.d GetDoubleAt(*Buffer.quad, Offset.i) ; TIA
  Protected value.udtDouble
  If *Buffer
    *Buffer + Offset
    value\llVal = bswap64(*Buffer\q)
  EndIf
  ProcedureReturn value\dblVal
EndProcedure

; ----

Procedure.a BCDtoByte(B.a)
  ProcedureReturn ((B >> 4) * 10) + (B & $0F)
EndProcedure  

Procedure GetDateTimeAt(*Buffer, Offset.i, *DateTime.tm, plcTIA = #False)
  
  Protected DateTime.tm, y.l, *plc.byteArray
  
  If *Buffer And *DateTime
    *plc = *Buffer + Offset
    
    If Not plcTIA
      y = BCDtoByte(*plc\a[0])
      
      If y >= 90 And y <= 99
        y = y + 1900
      ElseIf y >= 0 And y <= 89
        y = y + 2000        
      EndIf  
      
      *DateTime\tm_year = y
      
      *DateTime\tm_mon = BCDtoByte(*plc\a[1])
      *DateTime\tm_mday = BCDtoByte(*plc\a[2])
      *DateTime\tm_hour = BCDtoByte(*plc\a[3])
      *DateTime\tm_min = BCDtoByte(*plc\a[4])
      *DateTime\tm_sec = BCDtoByte(*plc\a[5])
      
      *DateTime\tm_wday = BCDtoByte(*plc\a[7] & $0F)
    Else
      y = BCDtoByte(*plc\a[7])
      
      If y >= 90 And y <= 99
        y = y + 1900
      ElseIf y >= 0 And y <= 89
        y = y + 2000        
      EndIf  
      
      *DateTime\tm_year = y
      
      *DateTime\tm_mon = BCDtoByte(*plc\a[6])
      *DateTime\tm_mday = BCDtoByte(*plc\a[5])
      *DateTime\tm_hour = BCDtoByte(*plc\a[4])
      *DateTime\tm_min = BCDtoByte(*plc\a[3])
      *DateTime\tm_sec = BCDtoByte(*plc\a[2])
      
      *DateTime\tm_wday = BCDtoByte(*plc\a[0] & $0F)
    EndIf
    
  EndIf  
  
EndProcedure  

; ----

Procedure.s GetS7StringAt(*Buffer.PS7String, Offset.i)
  Protected value.s
  If *Buffer
    *Buffer + Offset
    If *Buffer\Len <= *Buffer\Max
      value = PeekS(@*Buffer\Char, *Buffer\Len, #PB_Ascii)
    EndIf
  EndIf
  ProcedureReturn value
EndProcedure

; ----

;- SET functions

Procedure SetBitAt(*Buffer.byteArray, Offset.i, Bit.i, Value.i)
  If *Buffer
    If Bit >= 0 And Bit <= 7
      If Value = 1
        *Buffer\a[Offset] = *Buffer\a[Offset] | (1 << Bit)
      ElseIf Value = 0
        *Buffer\a[Offset] = *Buffer\a[Offset] & ~(1 << Bit)
      EndIf
    EndIf
  EndIf
EndProcedure

; ----

Procedure SetByteAt(*Buffer.byteArray, Offset.i, Value.a)
  If *Buffer
    *Buffer\a[Offset] = Value
  EndIf
EndProcedure

; ----

Procedure SetWordAt(*Buffer.unicode, Offset.i, Value.u)
  If *Buffer
    *Buffer + Offset
    *Buffer\u = bswap16(Value)
  EndIf
EndProcedure

; ----

Procedure SetIntAt(*Buffer.word, Offset.i, Value.w)
  If *Buffer
    *Buffer + Offset
    *Buffer\w = bswap16(Value)
  EndIf
EndProcedure

; ----

Procedure SetDWordAt(*Buffer.long, Offset.i, Value.q)
  If *Buffer
    *Buffer + Offset
    *Buffer\l = bswap32(Value)
  EndIf
EndProcedure

; ----

Procedure SetDIntAt(*Buffer.long, Offset.i, Value.l)
  If *Buffer
    *Buffer + Offset
    *Buffer\l = bswap32(Value)
  EndIf
EndProcedure

; ----

Procedure SetLIntAt(*Buffer.quad, Offset.i, Value.q) ; TIA Long Integer (8Byte)
  If *Buffer
    *Buffer + Offset
    *Buffer\q = bswap64(Value)
  EndIf
EndProcedure

; ----

Procedure SetRealAt(*Buffer.long, Offset.i, Value.f)
  Protected *value.udtFloat = @Value
  If *Buffer
    *Buffer + Offset
    *Buffer\l = bswap32(*value\lVal)
  EndIf
EndProcedure

; ----

Procedure SetDoubleAt(*Buffer.quad, Offset.i, Value.d) ; TIA PLC
  Protected *value.udtDouble = @Value
  If *Buffer
    *Buffer + Offset
    *Buffer\q = bswap64(*value\llVal)
  EndIf
EndProcedure

; ----

Procedure.a ByteToBCD(Value.a)
  ProcedureReturn ((Value / 10) << 4) | (Value % 10)
EndProcedure  

Procedure SetDateTimeAt(*Buffer, Offset.i, *DateTime.tm, plcTIA = #False)
  
  Protected y.l, *plc.byteArray
  
  If *Buffer And *DateTime
    *plc = *Buffer + Offset
    
    y = *DateTime\tm_year
    
    If y >= 1990 And y <= 1999
      y = y - 1900
    ElseIf y >= 2000 And y <= 2089
      y = y - 2000          
    EndIf  
    
    If Not plcTIA
      *plc\a[0] = ByteToBCD(y)
      *plc\a[1] = ByteToBCD(*DateTime\tm_mon)
      *plc\a[2] = ByteToBCD(*DateTime\tm_mday)
      *plc\a[3] = ByteToBCD(*DateTime\tm_hour)
      *plc\a[4] = ByteToBCD(*DateTime\tm_min)
      *plc\a[5] = ByteToBCD(*DateTime\tm_sec)
      *plc\a[6] = 0
      *plc\a[7] = ByteToBCD(*DateTime\tm_wday)
    Else
      *plc\a[7] = ByteToBCD(y)
      *plc\a[6] = ByteToBCD(*DateTime\tm_mon)
      *plc\a[5] = ByteToBCD(*DateTime\tm_mday)
      *plc\a[4] = ByteToBCD(*DateTime\tm_hour)
      *plc\a[3] = ByteToBCD(*DateTime\tm_min)
      *plc\a[2] = ByteToBCD(*DateTime\tm_sec)
      *plc\a[1] = 0
      *plc\a[0] = ByteToBCD(*DateTime\tm_wday)
    EndIf
  EndIf          
  
EndProcedure

; ----

Procedure SetS7StringAt(*Buffer.PS7String, Offset.i, Value.s)
  Protected len = Len(Value)
  If *Buffer
    *Buffer + Offset
    If *Buffer\Max > 0
      If len > *Buffer\Max
        len = *Buffer\Max
      EndIf
      FillMemory(@*Buffer\Char, *Buffer\Max, 0, #PB_Byte)
      PokeS(@*Buffer\Char, Value, len, #PB_Ascii | #PB_String_NoZero) 
      *Buffer\Len = len
      ProcedureReturn len
    EndIf
  EndIf
EndProcedure

; ----

Procedure InitS7StringAt(*Buffer.PS7String, Offset.i, Value.s, MaxLen.i)
  Protected len
  If MaxLen < 1 Or MaxLen > 255
    ProcedureReturn 0
  EndIf
  If *Buffer
    *Buffer + Offset
    *Buffer\Max = MaxLen
    *Buffer\Len = 0
    FillMemory(@*Buffer\Char, MaxLen, 0, #PB_Byte)
    len = Len(Value)
    If len > MaxLen
      len = MaxLen
    EndIf
    PokeS(@*Buffer\Char, Value, len, #PB_Ascii | #PB_String_NoZero) 
    *Buffer\Len = len
    ProcedureReturn len
  EndIf
EndProcedure

; ----

;- End

; ********

CompilerIf #PB_Compiler_IsMainFile
  
  ;- Test Helper data access functions
  
  *mem = AllocateMemory(2048)
  
  Debug "Init Strings"
  InitS7StringAt(*mem, 0, "", 14)
  InitS7StringAt(*mem, 16, "", 14)
  
  Debug "Test Strings"
  SetS7StringAt(*mem, 0, "Hello World!")
  Debug GetS7StringAt(*mem, 0)
  
  SetS7StringAt(*mem, 16, "12345678901234567890")
  Debug GetS7StringAt(*mem, 16)
  
  Debug "Init Values"
  PokeA(*mem + 32, $81)
  PokeA(*mem + 32 + 1, $02)
  PokeA(*mem + 32 + 3, $04)
  PokeA(*mem + 32 + 7, $08)
  
  Debug "Test Byte"
  Debug Hex(GetByteAt(*mem, 32))
  
  Debug "Test Word / Int"
  Debug Hex(GetWordAt(*mem, 32))
  Debug Hex(GetIntAt(*mem, 32))
  
  Debug "Test DWord / DInt"
  Debug Hex(GetDWordAt(*mem, 32))
  Debug Hex(GetDIntAt(*mem, 32))
  
  Debug "Test LInt"
  Debug Hex(GetLIntAt(*mem, 32))
  
  Debug "Test Real"
  SetRealAt(*mem + 48, 0, 100.555)
  PokeF(*mem + 48 + 4, 100.555)
  fltVal.f = GetRealAt(*mem + 48, 0)
  Debug fltVal
  
  Debug "Test Double"
  SetDoubleAt(*mem + 64, 0, 12345.6789)
  PokeD(*mem + 64 + 8, 12345.6789)
  dblVal.d = GetDoubleAt(*mem + 64, 0)
  Debug dblVal
  
  ShowMemoryViewer(*mem+64, 32)
  
CompilerEndIf
Last edited by mk-soft on Sat Jul 23, 2022 6:14 pm, edited 2 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
purenet
User
User
Posts: 30
Joined: Wed Oct 21, 2009 10:11 am

Re: Snap7 communication library for Siemens PLC

Post by purenet »

Thank you chris and mk-soft, a very useful library. :D
ehowington
Enthusiast
Enthusiast
Posts: 114
Joined: Sat Sep 12, 2009 3:06 pm

Re: Snap7 communication library for Siemens PLC

Post by ehowington »

have you updated this to 1.4.2 just curious
======================================================================[2016-12-04]
Version 1.4.2 - Platform release
----------------------------------------------------------------------------------
[Changed]
- Removed all the dependencies on STL to start the project IoT.
Now the GNU compiled library is fully compatible also with projects made with
a cross-compiler.
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Snap7 communication library for Siemens PLC

Post by mk-soft »

Works fine with snap7 files
- /1.4.2 - for Windows, macOS and Linux
- /Snap7-loT/snap7-iot-arm - for Raspberry PI

For Raspberry (Linux for Arm) must be remove ASM-Backend code from snap7_include.pbi :!:
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
ehowington
Enthusiast
Enthusiast
Posts: 114
Joined: Sat Sep 12, 2009 3:06 pm

Re: Snap7 communication library for Siemens PLC

Post by ehowington »

mk-soft wrote: Sat Jul 23, 2022 4:18 pm Works fine with snap7 files
- /1.4.2 - for Windows, macOS and Linux
- /Snap7-loT/snap7-iot-arm - for Raspberry PI

For Raspberry (Linux for Arm) must be remove ASM-Backend code from snap7_include.pbi :!:
hey do the have siemens virtual plc software? that this works with? for testing?
would this work for example PLCSIM Advanced
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Snap7 communication library for Siemens PLC

Post by mk-soft »

ehowington wrote: Sat Jul 23, 2022 4:53 pm hey do the have siemens virtual plc software? that this works with? for testing?
would this work for example PLCSIM Advanced
I haven't tried that yet. We can test it sometime (in the company).
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Snap7 communication library for Siemens PLC

Post by mk-soft »

Update snap7_include.pbi v2.01.2
- Added C-Backend support (Works with Raspberry PI)
- Optimize code

P.S.
Fix Linux path ...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
ehowington
Enthusiast
Enthusiast
Posts: 114
Joined: Sat Sep 12, 2009 3:06 pm

Re: Snap7 communication library for Siemens PLC

Post by ehowington »

mk-soft wrote: Sat Jul 23, 2022 4:59 pm
ehowington wrote: Sat Jul 23, 2022 4:53 pm hey do the have siemens virtual plc software? that this works with? for testing?
would this work for example PLCSIM Advanced
I haven't tried that yet. We can test it sometime (in the company).
Let me know 8)
Post Reply