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
20namespace 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
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
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 const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
virtual int debug(const char *format,...)
Outputs debug information.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this object.
virtual bool getConfigurationValueAsBool(const std::string &key) const
Gets a named configuration value as a Boolean.
virtual bool setConfigurationValue(const std::string &key, const std::string &value)
Sets a named configuration value to a string.
virtual ConfigString getConfigurationValue(const std::string &key) const
Gets a named configuration value as a string.
A configuration dictionary.
virtual bool hasKey(const std::string &key) const
Determines if the dictionary has the given key.
virtual BasicIntList getMembers() const
Gets the list of group members.
virtual bool enable(bool enabled=true)
Enables this component.
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this component.
virtual bool executeNbddcGroupCommand(int index, BasicIntList &groupMembers)
Executes the NBDDC group configuration set command.
virtual std::string getMembersString()
Gets the string representation of the member list.
virtual bool executeNbddcGroupMemberCommand(int index, int groupMember, bool &isMember)
Executes the NBDDC group member set command.
virtual ~NbddcGroupComponent()
Destroys a NbddcGroupComponent object.
virtual bool executeNbddcGroupEnableQuery(int index, bool &enabled)
Executes the NBDDC group enable query command.
virtual bool removeMember(int member)
Removes a NBDDC from the list of group members.
virtual bool addMember(int member)
Adds a NBDDC to the list of group members.
virtual NbddcGroupComponent & operator=(const NbddcGroupComponent &other)
Assignment operator for NbddcGroupComponent objects.
virtual bool setMembers(const BasicIntList &groupMembers)
Sets the list of group members.
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 void queryConfiguration()
Tells the component to query its hardware configuration in order to create its configuration dictiona...
virtual bool executeNbddcGroupQuery(int index, BasicIntList &groupMembers)
Executes the NBDDC group configuration query command.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual bool executeNbddcGroupMemberQuery(int index, int groupMember, bool &isMember)
Executes the NBDDC group member query command.
virtual bool executeNbddcGroupEnableCommand(int index, bool &enabled)
Executes the NBDDC group enable command.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual RadioComponent & operator=(const RadioComponent &other)
Assignment operator for RadioComponent objects.
RadioComponent(const std::string &name="<unknown>", int index=0, RadioHandler *parent=NULL, bool debug=false)
Constructs a RadioComponent object.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
Generic radio handler class.
static std::string Strip(const std::string &str, const std::string &chars=" \r\n\t\v\f")
Strips both leading and trailing whitespace from the given string.
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.
static std::string Join(const BasicStringList &vec, const std::string &sep)
Joins a list of string tokens, concatenating them into a single string.
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.
Provides programming elements for driving CRS NDR-class radios.
Defines functionality for LibCyberRadio applications.
Definition App.h:24
BASIC_LIST_CONTAINER< int > BasicIntList
Type representing a list of integers.
Definition BasicList.h:27
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition BasicList.h:25