Fawkes API  Fawkes Development Version
config_adapter.cpp
1 
2 /***************************************************************************
3  * config_adapter.cpp - PLEXIL adapter for protobuf_comm
4  *
5  * Created: Thu Aug 16 11:06:55 2018
6  * Copyright 2006-2018 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Library General Public License for more details.
18  *
19  * Read the full text in the LICENSE.GPL file in the doc directory.
20  */
21 
22 #include "config_adapter.h"
23 
24 #include "utils.h"
25 
26 #include <AdapterConfiguration.hh>
27 #include <AdapterExecInterface.hh>
28 #include <AdapterFactory.hh>
29 #include <Command.hh>
30 #include <InterfaceManager.hh>
31 #include <StateCacheEntry.hh>
32 #include <limits>
33 
34 using namespace fawkes;
35 
36 /** @class ConfigurationPlexilAdapter "config_adapter.h"
37  * Plexil adapter to provide access to the Fawkes configuration.
38  * @author Tim Niemueller
39  */
40 
41 /** Constructor.
42  * @param execInterface Reference to the parent AdapterExecInterface object.
43  */
44 ConfigurationPlexilAdapter::ConfigurationPlexilAdapter(PLEXIL::AdapterExecInterface &execInterface)
45 : InterfaceAdapter(execInterface)
46 {
47 }
48 
49 /** Constructor from configuration XML.
50  * @param execInterface Reference to the parent AdapterExecInterface object.
51  * @param xml A const reference to the XML element describing this adapter
52  * @note The instance maintains a shared pointer to the XML.
53  */
54 ConfigurationPlexilAdapter::ConfigurationPlexilAdapter(PLEXIL::AdapterExecInterface &execInterface,
55  pugi::xml_node const xml)
56 : InterfaceAdapter(execInterface, xml)
57 {
58 }
59 
60 /** Destructor. */
62 {
63 }
64 
65 /** Initialize adapter.
66  * @return true if initialization was successful, false otherwise.
67  */
68 bool
70 {
71  logger_ = reinterpret_cast<fawkes::Logger *>(m_execInterface.getProperty("::Fawkes::Logger"));
72  config_ =
73  reinterpret_cast<fawkes::Configuration *>(m_execInterface.getProperty("::Fawkes::Config"));
74 
75  namespace p = std::placeholders;
76  commands_ = {
77  {"config_get_int_or_default",
78  std::bind(&ConfigurationPlexilAdapter::config_get_value_or_default,
79  this,
80  p::_1,
81  PLEXIL::INTEGER_TYPE)},
82  {"config_get_real_or_default",
83  std::bind(
84  &ConfigurationPlexilAdapter::config_get_value_or_default, this, p::_1, PLEXIL::REAL_TYPE)},
85  {"config_get_bool_or_default",
86  std::bind(&ConfigurationPlexilAdapter::config_get_value_or_default,
87  this,
88  p::_1,
89  PLEXIL::BOOLEAN_TYPE)},
90  {"config_get_string_or_default",
91  std::bind(
92  &ConfigurationPlexilAdapter::config_get_value_or_default, this, p::_1, PLEXIL::STRING_TYPE)},
93  {"config_get_int",
94  std::bind(&ConfigurationPlexilAdapter::config_get_value, this, p::_1, PLEXIL::INTEGER_TYPE)},
95  {"config_get_real",
96  std::bind(&ConfigurationPlexilAdapter::config_get_value, this, p::_1, PLEXIL::REAL_TYPE)},
97  {"config_get_bool",
98  std::bind(&ConfigurationPlexilAdapter::config_get_value, this, p::_1, PLEXIL::BOOLEAN_TYPE)},
99  {"config_get_string",
100  std::bind(&ConfigurationPlexilAdapter::config_get_value, this, p::_1, PLEXIL::STRING_TYPE)},
101  {"config_exists", std::bind(&ConfigurationPlexilAdapter::config_exists, this, p::_1)},
102  };
103 
104  for (const auto &c : commands_) {
105  PLEXIL::g_configuration->registerCommandInterface(c.first, this);
106  }
107 
108  return true;
109 }
110 
111 /** Start adapter.
112  * @return true if starting was successful, false otherwise.
113  */
114 bool
116 {
117  return true;
118 }
119 
120 /** Stop adapter.
121  * @return true if successful, false otherwise.
122  */
123 bool
125 {
126  return true;
127 }
128 
129 /** Reset adapter.
130  * @return true if successful, false otherwise.
131  */
132 bool
134 {
135  return true;
136 }
137 
138 /** Shut adapter down.
139  * @return true if successful, false otherwise.
140  */
141 bool
143 {
144  return true;
145 }
146 
147 /** Perform given command.
148  * @param cmd command to execute
149  */
150 void
152 {
153  std::string const &name = cmd->getName();
154 
155  auto c = commands_.find(name);
156  if (c != commands_.end()) {
157  c->second(cmd);
158  } else {
159  warn("ConfigCommAdapter:executeCommand: called for unknown"
160  " command "
161  << name);
162  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_FAILED);
163  m_execInterface.notifyOfExternalEvent();
164  }
165 }
166 
167 /** Abort currently running execution.
168  * @param cmd command to abort
169  */
170 void
172 {
173  m_execInterface.handleCommandAbortAck(cmd, false);
174  m_execInterface.notifyOfExternalEvent();
175 }
176 
177 void
178 ConfigurationPlexilAdapter::config_get_value_or_default(PLEXIL::Command * cmd,
179  PLEXIL::ValueType value_type)
180 {
181  std::vector<PLEXIL::Value> const &args = cmd->getArgValues();
182  if (!verify_args(args,
183  "ConfigCommAdapter:config_get_value_or_default",
184  {{"path", PLEXIL::STRING_TYPE}, {"default", value_type}})) {
185  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_FAILED);
186  m_execInterface.notifyOfExternalEvent();
187  return;
188  }
189 
190  std::string path;
191  args[0].getValue(path);
192 
193  try {
194  switch (value_type) {
195  case PLEXIL::STRING_TYPE: {
196  std::string default_value;
197  args[1].getValue(default_value);
198  std::string v = config_->get_string_or_default(path.c_str(), default_value);
199  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
200  } break;
201 
202  case PLEXIL::REAL_TYPE: {
203  double default_value;
204  args[1].getValue(default_value);
205 
206  double v = default_value;
207  // do not use "or_default" here since it can only represent float
208  try {
209  v = config_->get_float(path.c_str());
210  } catch (Exception &e) {
211  } // ignored, use default
212  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
213  } break;
214 
215  case PLEXIL::BOOLEAN_TYPE: {
216  bool default_value;
217  args[1].getValue(default_value);
218  bool v = config_->get_bool_or_default(path.c_str(), default_value);
219  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
220  } break;
221 
222  case PLEXIL::INTEGER_TYPE: {
223  int default_value;
224  args[1].getValue(default_value);
225  if (config_->is_uint(path.c_str())) {
226  unsigned int uv = config_->get_uint(path.c_str());
227  if (uv > std::numeric_limits<int>::max()) {
228  warn("ConfigCommAdapter:config_get_value_or_default:"
229  << " Unsigned integer too large to store in int (" << uv << ")");
230  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
231  m_execInterface.notifyOfExternalEvent();
232  return;
233  }
234  }
235  int v = config_->get_int_or_default(path.c_str(), default_value);
236  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
237  } break;
238 
239  default:
240  // this would only occur when misconfiguring in initialize()
241  warn("ConfigCommAdapter:config_get_value_or_default:"
242  << " Unsupported Plexil type " << PLEXIL::valueTypeName(value_type));
243  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
244  m_execInterface.notifyOfExternalEvent();
245  return;
246  }
247 
248  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
249  m_execInterface.notifyOfExternalEvent();
250 
251  } catch (Exception &e) {
252  warn("ConfigCommAdapter:config_get_value_or_default:"
253  << " Failed to get value " << path << " as " << PLEXIL::valueTypeName(value_type) << ": "
254  << e.what_no_backtrace());
255  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
256  m_execInterface.notifyOfExternalEvent();
257  return;
258  }
259 }
260 
261 void
262 ConfigurationPlexilAdapter::config_get_value(PLEXIL::Command *cmd, PLEXIL::ValueType value_type)
263 {
264  std::vector<PLEXIL::Value> const &args = cmd->getArgValues();
265  if (!verify_args(args, "ConfigCommAdapter:config_get_value", {{"path", PLEXIL::STRING_TYPE}})) {
266  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_FAILED);
267  m_execInterface.notifyOfExternalEvent();
268  return;
269  }
270 
271  std::string path;
272  args[0].getValue(path);
273 
274  try {
275  switch (value_type) {
276  case PLEXIL::STRING_TYPE: {
277  std::string v = config_->get_string(path.c_str());
278  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
279  } break;
280 
281  case PLEXIL::REAL_TYPE: {
282  float v = config_->get_float(path.c_str());
283  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value((double)v));
284  } break;
285 
286  case PLEXIL::BOOLEAN_TYPE: {
287  bool v = config_->get_bool(path.c_str());
288  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
289  } break;
290 
291  case PLEXIL::INTEGER_TYPE: {
292  if (config_->is_uint(path.c_str())) {
293  unsigned int uv = config_->get_uint(path.c_str());
294  if (uv > std::numeric_limits<int>::max()) {
295  warn("ConfigCommAdapter:config_get_value:"
296  << " Unsigned integer too large to store in int (" << uv << ")");
297  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
298  m_execInterface.notifyOfExternalEvent();
299  return;
300  }
301  }
302  int v = config_->get_int(path.c_str());
303  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(v));
304  } break;
305 
306  default:
307  // this would only occur when misconfiguring in initialize()
308  warn("ConfigCommAdapter:config_get_value:"
309  << " Unsupported Plexil type " << PLEXIL::valueTypeName(value_type));
310  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_FAILED);
311  m_execInterface.notifyOfExternalEvent();
312  return;
313  }
314 
315  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
316  m_execInterface.notifyOfExternalEvent();
317 
318  } catch (Exception &e) {
319  warn("ConfigCommAdapter:config_get_value:"
320  << " Failed to get value " << path << " as " << PLEXIL::valueTypeName(value_type) << ": "
321  << e.what_no_backtrace());
322  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_FAILED);
323  m_execInterface.notifyOfExternalEvent();
324  return;
325  }
326 }
327 
328 void
329 ConfigurationPlexilAdapter::config_exists(PLEXIL::Command *cmd)
330 {
331  std::vector<PLEXIL::Value> const &args = cmd->getArgValues();
332  if (!verify_args(args, "ConfigCommAdapter:config_exists", {{"path", PLEXIL::STRING_TYPE}})) {
333  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_FAILED);
334  m_execInterface.notifyOfExternalEvent();
335  return;
336  }
337 
338  std::string path;
339  args[0].getValue(path);
340 
341  try {
342  m_execInterface.handleCommandReturn(cmd, PLEXIL::Value(config_->exists(path.c_str())));
343  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
344  m_execInterface.notifyOfExternalEvent();
345  } catch (Exception &e) {
346  warn("ConfigCommAdapter:config_exists:"
347  << " Failed to check " << path << ": " << e.what_no_backtrace());
348  m_execInterface.handleCommandAck(cmd, PLEXIL::COMMAND_SUCCESS);
349  m_execInterface.notifyOfExternalEvent();
350  return;
351  }
352 }
353 
354 extern "C" {
355 void
356 initFawkesConfigurationAdapter()
357 {
358  REGISTER_ADAPTER(ConfigurationPlexilAdapter, "FawkesConfigurationAdapter");
359 }
360 }
ConfigurationPlexilAdapter::~ConfigurationPlexilAdapter
virtual ~ConfigurationPlexilAdapter()
Destructor.
Definition: config_adapter.cpp:61
ConfigurationPlexilAdapter
Interface adapter to provide logging facilities.
Definition: config_adapter.h:35
ConfigurationPlexilAdapter::reset
virtual bool reset()
Reset adapter.
Definition: config_adapter.cpp:133
ConfigurationPlexilAdapter::stop
virtual bool stop()
Stop adapter.
Definition: config_adapter.cpp:124
fawkes::Configuration::get_bool
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
ConfigurationPlexilAdapter::initialize
virtual bool initialize()
Initialize adapter.
Definition: config_adapter.cpp:69
ConfigurationPlexilAdapter::ConfigurationPlexilAdapter
ConfigurationPlexilAdapter(PLEXIL::AdapterExecInterface &execInterface)
Constructor.
Definition: config_adapter.cpp:44
fawkes::Configuration::get_int
virtual int get_int(const char *path)=0
Get value from configuration which is of type int.
fawkes::Configuration
Interface for configuration handling.
Definition: config.h:65
fawkes::Configuration::get_bool_or_default
virtual bool get_bool_or_default(const char *path, const bool &default_val)
Get value from configuration which is of type bool, or the given default if the path does not exist.
Definition: config.cpp:726
fawkes::Logger
Interface for logging.
Definition: logger.h:42
fawkes
Fawkes library namespace.
ConfigurationPlexilAdapter::start
virtual bool start()
Start adapter.
Definition: config_adapter.cpp:115
fawkes::Configuration::is_uint
virtual bool is_uint(const char *path)=0
Check if a value is of type unsigned int.
fawkes::Exception::what_no_backtrace
virtual const char * what_no_backtrace() const
Get primary string (does not implicitly print the back trace).
Definition: exception.cpp:663
fawkes::Configuration::get_float
virtual float get_float(const char *path)=0
Get value from configuration which is of type float.
fawkes::Configuration::get_uint
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
fawkes::Configuration::get_string
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
ConfigurationPlexilAdapter::shutdown
virtual bool shutdown()
Shut adapter down.
Definition: config_adapter.cpp:142
ConfigurationPlexilAdapter::invokeAbort
void invokeAbort(PLEXIL::Command *cmd)
Abort currently running execution.
Definition: config_adapter.cpp:171
fawkes::Configuration::get_string_or_default
virtual std::string get_string_or_default(const char *path, const std::string &default_val)
Get value from configuration which is of type string, or the given default if the path does not exist...
Definition: config.cpp:736
fawkes::Configuration::get_int_or_default
virtual int get_int_or_default(const char *path, const int &default_val)
Get value from configuration which is of type int, or the given default if the path does not exist.
Definition: config.cpp:716
fawkes::Configuration::exists
virtual bool exists(const char *path)=0
Check if a given value exists.
ConfigurationPlexilAdapter::executeCommand
void executeCommand(PLEXIL::Command *cmd)
Perform given command.
Definition: config_adapter.cpp:151
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36