Removed simple example, which is now the makeBaseApp template "caServerApp".
This commit is contained in:
@@ -12,7 +12,7 @@ TOP=../../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
DIRS = simple directoryService
|
||||
DIRS = directoryService
|
||||
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
|
||||
This directory contains several server tool examples (which
|
||||
use the ca server library).
|
||||
|
||||
simple - complete CA server example (includes asynchronous
|
||||
io and arrays)
|
||||
This directory contains a server tool example (which uses the
|
||||
ca server library):
|
||||
|
||||
directoryService - fully functional pv name resolution server
|
||||
|
||||
|
||||
The simple example that was provided here has been become the
|
||||
makeBaseApp template "caServerApp"
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
TOP=../../../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_LIBS := cas ca gdd Com
|
||||
#cas_DIR = $(INSTALL_LIB)
|
||||
#ca_DIR = $(INSTALL_LIB)
|
||||
#gdd_DIR = $(INSTALL_LIB)
|
||||
#Com_DIR = $(INSTALL_LIB)
|
||||
|
||||
#
|
||||
# Added ws2_32 winmm user32 for the non-dll build
|
||||
#
|
||||
PROD_SYS_LIBS_WIN32 := ws2_32 advapi32 user32
|
||||
|
||||
SRCS += main.cc
|
||||
SRCS += exServer.cc
|
||||
SRCS += exPV.cc
|
||||
SRCS += exVectorPV.cc
|
||||
SRCS += exScalarPV.cc
|
||||
SRCS += exAsyncPV.cc
|
||||
SRCS += exChannel.cc
|
||||
|
||||
PROD_HOST = excas
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
This directory contains an example ca server. The example server
|
||||
exports 4 process variables (PVs): "fred", "freddy", "jane", and
|
||||
"janet". "fred" and "jane" are synchronous PVs. "freddy" and "janet"
|
||||
are asynchronous. Many ca servers will find that synchronous
|
||||
variables will meet there needs and therefore will not require
|
||||
the increased complexity associated with asynchronous PVs. The PVs in
|
||||
the example server are updated periodically. Some random "noise"
|
||||
is added to each PVs current value each time that it is updated.
|
||||
|
||||
The example server does not so far implement enumerated data types.
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
// Example EPICS CA server
|
||||
// (asynchrronous process variable)
|
||||
//
|
||||
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// exAsyncPV::read()
|
||||
// (virtual replacement for the default)
|
||||
//
|
||||
caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
|
||||
{
|
||||
exAsyncReadIO *pIO;
|
||||
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncReadIO ( this->cas, ctx, *this, valueIn );
|
||||
if (!pIO) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
return S_casApp_asyncCompletion;
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncPV::write()
|
||||
// (virtual replacement for the default)
|
||||
//
|
||||
caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
|
||||
{
|
||||
exAsyncWriteIO *pIO;
|
||||
|
||||
if ( this->simultAsychIOCount >= maxSimultAsyncIO ) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncWriteIO ( this->cas, ctx, *this, valueIn );
|
||||
if ( ! pIO ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
return S_casApp_asyncCompletion;
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncWriteIO::exAsyncWriteIO()
|
||||
//
|
||||
exAsyncWriteIO::exAsyncWriteIO ( exServer & cas,
|
||||
const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn ) :
|
||||
casAsyncWriteIO ( ctxIn ), pv ( pvIn ),
|
||||
timer ( cas.createTimer () ), pValue(valueIn)
|
||||
{
|
||||
this->timer.start ( *this, 0.1 );
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncWriteIO::~exAsyncWriteIO()
|
||||
//
|
||||
exAsyncWriteIO::~exAsyncWriteIO()
|
||||
{
|
||||
this->pv.removeIO();
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncWriteIO::expire()
|
||||
// (a virtual function that runs when the base timer expires)
|
||||
//
|
||||
epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
caStatus status;
|
||||
status = this->pv.update ( *this->pValue );
|
||||
this->postIOCompletion ( status );
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncReadIO::exAsyncReadIO()
|
||||
//
|
||||
exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn,
|
||||
exAsyncPV & pvIn, gdd & protoIn ) :
|
||||
casAsyncReadIO ( ctxIn ), pv ( pvIn ),
|
||||
timer ( cas.createTimer() ), pProto ( protoIn )
|
||||
{
|
||||
this->timer.start ( *this, 0.1 );
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncReadIO::~exAsyncReadIO()
|
||||
//
|
||||
exAsyncReadIO::~exAsyncReadIO()
|
||||
{
|
||||
this->pv.removeIO ();
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// exAsyncReadIO::expire()
|
||||
// (a virtual function that runs when the base timer expires)
|
||||
//
|
||||
epicsTimerNotify::expireStatus exAsyncReadIO::expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
//
|
||||
// map between the prototype in and the
|
||||
// current value
|
||||
//
|
||||
status = this->pv.exPV::readNoCtx ( this->pProto );
|
||||
|
||||
//
|
||||
// post IO completion
|
||||
//
|
||||
this->postIOCompletion ( status, *this->pProto );
|
||||
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
// Example EPICS CA server
|
||||
//
|
||||
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// exChannel::setOwner ()
|
||||
//
|
||||
void exChannel::setOwner(const char * const /* pUserName */,
|
||||
const char * const /* pHostName */)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// exChannel::readAccess ()
|
||||
//
|
||||
bool exChannel::readAccess () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// exChannel::writeAccess ()
|
||||
//
|
||||
bool exChannel::writeAccess () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,345 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
//
|
||||
// Example EPICS CA server
|
||||
//
|
||||
#include "exServer.h"
|
||||
#include "gddApps.h"
|
||||
|
||||
//
|
||||
// static data for exPV
|
||||
//
|
||||
char exPV::hasBeenInitialized = 0;
|
||||
gddAppFuncTable<exPV> exPV::ft;
|
||||
epicsTime exPV::currentTime;
|
||||
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
class exFixedStringDestructor: public gddDestructor {
|
||||
virtual void run (void *);
|
||||
};
|
||||
|
||||
//
|
||||
// exPV::exPV()
|
||||
//
|
||||
exPV::exPV ( exServer & casIn, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
cas ( casIn ),
|
||||
timer ( cas.createTimer() ),
|
||||
info ( setup ),
|
||||
interest ( false ),
|
||||
preCreate ( preCreateFlag ),
|
||||
scanOn ( scanOnIn )
|
||||
{
|
||||
//
|
||||
// no dataless PV allowed
|
||||
//
|
||||
assert (this->info.getElementCount()>=1u);
|
||||
|
||||
//
|
||||
// start a very slow background scan
|
||||
// (we will speed this up to the normal rate when
|
||||
// someone is watching the PV)
|
||||
//
|
||||
if ( this->scanOn && this->info.getScanPeriod () > 0.0 ) {
|
||||
this->timer.start ( *this, this->getScanPeriod() );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::~exPV()
|
||||
//
|
||||
exPV::~exPV()
|
||||
{
|
||||
this->timer.destroy ();
|
||||
this->info.unlinkPV();
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::destroy()
|
||||
//
|
||||
// this is replaced by a noop since we are
|
||||
// pre-creating most of the PVs during init in this simple server
|
||||
//
|
||||
void exPV::destroy()
|
||||
{
|
||||
if ( ! this->preCreate ) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::update()
|
||||
//
|
||||
caStatus exPV::update ( const gdd & valueIn )
|
||||
{
|
||||
# if DEBUG
|
||||
printf("Setting %s too:\n", this->info.getName().string());
|
||||
valueIn.dump();
|
||||
# endif
|
||||
|
||||
caStatus status = this->updateValue ( valueIn );
|
||||
if ( status || ( ! this->pValue.valid() ) ) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// post a value change event
|
||||
//
|
||||
caServer * pCAS = this->getCAS();
|
||||
if ( this->interest == true && pCAS != NULL ) {
|
||||
casEventMask select ( pCAS->valueEventMask() | pCAS->logEventMask() );
|
||||
this->postEvent ( select, *this->pValue );
|
||||
}
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exScanTimer::expire ()
|
||||
//
|
||||
epicsTimerNotify::expireStatus
|
||||
exPV::expire ( const epicsTime & /*currentTime*/ ) // X aCC 361
|
||||
{
|
||||
this->scan();
|
||||
if ( this->scanOn && this->getScanPeriod() > 0.0 ) {
|
||||
return expireStatus ( restart, this->getScanPeriod() );
|
||||
}
|
||||
else {
|
||||
return noRestart;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::bestExternalType()
|
||||
//
|
||||
aitEnum exPV::bestExternalType () const
|
||||
{
|
||||
return this->info.getType ();
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::interestRegister()
|
||||
//
|
||||
caStatus exPV::interestRegister ()
|
||||
{
|
||||
if ( ! this->getCAS() ) {
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
this->interest = true;
|
||||
if ( this->scanOn && this->getScanPeriod() > 0.0 &&
|
||||
this->getScanPeriod() < this->timer.getExpireDelay() ) {
|
||||
this->timer.start ( *this, this->getScanPeriod() );
|
||||
}
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::interestDelete()
|
||||
//
|
||||
void exPV::interestDelete()
|
||||
{
|
||||
this->interest = false;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::show()
|
||||
//
|
||||
void exPV::show ( unsigned level ) const
|
||||
{
|
||||
if (level>1u) {
|
||||
if ( this->pValue.valid () ) {
|
||||
printf ( "exPV: cond=%d\n", this->pValue->getStat () );
|
||||
printf ( "exPV: sevr=%d\n", this->pValue->getSevr () );
|
||||
printf ( "exPV: value=%f\n", static_cast < double > ( * this->pValue ) );
|
||||
}
|
||||
printf ( "exPV: interest=%d\n", this->interest );
|
||||
this->timer.show ( level - 1u );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::initFT()
|
||||
//
|
||||
void exPV::initFT ()
|
||||
{
|
||||
if ( exPV::hasBeenInitialized ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// time stamp, status, and severity are extracted from the
|
||||
// GDD associated with the "value" application type.
|
||||
//
|
||||
exPV::ft.installReadFunc ("value", &exPV::getValue);
|
||||
exPV::ft.installReadFunc ("precision", &exPV::getPrecision);
|
||||
exPV::ft.installReadFunc ("graphicHigh", &exPV::getHighLimit);
|
||||
exPV::ft.installReadFunc ("graphicLow", &exPV::getLowLimit);
|
||||
exPV::ft.installReadFunc ("controlHigh", &exPV::getHighLimit);
|
||||
exPV::ft.installReadFunc ("controlLow", &exPV::getLowLimit);
|
||||
exPV::ft.installReadFunc ("alarmHigh", &exPV::getHighLimit);
|
||||
exPV::ft.installReadFunc ("alarmLow", &exPV::getLowLimit);
|
||||
exPV::ft.installReadFunc ("alarmHighWarning", &exPV::getHighLimit);
|
||||
exPV::ft.installReadFunc ("alarmLowWarning", &exPV::getLowLimit);
|
||||
exPV::ft.installReadFunc ("units", &exPV::getUnits);
|
||||
exPV::ft.installReadFunc ("enums", &exPV::getEnums);
|
||||
|
||||
exPV::hasBeenInitialized = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::getPrecision()
|
||||
//
|
||||
caStatus exPV::getPrecision ( gdd & prec )
|
||||
{
|
||||
prec.put(4u);
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::getHighLimit()
|
||||
//
|
||||
caStatus exPV::getHighLimit ( gdd & value )
|
||||
{
|
||||
value.put(info.getHopr());
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::getLowLimit()
|
||||
//
|
||||
caStatus exPV::getLowLimit ( gdd & value )
|
||||
{
|
||||
value.put(info.getLopr());
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::getUnits()
|
||||
//
|
||||
caStatus exPV::getUnits( gdd & units )
|
||||
{
|
||||
aitString str("furlongs", aitStrRefConstImortal);
|
||||
units.put(str);
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::getEnums()
|
||||
//
|
||||
// returns the eneumerated state strings
|
||||
// for a discrete channel
|
||||
//
|
||||
// The PVs in this example are purely analog,
|
||||
// and therefore this isnt appropriate in an
|
||||
// analog context ...
|
||||
//
|
||||
caStatus exPV::getEnums ( gdd & enumsIn )
|
||||
{
|
||||
if ( this->info.getType () == aitEnumEnum16 ) {
|
||||
static const unsigned nStr = 2;
|
||||
aitFixedString *str;
|
||||
exFixedStringDestructor *pDes;
|
||||
|
||||
str = new aitFixedString[nStr];
|
||||
if (!str) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
pDes = new exFixedStringDestructor;
|
||||
if (!pDes) {
|
||||
delete [] str;
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
strncpy (str[0].fixed_string, "off",
|
||||
sizeof(str[0].fixed_string));
|
||||
strncpy (str[1].fixed_string, "on",
|
||||
sizeof(str[1].fixed_string));
|
||||
|
||||
enumsIn.setDimension(1);
|
||||
enumsIn.setBound (0,0,nStr);
|
||||
enumsIn.putRef (str, pDes);
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::getValue()
|
||||
//
|
||||
caStatus exPV::getValue ( gdd & value )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
if ( this->pValue.valid () ) {
|
||||
gddStatus gdds;
|
||||
|
||||
gdds = gddApplicationTypeTable::
|
||||
app_table.smartCopy ( &value, & (*this->pValue) );
|
||||
if (gdds) {
|
||||
status = S_cas_noConvert;
|
||||
}
|
||||
else {
|
||||
status = S_cas_success;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = S_casApp_undefined;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::write()
|
||||
// (synchronous default)
|
||||
//
|
||||
caStatus exPV::write ( const casCtx &, const gdd & valueIn )
|
||||
{
|
||||
return this->update ( valueIn );
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::read()
|
||||
// (synchronous default)
|
||||
//
|
||||
caStatus exPV::read ( const casCtx &, gdd & protoIn )
|
||||
{
|
||||
return this->ft.read ( *this, protoIn );
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::createChannel()
|
||||
//
|
||||
// for access control - optional
|
||||
//
|
||||
casChannel *exPV::createChannel ( const casCtx &ctx,
|
||||
const char * const /* pUserName */,
|
||||
const char * const /* pHostName */ )
|
||||
{
|
||||
return new exChannel ( ctx );
|
||||
}
|
||||
|
||||
//
|
||||
// exFixedStringDestructor::run()
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
void exFixedStringDestructor::run ( void * pUntyped )
|
||||
{
|
||||
aitFixedString *ps = (aitFixedString *) pUntyped;
|
||||
delete [] ps;
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "exServer.h"
|
||||
#include "gddApps.h"
|
||||
|
||||
#define myPI 3.14159265358979323846
|
||||
|
||||
//
|
||||
// SUN C++ does not have RAND_MAX yet
|
||||
//
|
||||
#if !defined(RAND_MAX)
|
||||
//
|
||||
// Apparently SUN C++ is using the SYSV version of rand
|
||||
//
|
||||
#if 0
|
||||
#define RAND_MAX INT_MAX
|
||||
#else
|
||||
#define RAND_MAX SHRT_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// exScalarPV::scan
|
||||
//
|
||||
void exScalarPV::scan()
|
||||
{
|
||||
caStatus status;
|
||||
double radians;
|
||||
smartGDDPointer pDD;
|
||||
float newValue;
|
||||
float limit;
|
||||
int gddStatus;
|
||||
|
||||
//
|
||||
// update current time (so we are not required to do
|
||||
// this every time that we write the PV which impacts
|
||||
// throughput under sunos4 because gettimeofday() is
|
||||
// slow)
|
||||
//
|
||||
this->currentTime = epicsTime::getCurrent ();
|
||||
|
||||
pDD = new gddScalar ( gddAppType_value, aitEnumFloat64 );
|
||||
if ( ! pDD.valid () ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// smart pointer class manages reference count after this point
|
||||
//
|
||||
gddStatus = pDD->unreference ();
|
||||
assert ( ! gddStatus );
|
||||
|
||||
radians = ( rand () * 2.0 * myPI ) / RAND_MAX;
|
||||
if ( this->pValue.valid () ) {
|
||||
this->pValue->getConvert(newValue);
|
||||
}
|
||||
else {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
newValue += (float) ( sin (radians) / 10.0 );
|
||||
limit = (float) this->info.getHopr ();
|
||||
newValue = tsMin ( newValue, limit );
|
||||
limit = (float) this->info.getLopr ();
|
||||
newValue = tsMax ( newValue, limit );
|
||||
*pDD = newValue;
|
||||
aitTimeStamp gddts = this->currentTime;
|
||||
pDD->setTimeStamp ( & gddts );
|
||||
status = this->update ( *pDD );
|
||||
if (status!=S_casApp_success) {
|
||||
errMessage ( status, "scalar scan update failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exScalarPV::updateValue ()
|
||||
//
|
||||
// NOTES:
|
||||
// 1) This should have a test which verifies that the
|
||||
// incoming value in all of its various data types can
|
||||
// be translated into a real number?
|
||||
// 2) We prefer to unreference the old PV value here and
|
||||
// reference the incomming value because this will
|
||||
// result in each value change events retaining an
|
||||
// independent value on the event queue.
|
||||
//
|
||||
caStatus exScalarPV::updateValue ( const gdd & valueIn )
|
||||
{
|
||||
//
|
||||
// Really no need to perform this check since the
|
||||
// server lib verifies that all requests are in range
|
||||
//
|
||||
if ( ! valueIn.isScalar() ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
if ( ! pValue.valid () ) {
|
||||
this->pValue = new gddScalar (
|
||||
gddAppType_value, aitEnumFloat64 );
|
||||
if ( ! pValue.valid () ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
}
|
||||
|
||||
this->pValue->put ( & valueIn );
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
@@ -1,416 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
//
|
||||
// fileDescriptorManager.process(delay);
|
||||
// (the name of the global symbol has leaked in here)
|
||||
//
|
||||
|
||||
//
|
||||
// Example EPICS CA server
|
||||
//
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// static list of pre-created PVs
|
||||
//
|
||||
pvInfo exServer::pvList[] = {
|
||||
pvInfo (1.0e-1, "jane", 10.0f, 0.0f, aitEnumFloat64, excasIoSync, 1u),
|
||||
pvInfo (2.0, "fred", 10.0f, -10.0f, aitEnumFloat64, excasIoSync, 1u),
|
||||
pvInfo (1.0e-1, "janet", 10.0f, 0.0f, aitEnumFloat64, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "freddy", 10.0f, -10.0f, aitEnumFloat64, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "alan", 10.0f, -10.0f, aitEnumFloat64, excasIoSync, 100u),
|
||||
pvInfo (20.0, "albert", 10.0f, -10.0f, aitEnumFloat64, excasIoSync, 1000u),
|
||||
pvInfo (-1.0, "boot", 10.0f, -10.0f, aitEnumEnum16, excasIoSync, 1u),
|
||||
pvInfo (-1.0, "booty", 10.0f, -10.0f, aitEnumEnum16, excasIoAsync, 1u),
|
||||
pvInfo (-1.0, "bill", 10.0f, -10.0f, aitEnumFloat64, excasIoSync, 1u)
|
||||
};
|
||||
|
||||
const unsigned exServer::pvListNElem = NELEMENTS (exServer::pvList);
|
||||
|
||||
//
|
||||
// static on-the-fly PVs
|
||||
//
|
||||
pvInfo exServer::billy (-1.0, "billy", 10.0f, -10.0f, aitEnumFloat64, excasIoAsync, 1u);
|
||||
pvInfo exServer::bloaty (-1.0, "bloaty", 10.0f, -10.0f, aitEnumFloat64, excasIoSync, 100000u);
|
||||
|
||||
//
|
||||
// exServer::exServer()
|
||||
//
|
||||
exServer::exServer ( const char * const pvPrefix,
|
||||
unsigned aliasCount, bool scanOnIn,
|
||||
bool asyncScan ) :
|
||||
pTimerQueue ( 0 ), simultAsychIOCount ( 0u ),
|
||||
scanOn ( scanOnIn )
|
||||
{
|
||||
unsigned i;
|
||||
exPV *pPV;
|
||||
pvInfo *pPVI;
|
||||
pvInfo *pPVAfter = &exServer::pvList[pvListNElem];
|
||||
char pvAlias[256];
|
||||
const char * const pNameFmtStr = "%.100s%.20s";
|
||||
const char * const pAliasFmtStr = "%.100s%.20s%u";
|
||||
|
||||
exPV::initFT();
|
||||
|
||||
if ( asyncScan ) {
|
||||
unsigned timerPriotity;
|
||||
epicsThreadBooleanStatus etbs = epicsThreadLowestPriorityLevelAbove (
|
||||
epicsThreadGetPrioritySelf (), & timerPriotity );
|
||||
if ( etbs != epicsThreadBooleanStatusSuccess ) {
|
||||
timerPriotity = epicsThreadGetPrioritySelf ();
|
||||
}
|
||||
this->pTimerQueue = & epicsTimerQueueActive::allocate ( false, timerPriotity );
|
||||
}
|
||||
|
||||
//
|
||||
// pre-create all of the simple PVs that this server will export
|
||||
//
|
||||
for (pPVI = exServer::pvList; pPVI < pPVAfter; pPVI++) {
|
||||
pPV = pPVI->createPV (*this, true, scanOnIn);
|
||||
if (!pPV) {
|
||||
fprintf(stderr, "Unable to create new PV \"%s\"\n",
|
||||
pPVI->getName());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Install canonical (root) name
|
||||
//
|
||||
sprintf(pvAlias, pNameFmtStr, pvPrefix, pPVI->getName());
|
||||
this->installAliasName(*pPVI, pvAlias);
|
||||
|
||||
//
|
||||
// Install numbered alias names
|
||||
//
|
||||
for (i=0u; i<aliasCount; i++) {
|
||||
sprintf(pvAlias, pAliasFmtStr, pvPrefix,
|
||||
pPVI->getName(), i);
|
||||
this->installAliasName(*pPVI, pvAlias);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Install create on-the-fly PVs
|
||||
// into the PV name hash table
|
||||
//
|
||||
sprintf ( pvAlias, pNameFmtStr, pvPrefix, billy.getName() );
|
||||
this->installAliasName ( billy, pvAlias );
|
||||
sprintf ( pvAlias, pNameFmtStr, pvPrefix, bloaty.getName() );
|
||||
this->installAliasName ( bloaty, pvAlias );
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::~exServer()
|
||||
//
|
||||
exServer::~exServer()
|
||||
{
|
||||
pvInfo *pPVI;
|
||||
pvInfo *pPVAfter =
|
||||
&exServer::pvList[NELEMENTS(exServer::pvList)];
|
||||
|
||||
//
|
||||
// delete all pre-created PVs (eliminate bounds-checker warnings)
|
||||
//
|
||||
for (pPVI = exServer::pvList; pPVI < pPVAfter; pPVI++) {
|
||||
pPVI->deletePV ();
|
||||
}
|
||||
|
||||
this->stringResTbl.traverse ( &pvEntry::destroy );
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::installAliasName()
|
||||
//
|
||||
void exServer::installAliasName(pvInfo &info, const char *pAliasName)
|
||||
{
|
||||
pvEntry *pEntry;
|
||||
|
||||
pEntry = new pvEntry(info, *this, pAliasName);
|
||||
if (pEntry) {
|
||||
int resLibStatus;
|
||||
resLibStatus = this->stringResTbl.add(*pEntry);
|
||||
if (resLibStatus==0) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
delete pEntry;
|
||||
}
|
||||
}
|
||||
fprintf ( stderr,
|
||||
"Unable to enter PV=\"%s\" Alias=\"%s\" in PV name alias hash table\n",
|
||||
info.getName(), pAliasName );
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::pvExistTest()
|
||||
//
|
||||
pvExistReturn exServer::pvExistTest // X aCC 361
|
||||
( const casCtx& ctxIn, const char * pPVName )
|
||||
{
|
||||
//
|
||||
// lifetime of id is shorter than lifetime of pName
|
||||
//
|
||||
stringId id ( pPVName, stringId::refString );
|
||||
pvEntry *pPVE;
|
||||
|
||||
//
|
||||
// Look in hash table for PV name (or PV alias name)
|
||||
//
|
||||
pPVE = this->stringResTbl.lookup ( id );
|
||||
if ( ! pPVE ) {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
|
||||
pvInfo & pvi = pPVE->getInfo();
|
||||
|
||||
//
|
||||
// Initiate async IO if this is an async PV
|
||||
//
|
||||
if ( pvi.getIOType() == excasIoSync ) {
|
||||
return pverExistsHere;
|
||||
}
|
||||
else {
|
||||
if ( this->simultAsychIOCount >= maxSimultAsyncIO ) {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
exAsyncExistIO *pIO;
|
||||
pIO = new exAsyncExistIO ( pvi, ctxIn, *this );
|
||||
if (pIO) {
|
||||
return pverAsyncCompletion;
|
||||
}
|
||||
else {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::pvAttach()
|
||||
//
|
||||
pvAttachReturn exServer::pvAttach // X aCC 361
|
||||
(const casCtx &ctx, const char *pName)
|
||||
{
|
||||
//
|
||||
// lifetime of id is shorter than lifetime of pName
|
||||
//
|
||||
stringId id(pName, stringId::refString);
|
||||
exPV *pPV;
|
||||
pvEntry *pPVE;
|
||||
|
||||
pPVE = this->stringResTbl.lookup(id);
|
||||
if (!pPVE) {
|
||||
return S_casApp_pvNotFound;
|
||||
}
|
||||
|
||||
pvInfo &pvi = pPVE->getInfo();
|
||||
|
||||
//
|
||||
// If this is a synchronous PV create the PV now
|
||||
//
|
||||
if (pvi.getIOType() == excasIoSync) {
|
||||
pPV = pvi.createPV(*this, false, this->scanOn);
|
||||
if (pPV) {
|
||||
return *pPV;
|
||||
}
|
||||
else {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Initiate async IO if this is an async PV
|
||||
//
|
||||
else {
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
exAsyncCreateIO *pIO =
|
||||
new exAsyncCreateIO(pvi, *this, ctx, this->scanOn);
|
||||
if (pIO) {
|
||||
return S_casApp_asyncCompletion;
|
||||
}
|
||||
else {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::setDebugLevel ()
|
||||
//
|
||||
void exServer::setDebugLevel ( unsigned level )
|
||||
{
|
||||
this->caServer::setDebugLevel ( level );
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::createTimer ()
|
||||
//
|
||||
class epicsTimer & exServer::createTimer ()
|
||||
{
|
||||
if ( this->pTimerQueue ) {
|
||||
return this->pTimerQueue->createTimer ();
|
||||
}
|
||||
else {
|
||||
return this->caServer::createTimer ();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// pvInfo::createPV()
|
||||
//
|
||||
exPV *pvInfo::createPV ( exServer & cas,
|
||||
bool preCreateFlag, bool scanOn )
|
||||
{
|
||||
if (this->pPV) {
|
||||
return this->pPV;
|
||||
}
|
||||
|
||||
exPV *pNewPV;
|
||||
|
||||
//
|
||||
// create an instance of the appropriate class
|
||||
// depending on the io type and the number
|
||||
// of elements
|
||||
//
|
||||
if (this->elementCount==1u) {
|
||||
switch (this->ioType){
|
||||
case excasIoSync:
|
||||
pNewPV = new exScalarPV ( cas, *this, preCreateFlag, scanOn );
|
||||
break;
|
||||
case excasIoAsync:
|
||||
pNewPV = new exAsyncPV ( cas, *this, preCreateFlag, scanOn );
|
||||
break;
|
||||
default:
|
||||
pNewPV = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( this->ioType == excasIoSync ) {
|
||||
pNewPV = new exVectorPV ( cas, *this, preCreateFlag, scanOn );
|
||||
}
|
||||
else {
|
||||
pNewPV = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// load initial value (this is not done in
|
||||
// the constructor because the base class's
|
||||
// pure virtual function would be called)
|
||||
//
|
||||
// We always perform this step even if
|
||||
// scanning is disable so that there will
|
||||
// always be an initial value
|
||||
//
|
||||
if (pNewPV) {
|
||||
this->pPV = pNewPV;
|
||||
pNewPV->scan();
|
||||
}
|
||||
|
||||
return pNewPV;
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::show()
|
||||
//
|
||||
void exServer::show (unsigned level) const
|
||||
{
|
||||
//
|
||||
// server tool specific show code goes here
|
||||
//
|
||||
this->stringResTbl.show(level);
|
||||
|
||||
//
|
||||
// print information about ca server libarary
|
||||
// internals
|
||||
//
|
||||
this->caServer::show(level);
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncExistIO::exAsyncExistIO()
|
||||
//
|
||||
exAsyncExistIO::exAsyncExistIO ( const pvInfo &pviIn, const casCtx &ctxIn,
|
||||
exServer &casIn ) :
|
||||
casAsyncPVExistIO ( ctxIn ), pvi ( pviIn ),
|
||||
timer ( casIn.createTimer () ), cas ( casIn )
|
||||
{
|
||||
this->timer.start ( *this, 0.00001 );
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncExistIO::~exAsyncExistIO()
|
||||
//
|
||||
exAsyncExistIO::~exAsyncExistIO()
|
||||
{
|
||||
this->cas.removeIO ();
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncExistIO::expire()
|
||||
// (a virtual function that runs when the base timer expires)
|
||||
//
|
||||
epicsTimerNotify::expireStatus exAsyncExistIO::expire ( const epicsTime & /*currentTime*/ )
|
||||
{
|
||||
//
|
||||
// post IO completion
|
||||
//
|
||||
this->postIOCompletion ( pvExistReturn(pverExistsHere) );
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// exAsyncCreateIO::exAsyncCreateIO()
|
||||
//
|
||||
exAsyncCreateIO::exAsyncCreateIO ( pvInfo &pviIn, exServer &casIn,
|
||||
const casCtx &ctxIn, bool scanOnIn ) :
|
||||
casAsyncPVAttachIO ( ctxIn ), pvi ( pviIn ),
|
||||
timer ( casIn.createTimer () ),
|
||||
cas ( casIn ), scanOn ( scanOnIn )
|
||||
{
|
||||
this->timer.start ( *this, 0.00001 );
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncCreateIO::~exAsyncCreateIO()
|
||||
//
|
||||
exAsyncCreateIO::~exAsyncCreateIO()
|
||||
{
|
||||
this->cas.removeIO ();
|
||||
this->timer.destroy ();
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncCreateIO::expire()
|
||||
// (a virtual function that runs when the base timer expires)
|
||||
//
|
||||
epicsTimerNotify::expireStatus exAsyncCreateIO::expire ( const epicsTime & /*currentTime*/ )
|
||||
{
|
||||
exPV *pPV;
|
||||
|
||||
pPV = this->pvi.createPV ( this->cas, false, this->scanOn );
|
||||
if ( pPV ) {
|
||||
this->postIOCompletion ( pvAttachReturn ( *pPV ) );
|
||||
}
|
||||
else {
|
||||
this->postIOCompletion ( pvAttachReturn ( S_casApp_noMemory ) );
|
||||
}
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
@@ -1,559 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
//
|
||||
// Example EPICS CA server
|
||||
//
|
||||
//
|
||||
// caServer
|
||||
// |
|
||||
// exServer
|
||||
//
|
||||
// casPV
|
||||
// |
|
||||
// exPV-----------
|
||||
// | |
|
||||
// exScalarPV exVectorPV
|
||||
// |
|
||||
// exAsyncPV
|
||||
//
|
||||
// casChannel
|
||||
// |
|
||||
// exChannel
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// ANSI C
|
||||
//
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "gddAppFuncTable.h"
|
||||
#include "smartGDDPointer.h"
|
||||
#include "epicsTimer.h"
|
||||
#include "casdef.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "resourceLib.h"
|
||||
#include "tsMinMax.h"
|
||||
|
||||
#ifndef NELEMENTS
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
#endif
|
||||
|
||||
#define maxSimultAsyncIO 1000u
|
||||
|
||||
//
|
||||
// info about all pv in this server
|
||||
//
|
||||
enum excasIoType { excasIoSync, excasIoAsync };
|
||||
|
||||
class exPV;
|
||||
class exServer;
|
||||
|
||||
//
|
||||
// pvInfo
|
||||
//
|
||||
class pvInfo {
|
||||
public:
|
||||
pvInfo ( double scanPeriodIn, const char *pNameIn,
|
||||
aitFloat32 hoprIn, aitFloat32 loprIn,
|
||||
aitEnum typeIn, excasIoType ioTypeIn,
|
||||
unsigned countIn );
|
||||
pvInfo ( const pvInfo & copyIn );
|
||||
~pvInfo ();
|
||||
double getScanPeriod () const;
|
||||
const char *getName () const;
|
||||
double getHopr () const;
|
||||
double getLopr () const;
|
||||
aitEnum getType () const;
|
||||
excasIoType getIOType () const;
|
||||
unsigned getElementCount () const;
|
||||
void unlinkPV ();
|
||||
exPV *createPV ( exServer & exCAS,
|
||||
bool preCreateFlag, bool scanOn );
|
||||
void deletePV ();
|
||||
|
||||
private:
|
||||
const double scanPeriod;
|
||||
const char * pName;
|
||||
const double hopr;
|
||||
const double lopr;
|
||||
aitEnum type;
|
||||
const excasIoType ioType;
|
||||
const unsigned elementCount;
|
||||
exPV * pPV;
|
||||
};
|
||||
|
||||
//
|
||||
// pvEntry
|
||||
//
|
||||
// o entry in the string hash table for the pvInfo
|
||||
// o Since there may be aliases then we may end up
|
||||
// with several of this class all referencing
|
||||
// the same pv info class (justification
|
||||
// for this breaking out into a seperate class
|
||||
// from pvInfo)
|
||||
//
|
||||
class pvEntry // X aCC 655
|
||||
: public stringId, public tsSLNode < pvEntry > {
|
||||
public:
|
||||
pvEntry ( pvInfo &infoIn, exServer & casIn,
|
||||
const char * pAliasName );
|
||||
~pvEntry();
|
||||
pvInfo & getInfo() const { return this->info; }
|
||||
void destroy ();
|
||||
|
||||
private:
|
||||
pvInfo & info;
|
||||
exServer & cas;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// exPV
|
||||
//
|
||||
class exPV : public casPV, public epicsTimerNotify,
|
||||
public tsSLNode < exPV > {
|
||||
public:
|
||||
exPV ( exServer & cas, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOn );
|
||||
virtual ~exPV();
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
//
|
||||
// Called by the server libary each time that it wishes to
|
||||
// subscribe for PV the server tool via postEvent() below.
|
||||
//
|
||||
caStatus interestRegister ();
|
||||
|
||||
//
|
||||
// called by the server library each time that it wishes to
|
||||
// remove its subscription for PV value change events
|
||||
// from the server tool via caServerPostEvents()
|
||||
//
|
||||
void interestDelete ();
|
||||
|
||||
aitEnum bestExternalType () const;
|
||||
|
||||
//
|
||||
// chCreate() is called each time that a PV is attached to
|
||||
// by a client. The server tool must create a casChannel object
|
||||
// (or a derived class) each time that this routine is called
|
||||
//
|
||||
// If the operation must complete asynchronously then return
|
||||
// the status code S_casApp_asyncCompletion and then
|
||||
// create the casChannel object at some time in the future
|
||||
//
|
||||
//casChannel *createChannel ();
|
||||
|
||||
//
|
||||
// This gets called when the pv gets a new value
|
||||
//
|
||||
caStatus update ( const gdd & );
|
||||
|
||||
//
|
||||
// Gets called when we add noise to the current value
|
||||
//
|
||||
virtual void scan () = 0;
|
||||
|
||||
//
|
||||
// If no one is watching scan the PV with 10.0
|
||||
// times the specified period
|
||||
//
|
||||
double getScanPeriod ();
|
||||
|
||||
caStatus read ( const casCtx &, gdd & protoIn );
|
||||
|
||||
caStatus readNoCtx ( smartGDDPointer pProtoIn );
|
||||
|
||||
caStatus write ( const casCtx &, const gdd & value );
|
||||
|
||||
void destroy ();
|
||||
|
||||
const pvInfo & getPVInfo ();
|
||||
|
||||
const char * getName() const;
|
||||
|
||||
static void initFT();
|
||||
|
||||
casChannel * createChannel ( const casCtx &ctx,
|
||||
const char * const pUserName,
|
||||
const char * const pHostName );
|
||||
|
||||
protected:
|
||||
smartGDDPointer pValue;
|
||||
exServer & cas;
|
||||
epicsTimer & timer;
|
||||
pvInfo & info;
|
||||
bool interest;
|
||||
bool preCreate;
|
||||
bool scanOn;
|
||||
static epicsTime currentTime;
|
||||
|
||||
virtual caStatus updateValue ( const gdd & ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// scan timer expire
|
||||
//
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
|
||||
//
|
||||
// Std PV Attribute fetch support
|
||||
//
|
||||
gddAppFuncTableStatus getPrecision(gdd &value);
|
||||
gddAppFuncTableStatus getHighLimit(gdd &value);
|
||||
gddAppFuncTableStatus getLowLimit(gdd &value);
|
||||
gddAppFuncTableStatus getUnits(gdd &value);
|
||||
gddAppFuncTableStatus getValue(gdd &value);
|
||||
gddAppFuncTableStatus getEnums(gdd &value);
|
||||
|
||||
//
|
||||
// static
|
||||
//
|
||||
static gddAppFuncTable<exPV> ft;
|
||||
static char hasBeenInitialized;
|
||||
};
|
||||
|
||||
//
|
||||
// exScalarPV
|
||||
//
|
||||
class exScalarPV : public exPV {
|
||||
public:
|
||||
exScalarPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( cas, setup,
|
||||
preCreateFlag, scanOnIn) {}
|
||||
void scan();
|
||||
private:
|
||||
caStatus updateValue ( const gdd & );
|
||||
};
|
||||
|
||||
//
|
||||
// exVectorPV
|
||||
//
|
||||
class exVectorPV : public exPV {
|
||||
public:
|
||||
exVectorPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exPV ( cas, setup,
|
||||
preCreateFlag, scanOnIn) {}
|
||||
void scan();
|
||||
|
||||
unsigned maxDimension() const;
|
||||
aitIndex maxBound (unsigned dimension) const;
|
||||
|
||||
private:
|
||||
caStatus updateValue ( const gdd & );
|
||||
};
|
||||
|
||||
//
|
||||
// exServer
|
||||
//
|
||||
class exServer : private caServer {
|
||||
public:
|
||||
exServer ( const char * const pvPrefix,
|
||||
unsigned aliasCount, bool scanOn,
|
||||
bool asyncScan );
|
||||
~exServer ();
|
||||
void show ( unsigned level ) const;
|
||||
void removeIO ();
|
||||
void removeAliasName ( pvEntry & entry );
|
||||
|
||||
class epicsTimer & createTimer ();
|
||||
void setDebugLevel ( unsigned level );
|
||||
|
||||
private:
|
||||
resTable < pvEntry, stringId > stringResTbl;
|
||||
epicsTimerQueueActive * pTimerQueue;
|
||||
unsigned simultAsychIOCount;
|
||||
bool scanOn;
|
||||
|
||||
void installAliasName ( pvInfo & info, const char * pAliasName );
|
||||
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
|
||||
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
|
||||
|
||||
//
|
||||
// list of pre-created PVs
|
||||
//
|
||||
static pvInfo pvList[];
|
||||
static const unsigned pvListNElem;
|
||||
|
||||
//
|
||||
// on-the-fly PVs
|
||||
//
|
||||
static pvInfo bill;
|
||||
static pvInfo billy;
|
||||
static pvInfo bloaty;
|
||||
static pvInfo boot;
|
||||
static pvInfo booty;
|
||||
};
|
||||
|
||||
//
|
||||
// exAsyncPV
|
||||
//
|
||||
class exAsyncPV : public exScalarPV {
|
||||
public:
|
||||
exAsyncPV ( exServer & cas, pvInfo &setup,
|
||||
bool preCreateFlag, bool scanOnIn );
|
||||
caStatus read ( const casCtx & ctxIn, gdd & protoIn );
|
||||
caStatus write ( const casCtx & ctxIn, const gdd & value );
|
||||
void removeIO();
|
||||
private:
|
||||
unsigned simultAsychIOCount;
|
||||
};
|
||||
|
||||
//
|
||||
// exChannel
|
||||
//
|
||||
class exChannel : public casChannel{
|
||||
public:
|
||||
exChannel ( const casCtx & ctxIn );
|
||||
void setOwner ( const char * const pUserName,
|
||||
const char * const pHostName );
|
||||
bool readAccess () const;
|
||||
bool writeAccess () const;
|
||||
private:
|
||||
};
|
||||
|
||||
//
|
||||
// exAsyncWriteIO
|
||||
//
|
||||
class exAsyncWriteIO : public casAsyncWriteIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncWriteIO ( exServer &, const casCtx & ctxIn, exAsyncPV &, const gdd & );
|
||||
~exAsyncWriteIO ();
|
||||
private:
|
||||
exAsyncPV & pv;
|
||||
epicsTimer & timer;
|
||||
smartConstGDDPointer pValue;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
//
|
||||
// exAsyncReadIO
|
||||
//
|
||||
class exAsyncReadIO : public casAsyncReadIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncReadIO ( exServer &, const casCtx &, exAsyncPV &, gdd & );
|
||||
virtual ~exAsyncReadIO ();
|
||||
private:
|
||||
exAsyncPV & pv;
|
||||
epicsTimer & timer;
|
||||
smartGDDPointer pProto;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
//
|
||||
// exAsyncExistIO
|
||||
// (PV exist async IO)
|
||||
//
|
||||
class exAsyncExistIO : public casAsyncPVExistIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncExistIO ( const pvInfo & pviIn, const casCtx & ctxIn,
|
||||
exServer & casIn );
|
||||
virtual ~exAsyncExistIO ();
|
||||
private:
|
||||
const pvInfo & pvi;
|
||||
epicsTimer & timer;
|
||||
exServer & cas;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// exAsyncCreateIO
|
||||
// (PV create async IO)
|
||||
//
|
||||
class exAsyncCreateIO : public casAsyncPVAttachIO, public epicsTimerNotify {
|
||||
public:
|
||||
exAsyncCreateIO ( pvInfo & pviIn, exServer & casIn,
|
||||
const casCtx & ctxIn, bool scanOnIn );
|
||||
virtual ~exAsyncCreateIO ();
|
||||
private:
|
||||
pvInfo & pvi;
|
||||
epicsTimer & timer;
|
||||
exServer & cas;
|
||||
bool scanOn;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
inline pvInfo::pvInfo ( double scanPeriodIn, const char *pNameIn,
|
||||
aitFloat32 hoprIn, aitFloat32 loprIn,
|
||||
aitEnum typeIn, excasIoType ioTypeIn,
|
||||
unsigned countIn ) :
|
||||
|
||||
scanPeriod ( scanPeriodIn ), pName ( pNameIn ),
|
||||
hopr ( hoprIn ), lopr ( loprIn ), type ( typeIn ),
|
||||
ioType ( ioTypeIn ), elementCount ( countIn ),
|
||||
pPV ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// for use when MSVC++ will not build a default copy constructor
|
||||
// for this class
|
||||
//
|
||||
inline pvInfo::pvInfo ( const pvInfo & copyIn ) :
|
||||
|
||||
scanPeriod ( copyIn.scanPeriod ), pName ( copyIn.pName ),
|
||||
hopr ( copyIn.hopr ), lopr ( copyIn.lopr ), type ( copyIn.type ),
|
||||
ioType ( copyIn.ioType ), elementCount ( copyIn.elementCount ),
|
||||
pPV ( copyIn.pPV )
|
||||
{
|
||||
}
|
||||
|
||||
inline pvInfo::~pvInfo ()
|
||||
{
|
||||
//
|
||||
// GDD cleanup gets rid of GDD's that are in use
|
||||
// by the PV before the file scope destructer for
|
||||
// this class runs here so this does not seem to
|
||||
// be a good idea
|
||||
//
|
||||
//if ( this->pPV != NULL ) {
|
||||
// delete this->pPV;
|
||||
//}
|
||||
}
|
||||
|
||||
inline void pvInfo::deletePV ()
|
||||
{
|
||||
if ( this->pPV != NULL ) {
|
||||
delete this->pPV;
|
||||
}
|
||||
}
|
||||
|
||||
inline double pvInfo::getScanPeriod () const
|
||||
{
|
||||
return this->scanPeriod;
|
||||
}
|
||||
|
||||
inline const char *pvInfo::getName () const
|
||||
{
|
||||
return this->pName;
|
||||
}
|
||||
|
||||
inline double pvInfo::getHopr () const
|
||||
{
|
||||
return this->hopr;
|
||||
}
|
||||
|
||||
inline double pvInfo::getLopr () const
|
||||
{
|
||||
return this->lopr;
|
||||
}
|
||||
|
||||
inline aitEnum pvInfo::getType () const
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
inline excasIoType pvInfo::getIOType () const
|
||||
{
|
||||
return this->ioType;
|
||||
}
|
||||
|
||||
inline unsigned pvInfo::getElementCount () const
|
||||
{
|
||||
return this->elementCount;
|
||||
}
|
||||
|
||||
inline void pvInfo::unlinkPV ()
|
||||
{
|
||||
this->pPV = NULL;
|
||||
}
|
||||
|
||||
inline pvEntry::pvEntry ( pvInfo & infoIn, exServer & casIn,
|
||||
const char * pAliasName ) :
|
||||
stringId ( pAliasName ), info ( infoIn ), cas ( casIn )
|
||||
{
|
||||
assert ( this->stringId::resourceName() != NULL );
|
||||
}
|
||||
|
||||
inline pvEntry::~pvEntry ()
|
||||
{
|
||||
this->cas.removeAliasName ( *this );
|
||||
}
|
||||
|
||||
inline void pvEntry::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
inline void exServer::removeAliasName ( pvEntry & entry )
|
||||
{
|
||||
pvEntry * pE;
|
||||
pE = this->stringResTbl.remove ( entry );
|
||||
assert ( pE == &entry );
|
||||
}
|
||||
|
||||
inline double exPV::getScanPeriod ()
|
||||
{
|
||||
double curPeriod = this->info.getScanPeriod ();
|
||||
if ( ! this->interest ) {
|
||||
curPeriod *= 10.0L;
|
||||
}
|
||||
return curPeriod;
|
||||
}
|
||||
|
||||
inline caStatus exPV::readNoCtx ( smartGDDPointer pProtoIn )
|
||||
{
|
||||
return this->ft.read ( *this, *pProtoIn );
|
||||
}
|
||||
|
||||
inline const pvInfo & exPV::getPVInfo ()
|
||||
{
|
||||
return this->info;
|
||||
}
|
||||
|
||||
inline const char * exPV::getName () const
|
||||
{
|
||||
return this->info.getName();
|
||||
}
|
||||
|
||||
inline void exServer::removeIO()
|
||||
{
|
||||
if ( this->simultAsychIOCount > 0u ) {
|
||||
this->simultAsychIOCount--;
|
||||
}
|
||||
else {
|
||||
fprintf ( stderr,
|
||||
"simultAsychIOCount underflow?\n" );
|
||||
}
|
||||
}
|
||||
|
||||
inline exAsyncPV::exAsyncPV ( exServer & cas, pvInfo & setup,
|
||||
bool preCreateFlag, bool scanOnIn ) :
|
||||
exScalarPV ( cas, setup, preCreateFlag, scanOnIn ),
|
||||
simultAsychIOCount ( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
inline void exAsyncPV::removeIO ()
|
||||
{
|
||||
if ( this->simultAsychIOCount > 0u ) {
|
||||
this->simultAsychIOCount--;
|
||||
}
|
||||
else {
|
||||
fprintf ( stderr, "inconsistent simultAsychIOCount?\n" );
|
||||
}
|
||||
}
|
||||
|
||||
inline exChannel::exChannel ( const casCtx & ctxIn ) :
|
||||
casChannel(ctxIn)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include "exServer.h"
|
||||
#include "gddApps.h"
|
||||
|
||||
#define myPI 3.14159265358979323846
|
||||
|
||||
//
|
||||
// SUN C++ does not have RAND_MAX yet
|
||||
//
|
||||
#if ! defined(RAND_MAX)
|
||||
//
|
||||
// Apparently SUN C++ is using the SYSV version of rand
|
||||
//
|
||||
# if 0
|
||||
# define RAND_MAX INT_MAX
|
||||
# else
|
||||
# define RAND_MAX SHRT_MAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
class exVecDestructor: public gddDestructor {
|
||||
virtual void run (void *);
|
||||
};
|
||||
|
||||
//
|
||||
// exVectorPV::maxDimension()
|
||||
//
|
||||
unsigned exVectorPV::maxDimension() const
|
||||
{
|
||||
return 1u;
|
||||
}
|
||||
|
||||
//
|
||||
// exVectorPV::maxBound()
|
||||
//
|
||||
aitIndex exVectorPV::maxBound (unsigned dimension) const // X aCC 361
|
||||
{
|
||||
if (dimension==0u) {
|
||||
return this->info.getElementCount();
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exVectorPV::scan
|
||||
//
|
||||
void exVectorPV::scan()
|
||||
{
|
||||
caStatus status;
|
||||
double radians;
|
||||
smartGDDPointer pDD;
|
||||
aitFloat32 *pF, *pFE;
|
||||
const aitFloat32 *pCF;
|
||||
float newValue;
|
||||
float limit;
|
||||
exVecDestructor *pDest;
|
||||
int gddStatus;
|
||||
|
||||
//
|
||||
// update current time (so we are not required to do
|
||||
// this every time that we write the PV which impacts
|
||||
// throughput under sunos4 because gettimeofday() is
|
||||
// slow)
|
||||
//
|
||||
this->currentTime = epicsTime::getCurrent();
|
||||
|
||||
pDD = new gddAtomic (gddAppType_value, aitEnumFloat64,
|
||||
1u, this->info.getElementCount());
|
||||
if ( ! pDD.valid () ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// smart pointer class manages reference count after this point
|
||||
//
|
||||
gddStatus = pDD->unreference();
|
||||
assert (!gddStatus);
|
||||
|
||||
//
|
||||
// allocate array buffer
|
||||
//
|
||||
pF = new aitFloat32 [this->info.getElementCount()];
|
||||
if (!pF) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDest = new exVecDestructor;
|
||||
if (!pDest) {
|
||||
delete [] pF;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// install the buffer into the DD
|
||||
// (do this before we increment pF)
|
||||
//
|
||||
pDD->putRef(pF, pDest);
|
||||
|
||||
//
|
||||
// double check for reasonable bounds on the
|
||||
// current value
|
||||
//
|
||||
pCF=NULL;
|
||||
if ( this->pValue.valid () ) {
|
||||
if (this->pValue->dimension()==1u) {
|
||||
const gddBounds *pB = this->pValue->getBounds();
|
||||
if (pB[0u].size()==this->info.getElementCount()) {
|
||||
pCF = *this->pValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pFE = &pF[this->info.getElementCount()];
|
||||
while (pF<pFE) {
|
||||
radians = (rand () * 2.0 * myPI)/RAND_MAX;
|
||||
if (pCF) {
|
||||
newValue = *pCF++;
|
||||
}
|
||||
else {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = tsMin (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = tsMax (newValue, limit);
|
||||
*(pF++) = newValue;
|
||||
}
|
||||
|
||||
status = this->update ( *pDD );
|
||||
if ( status != S_casApp_success ) {
|
||||
errMessage (status, "vector scan update failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exVectorPV::updateValue ()
|
||||
//
|
||||
// NOTES:
|
||||
// 1) This should have a test which verifies that the
|
||||
// incoming value in all of its various data types can
|
||||
// be translated into a real number?
|
||||
// 2) We prefer to unreference the old PV value here and
|
||||
// reference the incomming value because this will
|
||||
// result in value change events each retaining an
|
||||
// independent value on the event queue. With large arrays
|
||||
// this may result in too much memory consumtion on
|
||||
// the event queue.
|
||||
//
|
||||
caStatus exVectorPV::updateValue ( const gdd & value )
|
||||
{
|
||||
|
||||
//
|
||||
// Check bounds of incoming request
|
||||
// (and see if we are replacing all elements -
|
||||
// replaceOk==true)
|
||||
//
|
||||
// Perhaps much of this is unnecessary since the
|
||||
// server lib checks the bounds of all requests
|
||||
//
|
||||
if ( value.isAtomic()) {
|
||||
if ( value.dimension() != 1u ) {
|
||||
return S_casApp_badDimension;
|
||||
}
|
||||
const gddBounds* pb = value.getBounds ();
|
||||
if ( pb[0u].first() != 0u ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
else if ( pb[0u].size() > this->info.getElementCount() ) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
}
|
||||
else if ( ! value.isScalar() ) {
|
||||
//
|
||||
// no containers
|
||||
//
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new array data descriptor
|
||||
// (so that old values that may be referenced on the
|
||||
// event queue are not replaced)
|
||||
//
|
||||
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
|
||||
1u, this->info.getElementCount() ) );
|
||||
if ( ! pNewValue.valid() ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// smart pointer class takes care of the reference count
|
||||
// from here down
|
||||
//
|
||||
gddStatus gdds = pNewValue->unreference( );
|
||||
assert ( ! gdds );
|
||||
|
||||
//
|
||||
// allocate array buffer
|
||||
//
|
||||
aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()];
|
||||
if (!pF) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// Install (and initialize) array buffer
|
||||
// if no old values exist
|
||||
//
|
||||
unsigned count = this->info.getElementCount();
|
||||
for ( unsigned i = 0u; i < count; i++ ) {
|
||||
pF[i] = 0.0f;
|
||||
}
|
||||
|
||||
exVecDestructor * pDest = new exVecDestructor;
|
||||
if (!pDest) {
|
||||
delete [] pF;
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// install the buffer into the DD
|
||||
// (do this before we increment pF)
|
||||
//
|
||||
pNewValue->putRef ( pF, pDest );
|
||||
|
||||
//
|
||||
// copy in the values that they are writing
|
||||
//
|
||||
gdds = pNewValue->put( & value );
|
||||
if ( gdds ) {
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
|
||||
this->pValue = pNewValue;
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
//
|
||||
// exVecDestructor::run()
|
||||
//
|
||||
// special gddDestructor guarantees same form of new and delete
|
||||
//
|
||||
void exVecDestructor::run ( void *pUntyped )
|
||||
{
|
||||
aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped );
|
||||
delete [] pf;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include "envDefs.h"
|
||||
|
||||
#include "exServer.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
//
|
||||
// main()
|
||||
// (example single threaded ca server tool main loop)
|
||||
//
|
||||
extern int main (int argc, const char **argv)
|
||||
{
|
||||
epicsTime begin (epicsTime::getCurrent());
|
||||
exServer *pCAS;
|
||||
unsigned debugLevel = 0u;
|
||||
double executionTime;
|
||||
char pvPrefix[128] = "";
|
||||
unsigned aliasCount = 1u;
|
||||
unsigned scanOn = true;
|
||||
unsigned syncScan = true;
|
||||
char arraySize[64] = "";
|
||||
bool forever = true;
|
||||
int i;
|
||||
|
||||
for ( i = 1; i < argc; i++ ) {
|
||||
if ( sscanf(argv[i], "-d %u", & debugLevel ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-t %lf", & executionTime ) == 1 ) {
|
||||
forever = false;
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i], "-p %127s", pvPrefix ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-c %u", & aliasCount ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-s %u", & scanOn ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-a %63s", arraySize ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( sscanf ( argv[i],"-ss %u", & syncScan ) == 1 ) {
|
||||
continue;
|
||||
}
|
||||
printf ("\"%s\"?\n", argv[i]);
|
||||
printf (
|
||||
"usage: %s [-d<debug level> -t<execution time> -p<PV name prefix> "
|
||||
"-c<numbered alias count> -s<1=scan on (default), 0=scan off> "
|
||||
"-ss<1=synchronous scan (default), 0=asynchronous scan>]\n",
|
||||
argv[0]);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ( arraySize[0] != '\0' ) {
|
||||
epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", arraySize );
|
||||
}
|
||||
|
||||
try {
|
||||
pCAS = new exServer ( pvPrefix, aliasCount,
|
||||
scanOn != 0, syncScan == 0 );
|
||||
}
|
||||
catch ( ... ) {
|
||||
errlogPrintf ( "Server initialization error\n" );
|
||||
errlogFlush ();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pCAS->setDebugLevel(debugLevel);
|
||||
|
||||
if ( forever ) {
|
||||
//
|
||||
// loop here forever
|
||||
//
|
||||
while (true) {
|
||||
fileDescriptorManager.process(1000.0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
double delay = epicsTime::getCurrent() - begin;
|
||||
//
|
||||
// loop here untill the specified execution time
|
||||
// expires
|
||||
//
|
||||
while ( delay < executionTime ) {
|
||||
fileDescriptorManager.process ( delay );
|
||||
delay = epicsTime::getCurrent() - begin;
|
||||
}
|
||||
}
|
||||
pCAS->show(2u);
|
||||
delete pCAS;
|
||||
errlogFlush ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1,844 +0,0 @@
|
||||
file {
|
||||
name="test.dl"
|
||||
}
|
||||
display {
|
||||
magic="305419896"
|
||||
majv="2"
|
||||
mnrv="4"
|
||||
ndyng="0"
|
||||
npc="5"
|
||||
nstr="8"
|
||||
ndynamic="12"
|
||||
nplot="0"
|
||||
nrd="0"
|
||||
nes="0"
|
||||
nkd="0"
|
||||
object {
|
||||
x="0"
|
||||
y="0"
|
||||
width="421"
|
||||
height="306"
|
||||
}
|
||||
clr="0"
|
||||
bclr="1"
|
||||
nwords_dspy="1106"
|
||||
nwords_sta="28"
|
||||
nwords_cmap="36"
|
||||
nwords_crules="106"
|
||||
odyng="306"
|
||||
osta="278"
|
||||
odynamic="306"
|
||||
oplot="1106"
|
||||
ord="1106"
|
||||
oes="1106"
|
||||
okd="1106"
|
||||
opc="58"
|
||||
ostr="88"
|
||||
ocmap="136"
|
||||
ocrules="172"
|
||||
style="solid"
|
||||
fill="outline"
|
||||
width="0"
|
||||
clrmod="static"
|
||||
vismod="static"
|
||||
clrrule="alarm"
|
||||
pv=""
|
||||
cmap=""
|
||||
}
|
||||
"<<color map>>" {
|
||||
ncolors="8"
|
||||
dl_color {
|
||||
r="255"
|
||||
g="255"
|
||||
b="255"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="128"
|
||||
}
|
||||
dl_color {
|
||||
r="0"
|
||||
g="0"
|
||||
b="0"
|
||||
inten="0"
|
||||
blink="off"
|
||||
RISCpad="75"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="0"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="-14684"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="0"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="on"
|
||||
RISCpad="14744"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="255"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="-16536"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="255"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="on"
|
||||
RISCpad="-15536"
|
||||
}
|
||||
dl_color {
|
||||
r="0"
|
||||
g="0"
|
||||
b="255"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="-28408"
|
||||
}
|
||||
dl_color {
|
||||
r="0"
|
||||
g="0"
|
||||
b="255"
|
||||
inten="255"
|
||||
blink="on"
|
||||
RISCpad="0"
|
||||
}
|
||||
}
|
||||
"<<color rules>>" {
|
||||
nrules="1"
|
||||
dl_color_rule {
|
||||
name="alarm"
|
||||
info[0] {
|
||||
chan="$(C).SEVR"
|
||||
value="MAJOR"
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="2"
|
||||
RISCpad="0"
|
||||
}
|
||||
info[1] {
|
||||
chan="$(C).SEVR"
|
||||
value="MINOR"
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="4"
|
||||
RISCpad="127"
|
||||
}
|
||||
info[2] {
|
||||
chan="$(C).SEVR"
|
||||
value="INFO"
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="6"
|
||||
RISCpad="44"
|
||||
}
|
||||
info[3] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-128"
|
||||
}
|
||||
info[4] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-1"
|
||||
}
|
||||
info[5] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-104"
|
||||
}
|
||||
info[6] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-1"
|
||||
}
|
||||
info[7] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="8"
|
||||
}
|
||||
info[8] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="120"
|
||||
}
|
||||
info[9] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="1"
|
||||
}
|
||||
info[10] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="7"
|
||||
}
|
||||
info[11] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="19"
|
||||
}
|
||||
info[12] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="48"
|
||||
}
|
||||
info[13] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="28"
|
||||
}
|
||||
info[14] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-88"
|
||||
}
|
||||
info[15] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="0"
|
||||
}
|
||||
fg_enable="on"
|
||||
bg_enable="on"
|
||||
default_fg="0"
|
||||
default_bg="1"
|
||||
}
|
||||
}
|
||||
"<<basic attribute>>" {
|
||||
attr {
|
||||
clr="0"
|
||||
style="solid"
|
||||
fill="outline"
|
||||
width="0"
|
||||
}
|
||||
}
|
||||
"text" {
|
||||
object {
|
||||
x="44"
|
||||
y="16"
|
||||
width="104"
|
||||
height="14"
|
||||
groupid="0"
|
||||
}
|
||||
textix="Sync"
|
||||
align="horiz. left"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text" {
|
||||
object {
|
||||
x="260"
|
||||
y="13"
|
||||
width="92"
|
||||
height="17"
|
||||
groupid="0"
|
||||
}
|
||||
textix="Async"
|
||||
align="horiz. left"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="15"
|
||||
y="88"
|
||||
width="170"
|
||||
height="22"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="fred"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="16"
|
||||
y="133"
|
||||
width="169"
|
||||
height="17"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="fred"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="15"
|
||||
y="43"
|
||||
width="168"
|
||||
height="26"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="fred"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="215"
|
||||
y="81"
|
||||
width="170"
|
||||
height="30"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="freddy"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="216"
|
||||
y="133"
|
||||
width="171"
|
||||
height="18"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="freddy"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="215"
|
||||
y="43"
|
||||
width="168"
|
||||
height="28"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="freddy"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="16"
|
||||
y="225"
|
||||
width="171"
|
||||
height="19"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="jane"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="17"
|
||||
y="259"
|
||||
width="170"
|
||||
height="20"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="jane"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="15"
|
||||
y="187"
|
||||
width="170"
|
||||
height="19"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="jane"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="219"
|
||||
y="218"
|
||||
width="173"
|
||||
height="23"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="janet"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="220"
|
||||
y="257"
|
||||
width="174"
|
||||
height="20"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="janet"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="219"
|
||||
y="188"
|
||||
width="171"
|
||||
height="21"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="janet"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
//
|
||||
// $Id$
|
||||
// Author: Jeff HIll (LANL)
|
||||
//
|
||||
//
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// so we can call this from the vxWorks shell
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
exServer *pExampleCAS;
|
||||
|
||||
//
|
||||
// excas ()
|
||||
// (vxWorks example server entry point)
|
||||
//
|
||||
int excas (unsigned debugLevel, unsigned delaySec)
|
||||
{
|
||||
epicsTime begin(epicsTime::getCurrent());
|
||||
exServer *pCAS;
|
||||
|
||||
pCAS = new exServer(32u,5u,500u);
|
||||
if (!pCAS) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pCAS->setDebugLevel(debugLevel);
|
||||
pExampleCAS = pCAS;
|
||||
|
||||
if (delaySec==0u) {
|
||||
//
|
||||
// loop here forever
|
||||
//
|
||||
while (1) {
|
||||
taskDelay(10);
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsTime total( ((float)delaySec) );
|
||||
epicsTime delay(epicsTime::getCurrent() - begin);
|
||||
//
|
||||
// loop here untill the specified execution time
|
||||
// expires
|
||||
//
|
||||
while (delay < total) {
|
||||
taskDelay(10);
|
||||
delay = epicsTime::getCurrent() - begin;
|
||||
}
|
||||
}
|
||||
pCAS->show(debugLevel);
|
||||
pExampleCAS = NULL;
|
||||
delete pCAS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int excasShow(unsigned level)
|
||||
{
|
||||
if (pExampleCAS!=NULL) {
|
||||
pExampleCAS->show(level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user