Commit 741dd74cb34daabb5c4030757b57b948b38390fc

Authored by Adam Honse
Committed by Moritz Wirger
1 parent f367db9b

Add functionality to request client key from Hue bridge and be able to load the …

…client key with the username
include/hueplusplus/Bridge.h
... ... @@ -99,6 +99,12 @@ public:
99 99 //! \param username Username that is used to control the Hue bridge
100 100 void AddUsername(const std::string& mac, const std::string& username);
101 101  
  102 + //! \brief Function that adds a client key to the clientkeys map
  103 + //!
  104 + //! \param mac MAC address of Hue bridge
  105 + //! \param clientkey Client key that is used to control the Hue bridge in entertainment mode
  106 + void AddClientKey(const std::string& mac, const std::string& clientkey);
  107 +
102 108 //! \brief Function that returns a map of mac addresses and usernames.
103 109 //!
104 110 //! Note these should be saved at the end and re-loaded with \ref AddUsername
... ... @@ -120,6 +126,8 @@ private:
120 126  
121 127 std::map<std::string, std::string> usernames; //!< Maps all macs to usernames added by \ref
122 128 //!< BridgeFinder::AddUsername
  129 + std::map<std::string, std::string> clientkeys; //!< Maps all macs to clientkeys added by \ref
  130 + //!< BridgeFinder::AddClientKey
123 131 std::shared_ptr<const IHttpHandler> http_handler;
124 132 };
125 133  
... ... @@ -145,12 +153,12 @@ public:
145 153 //! \param username String that specifies the username that is used to control
146 154 //! the bridge. Can be left empty and acquired in \ref requestUsername.
147 155 //! \param handler HttpHandler for communication with the bridge
  156 + //! \param clientkey Optional client key for streaming
148 157 //! \param refreshDuration Time between refreshing the cached state.
149 158 //! \param sharedState Uses a single, shared cache for all objects on the bridge.
150 159 Bridge(const std::string& ip, const int port, const std::string& username,
151   - std::shared_ptr<const IHttpHandler> handler,
152   - std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10),
153   - bool sharedState = false);
  160 + std::shared_ptr<const IHttpHandler> handler, const std::string& clientkey = "",
  161 + std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10), bool sharedState = false);
154 162  
155 163 //! \brief Refreshes the bridge state.
156 164 //!
... ... @@ -193,6 +201,11 @@ public:
193 201 //! \return The username used for API access
194 202 std::string getUsername() const;
195 203  
  204 + //! \brief Function that returns the client key
  205 + //!
  206 + //! \return The client key used for Entertainment Mode API access
  207 + std::string getClientKey() const;
  208 +
196 209 //! \brief Function to set the ip address of this class representing a bridge
197 210 //!
198 211 //! \param ip String that specifies the ip in dotted decimal notation like "192.168.2.1"
... ... @@ -245,6 +258,7 @@ public:
245 258 //! \brief Provides access to the Rule%s on the bridge
246 259 //! \note Does not refresh state.
247 260 const RuleList& rules() const;
  261 +
248 262 private:
249 263 //! \brief Function that sets the HttpHandler and updates the HueCommandAPI.
250 264 //! \param handler a HttpHandler of type \ref IHttpHandler
... ... @@ -259,6 +273,7 @@ private:
259 273 std::string ip; //!< IP-Address of the hue bridge in dotted decimal notation
260 274 //!< like "192.168.2.1"
261 275 std::string username; //!< Username that is ussed to access the hue bridge
  276 + std::string clientkey; //!< Client key that is used for entertainment mode
262 277 int port;
263 278  
264 279 std::shared_ptr<const IHttpHandler> http_handler; //!< A IHttpHandler that is used to communicate with the
... ...
src/Bridge.cpp
... ... @@ -20,8 +20,6 @@
20 20 along with hueplusplus. If not, see <http://www.gnu.org/licenses/>.
21 21 **/
22 22  
23   -#include "hueplusplus/Bridge.h"
24   -
25 23 #include <algorithm>
26 24 #include <cctype>
27 25 #include <chrono>
... ... @@ -31,6 +29,7 @@
31 29 #include <stdexcept>
32 30 #include <thread>
33 31  
  32 +#include "hueplusplus/Bridge.h"
