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