API Manager Classes
WinCC OA provides a class "Manager" that already contains all basic functions required for a manager. For each manager it is necessary to derive another class from this class in which the specific functions of the new manager are implemented. The derived class contains a number of virtual functions that the new manager can and, in some cases, must implement.
Notes
Note on DLL search path
The program looks for DLLs in the following directories in this order:
-
the directory in which the executable is located
-
Windows system directories
-
all directories in the PATH environment variable
For an example see the DemoManager.
Initialization, managerState, dispatch()
When deriving your own manager class, ensure that the constructor initializes the base class properly, otherwise no connection can be made.
The managerState must be observed in all cases: for example, a connection to the Event Manager should only be made when managerState is set to STATE_ADJUST. Further processing can only take place when it is set to STATE_RUNNING. These states are set internally and should always only be read.
Messages are only received and sent when dispatch() is called. (However, messages are always sent when the internal message puffer is full (current size: 4096 bytes)). If dispatch() is not called regularly, the entire communication to the manager is locked and cannot, for example, receive any hotlink messages).
Use of alias names in the API manager
If you want to use alias names of DP elements in an API manager, you can get the DP identifiers or the names of the DP elements for the alias names and vice versa using the following functions:
Alias --> Name:
//gets the DP name with the aid of the DPIdentifier
Manager::getDpIdentificationPtr()->getName(const char *alias, char *&name)
Alias --> DpIdentifier:
//gets the DPIdentifier, (in this case the alias names have to begin with "@")
Manager::getId(const char *alias, DpIdentifier &dpId)
Name --> Alias:
//gets the alias name with the aid of the DP identifier
Manager::getDpIdentificationPtr()->getDpAlias(const char *dp, CharString &alias)
DpIdentifier --> Alias:
//gets the alias name with the aid of the DpIdentifier
Manager::getDpIdentificationPtr()->getDpAlias(const DpIdentifier &dp, CharString &alias)
Error Handling
There is a general error handler class in WinCC OA. This class represents an error handler used by each manager. Depending on the -log flags given on manager startup, the error messages are either written into the PVSS_II.log file and/or to stderr. The errors can also be written into a database. With ExternErrHdl-Plug-in you can implement an extension that writes into a database.
If the ErrHdl finds a shared library/dll with the name "ExternErrHdl" with one of the extensions ".so", ".shlib", ".dll" or "libExternErrHdl" (.dll only on Windows, .so or .shlib only on non-Windows platforms) in the bin directory of the project it will load this on startup, call extern "C" { ExternErrHdl *createExternErrHdl(); } to create an ExternErrHdl subclass instance, and call its handleError(const ErrClass &errorClass) method before it writes to the targets (log file or stderr) specified by the -log option.
If you would like, for example, to write the errors into a database (in addition to the PVSS_II log file) you can use the ExternErrHdl. You have to derive a class from the ExternErrHdl, compile it as shared libb/ and save it in the bin directory as ExternErrHdl shared lib.
The following example shows how to derive a class from the ExternErrHdl.
/* Example of an external Error Handler loaded as shared-lib/dll by the standard error handler /*
/* On LINUX this class writes the errors to the syslog, on Windows it prints the errors to stderr/*
#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
}
};
//This function creates the ExternErrHdl object
extern "C"
{
__declspec(dllexport) ExternErrHdl *createExternErrHdl()
{
return new MyExternErrHdl();
}
}