34 33 #include "hueplusplus/HueExceptionMacro.h"
35 34 #include "hueplusplus/LibConfig.h"
36 35 #include "hueplusplus/UPnP.h"
... ... @@ -79,10 +78,19 @@ Bridge BridgeFinder::GetBridge(const BridgeIdentification&amp; identification, bool
79 78 {
80 79 std::string normalizedMac = NormalizeMac(identification.mac);
81 80 auto pos = usernames.find(normalizedMac);
  81 + auto key = clientkeys.find(normalizedMac);
82 82 if (pos != usernames.end())
83 83 {
84   - return Bridge(
85   - identification.ip, identification.port, pos->second, http_handler, std::chrono::seconds(10), sharedState);
  84 + if (key != clientkeys.end())
  85 + {
  86 + return Bridge(identification.ip, identification.port, pos->second, http_handler, key->second,
  87 + std::chrono::seconds(10), sharedState);
  88 + }
  89 + else
  90 + {
  91 + return Bridge(identification.ip, identification.port, pos->second, http_handler, "",
  92 + std::chrono::seconds(10), sharedState);
  93 + }
86 94 }
87 95 Bridge bridge(identification.ip, identification.port, "", http_handler, std::chrono::seconds(10), sharedState);
88 96 bridge.requestUsername();
... ... @@ -92,6 +100,7 @@ Bridge BridgeFinder::GetBridge(const BridgeIdentification&amp; identification, bool
92 100 throw HueException(CURRENT_FILE_INFO, "Failed to request username!");
93 101 }
94 102 AddUsername(normalizedMac, bridge.getUsername());
  103 + AddClientKey(normalizedMac, bridge.getClientKey());
95 104  
96 105 return bridge;
97 106 }
... ... @@ -101,6 +110,11 @@ void BridgeFinder::AddUsername(const std::string&amp; mac, const std::string&amp; userna
101 110 usernames[NormalizeMac(mac)] = username;
102 111 }
103 112  
  113 +void BridgeFinder::AddClientKey(const std::string& mac, const std::string& clientkey)
  114 +{
  115 + clientkeys[NormalizeMac(mac)] = clientkey;
  116 +}
  117 +
104 118 const std::map<std::string, std::string>& BridgeFinder::GetAllUsernames() const
105 119 {
106 120 return usernames;
... ... @@ -139,9 +153,11 @@ std::string BridgeFinder::ParseDescription(const std::string&amp; description)
139 153 }
140 154  
141 155 Bridge::Bridge(const std::string& ip, const int port, const std::string& username,
142   - std::shared_ptr<const IHttpHandler> handler, std::chrono::steady_clock::duration refreshDuration, bool sharedState)
  156 + std::shared_ptr<const IHttpHandler> handler, const std::string& clientkey,
  157 + std::chrono::steady_clock::duration refreshDuration, bool sharedState)
143 158 : ip(ip),
144 159 username(username),
  160 + clientkey(clientkey),
145 161 port(port),
146 162 http_handler(std::move(handler)),
147 163 refreshDuration(refreshDuration),
... ... @@ -171,7 +187,6 @@ void Bridge::setRefreshDuration(std::chrono::steady_clock::duration refreshDurat
171 187 stateCache->setRefreshDuration(refreshDuration);
172 188 }
173 189  
174   -
175 190 std::string Bridge::getBridgeIP() const
176 191 {
177 192 return ip;
... ... @@ -192,6 +207,7 @@ std::string Bridge::requestUsername()
192 207 // when the link button was pressed we got 30 seconds to get our username for control
193 208 nlohmann::json request;
194 209 request["devicetype"] = "HuePlusPlus#User";
  210 + request["generateclientkey"] = true;
195 211  
196 212 nlohmann::json answer;
197 213 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
... ... @@ -201,6 +217,7 @@ std::string Bridge::requestUsername()
201 217 std::this_thread::sleep_for(checkInterval);
202 218 answer = http_handler->POSTJson("/api", request, ip, port);
203 219 nlohmann::json jsonUser = utils::safeGetMember(answer, 0, "success", "username");
  220 + nlohmann::json jsonKey = utils::safeGetMember(answer, 0, "success", "clientkey");
204 221 if (jsonUser != nullptr)
205 222 {
206 223 // [{"success":{"username": "<username>"}}]
... ... @@ -209,6 +226,12 @@ std::string Bridge::requestUsername()
209 226 setHttpHandler(http_handler);
210 227 std::cout << "Success! Link button was pressed!\n";
211 228 std::cout << "Username is \"" << username << "\"\n";
  229 +
  230 + if (jsonKey != nullptr)
  231 + {
  232 + clientkey = jsonKey.get<std::string>();
  233 + std::cout << "Client key is \"" << clientkey << "\"\n";
  234 + }
212 235 break;
213 236 }
214 237 else if (answer.size() > 0 && answer[0].count("error"))
... ... @@ -230,6 +253,11 @@ std::string Bridge::getUsername() const
230 253 return username;
231 254 }
232 255  
  256 +std::string Bridge::getClientKey() const
  257 +{
  258 + return clientkey;
  259 +}
  260 +
233 261 void Bridge::setIP(const std::string& ip)
234 262 {
235 263 this->ip = ip;
... ...