OPC Server Daten lesen und schreiben

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

OPC Server Daten lesen und schreiben

Beitrag von ne555 »

Hallo,

Ich habe eine SPS die Daten über einen OPC-Server verfügbar macht.
Mit einem einfachen Testclient kann ich mir die Daten von der SPS tabellarisch darstellen lassen. Nun möchte eine PB-Anwendung die über den OPC Server die Daten der SPS lesen und geänderte Werte auf die SPS zurückschreiben kann.

Ich habe gelesen, das es da die OPCDAAuto.dll gibt, womit man auf OPC-Serverdaten von einer VB-Applikation aus zugreifen kann. Auch über die Möglichkeit mit PureDispHelper diese dll unter PureBasic verfügbar zu machen, habe ich gelesen.
Wo bekomme ich eine Beschreibung dieser dll.
Sie wird offenbar mit Visual Studio mitgeliefert.
Aber wie finde ich heraus, über welche Funktionen die dll verfügt?
In der Hilfe von Visual Basic habe ich nichts gefunden.

leider blieb auch die googelei nach „funktionen opcdaauto.dll“ oder „beschreibung opcdaauto.dll“ sehr unbefriedigend.

Mein Ist-Zustand ist also der korrekt parametrierte und funktionierende OPC-Server.
Eine PureBasic Version. Die PureDispHelper lib und die OPCDAAuto.dll
Wie gehe ich jetzt weiter vor?

könnt ihr mir weiterhelfen

Grüße ne555
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: OPC Server Daten lesen und schreiben

Beitrag von Kiffi »

ne555 hat geschrieben:Mein Ist-Zustand ist also der korrekt parametrierte und funktionierende OPC-Server.
Eine PureBasic Version. Die PureDispHelper lib und die OPCDAAuto.dll
Wie gehe ich jetzt weiter vor?
am einfachsten wäre es jetzt, einen VB- oder VBS-Code aufzutreiben, der
diese OPCDAAuto ansprechen kann. Die Umsetzung dieser Codes in
PureDispHelper- oder COMate-Code wären dann i.d.R. ein leichtes.

Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Ich umgehe mit Purebasic die Automation Schnittstelle und verwende direkt die Costumer Interface direkt auf den OPC-Server.

Ist zwar zuerst eine Menge arbeit, läuft aber erheblich stabiler.

Eine gesamte veröffendlichung meiner Arbeit möchte ich nicht da ich diese Beruflich verwende.
Aber die Declaration kann ich Dir geben.

Compilermode UNICODE ist unbedingt erforderlich

"OpcDefineV21.pb"

Code: Alles auswählen

;- TOP

; Komment   : OPC Define 
; Version   : v2.101
; Erstellt  : 02.12.2004
; Geändert  : 13.06.2007
; Author    : Michael Kastner (mk-soft)

; Compiler  : Unicode

; *********************************************************************************************************

;- Konstanten CLSCTX

#CLSCTX_INPROC_SERVER  = $1 
#CLSCTX_INPROC_HANDLER = $2 
#CLSCTX_LOCAL_SERVER   = $4 
#CLSCTX_REMOTE_SERVER  = $10 
#CLSCTX_ALL = $17 ;#CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER

;- Konstanten OPC

#OPC_DS_CACHE = 1
#OPC_DS_DEVICE = 2

#OPC_READABLE = 1
#OPC_WRITEABLE = 2

#OPC_E_INVALIDHANDLE = ($C0040001)
#OPC_E_BADTYPE = ($C0040004)
#OPC_E_PUBLIC = ($C0040005)
#OPC_E_BADRIGHTS = ($C0040006)
#OPC_E_UNKNOWNITEMID = ($C0040007)
#OPC_E_INVALIDITEMID = ($C0040008)
#OPC_E_INVALIDFILTER = ($C0040009)
#OPC_E_UNKNOWNPATH = ($C004000A)
#OPC_E_RANGE = ($C004000B)
#OPC_E_DUPLICATENAME = ($C004000C)
#OPC_S_UNSUPPORTEDRATE = ($0004000D)
#OPC_S_CLAMP = ($0004000E)
#OPC_S_INUSE = ($0004000F)
#OPC_E_INVALIDCONFIGFILE = ($C0040010)
#OPC_E_NOTFOUND = ($C0040011)
#OPC_E_INVALID_PID = ($C0040203)

#OPC_QUALITY_MASK = $C0
#OPC_STATUS_MASK = $FC
#OPC_LIMIT_MASK = $03
#OPC_QUALITY_BAD = $00
#OPC_QUALITY_UNCERTAIN = $40
#OPC_QUALITY_GOOD = $C0
#OPC_QUALITY_CONFIG_ERROR = $04
#OPC_QUALITY_NOT_CONNECTED = $08
#OPC_QUALITY_DEVICE_FAILURE = $0c
#OPC_QUALITY_SENSOR_FAILURE = $10
#OPC_QUALITY_LAST_KNOWN = $14
#OPC_QUALITY_COMM_FAILURE = $18
#OPC_QUALITY_OUT_OF_SERVICE = $1C
#OPC_QUALITY_LAST_USABLE = $44
#OPC_QUALITY_SENSOR_CAL = $50
#OPC_QUALITY_EGU_EXCEEDED = $54
#OPC_QUALITY_SUB_NORMAL = $58
#OPC_QUALITY_LOCAL_OVERRIDE = $D8
#OPC_LIMIT_OK = $00
#OPC_LIMIT_LOW = $01
#OPC_LIMIT_HIGH = $02
#OPC_LIMIT_CONST = $03

