Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to stop spectra gettng into alarm or disconnected #78

Merged
merged 8 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions isisdaeApp/src/FixedValuePV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ bool FixedValuePV<std::string>::getNewValue(smartGDDPointer& pDD)
return true;
}

template class FixedValuePV<char>;
template class FixedValuePV<aitEnum16>;
template class FixedValuePV<int>;
template class FixedValuePV<float>;
template class FixedValuePV<double>;
template class FixedValuePV<std::string>;

1 change: 1 addition & 0 deletions isisdaeApp/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ isisdae_SRCS += SpectrumPV.cc NORDPV.cc MonLookupPV.cc CountsPV.cc FixedValuePV.
isisdae_SRCS += exChannel.cc exPV.cc exScalarPV.cc exVectorPV.cc exServer.cc
isisdae_SRCS += isisdaeDriver.cpp isisdaeInterface.cpp CRPTMapping.cpp
isisdae_SRCS += MonitorSpectrumPV.cpp MonitorCountsPV.cpp dae_isisicpint_dummy.cpp
isisdae_SRCS += NoAlarmPV.cpp

isisdae_LIBS += webget htmltidy asyn oncrpc utilities zlib pcrecpp pcre pugixml
isisdae_LIBS += ADnEDSupport
Expand Down
2 changes: 1 addition & 1 deletion isisdaeApp/src/MonLookupPV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

/// class for a PV that converts a monitor number into a spectrum number

MonLookupPV::MonLookupPV ( exServer & cas, pvInfo &setup, bool preCreateFlag, bool scanOnIn, int monitor ) : exScalarPV(cas, setup, preCreateFlag, scanOnIn, false), m_monitor(monitor)
MonLookupPV::MonLookupPV ( exServer & cas, pvInfo &setup, bool preCreateFlag, bool scanOnIn, int monitor ) : exScalarPV(cas, setup, preCreateFlag, scanOnIn, true), m_monitor(monitor)
{

}
Expand Down
37 changes: 37 additions & 0 deletions isisdaeApp/src/NoAlarmPV.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <stdlib.h>

#include "exServer.h"
#include "gddApps.h"

NoAlarmPV::NoAlarmPV ( exServer & cas, pvInfo &setup, bool preCreateFlag, bool scanOnIn) : FixedValuePV<aitEnum16>(cas, setup, preCreateFlag, scanOnIn, 0)
{
assert(this->info.getType () == aitEnumEnum16);
}

caStatus NoAlarmPV::getEnumsImpl ( gdd & enumsIn )
{
static const unsigned nStr = 1;
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, "NO_ALARM",
sizeof(str[0].fixed_string));

enumsIn.setDimension(1);
enumsIn.setBound (0,0,nStr);
enumsIn.putRef (str, pDes);

return S_cas_success;
}

78 changes: 46 additions & 32 deletions isisdaeApp/src/exPV.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ 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()
Expand All @@ -46,16 +40,9 @@ exPV::exPV ( exServer & casIn, pvInfo & setup,
//
assert (this->info.getElementCount()>=1u);

memset(&(this->lastTimer), 0, sizeof(this->lastTimer));
memset(&(this->lastScan), 0, sizeof(this->lastScan));

//
// 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() );
}
// we no longer start a very slow background scan here
}

//
Expand Down Expand Up @@ -114,11 +101,33 @@ epicsTimerNotify::expireStatus
exPV::expire ( const epicsTime & /*currentTime*/ ) // X aCC 361
{
static const double sleep_delay = atof(getenv("ISISDAE_TIMER_SLEEP") != NULL ? getenv("ISISDAE_TIMER_SLEEP") : ".001");
// only periodic scan if somebody is interested in us
if (isisdaePCASDebug > 0) {
std::cerr << "CAS: exPV::expire() timer expired \"" << getName() << "\"" << std::endl;
}
if (this->interest) {
doScan();
}
this->timerDone.signal();
epicsThreadSleep(sleep_delay); // yield thread, this is in case we have a big timer queue and start to starve DAE access
if ( this->scanOn && this->getScanPeriod() > 0.0 ) {
return expireStatus ( restart, this->getScanPeriod() );
}
else {
return noRestart;
}
}

