|
1.
|
Overview of cdev Services
|
|
What is a cdev
Service
|
The cdev library defines a command set that can be used to provide a homogenous
interface to differing control systems. In order to incorporate a control system into the
cdev environment, the developer must create linking code that allows the cdev system
to communicate with the system. This linking code is called a cdev service. At a
minimum, the cdev service developer must develop two interface classes and a simple
constructor function in order to create a new service. These classes and functions will
be described at length in the sections that follow.
|
|
Service Classes
|
Each service must define a service class that provides the mechanisms for
communicating with the underlying control system. This class is inherited from the
cdevService class, from which it gains most of its functionality. The main effort for the
developer in creating this class is in the flush, poll and pend methods. These methods
are functionally identical to those defined in the cdevSystem object, however, the
developer must provide concrete mechanisms for communicating with the intended
control system, as well as managing and reporting errors that might occur during
normal operation.
|
|
Request Object
Classes
|
The service developer must also create a request object class that provides the
mechanisms for a cdevDevice object to communicate with the developer's service
class. This class is inherited from the cdevRequestObject class, from which it gains
most of its functionality. The primary effort for the developer in creating this class is in
the send, sendNoBlock and sendCallback functions. The service creator must also
develop his strategy for efficiently communicating with the underlying system. The
source code in the following chapters will illustrate a queueing scheme that provides a
very simple and efficient linkage between the service and the request object. The
request object is also responsible for detecting and reporting errors that occur within
its domain.
|
|
Loader Functions
|
The loader function is an extern "C" function that is called by the cdevSystem object to
dynamically construct a copy of the service class.
|
|
What the
Developer Must
Understand
|
In order to create cdev services, the developer must have an extensive understanding
of the complete cdev system. A potential service developer should first develop
applications using existing cdev services in order to understand the expected behavior
of a service. The developer should then familiarize himself completely with all of the
classes within the cdev library, paying special attention to the cdevService class and
the cdevRequestObject class.
The following chapters describe the structure and syntax of the most important of
these classes and an overview of how certain messages are expected to behave. This
manual finishes with the complete annotated source code for a demonstration service
that operates on a virtual control system.
|
|
2.
|
Developing cdev Services
|
|
Steps in
Developing a cdev
Service
|
|
1.
|
Install and build the cdev distribution. Obtain a copy of the most recent cdev
distribution and install it on your system.
|
|
2.
|
Define the devices in your control system. Define the names, attributes and
messages associated with each device in your control system. This information
will be critical in the construction of the Device Definition Language file that cdev
will use to determine which service will process messages for a device.
|
|
3.
|
Design and document specific device/message behavior. Determine the
specific inputs and outputs required for each device to process a message.
Design and document how the service will route messages to the underlying
control system. Ensure that the disposition of standard messages within your
service is consistent with the behavior of standard cdev services.
|
|
4.
|
Develop your cdevService object. This object is a sub-class of the cdevService
class and will be responsible for responding to flush, poll, and pend requests from
the cdevSystem object. The service object should be able to perform all interface
tasks necessary to link the service specific cdevRequestObjects to the underlying
control system.
|
|
5.
|
Develop your cdevRequestObject object. This object is a sub-class of the
cdevRequestObject class and will be responsible for responding to send,
sendNoBlock and sendCallback requests from the cdev application.
|
|
6.
|
Develop your cdevCollectionRequest object (optional). If your service will
provide specialized support for collections of devices, it wil be necessary to
develop a cdevCollectionRequest object that processes these requests.
|
|
7.
|
Create a service loader function. This function is described earlier in this
document and is used by the cdevSystem object to an instantiate a new service
object for this service.
|
|
8.
|
Compile and link the shared object. Compile a position-independent shared
object file that cdev can load on request. The service's shared object file should
contain all of the object code necessary to directly load and utilize the service.
This file should be copied to the directory where the other cdev services are
stored.
|
|
|
3.
|
The cdevService Class
|
|
Overview of the
cdevService Class
|
The cdevService C++ class is an abstract base class for all cdev services. This class
defines the mechanisms that cdev will utilize to communicate with your underlying
control system. It is the responsibility of the service developer to 'flesh out' the virtual
functions that are defined within this class and to develop the code necessary to
communicate with the underlying control system.
The primary methods that developers must concern themselves with are flush, poll
pend, and getRequestObject. These methods represent the majority of the work that
must be performed in developing a cdev service.
|
|
The flush Method
|
The flush method is responsible for submitting any unsent messages to the device.
This may entail submission of a message using a network protocol or simply calling a
statically linked C function. The cdevSystem object will call this method prior to each
pend or poll operation, or whenever the flush method of the system object is called
directly by the user.
|
|
The poll Method
|
The poll method is responsible for directly polling each of the physical devices that are
managed by the service to detect if they require attention (typically by checking a
single socket). This method is typically utilized to allow the physical device an
opportunity to return a response to a previously sent message. The cdevSystem
object will call this method whenever the application calls the poll method of the
system object. Most services can route this call directly to their associated pend
method.
|
|
The pend Method
|
The pend method allows the service to wait for a period of time for one of its
underlying devices to require attention. After waiting for a specified period of time, this
method will return CDEV_SUCCESS if it successfully serviced any of its underlying
devices, or CDEV_TIMEOUT if no device became active during that period. This
method is typically called by the cdevSystem object in response to a change in state
of one or more of the service's file descriptors.
|
|
The
getRequestObject
Method
|
The getRequestObject method is used by the cdevSystem object to obtain a new
instance of one of the service's request objects in response to a request made by the
application. The service may internally define many request object types for use by
applications, therefore, it is the responsibility of this function to return the correct
request object for the specified device / message combination. Typically a service will
only define one type of request object and will use it for all requests.
|
|
Public Member
Functions of the
cdevService Class
Public Functions
of the
cdevService Class
|
|
flush
|
int flush (void);
Flushes any pending outbound requests to the appropriate
servers. This is a pure virtual function that must be provided by
the service developer.
|
|
poll
|
int poll (void);
Directly polls each of the cdevService's underlying file
descriptors for activity, and delivers any asynchronous
callbacks that are ready. This is a pure virtual function that must
be provided by the service developer.
|
|
pend
|
int pend (int fd);
Waits for a default period of time for the specified file descriptor
to have an I/O event. If the fd parameter is not provided, the
cdevService object will wait for an I/O event on any of its
contained file descriptors. When an event occurs on one of the
file descriptors, the cdevService object will call the appropriate
function to process the event and dispatch any asynchronous
callbacks that are ready. This is a pure virtual function that must
be provided by the service developer.
|
|
pend
|
int pend (double seconds, int fd);
Processes all I/O events that occur on the file descriptor during
the specified period of time. If the fd parameter is not provided,
the cdevService object will wait for I/O events on all of its
contained file descriptors. When an event occurs on one of the
file descriptors, the cdevService object will call the appropriate
functions to process the event and dispatch any asynchronous
callbacks that are ready. This is a pure virtual function that must
be provided by the service developer.
|
|
getRequestObject
|
int getRequestObject ( char *dev, char *msg,
cdevRequestObject* &req);
Obtains a pointer to a cdevRequestObject that is specific to this
service and the specified device/message combination. This
method should only be called by the cdevSystem object. This is
a pure virtual function that must be provided by the service
developer.
|
|
getNameServer
|
int getNameServer (cdevDevice* &server);
Obtains a cdevDevice object identifying the name server for
this service. A service is not required to provide its own name
server and may simply set the server parameter to NULL. This
is a pure virtual function an must be provided by the service
developer.
|
|
getCollectionRequest
|
int getCollectionRequest ( char ** devices,
int nDevices, char * msg,
cdevCollectionRequest * &req);
This method allows the caller to obtain a
cdevCollectionRequest object that will contain only devices that
are associated with the service. A default mechanism is
provided to support this functionality, however, the developer
may create a special request object to optimize these
operations.
|
|
getFd
|
int getFd (int* &fd, int &numFd);
Retrieves a list of file descriptors that are contained within the
cdevService object. The fd pointer will be given the pointer to
the internal array of file descriptors, and the numFD parameter
will be set to the number of file descriptors in the list. A service
that does not use file descriptors should set the fd and numFD
parameters to NULL and 0, respectively. This is a pure virtual
function that must be provided by the service developer.
|
|
registerFd
|
int registerFd (int fd, int opened);
The service developer may implement this method to allow
external file descriptors to be added to the list of file descriptors
in the service. The fd parameter should contain the file
descriptor, and the opened parameter should contain 1 to add it
to the list or 0 to remove it from the list.
|
|
autoErrorOn
|
int autoErrorOn (void);
Informs the cdevService object that it should use its internal
default error handler to process any error messages that are
generated by objects within its control. This is the default
operating condition for the cdevService object.
|
|
autoErrorOff
|
int autoErrorOff (void);
Informs the cdevService object that it should use its internal
default error handler to process any error messages that are
generated by objects within its control. This is the default
operating condition for the cdevService object.
|
|
reportError
|
int reportError ( int severity, char *name,
cdevRequestObject *obj,
char *formatString,...);
Emits an error message. The severity field indicates the
severity of the error, the name string identifies the object that
generated the error, the obj parameter is the
cdevRequestObject that was in use when the error occurred,
and the formatString and additional parameters (...) should be
formatted in the same manner as the parameters used by
printf.
The integer used by severity should have one of the following
values indicating the severity of the error that has occurred.
|
CDEV_SEVERITY_INFO:
|
No error.
|
|
CDEV_SEVERITY_WARN:
|
An error occurred that should
not impact continued
processing.
|
|
CDEV_SEVERITY_ERROR:
|
An error occurred and should
be corrected before
continuing.
|
|
CDEV_SEVERITY_SEVERE:
|
A severe or fatal error has
occurred and cdev cannot
continue normal execution.
|
|
|
setErrorHandler
|
void setErrorHandler (cdevErrorHandler handler);
Used to install a user specified error handler. This error handler
will be called when an error occurs if the autoErrorOff method
has been used to disable the default error handler. The user
provided error handler should have the following prototype:
void handler (int severity, char *text, cdevRequestObject *obj);
The severity parameter will contain one of the integers
specified in the reportError documentation, the text parameter
will contain the text of the error, and the obj parameter will
contain the cdevRequestObject that was in use when the error
occurred.
|
|
setThreshold
|
void setThreshold (int errorThreshold);
Used to specify the level of severity at which errors should be
submitted to the error handler. The value of errorThreshold
should be one of the severity levels specified in the reportError
method.
|
|
name
|
char *name (void) const;
Retrieves the name of the service. This method is used
extensively to determine the service that underlies a specific
cdevRequestObject object. If not over-ridden by the service
developer, this method will return the string "cdevService".
|
|
|
4.
|
The cdevRequestObject Class
|
|
Overview of the
cdevRequest
Object Class
|
The cdevRequestObject C++ class is the application's interface to the underlying
service. Each service must provide a service specific request object that applications
may use to send messages to the service.
The message associated with a cdevRequestObject may be sent to a device using
one of the three send member functions, these are: send, sendNoBlock, and
sendCallback. The syntax and functionality of these methods is described in the
section below. The majority of work in the development of a service specific request
object is in the development of these three methods.
|
|
Public Member
Functions of the
cdevRequest
Object Class
|
|
attachRef
|
static cdevRequestObject& attachRef (char *device, char *
msg);
Obtains a reference to a cdevRequestObject object by
specifying the name of the device and the message string. By
default, the new object will be managed by the default
cdevSystem.
|
|
attachRef
|
static cdevRequestObject& attachRef (cdevDevice &dev, char *
msg);
Obtains a reference to a cdevRequestObject object by
providing a reference to the associated cdevDevice object and
the message string. By default, the new object will be managed
by the default cdevSystem.
|
|
attachPtr
|
static cdevRequestObject* attachPtr (char *device, char * msg);
Obtains a pointer to a cdevRequestObject by specifying the
name of the device and the message string. By default, the new
object will be managed by the default cdevSystem.
|
|
attachPtr
|
static cdevRequestObject* attachPtr (cdevDevice &dev, char *
msg);
Obtains a pointer to a cdevRequestObject by providing a
reference to the associated cdevDevice object and the
message string. By default, the new object will be managed by
the default cdevSystem.
|
|
detach
|
static void detach (cdevRequestObject& dev);
Removes a referenced cdevRequestObject object from its
associated cdevSystem object. Ordinary applications should
never use this command.
|
|
detach
|
static void detach (cdevRequestObject* dev);
Detaches the cdevRequestObject object specified by dev from
its associated cdevSystem object. Ordinary applications should
never use this command.
|
|
message
|
char *message (void) const;
Retrieves the message string that is associated with this
cdevRequestObject.
|
|
device
|
cdevDevice &device (void) const;
Retrieves a reference to the cdevDevice object that is
associated with this cdevRequestObject.
|
|
system
|
cdevSystem& system (void) const;
Retrieves a reference to the underlying cdevSystem object that
manages this cdevRequestObject.
|
|
service
|
cdevService& service (void) const;
Retrieves a reference to the underlying cdevService object that
this cdevRequestObject is attached to.
|
|
getState
|
int getState (void);
Obtains the state of the underlying device. This function returns
one of the following values as defined in cdevErrCode.h.
|
CDEV_STATE_CONNECTED:
|
Object is connected.
|
|
CDEV_STATE_NOTCONNECTED:
|
Object is not connected.
|
|
CDEV_STATE_INVALID:
|
Object is invalid.
|
The service developer is responsible for implementing this
function correctly in the service related cdevRequestObject.
|
|
getAccess
|
int getAccess (void);
Obtains access control information about the underlying
device. This function returns one of the following values as
defined in cdevErrCode.h.
|
CDEV_ACCESS_NONE:
|
No access to attribute.
|
|
CDEV_ACCESS_READONLY:
|
Read-only access.
|
|
CDEV_ACCESS_WRITE:
|
Read-write access.
|
The service developer is responsible for implementing this
function correctly in the service related cdevRequestObject.
|
|
setContext
|
int setContext (cdevData& cxt);
Used to insert a cdevData object containing tagged values that
control optional behavior of the underlying device. The context
is often used to specify which properties (value, status,
severity) a device returns in response to a "get" message. The
service developer may override the default behavior of this
method to better accommodate the requirements of the
service.
|
|
getContext
|
cdevData & getContext (void);
Retrieves a reference to the cdevData object that contains the
context for a specific cdevRequestObject. The service
developer may override the default behavior of this method to
better accommodate the requirements of the service.
|
|
getPrivate
|
void * getPrivate (void);
Retrieves a pointer to a data object that was placed in this
object using the setPrivate function.
|
|
setPrivate
|
void setPrivate (void * data);
Associates a user specified data object with this
cdevRequestObject. The pointer can be retrieved later using
the getPrivate method.
|
|
send
|
int send (cdevData &out, cdevData& result);
int send (cdevData *out, cdevData& result);
int send (cdevData &out, cdevData* result);
int send (cdevData *out, cdevData* result);
The send function is the standard method for synchronously
communicating with a device. The out cdevData object
contains any property values that the device will need to
perform the task. The result cdevData object will contain the
output properties that resulted from the call. The service
developer is responsible for implementing this method in the
service specified cdevRequestObject. This function will return
one of the error code defined in cdevErrCode.h.
|
Figure 1:
Return codes generated by the send method.
|
|
CDEV_WARNING: The failure was non-critical.
CDEV_SUCCESS: The message was processed successfully.
CDEV_ERROR: Failed to process message.
CDEV_INVALIDOBJ: Invalid cdev request object used.
CDEV_INVALIDARG: Invalid argument passed to cdev call.
CDEV_INVALIDSVC: Wrong service during dynamic loading.
CDEV_INVALIDOP: The operation is not supported.
CDEV_NOTCONNECTED: Not connected to low level network
service.
CDEV_IOFAILED: Low level network service IO failed.
CDEV_CONFLICT: Conflicts of data types or tags.
CDEV_NOTFOUND: Cannot find specified data in cdevData.
CDEV_TIMEOUT: Time out.
CDEV_CONVERT: cdevData conversion error.
CDEV_OUTOFRANGE: Value out of range for device attribute.
CDEV_NOACCESS: Insufficient access to perform request.
CDEV_ACCESSCHANGED: Change in access permission of device.
CDEV_DISCONNECTED: The service has lost contact with the
device.
CDEV_RECONNECTED: The service has regained contact with
the device.
|
|
|
sendNoBlock
|
int sendNoBlock (cdevData &out, cdevData &result);
int sendNoBlock (cdevData *out, cdevData &result);
int sendNoBlock (cdevData &out, cdevData *result);
int sendNoBlock (cdevData *out, cdevData *result);
The sendNoBlock method uses the same parameters and
syntax as the send method. However, rather than waiting for
the underlying service to respond to the request, this function
will return immediately.The caller must use a cdevGroup object
in order to detect when the transaction has been completed.
The service developer is responsible for implementing this
method in the service specified cdevRequestObject.
|
|
sendCallback
|
int sendCallback (cdevData &out, cdevCallback &callback);
int sendCallback (cdevData *out, cdevCallback &callback);
The sendCallback function is the standard method for
asynchronously communicating with a device. Rather than
providing a result cdevData object, this method requires the
user to provide the address of a cdevCallback object. This
object contains a user supplied pointer and the address of a
function to call when the message has been successfully
processed. The service developer is responsible for
implementing this method in the service specified
cdevRequestObject.
|
|
|
5.
|
The cdevCollectionRequest Class
|
|
Overview of the
cdevCollection
Request Class
|
The cdevCollectionRequest class is an abstract base class from which other
cdevCollectionRequest objects are derived. It provides a protected constructor and
destructor that are used to initialize its internals, however, the primary mechanism that
is used to obtain a cdevCollectionRequest object is the attachPtr method.
Because the cdevCollectionRequest is inherited from the cdevRequestObject, all of
the methods of that class must be fulfilled in addition to those specific to the
cdevCollectionRequest class.
|
|
Public Member
Functions of the
cdevCollection
Request Class
|
|
constructor
|
cdevCollectionRequest( char **devices, int nDevices,
char * msg, cdevSystem & system);
This is the constructor for the cdevCollectionRequest class. It
has the following properties.
|
This method is protected to prevent the direct instantiation
of new cdevCollectionRequests. New instances of the
cdevCollectionRequest objects are created by using the
attachPtr or attachRef method of the cdevRequestObject
class which will call the local attachPtr method to create a
new object if necessary.
|
|
The constructor is called by the cdevCollection object and
is provided with a list and count of devices that will be
included in the collection and the message that will be sent
to them.
|
|
The cdevSystem reference that is provided is the
cdevSystem instance that will be used to poll, pend and
flush the cdevCollectionRequest object.
|
|
|
destructor
|
virtual ~cdevCollectionRequest (void);
This is the destructor for a cdevCollectionRequest object. It has
the following properties.
|
This method is protected to prevent the
cdevCollectionRequest object from being destroyed by the
application. This method should only be called by the
cdevSystem object when the application is terminating.
|
|
Because the cdevCollectionRequest object will normally be
referred to as a cdevRequestObject object, this destructor
is virtual to ensure that the 'most senior' destructor is
called first.
|
|
|
attachPtr
|
cdevCollectionRequest * attachPtr
( cdevCollection &col, char *msg, cdevSystem &sys);
This method is used by the cdevCollection object to obtain a
new cdevCollectionRequest object.
|
This method will obtain a copy of the device names from
the cdevCollection object and will poll the cdevDirectory
object to determine which service each of them is
associated with.
|
|
If the devices are all from a single service, this method will
return a service specific collection request object.
|
|
If the devices are from a variety of services, this method will
return a cdevGrpCollectionRequest that contains the
service specific collection request objects.
|
|
Device/message combinations that are not associated with
a service will be ignored.
|
|
If none of the device/message combinations can be
associated with a service, then an error message will be
generated and NULL will be returned.
|
|
|
className
|
char * className (void);
This method returns the name of the class;
"cdevCollectionRequest". If the developer inherits a service
specific cdevCollectionRequest, then this method should not be
altered or overridden.
|
|
resultCodeTag
|
int resultCodetag (void);
This method returns the integer tag that should be used to
insert the result code that was geneterated when the message
was sent to the actual device.
|
|
|
6.
|
The Service Loader Function
|
|
Overview
|
The service loader function is used to create an initial instance of the service after the
its associated shared object file has been dynamically loaded.
|
|
Naming
Convention
|
The naming convention for this class is very specific. The following syntax is required:
Figure 2:
Naming convention and syntax for the cdevService loader function
|
|
cdevService *newXxxxxService (char * name, cdevSystem * system);
|
|
In the function name above the Xxxxx should be replaced by the name of the service
with the first character capitalized. A service named demo would have a loader
function named newDemoService. The loader function is only required to allocate a
new service class for the service and return a pointer to it. The following example
illustrates how the loader function for the demo service would be written.
Figure 3:
Example cdevService loader function
|
|
#include <cdevService.h>
// ****************************************************************
// * Include file with definition of the service class
// ****************************************************************
#include "demoService.h"
// ****************************************************************
// * Loader function for the demoService class
// ****************************************************************
cdevService *newDemoService (char * name, cdevSystem * system)
{
return new demoService(name, *system);
}
|
|
|
|
7.
|
The cdevTranObj Class
|
|
Overview of the
cdevTranObj Class
|
The cdevTranObj (cdev transaction object) C++ class is a container class that is used
to maintain information that is required for individual operations within a service. This
class stores a copy of the cdevRequestObject that was used to submit a request, the
cdevSystem object in which the request object was created, the cdevCallback object
provided by the user, and the cdevData object that the returned data should be placed
in. Because this object is intended for usage only by cdev internals, all of its data
elements are public.
The cdevTranObj is used to submit a request from the cdevRequestObject to the
cdevService. It is also used to place a transaction into a group of requests using the
cdevGroup object. The service notifies the cdevSystem object and the cdevGroup
objects that this transaction has been processed by calling its removeFromGrps
method. This will effectively remove the cdevTranObj from all groups that it is
associated with.
|
|
Public Data
Properties of the
cdevTranObj Class
|
|
system_
|
cdevSystem *system_;
This is a pointer to the cdevSystem that contains this
transaction object. The transaction will be processed whenever
the poll or pend methods of this cdevSystem object are
executed.
|
|
reqObj_
|
cdevRequestObject *reqObj_;
This is a pointer to the cdevRequestObject that was called to
submit this transaction. This cdevRequestObject will be
submitted to the user specified callback function when the
transaction has been completed.
|
|
resultData_
|
cdevData *resultData_;
This is the cdevData object that will be populated with the
results of the transaction. This object will also be submitted to
the user specified callback function when the transaction has
been completed.
|
|
userCallback_
|
cdevCallback *userCallback_;
This class contains a pointer to the caller specified callback
function as well as any user argument. The callback function
will be executed when the transaction has been completed.
Note that it is the responsibility of the service to execute this
callback function when it has finished processing the
transaction.
|
|
|
Public Member
Functions of the
cdevTranObj Class
|
|
status
|
int status (void);
Returns the status of the cdevTranObj object. The value
returned will be 1 if this object is a member of any cdevGroup
object, or -1 if this object is not a member of any cdevGroup
object.
|
|
removeFromGrps
|
int removeFromGrps (void);
Removes this transaction object from any cdevGroup object
that it may be in.
|
|
enableDeleteCbk
|
void enableDeleteCbk (void);
Sets the internal flag telling the transaction object to delete its
internal callback object while executing its destructor. This is
the default behavior for the cdevTranObj.
|
|
disableDeleteCbk
|
void disableDeleteCbk (void);
Sets the internal flag telling the transaction object not to delete
its internal callback object while executing its destructor. This
mode should be used when the user specified callback object
is shared by numerous transaction objects.
|
|
|
8.
|
Default Service Behavior for Standard Messages
|
|
Overview
|
The cdev library is designed to provide a standard calling interface to dissimilar
devices within a control system. This interface is accommodated through the use of
the cdevDevice methods send, sendNoBlock and sendCallback. However, because
each service can define the names and behaviors of the messages that it supports,
the user must be increasingly aware of which service may process its messages.
In order to reduce the required knowledge of the user, and to improve the consistency
of all services, all cdev services should provide well-defined support for a minimum list
of verbs.
The following verbs should be implemented to provide a standard behavior in all cdev
services: get, set, monitorOn, and monitorOff.
|
|
"get" Message
|
The "get" verb can be joined with any attribute of a device to form a "get" message.
This message is then sent to the device in order to obtain the value of specified
properties of the attribute. The following steps should be executed in order to utilize a
"get" message.
|
1.
|
Obtain a pointer to the cdevDevice object for the device that you wish to address.
|
|
2.
|
Create a message string by concatenating the attribute that you wish to address
to the "get" verb. For instance, to get the VAL attribute of a device, the message
strings should be: "get VAL".
|
|
3.
|
Optionally, use the cdevDevice object created in step 1 and the message string
created in step 2 to obtain a pointer to a cdevRequestObject object.
|
|
4.
|
Set the context of the cdevDevice or cdevRequestObject to indicate which
properties you wish to obtain. A non-zero value in any property indicates that its
value should be returned. If no context has been specified, the service should
return the value property by default. A complete description of the context data
object is provided in the cdevDevice documentation.
|
|
5.
|
Use the send, sendNoBlock, or sendCallback message to submit the message
to the device.
|
|
6.
|
Evaluate the return value from the send command to determine if the operation
completed successful. Any value other than CDEV_SUCCESS indicates that an
error occurred in handling the message.
|
|
7.
|
If the call was completed successfully, extract the desired properties from the
resultant cdevData object.
|
|
|
"set" Message
|
The "set" verb can be joined with any attribute of a device to form a "set" message.
This message is then sent to the device in order to set the value property of the
attribute. The following steps should be executed in order to utilize a "set" message.
|
1.
|
Obtain a pointer to the cdevDevice object for the device that you wish to address.
|
|
2.
|
Create a message string by concatenating the attribute that you wish to address
to the "set" verb. For instance, to set the bdl attribute of a device, the message
string should be: "set bdl".
|
|
3.
|
Optionally, use the cdevDevice object created in step 1 and the message string
created in step 2 to obtain a pointer to a cdevRequestObject object.
|
|
4.
|
Set the value property of the outbound cdevData object to the new value.
|
|
5.
|
Use the send, sendNoBlock, or sendCallback message to submit the message
to the device.
|
|
6.
|
Evaluate the return value from the specific send command to determine if the
message was transmitted successful. Any value other than CDEV_SUCCESS
indicates that the message was not transmitted successfully.
|
In the following example, the "get" message will be used to obtain the properties
value, status and severity from the bdl attribute of device MQB1S01, the "set"
message will then be used to copy the value property to the bdl attribute of device
MQB1S02.
Figure 4:
Default behavior of the "get" and "set" messages
|
|
#include <cdevSystem.h>
#include <cdevDevice.h>
#include <cdevRequestObject.h>
#include <cdevData.h>
// ****************************************************************
// * The printError function will be used to output any error that
// * that occurs during the processing of the "get" or "set"
// * messages.
// ****************************************************************
int printError (int errCode)
{
switch(errCode)
{
// ******* Unknown device or device/message mismatch ******
case CDEV_INVALIDOBJ:
printf("Unknown device or device/message mismatch\\n");
break;
// * Communications error between application and service *
case CDEV_NOTCONNECTED:
case CDEV_IOFAILED:
case CDEV_TIMEOUT:
printf("Communications error while sending\\n");
break;
|
|
Figure 4:
Default behavior of the "get" and "set" messages (continued)
|
|
// ******* No data or bad data passed with message ********
case CDEV_INVALIDARG:
case CDEV_OUTOFRANGE:
case CDEV_NOTFOUND:
case CDEV_CONVERT:
printf("Bad or missing value passed in message\\n");
break;
// ******************** Generic Error *********************
case CDEV_ERROR:
case default:
printf("Unable to send message\\n");
break;
}
}
void main()
{
cdevRequestObject * req1, *req2;
cdevData ctx;
cdevData output, input;
double val;
int errorCode = CDEV_SUCCESS;
// ***********************************************************
// * Obtain a pointer to the cdevRequestObject for the
// * "get bdl" message on device "MQB1S01".
// ***********************************************************
req1 = cdevRequestObject::attachPtr("MQB1S01", "get bdl");
// ***********************************************************
// * Place a non-zero value in the properties value, status,
// * severity.
// ***********************************************************
ctx.set("value", 1);
ctx.set("status", 1);
ctx.set("severity", 1);
// ***********************************************************
// * Set the context of the cdevRequestObject.
// ***********************************************************
req1->setContext(ctx);
// ***********************************************************
// * Submit the message to the device and test the return
// * value to ensure that the message was processed correctly
// ***********************************************************
if((errorCode=req1->send(NULL, &output))==CDEV_SUCCESS)
{
// ********************************************************
// * Message was transmitted and processed successfuly.
// ********************************************************
char stat[50], sev[255];
output.get("value", &val);
output.get("status", stat, 50);
|
|
Figure 4:
Default behavior of the "get" and "set" messages
|
|
output.get("severity", sev, 50);
printf("Val:%f, status:%s, severity:%s", val, stat, sev);
}
else printError(errorCode);
// ***********************************************************
// * Obtain a pointer to the cdevRequestObject for the
// * "set bdl" message on device "MQB1S02".
// ***********************************************************
req2 = cdevRequestObject::attachPtr("MQB1S02", "set bdl");
// ***********************************************************
// * Insert the new value into the input cdevData object.
// ***********************************************************
input.insert("value", value);
// ***********************************************************
// * Submit the message "set bdl" to the device and test
// * the return value to ensure that the message was
// * processed successfully. Note that, by default, the set
// * message does not generate any output.
// ***********************************************************
if((errorCode==req2->send(&input, NULL))==CDEV_SUCCESS)
{
// ********************************************************
// * Message was transmitted and processed successfuly.
// ********************************************************
printf("Message was transmitted successfully\\n");
}
else printError(errorCode);
}
|
|
|
|
"monitorOn"
Message
|
The "monitorOn" verb can be joined with any attribute of a device to form a
"monitorOn" message. This message is tells the cdevDevice that each time one of the
monitored properties changes, it should call the user specified callback function with
the updated value. This message should always be submitted using the
sendCallback |