API Messages
As long as you use the documented API functions, it is not necessary to have detailed knowledge of messages: messages are generated and sent by API functions, the user does not have to deal with them.
Many messages are not received and handled automatically by managers, for example the message that a new data point has been created. However, if a manager queries specific attributes (dpGet(), dpGetPeriod(), ...) or registers for attribute changes (dpConnect()), it must process the ingoing messages itself. If it doesn't, they are automatically rejected.
WaitForAnswer objects
In case of most functions regarding the access to data points, messages are handled with the aid of WaitForAnswer objects. Thus, a HotlinkWaitForAnswer object is for example specified for a dpConnect.
static PVSSboolean dpConnect(const DpIdentifier &dpId,
WaitForAnswer *wait, PVSSboolean del = PVSS_TRUE);
The user has to overload the HotlinkWaitForAnswer object accordingly and edit the answer in the overloaded function. See the DemoManager example for details.
All six variants of dpConnect() also exist as dpConnectNoSource(). In principle, the function does the same like a dpConnect() with the difference that a DP_MSG_CONNECT_NOSOURCE message is sent instead of a DP_MSG_CONNECT Message.
The DP_MSG_CONNECT_NOSOURCE message is used to prevent that values are sent in a circle between the driver and the Event.
If a data point is configured as I/O, the driver registers for it. If the driver sends a value change to the Event manager, then the driver would receive a value again and would send it to the hardware again.
With dpConnectNoSource() the Event manager checks whether the value was already received from the driver or from somewhere else before it send the hotlink and send it only if the driver was not the trigger.
doReceive()
The manager processes incoming messages in the doReceive() function. doReceive() is automatically called by the dispatch() function for each incoming message. There are two ways of receiving a message.
void doReceive(DpMsg *msg)
void doReceive(DpMsg &msg)
Internally, doReceive(DpMsg *msg) is called first. In the standard implementation, doReceive(DpMsg &msg) is then called and then the message is deleted.
In the first method, doReceive(DpMsg *msg), a pointer to a DpMsg is passed to doReceive. The message is dynamically allocated and the manager is responsible for releasing the memory as soon as the message is no longer required.
This method makes sense if, for example, the message is queued for subsequent processing. In this case, the pointer can be used directly and it is not necessary to copy the message beforehand.
The second method is to pass a reference to a DpMsg. As soon as the function leaves doReceive, the message is automatically deleted. Thus this method is not suitable if the message is supposed to exist longer than the doReceive function.
Usually, the messages do not have to be processed in the doReceive since a bigger part of the functions can be handled easier with WaitForAnswer objects.
Msg
The Msg class is the abstract base class of allmessages used in WinCC OA. It contains the basic message functions.
The most important function of Msg is isA(). This function returns the message type that allows filtering of those messages in doReceive() that are intended to be processed in the manager.
All other messages must be passed to the doReceive() function of the base manager class, Manager::doReceive(), so that standard handling can take effect.
The most important message types are described below in the various messages.
SysMsg
Derived from the Msg class, the SysMsg class is the abstract base class of all system-related messages. Above all used when launching WinCC OA. Because system-related messages have no significance in normal WinCC OA operation, they are not described here.
DpMsg
Derived from the Msg class, the DpMsg class is the abstract base class of all data point related messages. As soon as the program is launched, almost all communication is handled using these messages.