Open Lighting Architecture  0.9.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 
163 
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  DiscoveryCompleteCallback *m_on_complete;
200  // uids to mute during incremental discovery
201  std::queue<UID> m_uids_to_mute;
202  // Callbacks used by the DiscoveryTarget
203  std::auto_ptr<DiscoveryTargetInterface::UnMuteDeviceCallback>
204  m_unmute_callback;
205  std::auto_ptr<DiscoveryTargetInterface::MuteDeviceCallback>
206  m_incremental_mute_callback;
207  std::auto_ptr<DiscoveryTargetInterface::MuteDeviceCallback>
208  m_branch_mute_callback;
209  std::auto_ptr<DiscoveryTargetInterface::BranchCallback> m_branch_callback;
210 
211  // The stack of UIDRanges
212  UIDRanges m_uid_ranges;
213  UID m_muting_uid; // the uid we're currently trying to mute
214  unsigned int m_unmute_count;
215  unsigned int m_mute_attempts;
216  bool m_tree_corrupt; // true if there was a problem with discovery
217 
218  void InitDiscovery(DiscoveryCompleteCallback *on_complete,
219  bool incremental);
220 
221  void UnMuteComplete();
222  void MaybeMuteNextDevice();
223  void IncrementalMuteComplete(bool status);
224  void SendDiscovery();
225 
226  void BranchComplete(const uint8_t *data, unsigned int length);
227  void BranchMuteComplete(bool status);
228  void HandleCollision();
229  void FreeCurrentRange();
230 
231  static const unsigned int PREAMBLE_SIZE = 8;
232  static const unsigned int EUID_SIZE = 12;
233  static const unsigned int CHECKSUM_SIZE = 4;
234 
235  /*
236  * The maximum numbers of times we'll retry discovery if we get a
237  * collision, but after splitting the range in two no nodes can be found.
238  */
239  static const unsigned int MAX_EMPTY_BRANCH_ATTEMPTS = 5;
240  /*
241  * The maximum number of times we'll perform discovery on a branch when we
242  * get an inconsistent result (responder not muting, etc.)
243  */
244  static const unsigned int MAX_BRANCH_FAILURES = 5;
245 
246  // The number of times we'll attempt to mute a UID
247  static const unsigned int MAX_MUTE_ATTEMPTS = 5;
248  // The number of times we'll send a broadcast unmute command
249  // This should be more than 1 to ensure that all devices are unmuted.
250  static const unsigned int BROADCAST_UNMUTE_REPEATS = 3;
251 
252  static const uint8_t PREAMBLE = 0xfe;
253  static const uint8_t PREAMBLE_SEPARATOR = 0xaa;
254 };
255 } // namespace rdm
256 } // namespace ola
257 #endif // INCLUDE_OLA_RDM_DISCOVERYAGENT_H_