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
19namespace 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
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 WbddcGroupComponent::enable(bool enabled)
60 {
61 bool adjEnabled = enabled;
62 bool ret = false;
63 if ( _config.hasKey("enable") )
64 {
65 ret = executeWbddcGroupEnableCommand(_index, adjEnabled);
66 if ( ret )
67 {
68 _enabled = adjEnabled;
70 }
71 }
72 return ret;
73 }
74
76 {
77 this->debug("[WbddcGroupComponent::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 &= executeWbddcGroupCommand(_index, adjMembers);
104 }
105 if ( enableCmdNeedsExecuting )
106 {
107 ret &= executeWbddcGroupEnableCommand(_index, adjEnabled);
108 }
109 if ( ret )
110 {
111 _enabled = adjEnabled;
112 _groupMembers = adjMembers;
114 }
115 this->debug("[WbddcGroupComponent::setConfiguration] Returning\n");
116 return ret;
117 }
118
120 {
121 this->debug("[WbddcGroupComponent::queryConfiguration] Called\n");
122 if ( _config.hasKey("enable") )
123 {
124 executeWbddcGroupEnableQuery(_index, _enabled);
125 }
126 if ( _config.hasKey("members") )
127 {
128 executeWbddcGroupQuery(_index, _groupMembers);
129 }
131 this->debug("[WbddcGroupComponent::queryConfiguration] Returning\n");
132 }
133
135 {
136 return _groupMembers;
137 }
138
140 {
141 this->debug("[WbddcGroupComponent::setMembers] Called\n");
142 bool ret = false;
143 if ( _config.hasKey("members") )
144 {
145 BasicIntList adjMembers = groupMembers;
146 ret = this->executeWbddcGroupCommand(_index, adjMembers);
147 if (ret)
148 {
149 _groupMembers = groupMembers;
151 }
152 }
153 this->debug("[WbddcGroupComponent::setMembers] Returning %s\n",
154 this->debugBool(ret));
155 return ret;
156 }
157
159 {
160 this->debug("[WbddcGroupComponent::addMember] Called\n");
161 bool ret = false;
162 if ( _config.hasKey("members") )
163 {
164 bool isMember = true;
165 ret = this->executeWbddcGroupMemberCommand(_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("[WbddcGroupComponent::addMember] Returning %s\n",
177 this->debugBool(ret));
178 return ret;
179 }
180
182 {
183 this->debug("[WbddcGroupComponent::removeMember] Called\n");
184 bool ret = false;
185 if ( _config.hasKey("members") )
186 {
187 bool isMember = false;
188 ret = this->executeWbddcGroupMemberCommand(_index, member, isMember);
189 if (ret)
190 {
191 BasicIntList::iterator it = std::find(_groupMembers.begin(), _groupMembers.end(),
192 member);
193 if ( it != _groupMembers.end() )
194 {
195 _groupMembers.erase(it);
197 }
198 }
199 }
200 this->debug("[WbddcGroupComponent::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("[WbddcGroupComponent::updateConfigurationDict] Called\n");
218 if ( _config.hasKey("members") )
220 this->debug("[WbddcGroupComponent::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("[WbddcGroupComponent::executeWbddcGroupEnableQuery] Called\n");
240 bool ret = false;
241 if ( (_parent != NULL) && (_parent->isConnected()) )
242 {
243 std::ostringstream oss;
244 oss << "WBGE? " << index << "\n";
245 BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
246 if ( _parent->getLastCommandErrorInfo() == "" )
247 {
249 Pythonesque::Replace(rsp.front(), "WBGE ", ""),
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("[WbddcGroupComponent::executeWbddcGroupEnableQuery] 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("[WbddcGroupComponent::executeWbddcGroupEnableCommand] Called\n");
267 bool ret = false;
268 if ( (_parent != NULL) && (_parent->isConnected()) )
269 {
270 std::ostringstream oss;
271 oss << "WBGE " << 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("[WbddcGroupComponent::executeWbddcGroupEnableCommand] 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("[WbddcGroupComponent::executeWbddcGroupQuery] 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 &= executeWbddcGroupMemberQuery(index, member, isMember);
297 if (ret)
298 {
299 if ( isMember )
300 groupMembers.push_back(member);
301 }
302 else
303 break;
304 }
305 this->debug("[WbddcGroupComponent::executeWbddcGroupQuery] 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("[WbddcGroupComponent::executeWbddcGroupCommand] 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 &= executeWbddcGroupMemberCommand(index, member, isMember);
322 if (!ret)
323 break;
324 }
325 this->debug("[WbddcGroupComponent::executeWbddcGroupCommand] Returning %s\n",
326 this->debugBool(ret));
327 return ret;
328 }
329
331 bool& isMember)
332 {
333 this->debug("[WbddcGroupComponent::executeWbddcGroupMemberQuery] 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 << "WBG? " << 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(), "WBG ", ""),
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("[WbddcGroupComponent::executeWbddcGroupMemberQuery] 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("[WbddcGroupComponent::executeWbddcGroupMemberCommand] Called\n");
366 bool ret = false;
367 if ( (_parent != NULL) && (_parent->isConnected()) )
368 {
369 std::ostringstream oss;
370 oss << "WBG " << 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("[WbddcGroupComponent::executeWbddcGroupMemberCommand] 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 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.
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 std::string getMembersString()
Gets the string representation of the member list.
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 ~WbddcGroupComponent()
Destroys a WbddcGroupComponent object.
virtual bool executeWbddcGroupCommand(int index, BasicIntList &groupMembers)
Executes the WBDDC group configuration set command.
virtual bool removeMember(int member)
Removes a WBDDC from the list of group members.
virtual bool addMember(int member)
Adds a WBDDC to the list of group members.
virtual bool setMembers(const BasicIntList &groupMembers)
Sets the list of group members.
virtual bool executeWbddcGroupQuery(int index, BasicIntList &groupMembers)
Executes the WBDDC group configuration query command.
virtual bool executeWbddcGroupMemberQuery(int index, int groupMember, bool &isMember)
Executes the WBDDC group member query command.
virtual void queryConfiguration()
Tells the component to query its hardware configuration in order to create its configuration dictiona...
virtual WbddcGroupComponent & operator=(const WbddcGroupComponent &other)
Assignment operator for WbddcGroupComponent objects.
virtual bool executeWbddcGroupEnableCommand(int index, bool &enabled)
Executes the WBDDC group enable command.
virtual void updateConfigurationDict()
Updates the configuration dictionary from component settings.
virtual bool executeWbddcGroupEnableQuery(int index, bool &enabled)
Executes the WBDDC group enable query command.
virtual bool executeWbddcGroupMemberCommand(int index, int groupMember, bool &isMember)
Executes the WBDDC group member set command.
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
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