// wrap7 project wrap7.go package wrap7 /* #cgo CFLAGS: -O2 -march=native #cgo LDFLAGS: -lm -lsnap7 #include #include #include #include #include #include #ifdef OS_WINDOWS # define WIN32_LEAN_AND_MEAN # include #endif #define MAXPDULENGTH 960 // https://support.industry.siemens.com...view/109747136 Seite 6813 // S7-300 240 Byte // S7-400 480 Byte // S7-1200 240 Byte // S7-1500 960 Byte int MultiRead(S7Object Client, byte (*buffer)[MAXPDULENGTH], TS7DataItem *psivar, int ItemsCount) { int i; TS7DataItem Items[ItemsCount]; for( i = 0; i< ItemsCount; i++ ) { //printf("Item Nr. %d\n",i); Items[i].Area = psivar[i].Area; Items[i].WordLen = psivar[i].WordLen; Items[i].DBNumber = psivar[i].DBNumber; Items[i].Start = psivar[i].Start; Items[i].Amount = psivar[i].Amount; Items[i].pdata = &buffer[i]; } return Cli_ReadMultiVars(Client, &Items[0], ItemsCount); } int MultiWrite(S7Object Client, byte (*buffer)[MAXPDULENGTH], TS7DataItem *psivar, int ItemsCount) { int i; TS7DataItem Items[ItemsCount]; for( i = 0; i< ItemsCount; i++ ) { //printf("Item Nr. %d\n",i); Items[i].Area = psivar[i].Area; Items[i].WordLen = psivar[i].WordLen; Items[i].DBNumber = psivar[i].DBNumber; Items[i].Start = psivar[i].Start; Items[i].Amount = psivar[i].Amount; Items[i].pdata = &buffer[i]; } return Cli_WriteMultiVars(Client, &Items[0], ItemsCount); } */ import ( "C" ) import ( "fmt" "log" "net" "unsafe" ) type ( // Type-Alias ist ansich nur Kosmetik S7Object = C.S7Object ) type ConditionType string const ( CONDITION_RUNNING ConditionType = "running" CONDITION_STOPPED ConditionType = "stopped" CONDITION_UNKNOWN ConditionType = "unknown" ) var ( // Damit im Go-Code nicht das C-Package importiert werden muß S7AreaDB = (int)(C.S7AreaDB) S7AreaMK = (int)(C.S7AreaMK) S7AreaPE = (int)(C.S7AreaPE) S7AreaPA = (int)(C.S7AreaPA) S7AreaTM = (int)(C.S7AreaTM) S7AreaCT = (int)(C.S7AreaCT) S7WLBit = (int)(C.S7WLBit) S7WLByte = (int)(C.S7WLByte) S7WLWord = (int)(C.S7WLWord) S7WLDWord = (int)(C.S7WLDWord) S7WLReal = (int)(C.S7WLReal) S7WLCounter = (int)(C.S7WLCounter) S7WLTimer = (int)(C.S7WLTimer) ) var EventCallBackLength = (int)(C.EventCallBackLength) var ( SrvAreaPE = (int)(C.srvAreaPE) SrvAreaPA = (int)(C.srvAreaPA) SrvAreaMK = (int)(C.srvAreaMK) SrvAreaCT = (int)(C.srvAreaCT) SrvAreaTM = (int)(C.srvAreaTM) SrvAreaDB = (int)(C.srvAreaDB) ) const ( BlockTypeOB = 0x38 BlockTypeDB = 0x41 BlockTypeSDB = 0x42 BlockTypeFC = 0x43 BlockTypeSFC = 0x44 BlockTypeFB = 0x45 BlockTypeSFB = 0x46 ) // Diese Konstante gibt es doppelt. Sie muß auch im C-Code angepaßt werden! const MAXPDULENGTH int = 960 const MULTIREADWRITE_BUFFERS = 10 // Wievele Buffers und Items MultiRead und MultiWrite anlegen soll. //const DEVICE_IP = "192.168.0.10" // https://support.industry.siemens.com...view/109747136 Seite 6813 // S7-300 240 Byte // S7-400 480 Byte // S7-1200 240 Byte // S7-1500 960 Byte type MultiReadWriteItem struct { Area, WordLen, DBNumber, Start, Amount int } type TS7OrderCode struct { Code string V1, V2, V3 int } type TSCpuInfo struct { ModuleTypeName, SerialNumber, ASName, Copyright, ModuleName string } type TS7CpInfo struct { MaxPduLength, MaxConnections, MaxMpiRate, MaxBusRate int // MaxPduLengt zu MaxPduLength korrigiert } type TS7BlocksList struct { OBCount, FBCount, FCCount, SFBCount, SFCCount, DBCount, SDBCount int } type TS7BlockInfo struct { BlkType int // Block Type (OB, DB) BlkNumber int // Block number BlkLang int // Block Language BlkFlags int // Block flags MC7Size int // The real size in bytes LoadSize int // Load memory size LocalData int // Local data SBBLength int // SBB Length CheckSum int // Checksum Version int // Block version // Chars info CodeDate string // Code date IntfDate string // Interface date Author string // Author Family string // Family Header string // Header } func GetOrderCode(client C.S7Object) (int, TS7OrderCode) { var info C.TS7OrderCode res := C.Cli_GetOrderCode(client, (*C.TS7OrderCode)(unsafe.Pointer(&info))) return (int)(res), TS7OrderCode{ Code: C.GoString((*C.char)(unsafe.Pointer(&info.Code[0]))), V1: (int)(info.V1), V2: (int)(info.V2), V3: (int)(info.V3)} /*, func() string { return fmt.Sprintf("Order Code: %s\n, Version: %d.%d.%d\n", C.GoString((*C.char)(unsafe.Pointer(&info.Code[0]))), (int)(info.V1), (int)(info.V2), (int)(info.V3)) }()*/ } func GetCpuInfo(client C.S7Object) (int, TSCpuInfo) { var info C.TS7CpuInfo res := C.Cli_GetCpuInfo(client, (*C.TS7CpuInfo)(unsafe.Pointer(&info))) return (int)(res), TSCpuInfo{ ModuleTypeName: C.GoString((*C.char)(unsafe.Pointer(&info.ModuleTypeName[0]))), SerialNumber: C.GoString((*C.char)(unsafe.Pointer(&info.SerialNumber[0]))), ASName: C.GoString((*C.char)(unsafe.Pointer(&info.ASName[0]))), Copyright: C.GoString((*C.char)(unsafe.Pointer(&info.Copyright[0]))), ModuleName: C.GoString((*C.char)(unsafe.Pointer(&info.ModuleName[0])))} } func GetCpInfo(client C.S7Object) (int, TS7CpInfo) { var info C.TS7CpInfo res := C.Cli_GetCpInfo(client, (*C.TS7CpInfo)(unsafe.Pointer(&info))) return (int)(res), TS7CpInfo{ MaxPduLength: (int)(info.MaxPduLengt), MaxConnections: (int)(info.MaxConnections), MaxMpiRate: (int)(info.MaxMpiRate), MaxBusRate: (int)(info.MaxBusRate)} } func ListBlocks(client C.S7Object) (int, TS7BlocksList) { var list C.TS7BlocksList res := C.Cli_ListBlocks(client, (*C.TS7BlocksList)(unsafe.Pointer(&list))) return (int)(res), TS7BlocksList{ OBCount: (int)(list.OBCount), FBCount: (int)(list.FBCount), FCCount: (int)(list.FCCount), SFBCount: (int)(list.SFBCount), SFCCount: (int)(list.SFCCount), DBCount: (int)(list.DBCount), SDBCount: (int)(list.SDBCount)} } func GetAgBlockInfo(client C.S7Object, blockType, blockNum int) (int, TS7BlockInfo) { var info C.TS7BlockInfo /* blockType: OB = 0x38 DB = 0x41 SDB = 0x42 FC = 0x43 SFC = 0x44 FB = 0x45 SFB =0x46 Wrap7BlockTypeOB = 0x38 Wrap7BlockTypeDB = 0x41 Wrap7BlockTypeSDB = 0x42 Wrap7BlockTypeFC = 0x43 Wrap7BlockTypeSFC = 0x44 Wrap7BlockTypeFB = 0x45 Wrap7BlockTypeSFB = 0x46 */ res := C.Cli_GetAgBlockInfo(client, (C.int)(blockType), (C.int)(blockNum), (*C.TS7BlockInfo)(unsafe.Pointer(&info))) return (int)(res), TS7BlockInfo{ BlkType: (int)(info.BlkType), BlkNumber: (int)(info.BlkNumber), BlkLang: (int)(info.BlkLang), BlkFlags: (int)(info.BlkFlags), MC7Size: (int)(info.MC7Size), LoadSize: (int)(info.LoadSize), LocalData: (int)(info.LocalData), SBBLength: (int)(info.SBBLength), CheckSum: (int)(info.CheckSum), Version: (int)(info.Version), CodeDate: C.GoString((*C.char)(unsafe.Pointer(&info.CodeDate[0]))), IntfDate: C.GoString((*C.char)(unsafe.Pointer(&info.IntfDate[0]))), Author: C.GoString((*C.char)(unsafe.Pointer(&info.Author[0]))), Family: C.GoString((*C.char)(unsafe.Pointer(&info.Family[0]))), Header: C.GoString((*C.char)(unsafe.Pointer(&info.Header[0])))} } /* int GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData); int GetPgBlockInfo(void *pBlock, PS7BlockInfo pUsrData, int Size); int ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount); */ func GetPlcStatus(client C.S7Object) (int, int8, ConditionType) { var status C.int res := C.Cli_GetPlcStatus(client, &status) return (int)(res), (int8)(status), func(sc int8) ConditionType { switch sc { case C.S7CpuStatusRun: return CONDITION_RUNNING case C.S7CpuStatusStop: return CONDITION_STOPPED default: //C.S7CpuStatusUnknown return CONDITION_UNKNOWN } }((int8)(status)) } /* Cli_GetPlcStatus(Client, &Status); if (Check(res, "CPU Status")) { switch (Status) { case S7CpuStatusRun: printf(" RUN\n"); break; case S7CpuStatusStop: printf(" STOP\n"); break; default: printf(" UNKNOWN\n"); break; } }; } */ // MultiRead liest ein Array von Werten aus der SPS func MultiRead(client C.S7Object, items []MultiReadWriteItem) (int, [][]byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() itemsCount := len(items) if itemsCount > MULTIREADWRITE_BUFFERS { panic("Error in \"func MultiRead(client C.S7Object, items []MultiReadWriteItem)\": Too many items\n\n") // FIXME: Standardfehlermeldung erzeugen } var mulitReadWriteBuffer [MULTIREADWRITE_BUFFERS][MAXPDULENGTH]byte var cItems [MULTIREADWRITE_BUFFERS]C.TS7DataItem for i, v := range items { cItems[i].Area = (C.int)(v.Area) cItems[i].WordLen = (C.int)(v.WordLen) cItems[i].DBNumber = (C.int)(v.DBNumber) cItems[i].Start = (C.int)(v.Start) cItems[i].Amount = (C.int)(v.Amount) } res := C.MultiRead(client, (*[MAXPDULENGTH]C.uchar)(unsafe.Pointer(&mulitReadWriteBuffer)), (*C.TS7DataItem)(unsafe.Pointer(&cItems)), (C.int)(itemsCount)) /*DEBUG // Baue eine Testinfo ein mulitReadWriteBuffer[0][2] = 'G' fmt.Println(mulitReadWriteBuffer) */ // Bereinige das von Snap7 gelieferte Ergebnis und begrenze die Ausgabe auf den tatsächlichen Inhalt var datares [][]byte datares = make([][]byte, itemsCount) for i := 0; i < itemsCount; i++ { datares[i] = make([]byte, items[i].Amount) copy(datares[i], mulitReadWriteBuffer[i][0:items[i].Amount]) } return (int)(res), datares } // MultiWrite schreibt ein Array von Werten in die SPS. Auf den ersten Blick ist ein Rücklesen der Werte in MultiWrite nun ein überflüssiger Overhead. Machen wir dies hier aber nicht, müßte in Fällen, wo mit dem veränderten Speicher weitergearbeitet werden soll, ein weiteres MultiRead folgen. Dies können wir hier einsparen, wenn wir den veränderten Speicher hier zurückgeben. Wir bleiben somit auch synchron zur MultiRead-Funktion func MultiWrite(client C.S7Object, items []MultiReadWriteItem, buffers *[][]byte) (int, [][]byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() itemsCount := len(items) if itemsCount > MULTIREADWRITE_BUFFERS { panic("Error in \"func MultiWrite(client C.S7Object, items []MultiReadWriteItem)\": Too many items\n\n") // FIXME: Standardfehlermeldung erzeugen } else if buffersCount := len(*buffers); itemsCount != buffersCount { panic("Error in \"func MultiWrite(client C.S7Object, items []MultiReadWriteItem)\": Number of items and number of buffers must be identical\n\n") // FIXME: Standardfehlermeldung erzeugen } var mulitReadWriteBuffer [MULTIREADWRITE_BUFFERS][MAXPDULENGTH]byte var cItems [MULTIREADWRITE_BUFFERS]C.TS7DataItem for i, v := range items { if len((*buffers)[i]) < v.Amount { panic(fmt.Sprintf("Error in \"func MultiWrite(client C.S7Object, items []MultiReadWriteItem) [Index %d]\": Amount must not be larger than buffer length!\n\n", i)) // FIXME: Standardfehlermeldung erzeugen } cItems[i].Area = (C.int)(v.Area) cItems[i].WordLen = (C.int)(v.WordLen) cItems[i].DBNumber = (C.int)(v.DBNumber) cItems[i].Start = (C.int)(v.Start) cItems[i].Amount = (C.int)(v.Amount) copy(mulitReadWriteBuffer[i][0:items[i].Amount], (*buffers)[i][0:items[i].Amount]) } res := C.MultiWrite(client, (*[MAXPDULENGTH]C.uchar)(unsafe.Pointer(&mulitReadWriteBuffer)), (*C.TS7DataItem)(unsafe.Pointer(&cItems)), (C.int)(itemsCount)) // Bereinige das von Snap7 gelieferte Ergebnis und begrenze die Ausgabe auf den tatsächlichen Inhalt var datares [][]byte datares = make([][]byte, itemsCount) for i := 0; i < itemsCount; i++ { datares[i] = make([]byte, items[i].Amount) copy(datares[i], mulitReadWriteBuffer[i][0:items[i].Amount]) } return (int)(res), datares } func ReadArea(client C.S7Object, Area, DBNumber, Start, Amount, WordLen int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_ReadArea(client, (C.int)(Area), (C.int)(DBNumber), (C.int)(Start), (C.int)(Amount), (C.int)(WordLen), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func WriteArea(client C.S7Object, Area, DBNumber, Start, Amount, WordLen int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func WriteArea(client C.S7Object, Area, DBNumber, Start, Amount, WordLen int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_WriteArea(client, (C.int)(Area), (C.int)(DBNumber), (C.int)(Start), (C.int)(Amount), (C.int)(WordLen), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func DBRead(client C.S7Object, DBNumber, Start, Amount int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_DBRead(client, (C.int)(DBNumber), (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func DBWrite(client C.S7Object, DBNumber, Start, Amount int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func DBWrite(client C.S7Object, DBNumber, Start, Amount int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_DBWrite(client, (C.int)(DBNumber), (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func MBRead(client C.S7Object, Start, Amount int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_MBRead(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func MBWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func MBWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_MBWrite(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func EBRead(client C.S7Object, Start, Amount int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_EBRead(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func EBWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func EBWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_EBWrite(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func ABRead(client C.S7Object, Start, Amount int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_ABRead(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func ABWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func ABWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_ABWrite(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func TMRead(client C.S7Object, Start, Amount int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_TMRead(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func TMWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func TMWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_TMWrite(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func CTRead(client C.S7Object, Start, Amount int) (int, []byte) { var cbuffer [MAXPDULENGTH]C.char res := C.Cli_CTRead(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } func CTWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte) (int, []byte) { defer func() { if err := recover(); err != nil { fmt.Printf("%v", err) } }() var cbuffer [MAXPDULENGTH]C.char if len(*gobuffer) < Amount { panic("Error in \"func CTWrite(client C.S7Object, Start, Amount int, gobuffer *[]byte)\": Amount must not be larger than buffer length!\n\n") // FIXME: Standardfehlermeldung erzeugen } cbuffer = *(*[MAXPDULENGTH]C.char)(C.CBytes(*gobuffer)) res := C.Cli_CTWrite(client, (C.int)(Start), (C.int)(Amount), unsafe.Pointer(&cbuffer)) return (int)(res), C.GoBytes(unsafe.Pointer(&cbuffer), (C.int)(Amount)) } // CliCreate creates a SPS-client func CliCreate() S7Object { return C.Cli_Create() } // CliConnect connects to SPS-client func CliConnect(client S7Object, ip net.IP, rack uint8, slot uint8) { C.Cli_ConnectTo(client, C.CString(ip.String()), (C.int)(rack), (C.int)(slot)) } // FIXME: Remove me sometimes // CreateAndConnect is a wrapper for CliDisconnect for compatibility purpose, has to be removed in a later version or wrap7 func CreateAndConnect(ip net.IP, rack uint8, slot uint8) S7Object { log.Println("CreateAndConnect is a wrapper for CliCreateAndConnect for compatibility purpose, has to be removed in a later version or wrap7") return CliCreateAndConnect(ip, rack, slot) } // CliCreateAndConnect creates a SPS-client and connect to SPS func CliCreateAndConnect(ip net.IP, rack uint8, slot uint8) S7Object { client := C.Cli_Create() C.Cli_ConnectTo(client, C.CString(ip.String()), (C.int)(rack), (C.int)(slot)) return client } // CliConditionalCreateAndConnect creates a SPS-client after successfull ping and connects to SPS func CliConditionalCreateAndConnect(ip net.IP, rack uint8, slot uint8) (S7Object, error) { _, loss := pingMyDing(ip) var client S7Object if loss < PINGER_CRITICAL_LOSS_PERCENT { client = C.Cli_Create() C.Cli_ConnectTo(client, C.CString(ip.String()), (C.int)(rack), (C.int)(slot)) return client, nil } else { return client, fmt.Errorf("Unable to ping SPS [%s, %v% loss]", ip.String(), loss) } } // CliDisconnect disconnects SPS-client from SPS func CliDisconnect(client S7Object) { C.Cli_Disconnect(client) } func CliDestroy(client *S7Object) { C.Cli_Destroy(client) } func CliDisconnectAndDestroy(client S7Object) { C.Cli_Disconnect(client) C.Cli_Destroy(&client) } // FIXME: Remove me sometimes // Disconnect is a wrapper for CliDisconnect for compatibility purpose, has to be removed in a later version or wrap7 func Disconnect(client S7Object) { log.Println("Disconnect is a wrapper for CliDisconnect for compatibility purpose, has to be removed in a later version or wrap7") CliDisconnect(client) } /*Server Functions*/ func SrvCreate() S7Object { return C.Srv_Create() } func SrvStart(server *S7Object) int { return (int)(C.Srv_Start(*server)) } func SrvStop(server *S7Object) { C.Srv_Stop(*server) } func SrvDestroy(server *S7Object) { C.Srv_Destroy(server) } func SrvErrorText(errorCode int, spsServerText *rune, eventCallBackLength int) { //C.Srv_ErrorText((C.int)(ErrorCode), (*C.char)(unsafe.Pointer(&spsServerText[0])), C.EventCallBackLength) C.Srv_ErrorText((C.int)(errorCode), (*C.char)(unsafe.Pointer(spsServerText)), (C.int)(eventCallBackLength)) } func SrvRegisterArea(server *S7Object, area int, index uint16, buffer []byte, length int) { C.Srv_RegisterArea(*server, (C.int)(area), // Area (C.ushort)(index), // Nummer des Datenbausteins //unsafe.Pointer(&(buffer[0])), // Buffer //unsafe.Pointer(&((*buffer)[0])), C.CBytes(buffer), (C.int)(length)) // Die Länge ist durch die Variablendefinition bereits vorgegeben und kann hier gemessen werden. } func SrvUnregisterArea(server *S7Object, area int, index uint16) { C.Srv_UnregisterArea(*server, (C.int)(area), (C.ushort)(index)) } func RegisterEventCallBack(server *S7Object) { C._RegisterEventCallBack(*server) } func SrvLockArea(server *S7Object, area int, index uint16) { C.Srv_LockArea(*server, (C.int)(area), // Area (C.ushort)(index)) // Nummer des Datenbausteins } func SrvUnlockArea(server *S7Object, area int, index uint16) { C.Srv_UnlockArea(*server, (C.int)(area), // Area (C.ushort)(index)) // Nummer des Datenbausteins }