OPC-Client
-
Hiho,
hat sich zufällig hier schon jemand mit OPC auseinander gesetzt und kann mir ein paar Codesnippets (oder nen schönen Link) posten für einen OPC-Client. Also am besten für Verbindung aufbauen und schliessen sowie nen Item einlesen und setzen...
-
Hallo,
ich habe bereits ein bisschen mit OPC programmiert. Von KEPWare gab es einmal eine Art Klassenbibliothek, die ich mir umgestrickt und in meinen Programmen verwendet habe. Funktioniert auch ganz gut soweit, wenn man mal dahintergestiegen ist.
Leider habe ich die Beispielprogramme und Erläuterungen von KEPWare danach nie mehr im Internet gefunden.
Ebenso gibt es von Softing eine komplette, sehr gut dokumentierte Klassenbibliothek, die allerdings etwas kostet.
Wenn du Interesse hast, kann ich dir die von mir gefundenen KEPWare Dateien mal zuschicken, es ist allerdings ohne jegliche Dokumentation und du musst halt zusehen, wie du damit zurechtkommst.Gruß
Andro
-
Wenn du Interesse hast, kann ich dir die von mir gefundenen KEPWare Dateien mal zuschicken, es ist allerdings ohne jegliche Dokumentation und du musst halt zusehen, wie du damit zurechtkommst.
Au ja guck ich mir sehr gerne an. Vielleicht hilfts mir ja ein wenig hinters konzept zu steigen. Bisher hab ich da nur ein bisschen Theorie zu im Netz gelesen aber mit so kleinen Beispielcodes werfen die ja nicht gerade um sich
über eine mail an windalf at gmx dot de würde ich mich freuen...
Danke Gruss windalf
-
OK,
Mail ist unterwegs...
-
besten Dank guck ich mir heute abend mal an ob ich da durchblicke...
-
Hoi hab heute mal ein bisschen mit rumgespielt und denke mal das mit der Serververbingung funzt jetzt.... Kann mir jemand sagen wie genau das nun geht (möglichst mit ein bisschen Quellcode und erklärung, das ich jetzt auf die einzelnen Items des Servers zugreifen kann...
USES_CONVERSION; HRESULT hr = S_OK; OPCServer opcServer; LPUNKNOWN pUnkn = NULL; COSERVERINFO si; MULTI_QI qi; CLSID m_clsid = {0xc87dba32,0xb28f,0x4632,{0x9b,0x29,0xba,0xB1,0x75,0x36,0x3f,0xbb}}; CString m_Node = "\\\\TRALALA"; //der Rechner auf dem der Spass läuft... si.dwReserved1 = 0; si.pwszName = T2OLE(m_Node.GetBuffer(0)); si.pAuthInfo = NULL; si.dwReserved2 = 0; qi.pIID = &IID_IOPCServer; qi.pItf = NULL; qi.hr = 0; hr = CoCreateInstanceEx(m_clsid, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi); if (FAILED(hr)){AfxMessageBox("Fehler hr");return;} if (FAILED(qi.hr)){AfxMessageBox("Fehler qi.hr");return;} pUnkn = qi.pItf; hr = opcServer.Attach( pUnkn ); pUnkn->Release(); //wird nicht mehr gebraucht pUnkn = NULL; if( FAILED(hr) )AfxMessageBox("Fehler ocsServerInterface");return;} AfxMessageBox("Supi verbindung steht"); ... // was muss ich hier veranstallten damit ich mir den Wert eines beligebigen Items von dem ich den Namen kenne z.B. in ner MessageBox ausschmeissen lassen kann... opcServer.Detach();
Danke im voraus falls jemand was dazu sagen kann
-
Hallo,
in Kürze solltest du folgendes tun:
- Dem Server eine (oder mehrere) OPC-Groups hinzufügen
- Der Group die gewünschten Items hinzufügen
- Asynchrones oder synchrones Lesen über die Gruppe anstossen, anschließend sollten in den Items (Value) die gewünschten Werte stehen.
-
Ach so, das heisst ich kann gar nicht spontan den Wert von Item xy auslesen sondern ich machen nur Gruppe auf, füge da die Items hinzu und der aktuelle Wert wird ständig ausgelesen...
Jetzt wird mir zumindest konzeptuell einiges klarer. Ich hätte so gerne ne Doku zu dem ganzen Spass... hmm mal probieren ob ich das hinbekomme...
Dazu aber noch ne Frage. Wenn der aktuelle Wert sagen wir mal synchorn jede Sekunde ausgelesen wird, muss ich dann darauf achten, dass gereade nicht schreibend darauf zugegriffen wird wenn ich dann auf der Clientseite an dem Item was auslesen will? Oder brauch ich mich um dieses Problem nicht weiter kümmern und risikiere allen falls einen ungültigen oder älteren Wert zu bekommen?
Wie läuft die Sache prinzipiell wenn ich es genau umgekehrt machen will. Also ein Item auf der Clientseite verändern, damit diese änderung auch serverseitig geschiet. Reicht es dafür das der Server dieses Item für den Client zum schreiben freigegeben hat? Muss ich dafür auch einfach nur den Wert Clientseitig überschreiben und der Server übernimmt das dann nach dem nächsten synchronisierungsschritt automatisch? Oder muss da dann anders verfahren werden?
-
Windalf schrieb:
Wenn der aktuelle Wert sagen wir mal synchorn jede Sekunde ausgelesen wird, muss ich dann darauf achten, dass gereade nicht schreibend darauf zugegriffen wird wenn ich dann auf der Clientseite an dem Item was auslesen will? Oder brauch ich mich um dieses Problem nicht weiter kümmern und risikiere allen falls einen ungültigen oder älteren Wert zu bekommen?
Die Verantwortung für die synchronisierung der Daten liegt ganz allein beim Server. Üblicherweise existieren die Daten auf die man mittels OPC-Server zugreifen will in einer dritten Quelle zb einer SPS. Der OPC-Server ist eigentlich nur ein Programm das den zugriff auf diese Datenquelle einheitlich zur verfügung stellt. Der übliche Weg um grössere Datenmengen von einem Steuerungssystem an einen OPC-Client zu übertragen ist asynchrones lesen. Du erstellst mehrere OPC-Groups die wiederum mehrere OPC-Items enthalten. Eine OPC-Group hat als parameter auch eine Update-time. Jedes OPC-Item hat eien parameter Hysterese.
Du erhätst die Daten vom OPCServer mittels callback. Das heist wenn du das asynchrone lesen einer OPC-Group startest erhältst du sofort eimal ein callback für jedes OPC-Item in der Gruppe. Danach checkt der Server diese daten zyklisch mit der eingestellten Updaterate. Nur wenn sich der wert eines OPC-Items geändert hat und die Änderung grösser als die Hysterese des Items ist sendet der OPC-server wieder ein callback für dieses Item an den Client.
Auf diese Weise wird der Datenmenge die zwischen Server und Client ausgetauscht werden muss minimiert. Der Nachteil dieser asynchronen Lesemethode liegt darin dass die minimale Update Rate einer OPC-Group glaube ich 500 ms ist. Weiters kannst du den Datenverkehr durch verscheidene Updaterates deiner OPC-Groups optimieren.Willst du schneller auf die Daten zugreifen dann verwendest du am besten synchrones lesen. Das wird mit synchronem lesen der OPC-Gruppe realisiert. Jedes mal wenn du einen Lesebefehl einer Gruppe absetzt bekommst du ein Callback für jedes einzelne Item dieser Gruppe.
Habe mich mit dem Schreiben von Werten im OPC-Server noch nicht so sehr auseinandergesetzt und weiss jetzt nicht ob das schreiben auch über die OPC-Groups geregelt wird oder ob man einzelne Items schreiben muss. Sicher ist jedoch dass der Server Für die synchronisation zuständig ist und dass jeder schreibzugriff auf eine Variable in einer SPS ( wenn dieser erlaubt ist ) auch durchgeführt wird.
Kurt
-
Das Schreiben geht prinzipiell genau so:
Einer Gruppe werden die zu schreibenden Items hinzugefügt, und anschließend das Schreiben der Gruppe synchron oder asynchron angestoßen.
Dem Schreiben wird als Parameter ein Array der Items und ein Array der Werte, die geschrieben werden sollen, mitgeliefert.
Der OPC-Server kümmert sich anschließend darum, dass die Werte an die SPS oder was auch immer übertragen werden.
Beim asynchronen Schreiben wird der Erfolg oder Misserfolg ebenso wie beim lesen über ein Callback mitgeteilt.
Die Richtigkeit der Werte einzelner Items können übrigens durch einen Quality- und einen Timestamp-Wert, die den jeweiligen Items zugeordnet sind, überprüft werden. Beim asynchronen Lesen kann somit auch überprüft werden, wann zu einem bestimmten Item das letzte mal ein Wert übertragen wurde.
-
Hallo,
endlich habe ich einmal Leute gefunden, die sich mit OPC auseinandersetzen.
Ich habe im Prinzip das gleiche Problem wie windalf.
AndRo67: könntest Du mir bitte die Samplefiles zukommen lassen (bilder at team-winners dot de)?
Danke, Dany.
-
-
Danke erstmal, werde mal sehen was ich hinkriege.
Bin aber weiterhin für Hinweise offen.
-
Interessant dazu natürlich auch: http://www.opcfoundation.org/ (vor allem, was aktuelle Entwicklungen angeht (z.B. Webzugriff per OPC XML-DA))
Gruß, Thomas.
-
Hi Dany,
ich hab dir die Beispiele mal per Mail zugeschickt.Gruß Andreas
-
Danke, werde jetzt mal das umfangreiche Material sichten.
-
So hab mich heute mal wieder drangesetzt... habs jetzt hinbekommen das er mir auf einen simulierte Server ein boolche variable liest und setzt... Nun kommt aber meine Frage. Was ist der Unterschied zwischen synchronen und asynchronen Lesen/Schreiben. bzw in meinem fall wie äussert sich den beim synchronen Lesen das der Wert immer wieder automatisch gelesen/geschrieben wird.
Ich seh da zunächst keinen Unterschied. Der Spass wird in einer Methode aufgerufen und sowie die durchgelaufen ist gibt es das objekt auch nicht mehr. auch will mir der sinn bei synchronen schreiben nicht einleuchten. Ist damit gemeint das ein wert den ich verändere in einer variable automatisch ständig abgeglichen wird. müsste ich dann aber nicht wieder aufpassen das der nicht gerade darauf lesend zugreift während der schreiben will, dann kann ich mir ja auch die ganze synchonisation sparen wenn ichs dann eh wieder selber machen muss... und noch eine Frage wie macht man das mit arrays. also angenommen ich habe mein item und mein item ist ein array. (ist dann ja ein COLEVariant) Wie genau bekomm ich da mein Array wieder raus?
Ach so und noch was... Wie kann ich abfragen (was für ein Interface brauch ich) um zu gucken welche Items alle in meiner Gruppe sind. Muss ich mir das selber merken oder kann ich das auch abfragen? Was passiet wenn ich ein Item nochmal hinzufüge. Ist das dann zweimal in der Gruppe (nen Fehler schmeisst der mir nicht) oder wird das einfach ignoriert weil es das Item schon einmal gibt...
-
Ich habe immer noch das Problem nicht in ein Array schreiben zu können... Dazu zunächst einmal folgende Fragen...
-
Wenn der OPC-Server ein Array vorgibt. Kann der Client die Grösse des Arrays beeinflussen oder muss er diese als Gott gegeben hinnehmen (oder hängt das vom Server ab das dies ggf erst neuere Versionen können)
-
Wenn ich richtig gelesen habe ist es nicht mögliche ein Array von Arrays zu erzeugen und auch kann ein Array nur die üblichen Typen aufnehmen (ich kann also keine structs oder ähnliches für ein Array definiert. Irre ich mich?
und nun zu der Frage. Lesen aus dem Array funzt aber ich habe wie gesagt das Problem mit dem Schreibe...
Beispiel
CString text="4711.0815 1234.5678"; COleVariant colevar(text); // initialize as a string colevar.ChangeType(VT_R8|VT_ARRAY); // let COleVariant convert!
das funzt leider nicht. wie mach ich das... das ich das Array in den Variant Typen bekomme... es ist mir prinzipiell egal ob ich aus dem array erst nen String machen muss oder wie auch immer aber ich bekomm den nicht in diesen verdammten Variant rein. ich brauch veraussichtlich ein double und ein integer-array...
kann mir da vielliecht jemand helfen das wäre geil ich bin am verzweifeln...
-