; *********************************************************************************************************

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

; *********************************************************************************************************

;- Structure MULTI_QI

Structure MULTI_QI
    *pIID.IID;
    *pItf.l;
    hr.l;
EndStructure

;- Structure COSERVERINFO

Structure COSERVERINFO
    dwReserved1.l;
    *pwszName;
    *pAuthInfo;
    dwReserved2.l;
EndStructure

;- Structure SAFEARRAYBOUND

Structure SAFEARRAYBOUND
  cElements.l
  lLbound.l
EndStructure

;- Structure SAFEARRAY

Structure pData
  StructureUnion  
    bVal.b[0]; AS BYTE            ' VT_UI1
    iVal.w[0]; AS INTEGER         ' VT_I2
    lVal.l[0]; AS LONG            ' VT_I4
    fltVal.f[0]; AS SINGLE        ' VT_R4
    dblVal.d[0]; AS DOUBLE        ' VT_R8
    boolVal.w[0]; AS INTEGER      ' VT_BOOL
    scode.l[0]; AS LONG           ' VT_ERROR
    cyVal.l[0]; AS LONG           ' VT_CY
    date.d[0]; AS DOUBLE          ' VT_DATE
    bstrVal.l[0]; AS LONG         ' VT_BSTR
    punkVal.l[0]; AS DWORD        ' VT_UNKNOWN
    pdispVal.l[0]; AS DWORD       ' VT_DISPATCH
    parray.l[0]; AS DWORD         ' VT_ARRAY|*
  EndStructureUnion
EndStructure
  
Structure SAFEARRAY
  cDims.w
  fFeatures.w
  cbElements.l
  cLocks.l
  *pvData.pData
  rgsabound.SAFEARRAYBOUND[1]
EndStructure

; *********************************************************************************************************

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

; *********************************************************************************************************

;- Structure OPC

;- Structure OPCGROUPHEADER

Structure OPCGROUPHEADER
  dwSize.l
  dwItemCount.l
  hClientGroup.l
  dwTransactionID.l
  hrStatus.l
EndStructure

;- Structure OPCITEMHEADER1

Structure OPCITEMHEADER1
  hClient.l
  dwValueOffset.l
  wQuality.w
  wReserved.w
  ftTimeStampItem.FILETIME
EndStructure

;- Structure OPCITEMHEADER2

Structure OPCITEMHEADER2
  hClient.l
  dwValueOffset.l
  wQuality.w
  wReserved.w
EndStructure

;- Structure OPCGROUPHEADERWRITE

Structure OPCGROUPHEADERWRITE
  dwItemCount.l
  hClientGroup.l
  dwTransactionID.l
  hrStatus.l
EndStructure

;- Structure OPCITEMHEADERWRITE

Structure OPCITEMHEADERWRITE
  hClient.l
  dwError.l
EndStructure

;- Structure OPCITEMSTATE

Structure OPCITEMSTATE
  hClient.l
  ftTimeStamp.FILETIME
  wQuality.w
  wReserved.w
  vDataValue.VARIANT
EndStructure

;- Structure OPCSERVERSTATUS

Structure OPCSERVERSTATUS
  ftStartTime.FILETIME
  ftCurrentTime.FILETIME
  ftLastUpdateTime.FILETIME
  dwServerState.l ;OPCSERVERSTATE
  dwGroupCount.l
  dwBandWidth.l
  wMajorVersion.w
  wMinorVersion.w
  wBuildNumber.w
  wReserved.w
EndStructure

;- Structure OPCITEMDEF

Structure OPCITEMDEF
  szAccessPath.s;
  szItemID.s;
  bActive.l;
  hClient.l;
  dwBlobSize.l;
  *pBlob.l;
  vtRequestedDataType.w;
  wReserved.w;
EndStructure

;- Structure OPCITEMATTRIBUTES

Structure OPCITEMATTRIBUTES
  szAccessPath.s;
  szItemID.s;
  bActive.l
  hClient.l
  hServer.l
  dwAccessRights.l
  dwBlobSize.l
  *pBlob.l;
  vtRequestedDataType.l
  vtCanonicalDataType.l
  dwEUType.l ;OPCEUTYPE
  vEUInfo.VARIANT
EndStructure

;- Structure OPCITEMRESULT

Structure OPCITEMRESULT
  hServer.l
  vtCanonicalDataType.w
  wReserved.w
  dwAccessRights.l
  dwBlobSize.l
  *pBlob.l;
EndStructure

; *********************************************************************************************************

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

; *********************************************************************************************************

;- OPC-Server Interfaces 
;-

;- IOPCServer interface definition

