From 57ecf70803021d19499ac30c9dd78bb6b49d3a9a Mon Sep 17 00:00:00 2001 From: Tomasz Kozak <tomasz.kozak@desy.de> Date: Tue, 27 Sep 2022 14:50:48 +0200 Subject: [PATCH] Fix examples --- example/TimerDummyDevice.cc | 8 +++ example/config/dummy.dmap | 2 + example/demoApp.cc | 45 +++++++------ example2/demoApp2.cc | 8 +-- example2a/demoApp2a.cc | 24 +++++-- example2c/demoApp2c.cc | 42 ++++++++----- example3/demoApp3.cc | 20 +++--- example_status_monitor/demoStatusMonitor.cc | 70 ++++++++++++--------- example_template/include/Server.h | 7 +-- example_template/src/Server.cc | 6 +- 10 files changed, 140 insertions(+), 92 deletions(-) diff --git a/example/TimerDummyDevice.cc b/example/TimerDummyDevice.cc index 8163cd54..0bd8d013 100644 --- a/example/TimerDummyDevice.cc +++ b/example/TimerDummyDevice.cc @@ -1,12 +1,15 @@ // SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de> // SPDX-License-Identifier: LGPL-3.0-or-later #include <ChimeraTK/BackendFactory.h> +#include <ChimeraTK/BackendRegisterCatalogue.h> #include <ChimeraTK/DeviceAccessVersion.h> #include <ChimeraTK/DeviceBackendImpl.h> +#include <ChimeraTK/LNMBackendRegisterInfo.h> #include <ChimeraTK/NDRegisterAccessor.h> template<typename UserType> class TimerDummyRegisterAccessor; +namespace ctk = ChimeraTK; class TimerDummy : public ChimeraTK::DeviceBackendImpl { public: @@ -32,6 +35,11 @@ class TimerDummy : public ChimeraTK::DeviceBackendImpl { std::string readDeviceInfo() override { return std::string("Dummy timing device "); } + // return just an empty Catalogue for interface compability + ctk::RegisterCatalogue getRegisterCatalogue() const override { + return ctk::RegisterCatalogue(std::make_unique<ctk::BackendRegisterCatalogue<ctk::LNMBackendRegisterInfo>>()); + } + /** Class to register the backend type with the factory. */ class BackendRegisterer { public: diff --git a/example/config/dummy.dmap b/example/config/dummy.dmap index bd8fc658..a9dfd880 100644 --- a/example/config/dummy.dmap +++ b/example/config/dummy.dmap @@ -1,2 +1,4 @@ Device sdm://./DemoDummy:0=DemoDummy.map DemoDummy.map Timer sdm://./TimerDummy:0=TimerDummy.map TimerDummy.map + +#Timer (TimerDummy?map=TimerDummy.map) diff --git a/example/demoApp.cc b/example/demoApp.cc index 8868f94c..facd512d 100644 --- a/example/demoApp.cc +++ b/example/demoApp.cc @@ -64,37 +64,46 @@ struct TableGeneration : public ctk::ApplicationModule { }; struct ExampleApp : public ctk::Application { - ExampleApp() : Application("exampleApp") {} + ExampleApp() : Application("exampleApp") { + dumpConnections(); + // dumpConnectionGraph(); + dumpGraph(); + dumpModuleGraph("module-graph.dot"); + } ~ExampleApp() { shutdown(); } + ctk::SetDMapFilePath dmapPath{"dummy.dmap"}; + Automation automation{this, "automation", "..."}; TableGeneration tableGeneration{this, "tableGeneration", "..."}; + // ctk::DeviceModule dev{this, "Device"}; ctk::DeviceModule dev{this, "Device"}; + // ctk::DeviceModule timer{this, "Timer"}; ctk::DeviceModule timer{this, "Timer"}; - ctk::ControlSystemModule cs; - void defineConnections(); + // ctk::ControlSystemModule cs; // -> not needed anymore as all is connected to cs automatically + // void defineConnections(); // -> not needed anymore as all is connected to cs automatically }; ExampleApp theExampleApp; -void ExampleApp::defineConnections() { - ChimeraTK::setDMapFilePath("dummy.dmap"); +// void ExampleApp::defineConnections() { +// ChimeraTK::setDMapFilePath("dummy.dmap"); - cs("setpoint") >> automation.opSP; - automation.curSP >> tableGeneration.tableParameters.setpoint >> cs("currentSetpoint"); +// cs("setpoint") >> automation.opSP; +// automation.curSP >> tableGeneration.tableParameters.setpoint >> cs("currentSetpoint"); - auto macropulseNr = timer("macropulseNr", typeid(int), 1, ctk::UpdateMode::push); - macropulseNr >> automation.trigger; +// auto macropulseNr = timer("macropulseNr", typeid(int), 1, ctk::UpdateMode::push); +// macropulseNr >> automation.trigger; - cs("pulseLength") >> tableGeneration.tableParameters.pulseLength; +// cs("pulseLength") >> tableGeneration.tableParameters.pulseLength; - tableGeneration.setpointTable >> dev("setpointTable"); - tableGeneration.feedforwardTable >> dev("feedforwardTable"); +// tableGeneration.setpointTable >> dev("setpointTable"); +// tableGeneration.feedforwardTable >> dev("feedforwardTable"); - dev("probeSignal", typeid(int), tableLength)[macropulseNr] >> cs("probeSignal"); +// dev("probeSignal", typeid(int), tableLength)[macropulseNr] >> cs("probeSignal"); - dumpConnections(); - dumpConnectionGraph(); - dumpGraph(); - dumpModuleGraph("module-graph.dot"); -} +// dumpConnections(); +// dumpConnectionGraph(); +// dumpGraph(); +// dumpModuleGraph("module-graph.dot"); +//} diff --git a/example2/demoApp2.cc b/example2/demoApp2.cc index 35fe6ef3..512e9088 100644 --- a/example2/demoApp2.cc +++ b/example2/demoApp2.cc @@ -24,14 +24,14 @@ struct Controller : public ctk::ApplicationModule { }; struct ExampleApp : public ctk::Application { - ExampleApp() : Application("demoApp2") { ChimeraTK::setDMapFilePath("example2.dmap"); } + ExampleApp() : Application("demoApp2") {} ~ExampleApp() { shutdown(); } - ctk::PeriodicTrigger timer{this, "Timer", "Periodic timer for the controller", 1000}; + ctk::SetDMapFilePath dmapPath{"example2.dmap"}; + ctk::PeriodicTrigger timer{this, "Timer", "Periodic timer for the controller", 1000}; // Look at the map file: This device provides "Heater/temperatureReadback" and "Heater/heatingCurrent". - ctk::ConnectingDeviceModule oven{this, "oven", "/Timer/tick"}; - + ctk::DeviceModule oven{this, "oven", "/Timer/tick"}; // Pick the name "Heater" for the controller module. Now the variable "Heater/temperatureReadback" and // "Heater/heatingCurrent" are automatically connected to the matching variables on the device. Controller controller{this, "Heater", "A controller for the heater of the oven."}; diff --git a/example2a/demoApp2a.cc b/example2a/demoApp2a.cc index f95783f5..c695d6b0 100644 --- a/example2a/demoApp2a.cc +++ b/example2a/demoApp2a.cc @@ -28,7 +28,7 @@ struct Automation : public ctk::ApplicationModule { using ctk::ApplicationModule::ApplicationModule; ctk::ScalarPollInput<double> opSp{this, "operatorSetpoint", "degC", "...", {"CS"}}; ctk::ScalarOutput<double> actSp{this, "temperatureSetpoint", "degC", "...", {"Controller"}}; - ctk::ScalarPushInput<uint64_t> trigger{this, "trigger", "", "..."}; + ctk::ScalarPushInput<uint64_t> trigger{this, "/Timer/tick", "", "..."}; void mainLoop() { const double maxStep = 0.1; @@ -41,23 +41,34 @@ struct Automation : public ctk::ApplicationModule { }; struct ExampleApp : public ctk::Application { - ExampleApp() : Application("exampleApp2a") {} + ExampleApp() : Application("exampleApp2a") { + if(config.get<int>("enableAutomation")) { + automation = Automation(this, "Automation", "Slow setpoint ramping algorithm"); + // automation.findTag("Controller").connectTo(controller); + // timer.tick >> automation.trigger; + } + } ~ExampleApp() { shutdown(); } + ctk::SetDMapFilePath dmapPath{"example2.dmap"}; + ctk::ConfigReader config{this, "config", "demoApp2a.xml"}; Controller controller{this, "Controller", "The Controller"}; - Automation automation; ctk::PeriodicTrigger timer{this, "Timer", "Periodic timer for the controller", 1000}; - ctk::DeviceModule oven{this, "oven"}; - ctk::ControlSystemModule cs; + // ctk::DeviceModule oven{this, "oven"}; + ctk::DeviceModule oven{this, "oven", "/Timer/tick"}; + + Automation automation; - void defineConnections(); + // ctk::ControlSystemModule cs; + // void defineConnections(); }; static ExampleApp theExampleApp; +/* void ExampleApp::defineConnections() { ChimeraTK::setDMapFilePath("example2.dmap"); @@ -71,3 +82,4 @@ void ExampleApp::defineConnections() { controller.findTag("DEV").connectTo(oven["heater"], timer.tick); findTag("CS").connectTo(cs); } +*/ diff --git a/example2c/demoApp2c.cc b/example2c/demoApp2c.cc index 9b052f93..fba63293 100644 --- a/example2c/demoApp2c.cc +++ b/example2c/demoApp2c.cc @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de> // SPDX-License-Identifier: LGPL-3.0-or-later #include <ChimeraTK/ApplicationCore/ApplicationCore.h> +#include <ChimeraTK/ApplicationCore/DeviceManager.h> #include <ChimeraTK/ApplicationCore/EnableXMLGenerator.h> #include <ChimeraTK/ApplicationCore/PeriodicTrigger.h> @@ -24,32 +25,41 @@ struct Controller : public ctk::ApplicationModule { }; struct ExampleApp : public ctk::Application { - ExampleApp() : Application("demoApp2") {} + ExampleApp() : Application("demoApp2") { + // ChimeraTK::setDMapFilePath("example2.dmap"); + // ovenManger.addInitialisationHandler(&initialiseOven); + } ~ExampleApp() { shutdown(); } + ctk::SetDMapFilePath dmapPath{"example2.dmap"}; + // We can pick any name for the module. "Oven" is what we want to see in the CS Controller controller{this, "Oven", "The controller of the oven"}; ctk::PeriodicTrigger timer{this, "Timer", "Periodic timer for the controller", 1000}; - ctk::DeviceModule oven{this, "oven", &initialiseOven}; - ctk::ControlSystemModule cs; + // ctk::DeviceManager ovenManger{this, "oven"}; - void defineConnections(); - static void initialiseOven(ChimeraTK::DeviceModule* oven); + // ctk::DeviceModule oven{this, "oven", &initialiseOven}; -> replaced with ConnectingDeviceModule + ctk::DeviceModule oven{this, "oven", "/Timer/tick", &initialiseOven}; + // ctk::ControlSystemModule cs; -> not needed anymore as all is connected to cs automatically + + // void defineConnections(); -> not needed anymore as all is connected to cs automatically + static void initialiseOven(ChimeraTK::DeviceManager* oven); }; static ExampleApp theExampleApp; -void ExampleApp::defineConnections() { - ChimeraTK::setDMapFilePath("example2.dmap"); - - // Connect everything to the CS (except for the device, which is special) - findTag(".*").connectTo(cs); - // Connect device's "heater" to "Oven" in the CS, and use timer.tick as trigger - oven["heater"].connectTo(cs["Oven"], timer.tick); -} - -void ExampleApp::initialiseOven(ChimeraTK::DeviceModule* oven) { +void ExampleApp::initialiseOven(ChimeraTK::DeviceManager* ovenManager) { // set the gain factors for the voltage monitoring ADCs - oven->device.write<uint32_t>("/settings/supplyVoltageAdcGains", {20, 1, 1, 1}); + // ovenManager->device.write<uint32_t>("/settings/supplyVoltageAdcGains", {20, 1, 1, 1}); + ovenManager->getDevice().write<uint32_t>("/settings/supplyVoltageAdcGains", {20, 1, 1, 1}); } + +// void ExampleApp::defineConnections() { +// ChimeraTK::setDMapFilePath("example2.dmap"); + +// // Connect everything to the CS (except for the device, which is special) +// findTag(".*").connectTo(cs); +// // Connect device's "heater" to "Oven" in the CS, and use timer.tick as trigger +// oven["heater"].connectTo(cs["Oven"], timer.tick); +//} diff --git a/example3/demoApp3.cc b/example3/demoApp3.cc index 1823c5b9..e3f8cb7e 100644 --- a/example3/demoApp3.cc +++ b/example3/demoApp3.cc @@ -7,19 +7,21 @@ namespace ctk = ChimeraTK; struct ExampleApp : public ctk::Application { - ExampleApp() : Application("exampleApp3") {} + ExampleApp() : Application("exampleApp3") { debugMakeConnections(); } ~ExampleApp() { shutdown(); } - ctk::PeriodicTrigger timer{this, "Timer", "Periodic timer for the controller", 1000}; + ctk::SetDMapFilePath dmapPath{"example2.dmap"}; - ctk::DeviceModule dev{this, "oven"}; - ctk::ControlSystemModule cs; + ctk::PeriodicTrigger timer{this, "Timer", "Periodic timer for the controller", 1000}; - void defineConnections(); + // ctk::DeviceModule dev{this, "oven"}; + ctk::DeviceModule dev{this, "oven", "/Timer/tick"}; + // ctk::ControlSystemModule cs; + // void defineConnections(); }; static ExampleApp theExampleApp; -void ExampleApp::defineConnections() { - ChimeraTK::setDMapFilePath("example2.dmap"); - dev.connectTo(cs, timer.tick); -} +// void ExampleApp::defineConnections() { +// ChimeraTK::setDMapFilePath("example2.dmap"); +// dev.connectTo(cs, timer.tick); +// } diff --git a/example_status_monitor/demoStatusMonitor.cc b/example_status_monitor/demoStatusMonitor.cc index ab86a7f7..2e81b027 100644 --- a/example_status_monitor/demoStatusMonitor.cc +++ b/example_status_monitor/demoStatusMonitor.cc @@ -48,7 +48,16 @@ struct SimulationModule : public ctk::ApplicationModule { }; struct ExampleApp : public ctk::Application { - ExampleApp() : Application("exampleApp") {} + ExampleApp() : Application("exampleApp") { + // show how it looks in the application (C++ hierarchy) + dump(); + + // show how it looks on the cs side (virtual hierarchy) + // cs.dump(); + + // show how it is connected + dumpConnections(); + } ~ExampleApp() { shutdown(); } // Create an instance of the simulation module. We name it "Simulation". @@ -73,44 +82,43 @@ struct ExampleApp : public ctk::Application { } simulationGroup{this, "Simulation", ""}; ctk::ConfigReader config{this, "Config", "demoStatusMonitor_config.xml"}; - ctk::ControlSystemModule cs; - - void defineConnections(); + // ctk::ControlSystemModule cs; + // void defineConnections(); }; ExampleApp theExampleApp; -void ExampleApp::defineConnections() { - // Usually you set the dmap file here. This example does not have one. +// void ExampleApp::defineConnections() { +// // Usually you set the dmap file here. This example does not have one. - // Connect everything in the app to the cs. This makes the connection of temperature from Simulation to the input of - // the monitor because they are the same variable in the CS module. Also the disable variable if the monitor is - // connected to the CS. Try what happens if you disable the monitor. - findTag(".*").connectTo(cs); +// // Connect everything in the app to the cs. This makes the connection of temperature from Simulation to the input of +// // the monitor because they are the same variable in the CS module. Also the disable variable if the monitor is +// // connected to the CS. Try what happens if you disable the monitor. +// findTag(".*").connectTo(cs); - /* The trick of connecting the temperature automatically only worked because we put the temperatureMonitor into the - * correct place in the hierarchy by putting it into the variable group "Simulation". However, the threshold - * parameters inside the monitor are not connected yet. - * - * When connecting the app, the config created the following variables: - * /Config/TemperatureMonitor/lowerWarningThreshold - * /Config/TemperatureMonitor/upperWarningThreshold - * /Config/TemperatureMonitor/lowerFaultThreshold - * /Config/TemperatureMonitor/upperFaultThreshold - */ +// /* The trick of connecting the temperature automatically only worked because we put the temperatureMonitor into the +// * correct place in the hierarchy by putting it into the variable group "Simulation". However, the threshold +// * parameters inside the monitor are not connected yet. +// * +// * When connecting the app, the config created the following variables: +// * /Config/TemperatureMonitor/lowerWarningThreshold +// * /Config/TemperatureMonitor/upperWarningThreshold +// * /Config/TemperatureMonitor/lowerFaultThreshold +// * /Config/TemperatureMonitor/upperFaultThreshold +// */ - // Now we connect the parameters of the temperature monitor to the control system, right into the Config directory so - // the variable names match. Like this the parameters are connected to the values coming from the configuration. - findTag("CONFIG").flatten().connectTo(cs["Config"]["TemperatureMonitor"]); +// // Now we connect the parameters of the temperature monitor to the control system, right into the Config directory so +// // the variable names match. Like this the parameters are connected to the values coming from the configuration. +// findTag("CONFIG").flatten().connectTo(cs["Config"]["TemperatureMonitor"]); - // FIXME: At this point a status aggregator would connect everything with tag STATUS +// // FIXME: At this point a status aggregator would connect everything with tag STATUS - // show how it looks in the application (C++ hierarchy) - dump(); +// // show how it looks in the application (C++ hierarchy) +// dump(); - // show how it looks on the cs side (virtual hierarchy) - cs.dump(); +// // show how it looks on the cs side (virtual hierarchy) +// cs.dump(); - // show how it is connected - dumpConnections(); -} +// // show how it is connected +// dumpConnections(); +//} diff --git a/example_template/include/Server.h b/example_template/include/Server.h index dcc4dac6..1b561651 100644 --- a/example_template/include/Server.h +++ b/example_template/include/Server.h @@ -25,11 +25,8 @@ namespace ctk = ChimeraTK; struct Server : public ctk::Application { Server(std::string appName = "TemplateServer"); ~Server() override; - + ctk::SetDMapFilePath dmapPath; ctk::ConfigReader config; - ctk::ConnectingDeviceModule device; + ctk::DeviceModule device; TemplateModule templateModule; }; - - - diff --git a/example_template/src/Server.cc b/example_template/src/Server.cc index 765c3776..b81bb579 100644 --- a/example_template/src/Server.cc +++ b/example_template/src/Server.cc @@ -6,12 +6,12 @@ #include "version.h" Server::Server(std::string appName) -: ctk::Application(appName), config{this, "Configuration", getName() + "-Config.xml"}, device{this, - "MappedDummyDevice"}, +: ctk::Application(appName), + dmapPath(appName + ".dmap"), config{this, "Configuration", getName() + "-Config.xml"}, device{this, + "MappedDummyDevice"}, templateModule{this, "TemplateModule", "This is a template module, adapt as needed!"} { std::cout << "*** Construction of " << appName << " in version " << AppVersion::major << "." << AppVersion::minor << "." << AppVersion::patch << " starts. ***" << std::endl; - ctk::setDMapFilePath(getName() + ".dmap"); std::cout << "*** Construction of " << appName << " in version " << AppVersion::major << "." << AppVersion::minor << "." << AppVersion::patch << " done. ***" << std::endl; } -- GitLab