wrap7/wrap7.go

706 lines
22 KiB
Go

// wrap7 project wrap7.go
package wrap7
/*
#cgo CFLAGS: -O2 -march=native
#cgo LDFLAGS: -lm -lsnap7
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <snap7b.h>
#ifdef OS_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#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
}