Open Lighting Architecture
 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <queue>
36 #include <stack>
37 #include <utility>
38 
39 
40 namespace ola {
41 namespace rdm {
42 
43 
44 using std::queue;
45 
52  public:
53  // Argument is true if the device responded
56  // Arguments are a pointer to the data & length of the DUB response,
57  // excluding the RDM start code.
60 
61  virtual ~DiscoveryTargetInterface() {}
62 
63  // Mute a device
64  virtual void MuteDevice(const UID &target,
65  MuteDeviceCallback *mute_complete) = 0;
66  // Un Mute all devices
67  virtual void UnMuteAll(UnMuteDeviceCallback *unmute_complete) = 0;
68 
69  // Send a branch request
70  virtual void Branch(const UID &lower,
71  const UID &upper,
72  BranchCallback *callback) = 0;
73 };
74 
75 
80  public:
81  explicit DiscoveryAgent(DiscoveryTargetInterface *target);
83 
86 
87  void Abort();
90 
91  private:
95  struct UIDRange {
96  UIDRange(const UID &lower, const UID &upper, UIDRange *parent)
97  : lower(lower),
98  upper(upper),
99  parent(parent),
100  attempt(0),
101  failures(0),
102  uids_discovered(0),
103  branch_corrupt(false) {
104  }
105  UID lower;
106  UID upper;
107  UIDRange *parent; // the parent Range
108  unsigned int attempt; // the # of attempts for this branch
109  unsigned int failures;
110  unsigned int uids_discovered;
111  bool branch_corrupt; // true if this branch contains a bad device
112  };
113 
114  typedef std::stack<UIDRange*> UIDRanges;
115 
116  DiscoveryTargetInterface *m_target;
117  UIDSet m_uids;
118  // uids that are misbehaved in some way
119  UIDSet m_bad_uids;
120  DiscoveryCompleteCallback *m_on_complete;
121  // uids to mute during incremental discovery
122  std::queue<UID> m_uids_to_mute;
123  // Callbacks used by the DiscoveryTarget
125  DiscoveryTargetInterface::MuteDeviceCallback *m_incremental_mute_callback;
126  DiscoveryTargetInterface::MuteDeviceCallback *m_branch_mute_callback;
127  DiscoveryTargetInterface::BranchCallback *m_branch_callback;
128  // The stack of UIDRanges
129  UIDRanges m_uid_ranges;
130  UID m_muting_uid; // the uid we're currently trying to mute
131  unsigned int m_mute_attempts;
132  bool m_tree_corrupt; // true if there was a problem with discovery
133 
134  void InitDiscovery(DiscoveryCompleteCallback *on_complete,
135  bool incremental);
136 
137  void UnMuteComplete();
138  void MaybeMuteNextDevice();
139  void IncrementalMuteComplete(bool status);
140  void SendDiscovery();
141 
142  void BranchComplete(const uint8_t *data, unsigned int length);
143  void BranchMuteComplete(bool status);
144  void HandleCollision();
145  void FreeCurrentRange();
146 
147  static const unsigned int MAX_DUB_RESPONSE_SIZE = 24;
148  static const unsigned int MIN_DUB_RESPONSE_SIZE = 17;
149  /*
150  * The maximum numbers of times we'll retry discovery if we get a
151  * collision, but after splitting the range in two no nodes can be found.
152  */
153  static const unsigned int MAX_EMPTY_BRANCH_ATTEMPTS = 5;
154  /*
155  * The maximum number of times we'll perform discovery on a branch when we
156  * get an inconsistent result (responder not muting, etc.)
157  */
158  static const unsigned int MAX_BRANCH_FAILURES = 5;
159  // The number of times we'll attempt to mute a UID
160  static const unsigned int MAX_MUTE_ATTEMPTS = 5;
161 };
162 } // namespace rdm
163 } // namespace ola
164 #endif // INCLUDE_OLA_RDM_DISCOVERYAGENT_H_