Interface IOPCServer
  QueryInterface(a, b)
  AddRef()
  Release()
  AddGroup(a, b, c, d, e, f, g, h, i, j, k)
  GetErrorString(a, b, c)
  GetGroupByName(a, b, c)
  GetStatus(a)
  RemoveGroup(a, b)
  CreateGroupEnumerator(a, b, c)
EndInterface

;- IOPCServerPublicGroups interface definition
;
Interface IOPCServerPublicGroups
  QueryInterface(a, b)
  AddRef()
  Release()
  GetPublicGroupByName(a, b, c)
  RemovePublicGroup(a, b)
EndInterface

;- IOPCBrowseServerAddressSpace interface definition
;
Interface IOPCBrowseServerAddressSpace
  QueryInterface(a, b)
  AddRef()
  Release()
  QueryOrganization(a)
  ChangeBrowsePosition(a, b)
  BrowseOPCItemIDs(a, b, c, d, e)
  GetItemID(a, b)
  BrowseAccessPaths(a, b)
EndInterface

;- IOPCGroupStateMgt interface definition
;
Interface IOPCGroupStateMgt
  QueryInterface(a, b)
  AddRef()
  Release()
  GetState(a, b, c, d, e, f, g, h)
  SetState(a, b, c, d, e, f, g)
  SetName(a)
  CloneGroup(a, b, c)
EndInterface

;- IOPCPublicGroupStateMgt interface definition
;
Interface IOPCPublicGroupStateMgt
  QueryInterface(a, b)
  AddRef()
  Release()
  GetState(a)
  MoveToPublic()
EndInterface

;- IOPCSyncIO interface definition
;
Interface IOPCSyncIO
  QueryInterface(a, b)
  AddRef()
  Release()
  Read(a, b, c, d, e)
  Write(a, b, c, d)
EndInterface

;- IOPCAsyncIO interface definition
;
Interface IOPCAsyncIO
  QueryInterface(a, b)
  AddRef()
  Release()
  Read(a, b, c, d, e, f)
  Write(a, b, c, d, e, f)
  Refresh(a, b, c)
  Cancel(a)
EndInterface

;- IOPCItemMgt interface definition
;
Interface IOPCItemMgt
  QueryInterface(a, b)
  AddRef()
  Release()
  AddItems(a, b, c, d)
  ValidateItems(a, b, c, d, e)
  RemoveItems(a, b, c)
  SetActiveState(a, b, c, d)
  SetClientHandles(a, b, c, d)
  SetDatatypes(a, b, c, d)
  CreateEnumerator(a, b)
EndInterface

;- IEnumOPCItemAttributes interface definition
;
Interface IEnumOPCItemAttributes
  QueryInterface(a, b)
  AddRef()
  Release()
  Next(a, b, c)
  Skip(a)
  Reset()
  Clone(a)
EndInterface

;- IOPCDataCallback interface definition
;
Interface IOPCDataCallback
  QueryInterface(a, b)
  AddRef()
  Release()
  OnDataChange(a, b, c, d, e, f, g, h, i, j)
  OnReadComplete(a, b, c, d, e, f, g, h, i, j)
  OnWriteComplete(a, b, c, d, e, f)
  OnCancelComplete(a, b)
EndInterface

;- IOPCAsyncIO2 interface definition
;
Interface IOPCAsyncIO2
  QueryInterface(a, b)
  AddRef()
  Release()
  Read(a, b, c, d, e)
  Write(a, b, c, d, e, f)
  Refresh2(a, b, c)
  Cancel2(a)
  SetEnable(a)
  GetEnable(a)
EndInterface

;- IOPCItemProperties interface definition
;
Interface IOPCItemProperties
  QueryInterface(a, b)
  AddRef()
  Release()
  QueryAvailableProperties(a, b, c, d, e)
  GetItemProperties(a, b, c, d, e)
  LookupItemIDs(a, b, c, d, e)
EndInterface



;- IOPCShutdown interface definition
;
Interface IOPCShutdown
  QueryInterface(a, b)
  AddRef()
  Release()
  ShutdownRequest(a)
EndInterface

;- IOPCCommon interface definition
;
Interface IOPCCommon
  QueryInterface(a, b)
  AddRef()
  Release()
  SetLocaleID(a)
  GetLocaleID(a)
  QueryAvailableLocaleIDs(a, b)
  GetErrorString(a, b)
  SetClientName(a)
EndInterface

;- IOPCEventServer interface definition
;
Interface IOPCEventServer
  QueryInterface(a, b)
  AddRef()
  Release()
  GetStatus(a)
  CreateEventSubscription(a, b, c, d, e, f, g, h)
  QueryAvailableFilters(a)
  QueryEventCategories(a, b, c, d)
  QueryConditionNames(a, b, c)
  QuerySubConditionNames(a, b, c)
  QuerySourceConditions(a, b, c)
  QueryEventAttributes(a, b, c, d, e)
  TranslateToItemIDs(a, b, c, d, e, f, g, h, i)
  GetConditionState(a, b, c, d, e)
  EnableConditionByArea(a, b)
  EnableConditionBySource(a, b)
  DisableConditionByArea(a, b)
  DisableConditionBySource(a, b)
  AckCondition(a, b, c, d, e, f, g, h)
  CreateAreaBrowser(a, b)
