API-Managerklassen
WinCC OA stellt eine Klasse "Manager" zur Verfügung, die bereits alle für einen Manager nötigen Basisfunktionen enthält. Für jeden Manager muss von dieser Klasse eine weitere Klasse abgeleitet werden, in welcher die spezielle Funktionalität des neuen Managers implementiert wird. In der abgeleiteten Klasse gibt es einige virtuelle Funktionen, welche der neue Manager implementieren kann und in machen Fällen auch implementieren muss.
Hinweise
Anmerkung zum DLL-Suchpfad
DLLs werden in folgenden Directories in dieser Reihenfolge gesucht:
-
Das Directory, in dem sich das Executable befindet
-
Windows-Systemdirectories
-
alle Directories der Environmentvariable PATH
Für ein Beispiel siehe DemoManager.
Initialisierung, managerState, dispatch()
Bei der Ableitung der eigenen Manager-Klasse ist darauf zu achten, dass der Konstruktor die Basisklasse richtig initialisiert, da sonst keine Verbindung zustande kommen kann.
In allen Fällen ist aber auf den managerState zu achten: Eine Verbindung zum Event-Manager sollte beispielsweise nur dann erfolgen, wenn der managerState auf STATE_ADJUST gesetzt ist. Die weitere Verarbeitung kann erst erfolgen, wenn er auf STATE_RUNNING geschaltet ist. Diese Zustände werden intern gesetzt und sollten immer nur abgefragt werden.
Messages werden nur empfangen und gesendet, wenn dispatch() aufgerufen wird. (Auf jeden Fall wird aber gesendet, wenn der interne Message-Buffer voll ist (derzeitige Größe: 4096 Bytes)). Wird dispatch() nicht regelmäßig aufgerufen, bleibt die gesamte Kommunikation zum Manager gesperrt, er kann beispielsweise keine Hotlink-Messages empfangen).
Verwenden von Alias-Namen im API-Manager
Wenn Sie in einem API-Manager Alias-Namen von DP-Elementen verwenden wollen, so können Sie mit den folgenden Funktionen die DP-Identifier oder die Namen von DP-Elementen zu den Alias-Namen bekommen und umgekehrt:
Alias --> Name:
//liefert den DP-Namen mit Hilfe vom DP-Identifikator
Manager::getDpIdentificationPtr()->getName(const char *alias, char *&name)
Alias --> DpIdentifier:
//liefert den DP-Identifikator (in diesem Fall muss der Alias-Name mit "@" beginnen)
Manager::getId(const char *alias, DpIdentifier &dpId)
Name --> Alias:
//liefert den Alias-Namen mit der Hilfe vom DP-Name
Manager::getDpIdentificationPtr()->getDpAlias(const char *dp, CharString &alias)
DpIdentifier --> Alias:
//liefert den Alias-Namen mit der Hilfe des DP-Identifikators
Manager::getDpIdentificationPtr()->getDpAlias(const DpIdentifier &dp, CharString &alias)
Error Handling
Es gibt die allgemeine Error-Handler-Klasse in WinCC OA, die von allen Managern verwendet wird. Abhängig von den -log Flags die beim Manager Start angegeben werden, werden die Fehlermeldungen in die PVSS_II.log-Datei oder in stderr geschrieben.
Die Fehler können auch in eine Datenbank geschrieben werden. Mit ExternErrHdl-Plug-in kann eine Erweiterung, die in die Datenbank schreibt, implementiert werden.
Wenn der ErrHandler eine shared library/dll mit dem Namen "ExternErrHdl" mit den Erweiterungen ".so", ".shlib", ".dll" oder "libExternErrHdl" (.dll auf Windows und .shlib auf nicht Windows-Plattformen) im bin-Verzeichnis findet, so lädt er diese beim Starten.
Daraufhin wird "C" {ExternErrHdl *createExternErrHdl(); } aufgerufen, um eine Instanz der ExternErrHdl-Subklasse zu erstellen und um deren handleError (const ErrClass &errorClass) Methode aufzurufen, bevor er in die mit der Option -log definierten Ziele (log-Datei oder stderr) schreibt.
Wenn Sie also z.B. die Fehler in eine Datenbank (zusätzlich zu der PVSS_II-log-Datei) schreiben möchten, müssen Sie eine Klasse von ExternErrHdl ableiten, als shared-libb/dll kompilieren und in ein bin-Verzeichnis als ExternErrHdl shared lib ablegen.
Das folgende Beispiel zeigt, wie Sie eine Klasse von ExternErrHdl ableiten
/*Beispiel für einen Error-Handler der als shared-lib/dll vom WinCC OA standard Error-Handler geladen wird */
/* Auf LINUX schreibt diese Klasse die Fehler in die syslog, auf Windows werden die auf stderr ausgegeben*/
#ifdef OS_LINUX
#include <syslog.h>
#endif
#include <ExternErrHdl.hxx>
#include <Resources.hxx>
CharString name"
class MyExternErrHdl : public ExternErrHdl
{
public:
MyExternErrHdl()
{
#ifdef OS_LINUX
name = Resources::getProgName() + "(" + CharString(Resources::getManNum()) + ")";
openlog((const char*)name, 0, LOG_USER);
#else
cerr << "Construct ExternErrHdl" << endl;
#endif
}
virtual ~MyExternErrHdl()
{
#ifdef OS_LINUX
closelog();
#else
cerr << "Destruct ExternErrHdl" << endl;
#endif
}
virtual void handleError(const ErrClass &errorClass)
{
#ifdef OS_LINUX
int level = 0;
switch ( errorClass.getPriority() )
{
case ErrClass::PRIO_FATAL: level = LOG_CRIT; break;
case ErrClass::PRIO_SEVERE: level = LOG_ERR; break;
case ErrClass::PRIO_WARNING: level = LOG_WARNING; break;
case ErrClass::PRIO_INFO: level = LOG_INFO; break;
}
syslog(LOG_USER + level, "%s", (const char*)(errorClass.getErrorText()));
#else
cerr << "ExternErrHdl: ";
errorClass.outStream(cerr);
#endif
}
};
//Diese Funktion erstellt das ExternErrHdl-Objekt
extern "C"
{
__declspec(dllexport) ExternErrHdl *createExternErrHdl()
{
return new MyExternErrHdl();
}
}