void exPV::doScan()
{
if (isisdaePCASDebug > 0) {
std::cerr << "CAS: exPV::doScan() updating data for \"" << getName() << "\"" << std::endl;
}
try
{
this->scan();
epicsGuard<epicsMutex> _lock(timerLock);
epicsTimeGetCurrent(&(this->lastTimer));
epicsTimeGetCurrent(&(this->lastScan));
}
catch(const std::exception& ex)
{
Expand All @@ -128,17 +137,9 @@ exPV::expire ( const epicsTime & /*currentTime*/ ) // X aCC 361
{
errlogSevPrintf(errlogMajor, "CAS: exPV::expire: Scan failed");
}
this->timerDone.signal();
epicsThreadSleep(sleep_delay); // yield thread, this is in case we have a big timer queue and start to starve DAE access
if ( this->scanOn && this->getScanPeriod() > 0.0 ) {
return expireStatus ( restart, this->getScanPeriod() );
}
else {
return noRestart;
}
}

//

// exPV::bestExternalType()
//
aitEnum exPV::bestExternalType () const
Expand All @@ -156,10 +157,14 @@ caStatus exPV::interestRegister ()
}

this->interest = true;
// std::cerr << "CAS: Interest registered in PV \"" << getName() << "\"" << std::endl;
if (isisdaePCASDebug > 0) {
std::cerr << "CAS: exPV::interestRegister() in PV \"" << getName() << "\"" << std::endl;
}
if ( this->scanOn && this->getScanPeriod() > 0.0 &&
this->getScanPeriod() < this->timer.getExpireDelay() ) {
(!this->timer.getExpireInfo().active || this->getScanPeriod() < this->timer.getExpireDelay())
) {
this->timer.start ( *this, this->getScanPeriod() );

}

return S_casApp_success;
Expand All @@ -170,8 +175,11 @@ caStatus exPV::interestRegister ()
//
void exPV::interestDelete()
{
// std::cerr << "CAS: Interest unregistered in PV \"" << getName() << "\"" << std::endl;
if (isisdaePCASDebug > 0) {
std::cerr << "CAS: exPV::interestDelete() in PV \"" << getName() << "\"" << std::endl;
}
this->interest = false;
this->timer.cancel();
}

//
Expand Down Expand Up @@ -258,7 +266,7 @@ caStatus exPV::getUnits( gdd & units )
}