EndInterface

;- IOPCEventSubscriptionMgt interface definition
;
Interface IOPCEventSubscriptionMgt
  QueryInterface(a, b)
  AddRef()
  Release()
  SetFilter(a, b, c, d, e, f, g, h, i)
  GetFilter(a, b, c, d, e, f, g, h, i)
  SelectReturnedAttributes(a, b, c)
  GetReturnedAttributes(a, b, c)
  Refresh(a)
  CancelRefresh(a)
  GetState(a, b, c, d)
  SetState(a, b, c, d, e, f)
EndInterface

;- IOPCEventAreaBrowser interface definition
;
Interface IOPCEventAreaBrowser
  QueryInterface(a, b)
  AddRef()
  Release()
  ChangeBrowsePosition(a, b)
  BrowseOPCAreas(a, b, c)
  GetQualifiedAreaName(a, b)
  GetQualifiedSourceName(a, b)
EndInterface

;- IOPCEventSink interface definition
;
Interface IOPCEventSink
  QueryInterface(a, b)
  AddRef()
  Release()
  OnEvent(a, b, c, d, e)
EndInterface

;- OPCEventServerCATID interface definition
;
Interface OPCEventServerCATID
EndInterface

; *********************************************************************************************************

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

; *********************************************************************************************************

;- Opc-Enum Interfaces
;-

Interface IOPCServerList2 Extends IUnknown
  EnumClassesOfCategories(a,b,c,d,e)
  GetClassDetails(a,b,c,d)
  CLSIDFromProgID(a,b)
EndInterface

Interface IOPCEnumGUID Extends IUnknown
  Next(a,b,c)
  Skip(a)
  Reset()
  Clone(a)
EndInterface

Interface IOPCServerList Extends IUnknown
  EnumClassesOfCategories(a,b,c,d,e)
  GetClassDetails(a,b,c)
  CLSIDFromProgID(a,b)
EndInterface

Interface CATID_OPCDAServer10 Extends IUnknown
EndInterface

Interface CATID_OPCDAServer20 Extends IUnknown
EndInterface

Interface CATID_OPCDAServer30 Extends IUnknown
EndInterface

Interface CATID_XMLDAServer10 Extends IUnknown
EndInterface

; *********************************************************************************************************

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

; *********************************************************************************************************

;- IID OPC-Server DataSection

DataSection

  IID_IOPCServer:
  Data.l $39c13a4d
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCServerPublicGroups:
  Data.l $39c13a4d
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCBrowseServerAddressSpace:
  Data.l $39c13a4f
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCGroupStateMgt:
  Data.l $39c13a50
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCPublicGroupStateMgt:
  Data.l $39c13a51
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCSyncIO:
  Data.l $39c13a52
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCAsyncIO:
  Data.l $39c13a53
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCItemMgt:
  Data.l $39c13a54
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IEnumOPCItemAttributes:
  Data.l $39c13a55
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCDataCallback:
  Data.l $39c13a70
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCAsyncIO2:
  Data.l $39c13a71
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  IID_IOPCItemProperties:
  Data.l $39c13a72
  Data.w $011e,$11d0
  Data.b $96,$75,$00,$20,$af,$d8,$ad,$b3

  LIBID_OPCDA:
  Data.l $B28EEDB2
  Data.w $AC6F,$11d1
  Data.b $84,$D5,$00,$60,$8C,$B8,$A7,$E9
  
EndDataSection

; *********************************************************************************************************

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

; *********************************************************************************************************

;- IID OPC Enum DataSection
  
