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 #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 NbddcGroupComponent::enable(bool enabled)
61  {
62  bool adjEnabled = enabled;
63  bool ret = false;
64  if ( _config.hasKey("enable") )
65  {
66  ret = executeNbddcGroupEnableCommand(_index, adjEnabled);
67  if ( ret )
68  {
69  _enabled = adjEnabled;
71  }
72  }
73  return ret;
74  }
75 
77  {
78  this->debug("[NbddcGroupComponent::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 &= executeNbddcGroupCommand(_index, adjMembers);
105  }
106  if ( enableCmdNeedsExecuting )
107  {
108  ret &= executeNbddcGroupEnableCommand(_index, adjEnabled);
109  }
110  if ( ret )
111  {
112  _enabled = adjEnabled;
113  _groupMembers = adjMembers;
115  }
116  this->debug("[NbddcGroupComponent::setConfiguration] Returning\n");
117  return ret;
118  }
119 
121  {
122  this->debug("[NbddcGroupComponent::queryConfiguration] Called\n");
123  if ( _config.hasKey("enable") )
124  {
125  executeNbddcGroupEnableQuery(_index, _enabled);
126  }
127  if ( _config.hasKey("members") )
128  {
129  executeNbddcGroupQuery(_index, _groupMembers);
130  }
132  this->debug("[NbddcGroupComponent::queryConfiguration] Returning\n");
133  }
134 
136  {
137  return _groupMembers;
138  }
139 
141  {
142  this->debug("[NbddcGroupComponent::setMembers] Called\n");
143  bool ret = false;
144  if ( _config.hasKey("members") )
145  {
146  BasicIntList adjMembers = groupMembers;
147  ret = this->executeNbddcGroupCommand(_index, adjMembers);
148  if (ret)
149  {
150  _groupMembers = groupMembers;
152  }
153  }
154  this->debug("[NbddcGroupComponent::setMembers] Returning %s\n",
155  this->debugBool(ret));
156  return ret;
157  }
158 
160  {
161  this->debug("[NbddcGroupComponent::addMember] Called\n");
162  bool ret = false;
163  if ( _config.hasKey("members") )
164  {
165  bool isMember = true;
166  ret = this->executeNbddcGroupMemberCommand(_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("[NbddcGroupComponent::addMember] Returning %s\n",
178  this->debugBool(ret));
179  return ret;
180  }
181 
183  {
184  this->debug("[NbddcGroupComponent::removeMember] Called\n");
185  bool ret = false;
186  if ( _config.hasKey("members") )
187  {
188  bool isMember = false;
189  ret = this->executeNbddcGroupMemberCommand(_index, member, isMember);
190  if (ret)
191  {
192  if ( std::count(_groupMembers.begin(), _groupMembers.end(), member) == 0 )
193  {
194  _groupMembers.push_back(member);
195  std::sort(_groupMembers.begin(), _groupMembers.end());
197  }
198  }
199  }
200  this->debug("[NbddcGroupComponent::removeMember] Returning %s\n",
201  this->debugBool(ret));
202  return ret;
203  }
204 
206  {
207  _config.clear();
208  // Call the base-class version
210  // Define component-specific keys
211  _config["members"] = "";
212  }
213 
215  {
216  this->debug("[NbddcGroupComponent::updateConfigurationDict] Called\n");
218  if ( _config.hasKey("members") )
220  this->debug("[NbddcGroupComponent::updateConfigurationDict] Returning\n");
221  }
222 
224  {
225  BasicStringList vec;
226  for (BasicIntList::const_iterator it = _groupMembers.begin();
227  it != _groupMembers.end(); it++)
228  {
229  vec.push_back( std::to_string(*it) );
230  }
231  std::string memberStr = Pythonesque::Join(vec, ", ");
232  return memberStr;
233  }
234 
235  // Default implementation is based on the NDR308 model
237  bool& enabled)
238  {
239  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableQuery] Called\n");
240  bool ret = false;
241  if ( (_parent != NULL) && (_parent->isConnected()) )
242  {
243  std::ostringstream oss;
244  oss << "NBGE? " << index << "\n";
245  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
246  if ( _parent->getLastCommandErrorInfo() == "" )
247  {
249  Pythonesque::Replace(rsp.front(), "NBGE ", ""),
250  ", ");
251  // vec[0] = Index
252  // vec[1] = Enabled indicator
253  enabled = (boost::lexical_cast<int>(vec[1]) == 1);
254  ret = true;
255  }
256  }
257  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableQuery] Returning %s\n",
258  this->debugBool(ret));
259  return ret;
260  }
261 
262  // Default implementation is based on the NDR308 model
264  bool& enabled)
265  {
266  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableCommand] Called\n");
267  bool ret = false;
268  if ( (_parent != NULL) && (_parent->isConnected()) )
269  {
270  std::ostringstream oss;
271  oss << "NBGE " << index
272  << ", " << (enabled ? 1 : 0)
273  << "\n";
274  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
275  if ( _parent->getLastCommandErrorInfo() == "" )
276  {
277  ret = true;
278  }
279  }
280  this->debug("[NbddcGroupComponent::executeNbddcGroupEnableCommand] Returning %s\n",
281  this->debugBool(ret));
282  return ret;
283  }
284 
285  // Default implementation is based on the NDR308 model
287  BasicIntList& groupMembers)
288  {
289  this->debug("[NbddcGroupComponent::executeNbddcGroupQuery] Called\n");
290  bool ret = true;
291  bool isMember;
292  groupMembers.clear();
293  for (int member = _groupMemberIndexBase;
294  member < (_groupMemberIndexBase + _numGroupMembers); member++)
295  {
296  ret &= executeNbddcGroupMemberQuery(index, member, isMember);
297  if (ret)
298  {
299  if ( isMember )
300  groupMembers.push_back(member);
301  }
302  else
303  break;
304  }
305  this->debug("[NbddcGroupComponent::executeNbddcGroupQuery] Returning %s\n",
306  this->debugBool(ret));
307  return ret;
308  }
309 
310  // Default implementation is based on the NDR308 model
312  BasicIntList& groupMembers)
313  {
314  this->debug("[NbddcGroupComponent::executeNbddcGroupCommand] Called\n");
315  bool ret = true;
316  bool isMember;
317  for (int member = _groupMemberIndexBase;
318  member < (_groupMemberIndexBase + _numGroupMembers); member++)
319  {
320  isMember = ( std::count(groupMembers.begin(), groupMembers.end(), member) > 0 );
321  ret &= executeNbddcGroupMemberCommand(index, member, isMember);
322  if (!ret)
323  break;
324  }
325  this->debug("[NbddcGroupComponent::executeNbddcGroupCommand] Returning %s\n",
326  this->debugBool(ret));
327  return ret;
328  }
329 
330  bool NbddcGroupComponent::executeNbddcGroupMemberQuery(int index, int groupMember,
331  bool& isMember)
332  {
333  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberQuery] Called\n");
334  bool ret = false;
335  if ( (_parent != NULL) && (_parent->isConnected()) )
336  {
337  std::ostringstream oss;
338  BasicStringList rsp, vec;
339  int inGroup;
340  oss << "NBG? " << index
341  << ", " << groupMember
342  << "\n";
343  rsp = _parent->sendCommand(oss.str(), 2.0);
344  if ( _parent->getLastCommandErrorInfo() == "" )
345  {
346  vec = Pythonesque::Split(
347  Pythonesque::Replace(rsp.front(), "NBG ", ""),
348  ", ");
349  // vec[0] = Group index
350  // vec[1] = Member index
351  // vec[2] = 0 if member is not in group, 1 if it is
352  isMember = ( boost::lexical_cast<int>(vec[2]) == 1 );
353  ret = true;
354  }
355  }
356  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberQuery] Returning %s\n",
357  this->debugBool(ret));
358  return ret;
359  }
360 
361  // Default implementation is based on the NDR308 model
363  bool& isMember)
364  {
365  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberCommand] Called\n");
366  bool ret = false;
367  if ( (_parent != NULL) && (_parent->isConnected()) )
368  {
369  std::ostringstream oss;
370  oss << "NBG " << index
371  << ", " << groupMember
372  << ", " << ( isMember ? 1 : 0 )
373  << "\n";
374  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
375  if ( _parent->getLastCommandErrorInfo() == "" )
376  {
377  ret = true;
378  }
379  }
380  this->debug("[NbddcGroupComponent::executeNbddcGroupMemberCommand] Returning %s\n",
381  this->debugBool(ret));
382  return ret;
383  }
384 
385  } // namespace Driver
386 
387 } // namespace LibCyberRadio
388 
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: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 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.