//
// exPV::getEnums()
// exPV::getEnumsImpl()
//
// returns the eneumerated state strings
// for a discrete channel
Expand All @@ -267,7 +275,7 @@ caStatus exPV::getUnits( gdd & units )
// and therefore this isnt appropriate in an
// analog context ...
//
caStatus exPV::getEnums ( gdd & enumsIn )
caStatus exPV::getEnumsImpl ( gdd & enumsIn )
{
if ( this->info.getType () == aitEnumEnum16 ) {
static const unsigned nStr = 2;
Expand Down Expand Up @@ -300,6 +308,11 @@ caStatus exPV::getEnums ( gdd & enumsIn )
return S_cas_success;
}

caStatus exPV::getEnums ( gdd & enumsIn )
{
return getEnumsImpl(enumsIn);
}

//
// exPV::getValue()
//
Expand Down Expand Up @@ -348,7 +361,7 @@ caStatus exPV::read ( const casCtx & ctx, gdd & protoIn )
double tdiff;
{
epicsGuard<epicsMutex> _lock(timerLock);
tdiff = epicsTimeDiffInSeconds(&now, &(this->lastTimer));
tdiff = epicsTimeDiffInSeconds(&now, &(this->lastScan));
}
if ( (this->interest && this->scanOn && this->getScanPeriod() > 0.0) || (tdiff < cache_time) )
{
Expand All @@ -357,6 +370,7 @@ caStatus exPV::read ( const casCtx & ctx, gdd & protoIn )
if (m_asyncIO)
{
myAsyncReadIO *pIO = new myAsyncReadIO(ctx, protoIn, *this); // will delete itself on IO completion
epicsThreadCreate("myAsyncReadIO", epicsThreadPriorityMedium, epicsThreadStackMedium, myAsyncReadIO::readThreadC, pIO);
return S_casApp_asyncCompletion;
}
else
Expand All @@ -367,7 +381,7 @@ caStatus exPV::read ( const casCtx & ctx, gdd & protoIn )

caStatus exPV::doRead ( const casCtx & ctx, gdd & protoIn )
{
this->expire(epicsTime()); // does a scan
this->doScan();
return this->ft.read(*this, protoIn);
}

Expand Down
90 changes: 64 additions & 26 deletions isisdaeApp/src/exServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ void exServer::createAxisPVs(bool is_monitor, int id, int period, const char* ax
char buffer[256], pvAlias[256];
const char* prefix = (is_monitor ? "MON" : "SPEC");
sprintf(buffer, "%s:%d:%d:%s", prefix, period, id, axis);
pvInfo* pPVI = new pvInfo (0.5, buffer, 1.0e9f, 0.0f, units.c_str(), aitEnumFloat32, m_ntc);
pvInfo* pPVI = new pvInfo (0.5, buffer, 0.0f, 0.0f, units.c_str(), aitEnumFloat32, m_ntc);
m_pvList[buffer] = pPVI;
SpectrumPV* pSPV = (is_monitor ? new MonitorSpectrumPV(*this, *pPVI, true, scanOn, axis, id, period) :
new SpectrumPV(*this, *pPVI, true, scanOn, axis, id, period));
Expand Down Expand Up @@ -367,18 +367,22 @@ void exServer::createAxisPVs(bool is_monitor, int id, int period, const char* ax
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
createStandardPVs(prefix, period, id, axis, units, is_monitor);
}

void exServer::createStandardPVs(const char* prefix, int period, int id, const char* axis, const std::string& units, bool is_monitor)
{
char buffer[256], pvAlias[256];
sprintf(buffer, "%s:%d:%d:%s.DESC", prefix, period, id, axis);
std::ostringstream desc;
desc << axis << " (" << (is_monitor ? "mon=" : "spec=") << id << ",period=" << period << ")";
pPVI = createFixedPV(buffer, desc.str(), "", aitEnumString);
pvInfo* pPVI = createFixedPV(buffer, desc.str(), "", aitEnumString);
if (period == 1)
{
sprintf(buffer, "%s:%d:%s.DESC", prefix, id, axis);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}

sprintf(buffer, "%s:%d:%d:%s.EGU", prefix, period, id, axis);
pPVI = createFixedPV(buffer, units, "", aitEnumString);
if (period == 1)
Expand All @@ -387,13 +391,53 @@ void exServer::createAxisPVs(bool is_monitor, int id, int period, const char* ax
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
sprintf(buffer, "%s:%d:%d:%s.UDF", prefix, period, id, axis);
pPVI = createFixedPV(buffer, 0, "", aitEnumInt8);
if (period == 1)
{
sprintf(buffer, "%s:%d:%s.UDF", prefix, id, axis);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
sprintf(buffer, "%s:%d:%d:%s.STAT", prefix, period, id, axis);
pPVI = createNoAlarmPV(buffer);
if (period == 1)
{
sprintf(buffer, "%s:%d:%s.STAT", prefix, id, axis);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
sprintf(buffer, "%s:%d:%d:%s.SEVR", prefix, period, id, axis);
pPVI = createNoAlarmPV(buffer);
if (period == 1)
{
sprintf(buffer, "%s:%d:%s.SEVR", prefix, id, axis);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
sprintf(buffer, "%s:%d:%d:%s.HOPR", prefix, period, id, axis);
pPVI = createFixedPV(buffer, 0.0, "", aitEnumFloat64);
if (period == 1)
{
sprintf(buffer, "%s:%d:%s.HOPR", prefix, id, axis);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
sprintf(buffer, "%s:%d:%d:%s.LOPR", prefix, period, id, axis);
pPVI = createFixedPV(buffer, 0.0, "", aitEnumFloat64);
if (period == 1)
{
sprintf(buffer, "%s:%d:%s.LOPR", prefix, id, axis);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
}

template <typename T>
pvInfo* exServer::createFixedPV(const std::string& pvStr, const T& value, const char* units, aitEnum ait_type)
{
char pvAlias[256];
pvInfo* pPVI = new pvInfo (0.5, pvStr.c_str(), 0.0f, 0.0f, units, ait_type, 1); /// @todo would be nice to use arithmetic value, but need to check for strings
pvInfo* pPVI = new pvInfo (5.0, pvStr.c_str(), 0.0f, 0.0f, units, ait_type, 1); /// @todo would be nice to use arithmetic value, but need to check for strings
m_pvList[pvStr.c_str()] = pPVI;
exPV* pPV = new FixedValuePV<T>(*this, *pPVI, true, scanOn, value);
pPVI->setPV(pPV);
Expand All @@ -402,13 +446,25 @@ pvInfo* exServer::createFixedPV(const std::string& pvStr, const T& value, const
return pPVI;
}

pvInfo* exServer::createNoAlarmPV(const std::string& pvStr)
{
char pvAlias[256];
pvInfo* pPVI = new pvInfo (5.0, pvStr.c_str(), 0.0f, 0.0f, "", aitEnumEnum16, 1); /// @todo would be nice to use arithmetic value, but need to check for strings
m_pvList[pvStr.c_str()] = pPVI;
exPV* pPV = new NoAlarmPV(*this, *pPVI, true, scanOn);
pPVI->setPV(pPV);
epicsSnprintf(pvAlias, sizeof(pvAlias), "%s%s", m_pvPrefix.c_str(), pvStr.c_str());
this->installAliasName(*pPVI, pvAlias);
return pPVI;
}

// id is spec or mon number
void exServer::createCountsPV(bool is_monitor, int id, int period)
{
char buffer[256], pvAlias[256];
const char* prefix = (is_monitor ? "MON" : "SPEC");
sprintf(buffer, "%s:%d:%d:C", prefix, period, id);
pvInfo* pPVI = new pvInfo (0.5, buffer, 1.0e9f, 0.0f, "cnt", aitEnumInt32, 1);
pvInfo* pPVI = new pvInfo (0.5, buffer, 0.0f, 0.0f, "cnt", aitEnumInt32, 1);
m_pvList[buffer] = pPVI;
exPV* pPV = (is_monitor ? new MonitorCountsPV(*this, *pPVI, true, scanOn, id, period) :
new CountsPV(*this, *pPVI, true, scanOn, id, period));
Expand All @@ -425,28 +481,10 @@ void exServer::createCountsPV(bool is_monitor, int id, int period)
sprintf(pvAlias, "%s%s.VAL", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}

sprintf(buffer, "%s:%d:%d:C.DESC", prefix, period, id);
std::ostringstream desc;
desc << "Integral (" << (is_monitor ? "mon=" : "spec=") << id << ",period=" << period << ")";
pPVI = createFixedPV(buffer, desc.str(), "", aitEnumString);
if (period == 1)
{
sprintf(buffer, "%s:%d:C.DESC", prefix, id);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}

sprintf(buffer, "%s:%d:%d:C.EGU", prefix, period, id);
pPVI = createFixedPV(buffer, std::string("cnt"), "", aitEnumString);
if (period == 1)
{
sprintf(buffer, "%s:%d:C.EGU", prefix, id);
sprintf(pvAlias, "%s%s", m_pvPrefix.c_str(), buffer);
this->installAliasName(*pPVI, pvAlias);
}
createStandardPVs(prefix, period, id, "C", "cnt", is_monitor);
}


bool exServer::createSpecPVs(const std::string& pvStr)
{
int spec, period;
Expand Down Expand Up @@ -491,7 +529,7 @@ bool exServer::createMonitorPVs(const std::string& pvStr)
createCountsPV(true, mon, period);

sprintf(buffer, "MON:%d:%d:S", period, mon);
pvInfo* pPVI = new pvInfo (0.5, buffer, 1.0e9f, 0.0f, "", aitEnumInt32, 1);
pvInfo* pPVI = new pvInfo (0.5, buffer, 0.0f, 0.0f, "", aitEnumInt32, 1);
m_pvList[buffer] = pPVI;
exPV* pPV = new MonLookupPV(*this, *pPVI, true, scanOn, mon);
pPVI->setPV(pPV);
Expand Down
Loading