DataSection
  
  LIBID_OPCCOMN: ; '{B28EEDB1-AC6F-11D1-84D5-00608CB8A7E9}'
  Data.l $B28EEDB1
  Data.w $AC6F,$11D1
  Data.b $84,$D5,$00,$60,$8C,$B8,$A7,$E9

  IID_IOPCCommon: ; '{F31DFDE2-07B6-11D2-B2D8-0060083BA1FB}'
  Data.l $F31DFDE2
  Data.w $07B6,$11D2
  Data.b $B2,$D8,$00,$60,$08,$3B,$A1,$FB
  
  IID_IOPCShutdown: ; '{F31DFDE1-07B6-11D2-B2D8-0060083BA1FB}'
  Data.l $F31DFDE1
  Data.w $07B6,$11D2
  Data.b $B2,$D8,$00,$60,$08,$3B,$A1,$FB
  
  IID_IOPCServerList: ; '{13486D50-4821-11D2-A494-3CB306C10000}'
  Data.l $13486D50
  Data.w $4821,$11D2
  Data.b $A4,$94,$3C,$B3,$06,$C1,$00,$00
  
  IID_IOPCEnumGUID: ; '{55C382C8-21C7-4e88-96C1-BECFB1E3F483}'
  Data.l $55C382C8
  Data.w $21C7,$4e88
  Data.b $96,$C1,$BE,$CF,$B1,$E3,$F4,$83
  
  IID_IOPCServerList2: ; '{9DD0B56C-AD9E-43ee-8305-487F3188BF7A}'
  Data.l $9DD0B56C
  Data.w $AD9E,$43ee
  Data.b $83,$05,$48,$7F,$31,$88,$BF,$7A
  
  CLSID_OPCServerList: ; '{13486D51-4821-11D2-A494-3CB306C10000}'
  Data.l $13486D51
  Data.w $4821,$11D2
  Data.b $A4,$94,$3C,$B3,$06,$C1,$00,$00
  
  IID_CATID_OPCDAServer10: ; {63D5F430-CFE4-11d1-B2C8-0060083BA1FB}
  Data.l $63D5F430
  Data.w $CFE4,$11d1
  Data.b $B2,$C8,$00,$60,$08,$3B,$A1,$FB
  
  IID_CATID_OPCDAServer20: ; {63D5F432-CFE4-11d1-B2C8-0060083BA1FB}
  Data.l $63D5F432
  Data.w $CFE4,$11d1
  Data.b $B2,$C8,$00,$60,$08,$3B,$A1,$FB
  
  IID_CATID_OPCDAServer30: ; {CC603642-66D7-48f1-B69A-B625E73652D7}
  Data.l $CC603642
  Data.w $66D7,$48f1
  Data.b $B6,$9A,$B6,$25,$E7,$36,$52,$D7
  
  IID_CATID_XMLDAServer10: ; {3098EDA4-A006-48b2-A27F-247453959408}
  Data.l $3098EDA4
  Data.w $A006,$48b2
  Data.b $A2,$7F,$24,$74,$53,$95,$94,$08

EndDataSection
Auszug aus "OpcFunctionV21.pb"

Code: Alles auswählen

;- TOP

; Komment   : OPC Funktionen 
; Version   : v2.101
; Erstellt  : 02.12.2004
; Geändert  : 21.01.2008
; Author    : Michael Kastner (mk-soft)

; Compiler  : Unicode

EnableExplicit

; *********************************************************************************************************

IncludeFile "OpcDefineV21.PB"

; *********************************************************************************************************

Global OpcLastMessage.s
Global OpcLastError.l

; *********************************************************************************************************

;- MaxItems Constant
#MAXITEMS = 64

;- Structure Group

Structure Group
  GroupName.s
  TimBias.l
  PercentDeadband.f
  RevisedUpdateRate.l
  GrpSrvHandle.l
EndStructure

;- Structure OPCITEMRESULT ARRAY

Structure OPCITEMRESULT100
  ID.OPCITEMRESULT[0]
EndStructure

;- Structure OPCITEMSTATE ARRAY

Structure OPCITEMSTATE100
  VALUE.OPCITEMSTATE[0]
EndStructure

;- Structure ERROR ARRAY

Structure ERROR100
  ID.l[0]
EndStructure

;- Structure Item

