/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvxs is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "utilpvt.h" namespace { using namespace pvxs; using namespace pvxs::server; DEFINE_LOGGER(dummy,"dummyserv"); struct DummySource : public Source { const std::string name; epicsMutex lock; Value current; explicit DummySource(const std::string& name) :name(name) ,current(nt::NTScalar{TypeCode::Int32}.build().create()) { epicsTimeStamp now; epicsTimeGetCurrent(&now); current["value"] = 0u; current["timeStamp.secondsPastEpoch"] = now.secPastEpoch+POSIX_TIME_AT_EPICS_EPOCH; current["timeStamp.nanoseconds"] = now.nsec; } virtual ~DummySource() {} // Source interface public: virtual void onSearch(Search &search) override final { for(auto& op : search) { if(op.name()==name) { log_printf(dummy, Info, "Claiming '%s'\n", op.name()); op.claim(); } else { log_printf(dummy, Debug, "Ignoring '%s'\n", op.name()); } } } virtual List onList() override final { auto names(std::make_shared>()); names->insert(name); return List{names}; } virtual void onCreate(std::unique_ptr&& raw) override final { if(raw->name()!=name) return; std::shared_ptr chan(std::move(raw)); log_printf(dummy, Info, "Create '%s'\n", chan->name().c_str()); // callback when client creating Get/Put chan->onOp([this, chan](std::shared_ptr&& raw){ std::shared_ptr conn(std::move(raw)); log_printf(dummy, Info, "Begin Operation on '%s'\n", chan->name().c_str()); conn->onGet([this, chan](std::unique_ptr&& raw) { // client executing Get or Put log_printf(dummy, Info, "Exec Get on '%s'\n", chan->name().c_str()); { epicsGuard G(lock); raw->reply(current); } }); conn->onPut([this, chan](std::unique_ptr&& raw, Value&& top) { log_printf(dummy, Info, "Exec Put on '%s'\n", chan->name().c_str()); { epicsTimeStamp now; epicsTimeGetCurrent(&now); epicsGuard G(lock); current["value"] = top["value"].as(); current["timeStamp.secondsPastEpoch"] = now.secPastEpoch+POSIX_TIME_AT_EPICS_EPOCH; current["timeStamp.nanoseconds"] = now.nsec; } raw->reply(); // inform client that Put was successful }); epicsGuard G(lock); conn->connect(current); // only type is used }); // callback when client executing RPC chan->onRPC([this, chan](std::unique_ptr&& raw, Value&& top) { log_printf(dummy, Info, "Begin RPC on '%s' with %s\n", chan->name().c_str(), std::string(SB()<reply(ret); }); } }; } // namespace int main(int argc, char *argv[]) { int ret = 0; try { pvxs::logger_level_set("dummyserv", pvxs::Level::Info); pvxs::logger_config_env(); auto src = std::make_shared("blah"); auto serv = Server::Config::from_env() .build() .addSource("dummy", src); auto& conf = serv.config(); std::cout<<"Serving from :\n"; for(auto& iface : conf.interfaces) { std::cout<<" "<