libcyberradio  22.01.24
NbddcGroupComponent.cpp
1 /***************************************************************************
2  * \file NbddcGroupComponent.cpp
3  * \brief Defines the basic NBDDC 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/NbddcGroupComponent.h"
13 #include "LibCyberRadio/Common/Pythonesque.h"
14 #include <boost/lexical_cast.hpp>
15 #include <sstream>
16 #include <iomanip>
17 
18 
19 namespace LibCyberRadio
20 {
21  namespace Driver
22  {
24  const std::string& name,
25  int index,
26  RadioHandler* parent,
27  bool debug,
28  int numGroupMembers,
29  int groupMemberIndexBase) :
30  RadioComponent(name, index, parent, debug),
31  _numGroupMembers(numGroupMembers),
32  _groupMemberIndexBase(groupMemberIndexBase)
33  {
35  }
36 
38  {
39  }
40 
42  RadioComponent(other),
43  _numGroupMembers(other._numGroupMembers),
44  _groupMemberIndexBase(other._groupMemberIndexBase)
45  {
46  }
47 
49  {
51  if ( this != &other )
52  {
53  _numGroupMembers = other._numGroupMembers;
54  _groupMemberIndexBase = other._groupMemberIndexBase;
55  }
56  return *this;
57  }
58 
59  bool NbddcGroupComponent::enable(bool enabled)
60  {
61  bool adjEnabled = enabled;
62  bool ret = false;
63  if ( _config.hasKey("enable") )
64  {
65  ret = executeNbddcGroupEnableCommand(_index, adjEnabled);
66  if ( ret )
67  {
68  _enabled = adjEnabled;
70  }
71  }
72  return ret;
73  }
74 
76  {
77  this->debug("[NbddcGroupComponent::setConfiguration] Called\n");
78  // Call the "grandparent" version of this method instead of the
79  // parent version. We want the normalization, but not the
80  // automatic enabling.
81  bool ret = Configurable::setConfiguration(cfg);
82  bool adjEnabled = _enabled;
83  BasicIntList adjMembers = _groupMembers;
84  bool enableCmdNeedsExecuting = false;
85  bool memberCmdNeedsExecuting = false;
86  if ( cfg.hasKey("enable") && _config.hasKey("enable") )
87  {
88  adjEnabled = getConfigurationValueAsBool("enable");
89  enableCmdNeedsExecuting = true;
90  }
91  if ( cfg.hasKey("members") && _config.hasKey("members") )
92  {
94  adjMembers.clear();
95  for( BasicStringList::const_iterator it = vec.begin(); it != vec.end(); it++ )
96  {
97  adjMembers.push_back( boost::lexical_cast<int>(Pythonesque::Strip(*it)) );
98  }
99  memberCmdNeedsExecuting = true;
100  }
101  if ( memberCmdNeedsExecuting )
102  {
103  ret &= executeNbddcGroupCommand(_index, adjMembers);
104  }
105  if ( enableCmdNeedsExecuting )
106  {
107  ret &= executeNbddcGroupEnableCommand(_index, adjEnabled);
108  }
109  if ( ret )
110  {
111  _enabled = adjEnabled;
112  _groupMembers = adjMembers;
114  }
115  this->debug("[NbddcGroupComponent::setConfiguration] Returning\n");
116  return ret;
117  }
118 
120  {
121  this->debug("[NbddcGroupComponent::queryConfiguration] Called\n");
122  if ( _config.hasKey("enable") )
123  {
124  executeNbddcGroupEnableQuery(_index, _enabled);
125  }
126  if ( _config.hasKey("members") )
127  {
128  executeNbddcGroupQuery(_index, _groupMembers);
129  }
131  this->debug("[NbddcGroupComponent::queryConfiguration] Returning\n");
132  }
133 
135  {
136  return _groupMembers;
137  }
138 
140  {
141  this->debug("[NbddcGroupComponent::setMembers] Called\n");
142  bool ret = false;
143  if ( _config.hasKey("members") )
144  {
145  BasicIntList adjMembers = groupMembers;
146  ret = this->executeNbddcGroupCommand(_index, adjMembers);
147  if (ret)
148  {
149  _groupMembers = groupMembers;
151  }
152  }
153  this->debug("[NbddcGroupComponent::setMembers] Returning %s\n",
154  this->debugBool(ret));
155  return ret;
156  }
157 
159  {
160  this->debug("[NbddcGroupComponent::addMember] Called\n");
161  bool ret = false;
162  if ( _config.hasKey("members") )
163  {
164  bool isMember = true;
165  ret = this->executeNbddcGroupMemberCommand(_index, member, isMember);
166  if (ret)
167  {
168  if ( std::count(_groupMembers.begin(), _groupMembers.end(), member) == 0 )
169  {
170  _groupMembers.push_back(member);
171  std::sort(_groupMembers.begin(), _groupMembers.end());
173  }
174  }
175  }
176  this->debug("[NbddcGroupComponent::addMember] Returning %s\n",
177  this->debugBool(ret));
178  return ret;
179  }
180 
182  {
183  this->debug("[NbddcGroupComponent::removeMember] Called\n");
184  bool ret = false;
185  if ( _config.hasKey("members") )
186  {
187  bool isMember = false;
188  ret = this->executeNbddcGroupMemberCommand(_index, member, isMember);
189  if (ret)
190  {
191  if ( std::count(_groupMembers.begin(), _groupMembers.end(), member) == 0 )
192  {
193  _groupMembers.push_back(member);
194  std::sort(_groupMembers.begin(), _groupMembers.end());
196  }
197  }
198  }
199  this->debug("[NbddcGroupComponent::removeMember] Returning %s\n",
200  this->debugBool(ret));
201  return ret;
202  }
203 
205  {
206  _config.clear();
207  // Call the base-class version
209  // Define component-specific keys
210  _config["members"] = "";
211  }
212 
214  {
215  this->debug("[NbddcGroupComponent::updateConfigurationDict] Called\n");
217  if ( _config.hasKey("members") )
219  this->debug("[NbddcGroupComponent::updateConfigurationDict] Returning\n");
220  }
221 
223  {
224  BasicStringList vec;
225  for (BasicIntList::const_iterator it = _groupMembers.begin();
226  it != _groupMembers.end(); it++)
227  {
228  vec.push_back( std::to_string(*it) );
229  }
230  std::string memberStr = Pythonesque::Join(vec, ", ");
231  return memberStr;
232  }
233 
234  // Default implementation is based on the NDR308 model
236  bool& enabled)
237  {
238  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableQuery] Called\n");
239  bool ret = false;
240  if ( (_parent != NULL) && (_parent->isConnected()) )
241  {
242  std::ostringstream oss;
243  oss << "NBGE? " << index << "\n";
244  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
245  if ( _parent->getLastCommandErrorInfo() == "" )
246  {
248  Pythonesque::Replace(rsp.front(), "NBGE ", ""),
249  ", ");
250  // vec[0] = Index
251  // vec[1] = Enabled indicator
252  enabled = (boost::lexical_cast<int>(vec[1]) == 1);
253  ret = true;
254  }
255  }
256  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableQuery] Returning %s\n",
257  this->debugBool(ret));
258  return ret;
259  }
260 
261  // Default implementation is based on the NDR308 model
263  bool& enabled)
264  {
265  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableCommand] Called\n");
266  bool ret = false;
267  if ( (_parent != NULL) && (_parent->isConnected()) )
268  {
269  std::ostringstream oss;
270  oss << "NBGE " << index
271  << ", " << (enabled ? 1 : 0)
272  << "\n";
273  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
274  if ( _parent->getLastCommandErrorInfo() == "" )
275  {
276  ret = true;
277  }
278  }
279  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableCommand] Returning %s\n",
280  this->debugBool(ret));
281  return ret;
282  }
283 
284  // Default implementation is based on the NDR308 model
286  BasicIntList& groupMembers)
287  {
288  this->debug("[NbddcGroupComponent::executeNbddcGroupQuery] Called\n");
289  bool ret = true;
290  bool isMember;
291  groupMembers.clear();
292  for (int member = _groupMemberIndexBase;
293  member < (_groupMemberIndexBase + _numGroupMembers); member++)
294  {
295  ret &= executeNbddcGroupMemberQuery(index, member, isMember);
296  if (ret)
297  {
298  if ( isMember )
299  groupMembers.push_back(member);
300  }
301  else
302  break;
303  }
304  this->debug("[NbddcGroupComponent::executeNbddcGroupQuery] Returning %s\n",
305  this->debugBool(ret));
306  return ret;
307  }
308 
309  // Default implementation is based on the NDR308 model
311  BasicIntList& groupMembers)
312  {
313  this->debug("[NbddcGroupComponent::executeNbddcGroupCommand] Called\n");
314  bool ret = true;
315  bool isMember;
316  for (int member = _groupMemberIndexBase;
317  member < (_groupMemberIndexBase + _numGroupMembers); member++)
318  {
319  isMember = ( std::count(groupMembers.begin(), groupMembers.end(), member) > 0 );
320  ret &= executeNbddcGroupMemberCommand(index, member, isMember);
321  if (!ret)
322  break;
323  }
324  this->debug("[NbddcGroupComponent::executeNbddcGroupCommand] Returning %s\n",
325  this->debugBool(ret));
326  return ret;
327  }
328 
329  bool NbddcGroupComponent::executeNbddcGroupMemberQuery(int index, int groupMember,
330  bool& isMember)
331  {
332  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberQuery] Called\n");
333  bool ret = false;
334  if ( (_parent != NULL) && (_parent->isConnected()) )
335  {
336  std::ostringstream oss;
337  BasicStringList rsp, vec;
338  int inGroup;
339  oss << "NBG? " << index
340  << ", " << groupMember
341  << "\n";
342  rsp = _parent->sendCommand(oss.str(), 2.0);
343  if ( _parent->getLastCommandErrorInfo() == "" )
344  {
345  vec = Pythonesque::Split(
346  Pythonesque::Replace(rsp.front(), "NBG ", ""),
347  ", ");
348  // vec[0] = Group index
349  // vec[1] = Member index
350  // vec[2] = 0 if member is not in group, 1 if it is
351  isMember = ( boost::lexical_cast<int>(vec[2]) == 1 );
352  ret = true;
353  }
354  }
355  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberQuery] Returning %s\n",
356  this->debugBool(ret));
357  return ret;
358  }
359 
360  // Default implementation is based on the NDR308 model
362  bool& isMember)
363  {
364  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberCommand] Called\n");
365  bool ret = false;
366  if ( (_parent != NULL) && (_parent->isConnected()) )
367  {
368  std::ostringstream oss;
369  oss << "NBG " << index
370  << ", " << groupMember
371  << ", " << ( isMember ? 1 : 0 )
372  << "\n";
373  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
374  if ( _parent->getLastCommandErrorInfo() == "" )
375  {
376  ret = true;
377  }
378  }
379  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberCommand] Returning %s\n",
380  this->debugBool(ret));
381  return ret;
382  }
383 
384  } // namespace Driver
385 
386 } // namespace LibCyberRadio
387 
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 bool executeNbddcGroupMemberQuery(int index, int groupMember, bool &isMember)
Executes the NBDDC group member query command.
virtual ConfigString getConfigurationValue(const std::string &key) const
Gets a named configuration value as a string.
virtual bool executeNbddcGroupEnableCommand(int index, bool &enabled)
Executes the NBDDC group enable command.
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
Base hardware component class.
virtual bool hasKey(const std::string &key) const
Determines if the dictionary has the given key.
virtual bool executeNbddcGroupMemberCommand(int index, int groupMember, bool &isMember)
Executes the NBDDC group member set command.
Base NBDDC group component class.
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
NbddcGroupComponent(const std::string &name="NBG", int index=1, RadioHandler *parent=NULL, bool debug=false, int numGroupMembers=0, int groupMemberIndexBase=1)
Constructs a NbddcGroupComponent object.
virtual bool enable(bool enabled=true)
Enables this component.
virtual void queryConfiguration()
Tells the component to query its hardware configuration in order to create its configuration dictiona...
virtual bool executeNbddcGroupCommand(int index, BasicIntList &groupMembers)
Executes the NBDDC group configuration set command.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
virtual bool addMember(int member)
Adds a NBDDC to the list of group members.
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
virtual bool executeNbddcGroupQuery(int index, BasicIntList &groupMembers)
Executes the NBDDC group configuration query command.
virtual bool setMembers(const BasicIntList &groupMembers)
Sets the list of group members.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
Generic radio handler class.
Definition: RadioHandler.h:53
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 std::string getMembersString()
Gets the string representation of the member list.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
A configuration dictionary.
Definition: Configurable.h:51
virtual std::string getLastCommandErrorInfo() const
Gets the error message from the last command attempted.
virtual BasicIntList getMembers() const
Gets the list of group members.
virtual const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
Definition: Debuggable.cpp:126
virtual NbddcGroupComponent & operator=(const NbddcGroupComponent &other)
Assignment operator for NbddcGroupComponent objects.
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.
BASIC_LIST_CONTAINER< int > BasicIntList
Type representing a list of integers.
Definition: BasicList.h:27
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
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 executeNbddcGroupEnableQuery(int index, bool &enabled)
Executes the NBDDC group enable query command.
virtual bool setConfigurationValue(const std::string &key, const std::string &value)
Sets a named configuration value to a string.
virtual ~NbddcGroupComponent()
Destroys a NbddcGroupComponent object.
virtual bool removeMember(int member)
Removes a NBDDC from the list of group members.