Visual C++ und OLE Server
-
Ich habe ja bereits ein funktionierenden OPC Client! Nur leider habe ich keine Doku dazu!
Ein Verbindung herzustellen klappt ja auch ganz gut, aber nun weiss ich nicht, wie ich in meinem C++ Programm darauf zugreifen kann...
-
WAS willst Du nun?
Willst Du den vorhandenen OPC-Client "fernsteuern"?
Oder willst Du selber auf den OPC-Server zugreifen?
-
Eigentlich moechte ich Daten von der SPS lesen! Ab das nun ueber einen OPC Client mache oder nicht is egal!
Ich hatte gehofft, dass ich mit meinem selbstgeschriebenen Programm einen OPC Client oeffne, der die Verbindung herstellt und ich dann in meinem Code ueber ne Read funktion die Items auslesen kann.
Vom Prinzip her kann ich die Items schon quasi manuell auslesen, indem ich das Programm "Diagnostic OPC Client" starte, eine Verbindung herstelle, eine Group erstelle, auf add all Items gehe und dann auf Read! Da sehe ich auch, wenn sich der Sensor aendert. Sensor = einfacher Schalter! Ich sehe vDataValue[0] = 1 oder 0!
-
Der Test-OPC-Client bringt dir garnichts. Du musst einen OPC-Client selbst erstellen, d.h. in dein Programm integrieren (z.B. mit Hilfe eines OPC-Client-Toolkits oder per Hand).
Dieser Diagnostic OPC Client dient nur zum Testen von OPC-Servern bzw. um per Hand auf die SPS-Variablen zuzugreifen. Dieser fertige OPC-Client hat keine standardisierte Schnittstelle, mit der du von C++ aus auf diesen zugreifen kannst.
Du musst in deinem Code den OPC-Server starten (CoCreateInstanceEx) und dir den Pointer auf das IOPC-Server Interface holen. Mit der Funktion AddGroup von IOPC-Server legst du eine Gruppe an und bekommst einen Pointer auf das neue OPC-Group Objekt bzw. auf dessen Interface IOPCItemMgt. Das Interface hat Funktionen mit der du Items (Prozessvariablen) in der Gruppe anlegen kannst. Das Group-Objekt hat auch Funktionen zum Lesen und Schreiben von Werten des angelegten Items (Interface IOPCSyncIO, IOPCASyncIO).google nach "opcda204_cust.doc" und nehme den ersten Eintrag, das Doc beschreibt alle Interfaces mit seinen Methoden. (oder Link von Jochen)
-
Hey Softwaremaker!
Danke fuer deine Antwort! Das hat mich schon mal einen Schritt weitergebracht! Ich habe mir das Doc angeguckt und durchgelesen...allerdings hatte ich eher nach einer Anleitung gesucht. Meiner Meinung nach ist das ja eher eine Dokumentation...Kennst du vielleicht ein Tutorial, etc. wo beschrieben ist, wie man einen OPC Client zum laufen bekommt?! Leider reichen meine C/C++ Kenntnisse wohl eher nicht aus um aus dem Doc schlau zu werden!
-
Schau dir die opctest.cpp in meinem vorangegangenen Post-Link ftp://ftp.mysst.com/pub/beta/client.zip an.
In der Methode OpcStart() wird der OPC-Server gestartet:
- CLSIDFromProgID um aus Name die CLSID zu bekommen (oder du weisst diese)
- CoInitializeEx um COM zu initialisieren
- CoCreateInstance(clsid, ... IID_IOPCServer...) startet den OPC-Server und gibt Zeiger auf IOPCServer zurück
- g_pIOPCServer->AddGroup(...) legt eine Gruppe an und gibt IUnknown der OPCGroup zurück
- g_pIGroupUnknown->QueryInterface(IID_IOPCGroupxxx,...) holt Zeiger auf die Interfaces der OPCGroup (werden später benötigt um Items anzulegen und Lesen/Schreiben)In AddItems() wird ein Item angelegt
- g_pIOPCItemMgt->AddItems(...)Daten lesen schreiben erfolgt über Methoden der Schnittstelle IOPCAsyncIO oder IOPCSyncIO.
Um das ganze zu verstehen musst du dich mit dem Komponentenmodell von Microsoft = COM beschäftigen (CoCreateInstance, QueryInterface, ...).
-
Hey Softwaremaker!
Vielen Dank fuer die Datei! Sie hat mir sehr viel weiter geholfen, allerdings haette ich da noch ein paar Fragen zu. Generell verstehe ich, was das Programm macht. Es laeuft auch mit meiner SPS!
Was ich nicht verstehe, wo die Anweisung steht, um meine boolean Ausgaenge anzeigen zu lassen.
Also kurz von anfang an! Ich verbinde zur SPS, fuege Items hinzu und nehm dann "Async2 reads" als auswahl => read from devide und schon sehe ich meine ausgaenge. Wenn ich nun aber im Code gucke sehe ich nicht, wo dort genau diese Zeile geschrieben wird?!? Beim Debuggen habe ich rausgefunden, dass das programm fuer die Updaterate angehalten wird ueber Sleep und waehrend der zeit die Zeile geaendert wird....aber ich seh nix wieprintf("b\tb\tb",WertItem1,WertItem2,WertItem3);Ich sehe im Code, dass vorher ueber g_pIOPCAsyncIO2->Read(...) die Werte gelesen werden, aber wo ist die Ausgabe?!
-
Du hast zwei Möglichkeiten Werte zu lesen/schreiben:
-
Synchron: bei Aufruf g_pIOPCSyncIO->Read gibt der OPC-Server sofort die zu lesenden Werte zurück (Paramater). Nachteil: benötigt der OPC-Server längerere Zeit um die Werte zu ermitteln, dann wird deine Anwendung blockiert, da der Funktionsaufruf länger dauert.
-
Asynchron: bei Aufruf g_pIOPCAsyncIO2->Read wird eine Leseanforderung an den OPC-Server gestellt, der Funktionsaufruf dauert nur kurz, da die Werte nicht zurückgegeben werden. Nun ermittelt der OPC-Server die Werte und wenn er fertig ist ruft er selbständig eine Funktion in deinem Programm auf und übergibt die Werte.
Problem: In der DataAcces-Spezifikation 1 wurde dafür IOPCDataCallback benutzt, ab Spezifikation 2 IConnectionPointContainer.
Für Spez. 2: Du musst das IID_IConnectionPointContainer-Interface von der Gruppe holen und dann den ConnectionPoint IID_IOPCDataCallback, diesem übergibst du den Zeiger auf deine Funktion im Programm mit pCP->Advise(pSink,...);
In dem Source-Beispiel ist pSink nicht weiter ausgeführt, google mal, da gibts sicher Beispiele im Netz.
-
-
Hey! Tausenddank für die Antwort!
Hab's hinbekommen die einzelnen Zustände der Sensoren in "normale" Variable zu bringen!
jetzt muss ich "nur" noch meine beiden Programme (Visualisierung + Datenabfrage) zusammen bringen...bzw. ich hab´s heute schon versucht und nicht wirklich hinbekommen. Am liebsten würde ich ja einfach die ocptest.cpp includen, aber da steht ja vermutlich höchststrafe drauf, wenn man ne .cpp includet!
Ansonsten is mir mal wieder aufgefallen, dass es mir da an den Grundlagen fehlt!Werd´s die Tage mal weiter machen und würde mich dann melden bei Fragen!
Also erste mal danke für die OLE Abfrage!
-
Hallo!
Ich habe es soweit zum Laufen bekommen
, sprich die OLE Befehle in meine Visualisierung rein gebracht und es funktioniert soweit!Nun wuerde ich gerne an gewissen Stellen einen Status abfragen! Als Beispiel durchlaueft das Program die Funktionen wie "OPCStart" und "AddItems" auch, wenn die SPS gar nicht angeschlossen ist. Beim debuggen ist mir aufgefallen, dass die jeweiligen Anweisungen (CoCreateinstance, g_pIOPCServer->QueryInterface, g_pIOPCServer->AddGroup, etc) auch keine Fehlermeldung zurueck geben! der HRESULT hr ist immer 0!
Nun habe ich in den Unterlagen der OPC Foundation gesucht und habe die Anweisung OPCSERVERSTATUS bei IOPCServer::GetStatus() gefunden.
Aber selbst die gibt dwServerState == OPC_STATUS_RUNING nach dem ich CoCreateInstance ausfuere zurueck, obwohl der Server gar nicht angeschlossen ist?!?
Das Programm laeuft durch, bis irgendwann die Datenabfrage aufgerufen wird und nach einiger Zeit eine Fehlermeldung kommt!
Die wuerde ich aber natuerlich vorher schon umgehen!Hat jemand eine Idee, wie man das machen koennte?!
Gruss!
-
Du solltest eher die Quality der Items auswerten...
Der OPC-Server läuft vermutlich auch, wenn die SPS nicht angeschlossen ist...