Structure Items
  MaxItems.l
  Item.OPCITEMDEF[#MAXITEMS]
  hServer.l[#MAXITEMS]
  *pItemResults.OPCITEMRESULT100
  *pItemErrors.ERROR100
  *pItemValues.OPCITEMSTATE100
  *pErrors.ERROR100
EndStructure

;- Structure ServerList

Structure ServerList
  ProgID.s
  UserType.s
  VerIndProgID.s
  CLSID.IID
EndStructure

; *********************************************************************************************************

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

; *********************************************************************************************************

Procedure.s StringFromCLSID(*clsid.iid)

  ;-- Para 1: IN CLSID.IID
  ;
  ;-- Result: LCSID String
  
  Protected result.s, i, b
  
  result = "{"
  result + RSet(Hex(*clsid\data1),8,"0")
  result + "-" + RSet(Hex(*clsid\data2),4,"0")
  result + "-" + RSet(Hex(*clsid\data3),4,"0")
  result + "-"
  b = *clsid\data4[0] & $FF
  result + RSet(Hex(b),2,"0")
  b = *clsid\data4[1] & $FF
  result + RSet(Hex(b),2,"0")
  result + "-"
  For i = 2 To 7 
    b = *clsid\data4[i] & $FF
    result + RSet(Hex(b),2,"0")
  Next
  result + "}"
  
  ProcedureReturn result
 
EndProcedure
 
; *********************************************************************************************************

Procedure.l OpcEnum_CLSIDFromProgID(ServerName.s, ServerNode.s, *CLSID.IID)

  ;-- Para 1: IN ServerName
  ;-- Para 2: IN ServerNode
  ;-- Para 3: OUT CLSID.IID
  ;
  ;-- Result: True or False

  Protected r1
  Protected mqi.MULTI_QI
  Protected serverInfo.COSERVERINFO
  Protected *OpcServerList2.IOPCServerList2
  
  If ServerNode = ""
    ServerNode = "localhost"
  EndIf
  
  serverInfo\dwReserved1 = 0
  serverInfo\pwszName = @ServerNode
  serverInfo\pAuthInfo = 0
  serverInfo\dwReserved2 = 0

  mqi\pIID = ?IID_IOPCServerList2;
  mqi\pItf = 0;
  mqi\hr = #S_OK;
  
  r1 = CoInitialize_(#Null);
  If (r1 <> #S_OK)
    If (r1 = #S_FALSE)
      OpcLastMessage = "COM Library already initialized"
      OpcLastError = r1
    Else
      OpcLastMessage = "Initialisation of COM Library failed. ErrorCode= " + Hex(r1);
      OpcLastError = r1
      ProcedureReturn 0
    EndIf
  EndIf
  
  r1 = CoCreateInstanceEx_(?CLSID_OPCServerList, #Null, #CLSCTX_REMOTE_SERVER, @serverInfo, 1,@mqi)
  If (r1 <> #S_OK) Or (mqi\hr <> #S_OK) 
    OpcLastMessage = "Creation of IOPCServerList-Object failed: ErrorCode= " + Hex(r1);
    OpcLastError = r1
    ProcedureReturn #False
  EndIf
  
  *OpcServerList2 = mqi\pItf
  
  r1 = *OpcServerList2\CLSIDFromProgID(@ServerName, *clsid)
  OpcLastError = r1
  *OpcServerList2\Release()
  If r1 = #S_OK
    OpcLastMessage = "CLSID Found"
    ProcedureReturn #True
  Else
    OpcLastMessage = "Retrival of CLSID failed: ErrorCode= " + Hex(r1);
    ProcedureReturn #False
  EndIf
  
EndProcedure

; *********************************************************************************************************

Procedure.l OpcEnum_ServerList(ServerNode.s, *IID_CATID.IID, ServerList.ServerList())

  ;-- Para 1: IN ServerNode
  ;-- Para 2: IN IID_CADID : ?IID_CATID_OPCDAServer10
  ;                          ?IID_CATID_OPCDAServer20
  ;                          ?IID_CATID_OPCDAServer30
  ;                          ?IID_CATID_XMLDAServer10
  ;-- Para 3: OUT LinkedList.ServerList
  ;
  ;-- Result: True or False

  Protected r1
  Protected mqi.MULTI_QI
  Protected serverInfo.COSERVERINFO
  Protected *OpcServerList2.IOPCServerList2
  
  Protected *OPCEnumGUID.IOPCEnumGUID
  Protected clsid.iid
  Protected fetched.l
  Protected *str1, *str2, *str3
  
  If ServerNode = ""
    ServerNode = "localhost"
  EndIf
  
  serverInfo\dwReserved1 = 0
  serverInfo\pwszName = @ServerNode
  serverInfo\pAuthInfo = 0
  serverInfo\dwReserved2 = 0

  mqi\pIID = ?IID_IOPCServerList2;
  mqi\pItf = 0;
  mqi\hr = #S_OK;
  
  r1 = CoInitialize_(#Null);
  If (r1 <> #S_OK)
    If (r1 = #S_FALSE)
      OpcLastMessage = "COM Library already initialized"
      OpcLastError = r1
    Else
      OpcLastMessage = "Initialisation of COM Library failed. ErrorCode= " + Hex(r1);
      OpcLastError = r1
      ProcedureReturn #False
    EndIf
  EndIf
  
  r1 = CoCreateInstanceEx_(?CLSID_OPCServerList, #Null, #CLSCTX_REMOTE_SERVER, @serverInfo, 1,@mqi)
  If (r1 <> #S_OK) Or (mqi\hr <> #S_OK) 
    OpcLastMessage = "Creation of IOPCServerList-Object failed: ErrorCode= " + Hex(r1);
    OpcLastError = r1
    ProcedureReturn #False
  EndIf
  
  *OpcServerList2 = mqi\pItf
  
  r1 = *OPCServerList2\EnumClassesOfCategories (1, *IID_CATID, 0, 0, @*OPCEnumGUID);
  OpcLastError = r1
  If r1 <> #S_OK
    OpcLastMessage = "Creation of EnumClassesOfCategories-Object failed: ErrorCode= " + Hex(r1);
    ProcedureReturn #False
  EndIf
    
  While *OPCEnumGUID\Next(1, @clsid, @fetched) = #S_OK
    r1 = *OPCServerList2\GetClassDetails(clsid, @*str1, @*str2, @*str3)
    OpcLastError = r1
    If r1 <> #S_OK
      OpcLastMessage = "GetClassDetails failed: ErrorCode= " + Hex(r1);
      Break
    Else
      AddElement(ServerList())
      Serverlist()\ProgID = PeekS(*str1)
      Serverlist()\UserType = PeekS(*str2)
      Serverlist()\VerIndProgID = PeekS(*str3)
      CopyMemory(CLSID, ServerList()\CLSID, SizeOf(IID))
      SysFreeString_(*str1)
      SysFreeString_(*str2)
      SysFreeString_(*str3)
    EndIf
  Wend
  
  *OPCEnumGUID\Release()
  *OpcServerList2\Release()
  
  If r1 = #S_OK
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; *********************************************************************************************************

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

; *********************************************************************************************************

Procedure.l OpcConnect(ServerName.s)

  ;-- Para 1: IN ServerName
  ;
  ;-- Result: *m_pIOPCServer

  Protected r1
  Protected *Server
  Protected clsid.IID
  
  r1 = CoInitialize_(#Null);
  If (r1 <> #S_OK)
    If (r1 = #S_FALSE)
      OpcLastMessage = "COM Library already initialized"
      OpcLastError = r1
    Else
      OpcLastMessage = "Initialisation of COM Library failed. ErrorCode= " + Hex(r1);
      OpcLastError = r1
      ProcedureReturn 0
    EndIf
  EndIf
  
  r1 = CLSIDFromProgID_(ServerName, @clsid)
  
  If (r1 <> #S_OK)
    OpcLastMessage = "Retrival of CLSID failed: ErrorCode= " + Hex(r1);
    OpcLastError = r1
    ProcedureReturn 0
  EndIf

  r1 = CoCreateInstance_(@clsid, #Null, #CLSCTX_LOCAL_SERVER, ?IID_IOPCServer, @*Server)
  If (r1 <> #S_OK)
    OpcLastMessage = "Creation of IOPCServer-Object failed: ErrorCode= " + Hex(r1);
    OpcLastError = r1
    ProcedureReturn 0
  Else 
    OpcLastMessage = "Connect to OPC Server " + ServerName
    OpcLastError = 0
    ProcedureReturn *Server
  EndIf
  
EndProcedure


; *********************************************************************************************************

Procedure.l OpcConnectEx(ServerName.s, ServerNode.s)

  ;-- Para 1: IN ServerName
  ;-- Para 2: IN ServerNode
  ;
  ;-- Result: *m_pIOPCServer

  Protected r1
  Protected *m_pIOPCServer.IOPCServer
  Protected clsid.IID
  Protected mqi.MULTI_QI
  Protected serverInfo.COSERVERINFO
  
  serverInfo\dwReserved1 = 0
  serverInfo\pwszName = @ServerNode
  serverInfo\pAuthInfo = 0
  serverInfo\dwReserved2 = 0

  mqi\pIID = ?IID_IOPCServer;
  mqi\pItf = 0;
  mqi\hr = #S_OK;
  
  
  r1 = CoInitialize_(#Null);
  If (r1 <> #S_OK)
    If (r1 = #S_FALSE)
      OpcLastMessage = "COM Library already initialized"
      OpcLastError = r1
    Else
      OpcLastMessage = "Initialisation of COM Library failed. ErrorCode= " + Hex(r1);
      OpcLastError = r1
      ProcedureReturn 0
    EndIf
  EndIf
  
  r1 = CLSIDFromProgID_(ServerName, @clsid)
  If (r1 <> #S_OK)
    OpcLastMessage = "Retrival of CLSID failed: ErrorCode= " + Hex(r1);
    OpcLastError = r1
    If OpcEnum_CLSIDFromProgID(ServerName, ServerNode, @clsid) = #False
      ProcedureReturn 0
    EndIf
  EndIf
  
  r1 = CoCreateInstanceEx_(@clsid, #Null, #CLSCTX_REMOTE_SERVER, @serverInfo, 1,@mqi)
  If (r1 <> #S_OK) Or (mqi\hr <> #S_OK) 
    OpcLastMessage = "Creation of IOPCServer-Object failed: ErrorCode= " + Hex(r1);
    OpcLastError = r1
    ProcedureReturn 0
  Else 
    OpcLastMessage = "Connect to OPC Server " + ServerName
    OpcLastError = 0
    ProcedureReturn mqi\pItf ;*m_pIOPCServer.IOPCServer
  EndIf  
EndProcedure


; *********************************************************************************************************

Test

Code: Alles auswählen

;- TOP

; Komment   : OPC Test 
; Version   : v2.1
; Erstellt  : 11.06.2007
; Geändert  : 11.06.2007
; Author    : Michael Kastner (mk-soft)

; Compiler  : Unicode

; *********************************************************************************************************

EnableExplicit

IncludeFile "OpcFunctionsV21.PB"

DisableExplicit

; *********************************************************************************************************

Global Exit = 0
Global Item.Items ; Definiert in OpcFunction

Global Dim *psa(6)

; *********************************************************************************************************

Procedure.s FormatMessage(ErrorNumber.l)

  Protected *Buffer, len, result.s
  
  len = FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER|#FORMAT_MESSAGE_FROM_SYSTEM,0,ErrorNumber,0,@*Buffer,0,0)
  If len
    result = PeekS(*Buffer, len - 2)
    LocalFree_(*Buffer)
    ProcedureReturn result
  Else
    ProcedureReturn "Errorcode: " + Hex(ErrorNumber)
  EndIf
  
EndProcedure



Procedure Test()

  ; OPC Server verbinden
  ;*Server = OpcConnectEx("OPC.SimaticNET", "pgm01")
  *Server = OpcConnectEx("INAT TCPIPH1 OPC Server", "pc001")
  Debug OpcLastMessage
  Debug FormatMessage(OpcLastError)
  If *Server = 0
    ProcedureReturn 0
  EndIf
  
  ; Gruppe anlegen
  Group.Group\GroupName = "Daten"
  *ItemMgt = OpcAddGroup(Group, *Server)
  Debug OpcLastMessage
  If *ItemMgt = 0
    ProcedureReturn 0
  EndIf
  
  ProcedureReturn 1
EndProcedure

; *********************************************************************************************************

; *********************************************************************************************************

;- Main

If Test() = 0
  Debug "Test nicht erfolgleich!"
  End
EndIf

Debug "Fertig"
Überlege mir eine LIB zu erstellen
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

Beitrag von ne555 »

Danke, aber das verunsichert mich ehr als das es mir hilft.
Ich muss wohl erst mehr Grundlagen über OPC wissen.
Ich habe es mir einfacher vorgestellt auf einen OPC Server zuzugreifen.
Kann mir jemand Links zu einer deutschsprachigen Beschreibung geben oder mir eine Buchempfehlung geben?

Grüße ne555
Benutzeravatar
mueckerich
Beiträge: 220
Registriert: 13.09.2004 11:33
Wohnort: Am schönsten Flecken der Erde, zwischen PC und Motorrad

Beitrag von mueckerich »

mk-soft hat geschrieben:Überlege mir eine LIB zu erstellen
Wäre eine angenehme Sache. :allright:
"Wenn Sie glauben, mich verstanden zu haben, dann habe ich mich falsch ausgedrückt" ( Alan Greenspan)
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Bei Siemens gibt es ein gutes Handbuch.
http://support.automation.siemens.com/W ... aller=view

Man muss aber Erfahrung sammeln mit OOP Programmierung.
Mit Purebasic ging es besser die `C` Beispiele für Costum-Schnittstelle für Synchone Kommunikation um zu setzen.

Erste Testprogramme mit der Automation-Schnittstelle liefen aber auch schon.
COMate müsten diese laufen
http://www.purebasic.fr/english/viewtop ... ght=comate

FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mueckerich
Beiträge: 220
Registriert: 13.09.2004 11:33
Wohnort: Am schönsten Flecken der Erde, zwischen PC und Motorrad

Beitrag von mueckerich »

Vielen Dank für den Link zu dem Handbuch. Das kann ich im Augenblick sehr gut gebrauchen. :allright:
"Wenn Sie glauben, mich verstanden zu haben, dann habe ich mich falsch ausgedrückt" ( Alan Greenspan)
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

Beitrag von ne555 »

schöner Link,
ich werde meine Erfahrungen um das Thema OPC dann an dieser Stelle bekannt machen.

danke und viele
Grüße ne555
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

Beitrag von ne555 »

Hallo mueckerich,

ich habe von Siemens auch eine schöne Anleitung zum anbinden eines OPC-Servers mit VBA in Excel gefunden.
Das probiere ich gerade aus und werde versuchen es auf PB umzusetzen.
schau dir den link mal an
http://support.automation.siemens.com/
gib dort bei search „GS_CP243-1_Excel_d.pdf“ ein und lade dir die Anleitung

schönes Wochenende
ne555
Benutzeravatar
BlueHoschi
Beiträge: 97
Registriert: 02.10.2007 07:19

Re: OPC Server Daten lesen und schreiben

Beitrag von BlueHoschi »

Hallo,

der Thread ist schon was älter, aber bei mir ist das Thema grade aktuell geworden.

@ne555: Gibt es schon Neuigkeiten?

@mk-soft: bei den Strukturen SAFEARRAY und SAFERRAYBOUND gibt der Debugger mir die Meldung aus, dass es diese Strukturen schon in einem residenten File gibt.
Außerdem gibt es immer eine Fehlermeldung in dieser Zeile:

Code: Alles auswählen

Procedure.l OpcEnum_ServerList(ServerNode.s, *IID_CATID.IID, ServerList.ServerList())
"Syntax Error"
Hab die Erstellung der Liste aus den Argumenten heraus genommen und eine Zeile tiefer eingefügt ("Newlist").

Im Test wird eine Prozedur Namens "OpcAddGroup" aufgerufen, die es nicht gibt.
Habe es zunächst rausgenommen. Mal sehn ob ich es hin bekomme eine zu schreiben.

Werde dieses Beispiel so mal in der Firma testen, sobald ich dazu komme und Du nichts dagegen hast.
Dann bräuchte ich keine DLL zum Auslesen von SPS-Werten nutzen.

Hast Du schon eine Lib fertig?

@All:
Ist die folgende Vorgehensweise richtig?

- Zunächst lade ich mir die PureDispHelper-lib und hinterlege sie im PB-Ordner
- Damit habe ich dann neue Befehle für den Umgang mit COM-Objekten
- Diese Befehle nutze ich um z.B. die gdbaauto.dll anzusprechen
- Die Beschreibung zur DLL hilft mir dann vermutlich weiter

Frage: Server ist immer der Name des SPS-Programms? Und die Gruppen?
Items sind einzelne Werte, oder?
Woher bekomme ich die Namen der Server und der Gruppen (Groups)?
Kann ich mir auch eine Liste der Gruppen-, Itemnamen anzeigen lassen?

Gruß Holger
Wer Dir Steine in den Weg legt, pflastert den vielleicht.

PB 5.21, Win 7 64 bit
Antworten