|
|
|
@ -1,12 +1,23 @@
|
|
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <exception>
|
|
|
|
|
|
|
|
|
|
#if !defined(_WIN32)
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#define USE_SIGNAL
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <epicsExit.h>
|
|
|
|
|
#include <epicsEvent.h>
|
|
|
|
|
|
|
|
|
|
//! [Headers]
|
|
|
|
|
#include <pv/configuration.h>
|
|
|
|
|
#include <pv/pvAccess.h>
|
|
|
|
|
#include <pv/clientFactory.h>
|
|
|
|
|
#include <pv/caProvider.h>
|
|
|
|
|
//! [Headers]
|
|
|
|
|
|
|
|
|
|
namespace pvd = epics::pvData;
|
|
|
|
|
namespace pva = epics::pvAccess;
|
|
|
|
@ -15,6 +26,19 @@ namespace {
|
|
|
|
|
|
|
|
|
|
epicsEvent done;
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SIGNAL
|
|
|
|
|
void alldone(int num)
|
|
|
|
|
{
|
|
|
|
|
(void)num;
|
|
|
|
|
done.signal();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void onthewayout(void* arg) {
|
|
|
|
|
(void)arg;
|
|
|
|
|
std::cout<<"Done\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ChanReq : public pva::ChannelRequester
|
|
|
|
|
{
|
|
|
|
|
virtual ~ChanReq() {}
|
|
|
|
@ -22,7 +46,9 @@ struct ChanReq : public pva::ChannelRequester
|
|
|
|
|
virtual std::string getRequesterName() { return "ChanReq"; }
|
|
|
|
|
|
|
|
|
|
virtual void channelCreated(const epics::pvData::Status& status,
|
|
|
|
|
pva::Channel::shared_pointer const & channel) {
|
|
|
|
|
pva::Channel::shared_pointer const & channel)
|
|
|
|
|
{
|
|
|
|
|
// called once, recursively during ChannelProvider::createChannel()
|
|
|
|
|
if(!status.isSuccess()) {
|
|
|
|
|
std::cout<<"Oops Connect: "<<status<<"\n";
|
|
|
|
|
} else {
|
|
|
|
@ -31,13 +57,15 @@ struct ChanReq : public pva::ChannelRequester
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void channelStateChange(pva::Channel::shared_pointer const & channel,
|
|
|
|
|
pva::Channel::ConnectionState connectionState) {
|
|
|
|
|
pva::Channel::ConnectionState connectionState)
|
|
|
|
|
{
|
|
|
|
|
// Called for each connect/disconnect event, and on shutdown (destroy)
|
|
|
|
|
switch(connectionState) {
|
|
|
|
|
case pva::Channel::NEVER_CONNECTED:
|
|
|
|
|
case pva::Channel::CONNECTED:
|
|
|
|
|
case pva::Channel::DISCONNECTED:
|
|
|
|
|
case pva::Channel::DESTROYED:
|
|
|
|
|
std::cout<<channel->getChannelName()<<" "<<pva::Channel::ConnectionStateNames[connectionState]<<"\n";
|
|
|
|
|
std::cout<<"CHANNEL "<<channel->getChannelName()<<" "<<pva::Channel::ConnectionStateNames[connectionState]<<"\n";
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
@ -57,20 +85,29 @@ struct GetReq : public pva::ChannelGetRequester
|
|
|
|
|
pva::ChannelGet::shared_pointer const & channelGet,
|
|
|
|
|
pvd::Structure::const_shared_pointer const & structure)
|
|
|
|
|
{
|
|
|
|
|
// Called each time get operation becomes "ready" (channel connected)
|
|
|
|
|
if(status.isSuccess()) {
|
|
|
|
|
std::cout<<"Get request"<<channelGet->getChannel()->getChannelName()<<"\n";
|
|
|
|
|
std::cout<<"Get execute "<<channelGet->getChannel()->getChannelName()<<"\n";
|
|
|
|
|
// can now execute the get operation
|
|
|
|
|
channelGet->get();
|
|
|
|
|
} else {
|
|
|
|
|
std::cout<<"Oops GetConnect: "<<channelGet->getChannel()->getChannelName()<<" "<<status<<"\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void channelDisconnect(bool destroy) {
|
|
|
|
|
// Called each time operation becomes no "ready" (channel disconnected)
|
|
|
|
|
// same as channelStateChange() for DISCONNECTED and DESTROYED
|
|
|
|
|
std::cout<<"Get disconnected\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void getDone(
|
|
|
|
|
const epics::pvData::Status& status,
|
|
|
|
|
pva::ChannelGet::shared_pointer const & channelGet,
|
|
|
|
|
pvd::PVStructure::shared_pointer const & pvStructure,
|
|
|
|
|
pvd::BitSet::shared_pointer const & bitSet)
|
|
|
|
|
{
|
|
|
|
|
// when execution completes
|
|
|
|
|
if(status.isSuccess()) {
|
|
|
|
|
pvd::PVFieldPtr valfld(pvStructure->getSubField("value"));
|
|
|
|
|
if(!valfld)
|
|
|
|
@ -86,33 +123,75 @@ struct GetReq : public pva::ChannelGetRequester
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
try {
|
|
|
|
|
// an empty structure
|
|
|
|
|
pvd::PVStructurePtr pvReq(pvd::getPVDataCreate()->createPVStructure(
|
|
|
|
|
pvd::getFieldCreate()->createFieldBuilder()->createStructure()
|
|
|
|
|
));
|
|
|
|
|
std::string providerName("pva");
|
|
|
|
|
typedef std::vector<std::string> pvs_t;
|
|
|
|
|
pvs_t pvs;
|
|
|
|
|
|
|
|
|
|
for(int i=1; i<argc; i++) {
|
|
|
|
|
if(argv[i][0]=='-') {
|
|
|
|
|
if(strcmp(argv[i], "-P")==0 || strcmp(argv[i], "--provider")==0) {
|
|
|
|
|
if(i<argc-1) {
|
|
|
|
|
providerName = argv[i+1];
|
|
|
|
|
} else {
|
|
|
|
|
std::cerr << "--provider requires value\n";
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
std::cerr<<"Unknown argument: "<<argv[i]<<"\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
pvs.push_back(argv[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
epicsAtExit(&onthewayout, 0);
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SIGNAL
|
|
|
|
|
signal(SIGINT, alldone);
|
|
|
|
|
signal(SIGTERM, alldone);
|
|
|
|
|
signal(SIGQUIT, alldone);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// build "pvRequest" which asks for all fields
|
|
|
|
|
pvd::PVStructure::shared_pointer pvReq(pvd::createRequest("field()"));
|
|
|
|
|
|
|
|
|
|
// explicitly select configuration from process environment
|
|
|
|
|
pva::Configuration::shared_pointer conf(pva::ConfigurationBuilder()
|
|
|
|
|
.push_env()
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
// add "pva" provider to registry
|
|
|
|
|
pva::ClientFactory::start();
|
|
|
|
|
// add "ca" provider to registry
|
|
|
|
|
pva::ca::CAClientFactory::start();
|
|
|
|
|
|
|
|
|
|
pva::ChannelProvider::shared_pointer provider(pva::getChannelProviderRegistry()->createProvider("pva", conf));
|
|
|
|
|
std::cout<<"Use provider: "<<providerName<<"\n";
|
|
|
|
|
pva::ChannelProvider::shared_pointer provider(pva::getChannelProviderRegistry()->createProvider(providerName, conf));
|
|
|
|
|
if(!provider)
|
|
|
|
|
throw std::logic_error("pva provider not registered");
|
|
|
|
|
|
|
|
|
|
// need to store references to keep get (and channel) from being closed
|
|
|
|
|
typedef std::set<pva::ChannelGet::shared_pointer> gets_t;
|
|
|
|
|
gets_t gets;
|
|
|
|
|
|
|
|
|
|
// as we have no channel or operation specific data,
|
|
|
|
|
// use the same requesters for all PVs
|
|
|
|
|
pva::ChannelRequester::shared_pointer chanreq(new ChanReq);
|
|
|
|
|
pva::ChannelGetRequester::shared_pointer getreq(new GetReq);
|
|
|
|
|
|
|
|
|
|
for(int i=1; i<argc; i++) {
|
|
|
|
|
if(argv[i][0]=='-') continue;
|
|
|
|
|
pva::Channel::shared_pointer chan(provider->createChannel(argv[i], chanreq));
|
|
|
|
|
for(pvs_t::const_iterator it=pvs.begin(); it!=pvs.end(); ++it) {
|
|
|
|
|
const std::string& pv = *it;
|
|
|
|
|
|
|
|
|
|
pva::Channel::shared_pointer chan(provider->createChannel(pv, chanreq));
|
|
|
|
|
// if !chan then channelCreated() called with error status
|
|
|
|
|
if(!chan) continue;
|
|
|
|
|
|
|
|
|
|
// no need to wait for connection
|
|
|
|
|
|
|
|
|
|
pva::ChannelGet::shared_pointer op(chan->createChannelGet(getreq, pvReq));
|
|
|
|
|
// if !op then channelGetConnect() called with error status
|
|
|
|
|
if(!op) continue;
|
|
|
|
|
|
|
|
|
|
gets.insert(op);
|
|
|
|
|