Open Lighting Architecture  Latest Git
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
DiscoveryAgent.h
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * DiscoveryAgent.h
17  * Implements the RDM Discovery algorithm.
18  * Copyright (C) 2011 Simon Newton
19  */
20 
29 #ifndef INCLUDE_OLA_RDM_DISCOVERYAGENT_H_
30 #define INCLUDE_OLA_RDM_DISCOVERYAGENT_H_
31 
32 #include <ola/Callback.h>
33 #include <ola/rdm/UID.h>
34 #include <ola/rdm/UIDSet.h>
35 #include <memory>
36 #include <queue>
37 #include <stack>
38 #include <utility>
39 
40 namespace ola {
41 namespace rdm {
42 
54  public:
61 
66 
74 
75  virtual ~DiscoveryTargetInterface() {}
76 
83  virtual void MuteDevice(const UID &target,
84  MuteDeviceCallback *mute_complete) = 0;
85 
91  virtual void UnMuteAll(UnMuteDeviceCallback *unmute_complete) = 0;
92 
102  virtual void Branch(const UID &lower,
103  const UID &upper,
104  BranchCallback *callback) = 0;
105 };
106 
107 
136  public:
141  explicit DiscoveryAgent(DiscoveryTargetInterface *target);
142 
146  ~DiscoveryAgent();
147 
150 
156  void Abort();
157 
162  void StartFullDiscovery(DiscoveryCompleteCallback *on_complete);
163 
168  void StartIncrementalDiscovery(DiscoveryCompleteCallback *on_complete);
169 
170  private:
174  struct UIDRange {
175  UIDRange(const UID &_lower, const UID &_upper, UIDRange *_parent)
176  : lower(_lower),
177  upper(_upper),
178  parent(_parent),
179  attempt(0),
180  failures(0),
181  uids_discovered(0),
182  branch_corrupt(false) {
183  }
184  UID lower;
185  UID upper;
186  UIDRange *parent; // the parent Range
187  unsigned int attempt; // the # of attempts for this branch
188  unsigned int failures;
189  unsigned int uids_discovered;
190  bool branch_corrupt; // true if this branch contains a bad device
191  };
192 
193  typedef std::stack<UIDRange*> UIDRanges;
194 
195  DiscoveryTargetInterface *m_target;
196  UIDSet m_uids;
197  // uids that are misbehaved in some way
198  UIDSet m_bad_uids;
199  // uids that are misbehaved in some way which we've already split around
200  UIDSet m_split_uids;
201  DiscoveryCompleteCallback *m_on_complete;
202  // uids to mute during incremental discovery
203  std::queue<UID> m_uids_to_mute;
204  // Callbacks used by the DiscoveryTarget
205  std::auto_ptr<DiscoveryTargetInterface::UnMuteDeviceCallback>
206  m_unmute_callback;
207  std::auto_ptr<DiscoveryTargetInterface::MuteDeviceCallback>
208  m_incremental_mute_callback;
209  std::auto_ptr<DiscoveryTargetInterface::MuteDeviceCallback>
210  m_branch_mute_callback;
211  std::auto_ptr<DiscoveryTargetInterface::BranchCallback> m_branch_callback;
212 
213  // The stack of UIDRanges
214  UIDRanges m_uid_ranges;
215  UID m_muting_uid; // the uid we're currently trying to mute
216  unsigned int m_unmute_count;
217  unsigned int m_mute_attempts;
218  bool m_tree_corrupt; // true if there was a problem with discovery
219 
220  void InitDiscovery(DiscoveryCompleteCallback *on_complete,
221  bool incremental);
222 
223  void UnMuteComplete();
224  void MaybeMuteNextDevice();
225  void IncrementalMuteComplete(bool status);
226  void SendDiscovery();
227 
228  void BranchComplete(const uint8_t *data, unsigned int length);
229  void BranchMuteComplete(bool status);
230  void HandleCollision();
231  void SplitAroundBadUID(UID bad_uid);
232  void FreeCurrentRange();
233 
234  static const unsigned int PREAMBLE_SIZE = 8;
235  static const unsigned int EUID_SIZE = 12;
236  static const unsigned int CHECKSUM_SIZE = 4;
237 
238  /*
239  * The maximum numbers of times we'll retry discovery if we get a
240  * collision, but after splitting the range in two no nodes can be found.
241  */
242  static const unsigned int MAX_EMPTY_BRANCH_ATTEMPTS = 5;
243  /*
244  * The maximum number of times we'll perform discovery on a branch when we
245  * get an inconsistent result (responder not muting, etc.)
246  */
247  static const unsigned int MAX_BRANCH_FAILURES = 5;
248 
249  // The number of times we'll attempt to mute a UID
250  static const unsigned int MAX_MUTE_ATTEMPTS = 5;
251  // The number of times we'll send a broadcast unmute command
252  // This should be more than 1 to ensure that all devices are unmuted.
253  static const unsigned int BROADCAST_UNMUTE_REPEATS = 3;
254 
255  static const uint8_t PREAMBLE = 0xfe;
256  static const uint8_t PREAMBLE_SEPARATOR = 0xaa;
257 };
258 } // namespace rdm
259 } // namespace ola
260 #endif // INCLUDE_OLA_RDM_DISCOVERYAGENT_H_
Represents a set of RDM UIDs.
Definition: UIDSet.h:48
virtual void Branch(const UID &lower, const UID &upper, BranchCallback *callback)=0
Send a DUB command.
ola::BaseCallback2< void, const uint8_t *, unsigned int > BranchCallback
The callback run when a DUB command completes.
Definition: DiscoveryAgent.h:73
ola::BaseCallback1< void, bool > MuteDeviceCallback
The callback run when a mute command completes.
Definition: DiscoveryAgent.h:60
~DiscoveryAgent()
Destructor.
Definition: DiscoveryAgent.cpp:51
virtual void UnMuteAll(UnMuteDeviceCallback *unmute_complete)=0
Unmute all devices.
A RDM unique identifier (UID).
void Abort()
Cancel any in-progress discovery operation. If a discovery operation is running, this will result in ...
Definition: DiscoveryAgent.cpp:55
void StartIncrementalDiscovery(DiscoveryCompleteCallback *on_complete)
Initiate an incremental discovery operation.
Definition: DiscoveryAgent.cpp:75
A set of UIDs.
void StartFullDiscovery(DiscoveryCompleteCallback *on_complete)
Initiate a full discovery operation.
Definition: DiscoveryAgent.cpp:70
ola::BaseCallback0< void > UnMuteDeviceCallback
The callback run when an unmute command completes.
Definition: DiscoveryAgent.h:65
virtual void MuteDevice(const UID &target, MuteDeviceCallback *mute_complete)=0
Mute a device.
The base class for all 1 argument callbacks.
Definition: Callback.h:982
An asynchronous RDM Discovery algorithm.
Definition: DiscoveryAgent.h:135
DiscoveryAgent(DiscoveryTargetInterface *target)
Create a new DiscoveryAgent.
Definition: DiscoveryAgent.cpp:34
Represents a RDM UID.
Definition: UID.h:57
The namespace containing all OLA symbols.
Definition: Credentials.cpp:44
The base class for all 2 argument callbacks.
Definition: Callback.h:1885
The interface used by the DiscoveryTarget to send RDM commands.
Definition: DiscoveryAgent.h:53
A 2 argument callback which deletes itself after it's run.
Definition: Callback.h:1907