libcyberradio  22.01.24
WbddcGroupComponent.cpp
1 /***************************************************************************
2  * \file WbddcGroupComponent.cpp
3  * \brief Defines the basic WBDDC group interface for an NDR-class radio.
4  * \author DA
5  * \author NH
6  * \author MN
7  * \copyright (c) 2018 CyberRadio Solutions, Inc. All rights reserved.
8  *
9  ***************************************************************************/
10 
11 #include "LibCyberRadio/Driver/RadioHandler.h"
12 #include "LibCyberRadio/Driver/WbddcGroupComponent.h"
13 #include "LibCyberRadio/Common/Pythonesque.h"
14 #include <boost/lexical_cast.hpp>
15 #include <sstream>
16 #include <iomanip>
17 #include <algorithm>
18 
19 
20 namespace LibCyberRadio
21 {
22  namespace Driver
23  {
25  const std::string& name,
26  int index,
27  RadioHandler* parent,
28  bool debug,
29  int numGroupMembers,
30  int groupMemberIndexBase) :
31  RadioComponent(name, index, parent, debug),
32  _numGroupMembers(numGroupMembers),
33  _groupMemberIndexBase(groupMemberIndexBase)
34  {
36  }
37 
39  {
40  }
41 
43  RadioComponent(other),
44  _numGroupMembers(other._numGroupMembers),
45  _groupMemberIndexBase(other._groupMemberIndexBase)
46  {
47  }
48 
50  {
52  if ( this != &other )
53  {
54  _numGroupMembers = other._numGroupMembers;
55  _groupMemberIndexBase = other._groupMemberIndexBase;
56  }
57  return *this;
58  }
59 
60  bool WbddcGroupComponent::enable(bool enabled)
61  {
62  bool adjEnabled = enabled;
63  bool ret = false;
64  if ( _config.hasKey("enable") )
65  {
66  ret = executeWbddcGroupEnableCommand(_index, adjEnabled);
67  if ( ret )
68  {
69  _enabled = adjEnabled;
71  }
72  }
73  return ret;
74  }
75 
77  {
78  this->debug("[WbddcGroupComponent::setConfiguration] Called\n");
79  // Call the "grandparent" version of this method instead of the
80  // parent version. We want the normalization, but not the
81  // automatic enabling.
82  bool ret = Configurable::setConfiguration(cfg);
83  bool adjEnabled = _enabled;
84  BasicIntList adjMembers = _groupMembers;
85  bool enableCmdNeedsExecuting = false;
86  bool memberCmdNeedsExecuting = false;
87  if ( cfg.hasKey("enable") && _config.hasKey("enable") )
88  {
89  adjEnabled = getConfigurationValueAsBool("enable");
90  enableCmdNeedsExecuting = true;
91  }
92  if ( cfg.hasKey("members") && _config.hasKey("members") )
93  {
95  adjMembers.clear();
96  for( BasicStringList::const_iterator it = vec.begin(); it != vec.end(); it++ )
97  {
98  adjMembers.push_back( boost::lexical_cast<int>(Pythonesque::Strip(*it)) );
99  }
100  memberCmdNeedsExecuting = true;
101  }
102  if ( memberCmdNeedsExecuting )
103  {
104  ret &= executeWbddcGroupCommand(_index, adjMembers);
105  }
106  if ( enableCmdNeedsExecuting )
107  {
108  ret &= executeWbddcGroupEnableCommand(_index, adjEnabled);
109  }
110  if ( ret )
111  {
112  _enabled = adjEnabled;
113  _groupMembers = adjMembers;
115  }
116  this->debug("[WbddcGroupComponent::setConfiguration] Returning\n");
117  return ret;
118  }
119 
121  {
122  this->debug("[WbddcGroupComponent::queryConfiguration] Called\n");
123  if ( _config.hasKey("enable") )
124  {
125  executeWbddcGroupEnableQuery(_index, _enabled);
126  }
127  if ( _config.hasKey("members") )
128  {
129  executeWbddcGroupQuery(_index, _groupMembers);
130  }
132  this->debug("[WbddcGroupComponent::queryConfiguration] Returning\n");
133  }
134 
136  {
137  return _groupMembers;
138  }
139 
141  {
142  this->debug("[WbddcGroupComponent::setMembers] Called\n");
143  bool ret = false;
144  if ( _config.hasKey("members") )
145  {
146  BasicIntList adjMembers = groupMembers;
147  ret = this->executeWbddcGroupCommand(_index, adjMembers);
148  if (ret)
149  {
150  _groupMembers = groupMembers;
152  }
153  }
154  this->debug("[WbddcGroupComponent::setMembers] Returning %s\n",
155  this->debugBool(ret));
156  return ret;
157  }
158 
160  {
161  this->debug("[WbddcGroupComponent::addMember] Called\n");
162  bool ret = false;
163  if ( _config.hasKey("members") )
164  {
165  bool isMember = true;
166  ret = this->executeWbddcGroupMemberCommand(_index, member, isMember);
167  if (ret)
168  {
169  if ( std::count(_groupMembers.begin(), _groupMembers.end(), member) == 0 )
170  {
171  _groupMembers.push_back(member);
172  std::sort(_groupMembers.begin(), _groupMembers.end());
174  }
175  }
176  }
177  this->debug("[WbddcGroupComponent::addMember] Returning %s\n",
178  this->debugBool(ret));
179  return ret;
180  }
181 
183  {
184  this->debug("[WbddcGroupComponent::removeMember] Called\n");
185  bool ret = false;
186  if ( _config.hasKey("members") )
187  {
188  bool isMember = false;
189  ret = this->executeWbddcGroupMemberCommand(_index, member, isMember);
190  if (ret)
191  {
192  BasicIntList::iterator it = std::find(_groupMembers.begin(), _groupMembers.end(),
193  member);
194  if ( it != _groupMembers.end() )
195  {
196  _groupMembers.erase(it);
198  }
199  }
200  }
201  this->debug("[WbddcGroupComponent::removeMember] Returning %s\n",
202  this->debugBool(ret));
203  return ret;
204  }
205 
207  {
208  _config.clear();
209  // Call the base-class version
211  // Define component-specific keys
212  _config["members"] = "";
213  }
214 
216  {
217  this->debug("[WbddcGroupComponent::updateConfigurationDict] Called\n");
219  if ( _config.hasKey("members") )
221  this->debug("[WbddcGroupComponent::updateConfigurationDict] Returning\n");
222  }
223 
225  {
226  BasicStringList vec;
227  for (BasicIntList::const_iterator it = _groupMembers.begin();
228  it != _groupMembers.end(); it++)
229  {
230  vec.push_back( std::to_string(*it) );
231  }
232  std::string memberStr = Pythonesque::Join(vec, ", ");
233  return memberStr;
234  }
235 
236  // Default implementation is based on the NDR308 model
238  bool& enabled)
239  {
240  this->debug("[WbddcGroupComponent::executeWbddcGroupEnableQuery] Called\n");
241  bool ret = false;
242  if ( (_parent != NULL) && (_parent->isConnected()) )
243  {
244  std::ostringstream oss;
245  oss << "WBGE? " << index << "\n";
246  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
247  if ( _parent->getLastCommandErrorInfo() == "" )
248  {
250  Pythonesque::Replace(rsp.front(), "WBGE ", ""),
251  ", ");
252  // vec[0] = Index
253  // vec[1] = Enabled indicator
254  enabled = (boost::lexical_cast<int>(vec[1]) == 1);
255  ret = true;
256  }
257  }
258  this->debug("[WbddcGroupComponent::executeWbddcGroupEnableQuery] Returning %s\n",
259  this->debugBool(ret));
260  return ret;
261  }
262 
263  // Default implementation is based on the NDR308 model
265  bool& enabled)
266  {
267  this->debug("[WbddcGroupComponent::executeWbddcGroupEnableCommand] Called\n");
268  bool ret = false;
269  if ( (_parent != NULL) && (_parent->isConnected()) )
270  {
271  std::ostringstream oss;
272  oss << "WBGE " << index
273  << ", " << (enabled ? 1 : 0)
274  << "\n";
275  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
276  if ( _parent->getLastCommandErrorInfo() == "" )
277  {
278  ret = true;
279  }
280  }
281  this->debug("[WbddcGroupComponent::executeWbddcGroupEnableCommand] Returning %s\n",
282  this->debugBool(ret));
283  return ret;
284  }
285 
286  // Default implementation is based on the NDR308 model
288  BasicIntList& groupMembers)
289  {
290  this->debug("[WbddcGroupComponent::executeWbddcGroupQuery] Called\n");
291  bool ret = true;
292  bool isMember;
293  groupMembers.clear();
294  for (int member = _groupMemberIndexBase;
295  member < (_groupMemberIndexBase + _numGroupMembers); member++)
296  {
297  ret &= executeWbddcGroupMemberQuery(index, member, isMember);
298  if (ret)
299  {
300  if ( isMember )
301  groupMembers.push_back(member);
302  }
303  else
304  break;
305  }
306  this->debug("[WbddcGroupComponent::executeWbddcGroupQuery] Returning %s\n",
307  this->debugBool(ret));
308  return ret;
309  }
310 
311  // Default implementation is based on the NDR308 model
313  BasicIntList& groupMembers)
314  {
315  this->debug("[WbddcGroupComponent::executeWbddcGroupCommand] Called\n");
316  bool ret = true;
317  bool isMember;
318  for (int member = _groupMemberIndexBase;
319  member < (_groupMemberIndexBase + _numGroupMembers); member++)
320  {
321  isMember = ( std::count(groupMembers.begin(), groupMembers.end(), member) > 0 );
322  ret &= executeWbddcGroupMemberCommand(index, member, isMember);
323  if (!ret)
324  break;
325  }
326  this->debug("[WbddcGroupComponent::executeWbddcGroupCommand] Returning %s\n",
327  this->debugBool(ret));
328  return ret;
329  }
330 
331  bool WbddcGroupComponent::executeWbddcGroupMemberQuery(int index, int groupMember,
332  bool& isMember)
333  {
334  this->debug("[WbddcGroupComponent::executeWbddcGroupMemberQuery] Called\n");
335  bool ret = false;
336  if ( (_parent != NULL) && (_parent->isConnected()) )
337  {
338  std::ostringstream oss;
339  BasicStringList rsp, vec;
340  int inGroup;
341  oss << "WBG? " << index
342  << ", " << groupMember
343  << "\n";
344  rsp = _parent->sendCommand(oss.str(), 2.0);
345  if ( _parent->getLastCommandErrorInfo() == "" )
346  {
347  vec = Pythonesque::Split(
348  Pythonesque::Replace(rsp.front(), "WBG ", ""),
349  ", ");
350  // vec[0] = Group index
351  // vec[1] = Member index
352  // vec[2] = 0 if member is not in group, 1 if it is
353  isMember = ( boost::lexical_cast<int>(vec[2]) == 1 );
354  ret = true;
355  }
356  }
357  this->debug("[WbddcGroupComponent::executeWbddcGroupMemberQuery] Returning %s\n",
358  this->debugBool(ret));
359  return ret;
360  }
361 
362  // Default implementation is based on the NDR308 model
364  bool& isMember)
365  {
366  this->debug("[WbddcGroupComponent::executeWbddcGroupMemberCommand] Called\n");
367  bool ret = false;
368  if ( (_parent != NULL) && (_parent->isConnected()) )
369  {
370  std::ostringstream oss;
371  oss << "WBG " << index
372  << ", " << groupMember
373  << ", " << ( isMember ? 1 : 0 )
374  << "\n";
375  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
376  if ( _parent->getLastCommandErrorInfo() == "" )
377  {
378  ret = true;
379  }
380  }
381  this->debug("[WbddcGroupComponent::executeWbddcGroupMemberCommand] Returning %s\n",
382  this->debugBool(ret));
383  return ret;
384  }
385 
386  } // namespace Driver
387 
388 } // namespace LibCyberRadio
389 
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual bool getConfigurationValueAsBool(const std::string &key) const
Gets a named configuration value as a Boolean.
virtual void queryConfiguration()
Tells the component to query its hardware configuration in order to create its configuration dictiona...
virtual bool removeMember(int member)
Removes a WBDDC from the list of group members.
virtual bool executeWbddcGroupEnableQuery(int index, bool &enabled)
Executes the WBDDC group enable query command.
virtual std::string getMembersString()
Gets the string representation of the member list.
virtual ConfigString getConfigurationValue(const std::string &key) const
Gets a named configuration value as a string.
virtual WbddcGroupComponent & operator=(const WbddcGroupComponent &other)
Assignment operator for WbddcGroupComponent objects.
static std::string Strip(const std::string &str, const std::string &chars=" \\\)
Strips both leading and trailing whitespace from the given string.
Definition: Pythonesque.cpp:57
virtual BasicIntList getMembers() const
Gets the list of group members.
Base hardware component class.
virtual bool addMember(int member)
Adds a WBDDC to the list of group members.
virtual bool hasKey(const std::string &key) const
Determines if the dictionary has the given key.
virtual bool executeWbddcGroupCommand(int index, BasicIntList &groupMembers)
Executes the WBDDC group configuration set command.
virtual bool isConnected() const
Gets whether or not the handler is connected.
virtual RadioComponent & operator=(const RadioComponent &other)
Assignment operator for RadioComponent objects.
static std::string Replace(const std::string &str, const std::string &oldstr, const std::string &newstr, int count=INT_MAX)
Replaces occurrences of one substring with another within the given string.
Definition: Pythonesque.cpp:62
virtual bool executeWbddcGroupEnableCommand(int index, bool &enabled)
Executes the WBDDC group enable command.
virtual bool enable(bool enabled=true)
Enables this component.
virtual bool executeWbddcGroupQuery(int index, BasicIntList &groupMembers)
Executes the WBDDC group configuration query command.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
static BasicStringList Split(const std::string &str, const std::string &sep, int maxsplit=INT_MAX)
Splits the given string into a list of string tokens.
Definition: Pythonesque.cpp:77
Base WBDDC group component class.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
Generic radio handler class.
Definition: RadioHandler.h:54
virtual int debug(const char *format,...)
Outputs debug information.
Definition: Debuggable.cpp:95
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition: BasicList.h:25
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
A configuration dictionary.
Definition: Configurable.h:51
virtual ~WbddcGroupComponent()
Destroys a WbddcGroupComponent object.
virtual std::string getLastCommandErrorInfo() const
Gets the error message from the last command attempted.
virtual const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
Definition: Debuggable.cpp:126
WbddcGroupComponent(const std::string &name="WBG", int index=1, RadioHandler *parent=NULL, bool debug=false, int numGroupMembers=0, int groupMemberIndexBase=1)
Constructs a WbddcGroupComponent object.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this object.
virtual BasicStringList sendCommand(const std::string &cmdString, double timeout=-1)
Sends a command to the radio.
virtual bool executeWbddcGroupMemberCommand(int index, int groupMember, bool &isMember)
Executes the WBDDC group member set command.
BASIC_LIST_CONTAINER< int > BasicIntList
Type representing a list of integers.
Definition: BasicList.h:27
virtual bool executeWbddcGroupMemberQuery(int index, int groupMember, bool &isMember)
Executes the WBDDC group member query command.
static std::string Join(const BasicStringList &vec, const std::string &sep)
Joins a list of string tokens, concatenating them into a single string.
Definition: Pythonesque.cpp:98
virtual bool setMembers(const BasicIntList &groupMembers)
Sets the list of group members.
virtual bool setConfigurationValue(const std::string &key, const std::string &value)
Sets a named configuration value to a string.