Commit 741dd74cb34daabb5c4030757b57b948b38390fc
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
Showing
2 changed files
with
52 additions
and
9 deletions
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& 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& 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& mac, const std::string& 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& 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; | ... | ... |