Commit aa828bf83b4034ed875af93d5ca9a338bc4ef13a
Committed by
Moritz Wirger
1 parent
710ee59b
Implement a shared-state cache model.
All resources on the bridge internally use the same json state. Advantages: Different resources are always consistent. Disadvantages: Different objects are no longer thread safe, changes are not transparent.
Showing
15 changed files
with
110 additions
and
54 deletions
include/hueplusplus/BaseDevice.h
| ... | ... | @@ -120,6 +120,7 @@ public: |
| 120 | 120 | virtual void refresh(bool force = false); |
| 121 | 121 | |
| 122 | 122 | protected: |
| 123 | + BaseDevice(int id, const std::shared_ptr<APICache>& baseCache); | |
| 123 | 124 | //! \brief Protected ctor that is used by subclasses. |
| 124 | 125 | //! |
| 125 | 126 | //! \param id Integer that specifies the id of this device | ... | ... |
include/hueplusplus/Bridge.h
| ... | ... | @@ -145,9 +145,11 @@ public: |
| 145 | 145 | //! the bridge. Can be left empty and acquired in \ref requestUsername. |
| 146 | 146 | //! \param handler HttpHandler for communication with the bridge |
| 147 | 147 | //! \param refreshDuration Time between refreshing the cached state. |
| 148 | + //! \param sharedState Uses a single, shared cache for all objects on the bridge. | |
| 148 | 149 | Bridge(const std::string& ip, const int port, const std::string& username, |
| 149 | 150 | std::shared_ptr<const IHttpHandler> handler, |
| 150 | - std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10)); | |
| 151 | + std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10), | |
| 152 | + bool sharedState = false); | |
| 151 | 153 | |
| 152 | 154 | //! \brief Refreshes the bridge state. |
| 153 | 155 | //! |
| ... | ... | @@ -265,6 +267,7 @@ private: |
| 265 | 267 | detail::MakeCopyable<SensorList> sensorList; |
| 266 | 268 | detail::MakeCopyable<RuleList> ruleList; |
| 267 | 269 | detail::MakeCopyable<BridgeConfig> bridgeConfig; |
| 270 | + bool sharedState; | |
| 268 | 271 | }; |
| 269 | 272 | } // namespace hueplusplus |
| 270 | 273 | ... | ... |
include/hueplusplus/Group.h
include/hueplusplus/HueDeviceTypes.h
| ... | ... | @@ -46,7 +46,7 @@ public: |
| 46 | 46 | //! \throws HueException when light type is unknown |
| 47 | 47 | //! \throws HueAPIResponseException when response contains an error |
| 48 | 48 | //! \throws nlohmann::json::parse_error when response could not be parsed |
| 49 | - Light createLight(const nlohmann::json& lightState, int id); | |
| 49 | + Light createLight(const nlohmann::json& lightState, int id, const std::shared_ptr<APICache>& baseCache = {}); | |
| 50 | 50 | |
| 51 | 51 | private: |
| 52 | 52 | //! \brief Get color type from light JSON. | ... | ... |
include/hueplusplus/Light.h
| ... | ... | @@ -554,6 +554,7 @@ public: |
| 554 | 554 | ///@} |
| 555 | 555 | |
| 556 | 556 | protected: |
| 557 | + | |
| 557 | 558 | //! \brief Protected ctor that is used by \ref Bridge class. |
| 558 | 559 | //! |
| 559 | 560 | //! \param id Integer that specifies the id of this light |
| ... | ... | @@ -562,6 +563,9 @@ protected: |
| 562 | 563 | //! leaves strategies unset |
| 563 | 564 | Light(int id, const HueCommandAPI& commands); |
| 564 | 565 | |
| 566 | + | |
| 567 | + Light(int id, const std::shared_ptr<APICache>& baseCache); | |
| 568 | + | |
| 565 | 569 | //! \brief Protected ctor that is used by \ref Bridge class, also sets |
| 566 | 570 | //! strategies. |
| 567 | 571 | //! | ... | ... |
include/hueplusplus/ResourceList.h
| ... | ... | @@ -45,6 +45,9 @@ template <typename Resource, typename IdT> |
| 45 | 45 | class ResourceList |
| 46 | 46 | { |
| 47 | 47 | public: |
| 48 | + struct SharedStateTag | |
| 49 | + { }; | |
| 50 | + | |
| 48 | 51 | using ResourceType = Resource; |
| 49 | 52 | using IdType = IdT; |
| 50 | 53 | static_assert(std::is_integral<IdType>::value || std::is_same<std::string, IdType>::value, |
| ... | ... | @@ -57,9 +60,13 @@ public: |
| 57 | 60 | //! \param factory Optional factory function to create Resources. |
| 58 | 61 | //! Necessary if Resource is not constructible as described above. |
| 59 | 62 | ResourceList(std::shared_ptr<APICache> baseCache, const std::string& cacheEntry, |
| 60 | - std::chrono::steady_clock::duration refreshDuration, | |
| 61 | - const std::function<Resource(IdType, const nlohmann::json&)>& factory = nullptr) | |
| 62 | - : stateCache(baseCache, cacheEntry, refreshDuration), factory(factory), path(stateCache.getRequestPath() + '/') | |
| 63 | + std::chrono::steady_clock::duration refreshDuration, bool sharedState = false, | |
| 64 | + const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory | |
| 65 | + = nullptr) | |
| 66 | + : stateCache(std::make_shared<APICache>(baseCache, cacheEntry, refreshDuration)), | |
| 67 | + factory(factory), | |
| 68 | + path(stateCache->getRequestPath() + '/'), | |
| 69 | + sharedState(sharedState) | |
| 63 | 70 | { } |
| 64 | 71 | //! \brief Construct ResourceList with a separate cache and optional factory function |
| 65 | 72 | //! \param commands HueCommandAPI for requests |
| ... | ... | @@ -69,8 +76,12 @@ public: |
| 69 | 76 | //! Necessary if Resource is not constructible as described above. |
| 70 | 77 | ResourceList(const HueCommandAPI& commands, const std::string& path, |
| 71 | 78 | std::chrono::steady_clock::duration refreshDuration, |
| 72 | - const std::function<Resource(IdType, const nlohmann::json&)>& factory = nullptr) | |
| 73 | - : stateCache(path, commands, refreshDuration), factory(factory), path(path + '/') | |
| 79 | + const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory | |
| 80 | + = nullptr) | |
| 81 | + : stateCache(std::make_shared<APICache>(path, commands, refreshDuration)), | |
| 82 | + factory(factory), | |
| 83 | + path(path + '/'), | |
| 84 | + sharedState(false) | |
| 74 | 85 | { } |
| 75 | 86 | |
| 76 | 87 | //! \brief Deleted copy constructor |
| ... | ... | @@ -79,7 +90,7 @@ public: |
| 79 | 90 | ResourceList& operator=(const ResourceList&) = delete; |
| 80 | 91 | |
| 81 | 92 | //! \brief Refreshes internal state now |
| 82 | - void refresh() { stateCache.refresh(); } | |
| 93 | + void refresh() { stateCache->refresh(); } | |
| 83 | 94 | |
| 84 | 95 | //! \brief Get all resources that exist |
| 85 | 96 | //! \returns A vector of references to every Resource |
| ... | ... | @@ -89,7 +100,7 @@ public: |
| 89 | 100 | //! \throws nlohmann::json::parse_error when response could not be parsed |
| 90 | 101 | std::vector<std::reference_wrapper<Resource>> getAll() |
| 91 | 102 | { |
| 92 | - nlohmann::json state = stateCache.getValue(); | |
| 103 | + nlohmann::json state = stateCache->getValue(); | |
| 93 | 104 | for (auto it = state.begin(); it != state.end(); ++it) |
| 94 | 105 | { |
| 95 | 106 | get(maybeStoi(it.key())); |
| ... | ... | @@ -118,7 +129,7 @@ public: |
| 118 | 129 | pos->second.refresh(true); |
| 119 | 130 | return pos->second; |
| 120 | 131 | } |
| 121 | - const nlohmann::json& state = stateCache.getValue(); | |
| 132 | + const nlohmann::json& state = stateCache->getValue(); | |
| 122 | 133 | std::string key = maybeToString(id); |
| 123 | 134 | if (!state.count(key)) |
| 124 | 135 | { |
| ... | ... | @@ -141,7 +152,7 @@ public: |
| 141 | 152 | { |
| 142 | 153 | return true; |
| 143 | 154 | } |
| 144 | - return stateCache.getValue().count(maybeToString(id)) != 0; | |
| 155 | + return stateCache->getValue().count(maybeToString(id)) != 0; | |
| 145 | 156 | } |
| 146 | 157 | |
| 147 | 158 | //! \brief Checks whether resource with id exists |
| ... | ... | @@ -156,7 +167,7 @@ public: |
| 156 | 167 | { |
| 157 | 168 | return true; |
| 158 | 169 | } |
| 159 | - return stateCache.getValue().count(maybeToString(id)) != 0; | |
| 170 | + return stateCache->getValue().count(maybeToString(id)) != 0; | |
| 160 | 171 | } |
| 161 | 172 | |
| 162 | 173 | //! \brief Removes the resource |
| ... | ... | @@ -171,7 +182,7 @@ public: |
| 171 | 182 | bool remove(const IdType& id) |
| 172 | 183 | { |
| 173 | 184 | std::string requestPath = path + maybeToString(id); |
| 174 | - nlohmann::json result = stateCache.getCommandAPI().DELETERequest( | |
| 185 | + nlohmann::json result = stateCache->getCommandAPI().DELETERequest( | |
| 175 | 186 | requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__}); |
| 176 | 187 | bool success = utils::safeGetMember(result, 0, "success") == requestPath + " deleted"; |
| 177 | 188 | auto it = resources.find(id); |
| ... | ... | @@ -208,11 +219,18 @@ private: |
| 208 | 219 | { |
| 209 | 220 | if (factory) |
| 210 | 221 | { |
| 211 | - return factory(id, state); | |
| 222 | + return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>()); | |
| 212 | 223 | } |
| 213 | 224 | else |
| 214 | 225 | { |
| 215 | - return Resource(id, stateCache.getCommandAPI(), stateCache.getRefreshDuration()); | |
| 226 | + if (sharedState) | |
| 227 | + { | |
| 228 | + return Resource(id, stateCache); | |
| 229 | + } | |
| 230 | + else | |
| 231 | + { | |
| 232 | + return Resource(id, stateCache->getCommandAPI(), stateCache->getRefreshDuration()); | |
| 233 | + } | |
| 216 | 234 | } |
| 217 | 235 | } |
| 218 | 236 | // Resource is not constructable |
| ... | ... | @@ -223,7 +241,7 @@ private: |
| 223 | 241 | throw HueException(FileInfo {__FILE__, __LINE__, __func__}, |
| 224 | 242 | "Resource is not constructable with default parameters, but no factory given"); |
| 225 | 243 | } |
| 226 | - return factory(id, state); | |
| 244 | + return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>()); | |
| 227 | 245 | } |
| 228 | 246 | |
| 229 | 247 | private: |
| ... | ... | @@ -233,10 +251,11 @@ private: |
| 233 | 251 | static std::string maybeToString(const IdType& id, std::false_type) { return id; } |
| 234 | 252 | |
| 235 | 253 | protected: |
| 236 | - APICache stateCache; | |
| 237 | - std::function<Resource(IdType, const nlohmann::json&)> factory; | |
| 254 | + std::shared_ptr<APICache> stateCache; | |
| 255 | + std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)> factory; | |
| 238 | 256 | std::string path; |
| 239 | 257 | std::map<IdType, Resource> resources; |
| 258 | + bool sharedState; | |
| 240 | 259 | }; |
| 241 | 260 | |
| 242 | 261 | //! \brief Handles a ResourceList of physical devices which can be searched for |
| ... | ... | @@ -258,12 +277,12 @@ public: |
| 258 | 277 | requestPath.pop_back(); |
| 259 | 278 | if (deviceIds.empty()) |
| 260 | 279 | { |
| 261 | - this->stateCache.getCommandAPI().POSTRequest( | |
| 280 | + this->stateCache->getCommandAPI().POSTRequest( | |
| 262 | 281 | requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__}); |
| 263 | 282 | } |
| 264 | 283 | else |
| 265 | 284 | { |
| 266 | - this->stateCache.getCommandAPI().POSTRequest( | |
| 285 | + this->stateCache->getCommandAPI().POSTRequest( | |
| 267 | 286 | requestPath, nlohmann::json {{"deviceid", deviceIds}}, FileInfo {__FILE__, __LINE__, __func__}); |
| 268 | 287 | } |
| 269 | 288 | } |
| ... | ... | @@ -271,7 +290,7 @@ public: |
| 271 | 290 | //! \brief Get devices found in last search |
| 272 | 291 | NewDeviceList getNewDevices() const |
| 273 | 292 | { |
| 274 | - nlohmann::json response = this->stateCache.getCommandAPI().GETRequest( | |
| 293 | + nlohmann::json response = this->stateCache->getCommandAPI().GETRequest( | |
| 275 | 294 | this->path + "new", nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__}); |
| 276 | 295 | return NewDeviceList::parse(response); |
| 277 | 296 | } |
| ... | ... | @@ -306,7 +325,7 @@ public: |
| 306 | 325 | std::string requestPath = this->path; |
| 307 | 326 | // Remove slash |
| 308 | 327 | requestPath.pop_back(); |
| 309 | - nlohmann::json response = this->stateCache.getCommandAPI().POSTRequest( | |
| 328 | + nlohmann::json response = this->stateCache->getCommandAPI().POSTRequest( | |
| 310 | 329 | requestPath, params.getRequest(), FileInfo {__FILE__, __LINE__, __func__}); |
| 311 | 330 | nlohmann::json id = utils::safeGetMember(response, 0, "success", "id"); |
| 312 | 331 | if (id.is_string()) |
| ... | ... | @@ -316,7 +335,7 @@ public: |
| 316 | 335 | { |
| 317 | 336 | idStr.erase(0, this->path.size()); |
| 318 | 337 | } |
| 319 | - this->stateCache.refresh(); | |
| 338 | + this->stateCache->refresh(); | |
| 320 | 339 | return this->maybeStoi(idStr); |
| 321 | 340 | } |
| 322 | 341 | return typename BaseResourceList::IdType {}; |
| ... | ... | @@ -350,7 +369,7 @@ public: |
| 350 | 369 | pos->second.refresh(); |
| 351 | 370 | return pos->second; |
| 352 | 371 | } |
| 353 | - const nlohmann::json& state = this->stateCache.getValue(); | |
| 372 | + const nlohmann::json& state = this->stateCache->getValue(); | |
| 354 | 373 | std::string key = this->maybeToString(id); |
| 355 | 374 | if (!state.count(key) && id != 0) |
| 356 | 375 | { | ... | ... |
include/hueplusplus/Sensor.h
| ... | ... | @@ -59,6 +59,8 @@ Alert alertFromString(const std::string& s); |
| 59 | 59 | class Sensor : public BaseDevice |
| 60 | 60 | { |
| 61 | 61 | public: |
| 62 | + Sensor(int id, const std::shared_ptr<APICache>& baseCache); | |
| 63 | + | |
| 62 | 64 | //! \brief Construct Sensor. |
| 63 | 65 | //! \param id Integer that specifies the id of this sensor |
| 64 | 66 | //! \param commands HueCommandAPI for communication with the bridge | ... | ... |
include/hueplusplus/SensorList.h
| ... | ... | @@ -58,7 +58,7 @@ public: |
| 58 | 58 | template <typename T> |
| 59 | 59 | std::vector<T> getAllByType() |
| 60 | 60 | { |
| 61 | - nlohmann::json state = this->stateCache.getValue(); | |
| 61 | + nlohmann::json state = this->stateCache->getValue(); | |
| 62 | 62 | std::vector<T> result; |
| 63 | 63 | for (auto it = state.begin(); it != state.end(); ++it) |
| 64 | 64 | { | ... | ... |
src/BaseDevice.cpp
| ... | ... | @@ -91,6 +91,10 @@ bool BaseDevice::setName(const std::string& name) |
| 91 | 91 | return utils::safeGetMember(reply, 0, "success", "/lights/" + std::to_string(id) + "/name").is_string(); |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | +BaseDevice::BaseDevice(int id, const std::shared_ptr<APICache>& baseCache) | |
| 95 | + : id(id), state(baseCache, std::to_string(id), baseCache->getRefreshDuration()) | |
| 96 | +{ } | |
| 97 | + | |
| 94 | 98 | BaseDevice::BaseDevice( |
| 95 | 99 | int id, const HueCommandAPI& commands, const std::string& path, std::chrono::steady_clock::duration refreshDuration) |
| 96 | 100 | : id(id), path(path), state(path + std::to_string(id), commands, refreshDuration) | ... | ... |
src/Bridge.cpp
| ... | ... | @@ -138,7 +138,7 @@ std::string BridgeFinder::ParseDescription(const std::string& description) |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | 140 | Bridge::Bridge(const std::string& ip, const int port, const std::string& username, |
| 141 | - std::shared_ptr<const IHttpHandler> handler, std::chrono::steady_clock::duration refreshDuration) | |
| 141 | + std::shared_ptr<const IHttpHandler> handler, std::chrono::steady_clock::duration refreshDuration, bool sharedState) | |
| 142 | 142 | : ip(ip), |
| 143 | 143 | username(username), |
| 144 | 144 | port(port), |
| ... | ... | @@ -146,15 +146,18 @@ Bridge::Bridge(const std::string& ip, const int port, const std::string& usernam |
| 146 | 146 | refreshDuration(refreshDuration), |
| 147 | 147 | stateCache(std::make_shared<APICache>( |
| 148 | 148 | "", HueCommandAPI(ip, port, username, http_handler), std::chrono::steady_clock::duration::max())), |
| 149 | - lightList(stateCache, "lights", refreshDuration, | |
| 149 | + lightList(stateCache, "lights", refreshDuration, sharedState, | |
| 150 | 150 | [factory = LightFactory(stateCache->getCommandAPI(), refreshDuration)]( |
| 151 | - int id, const nlohmann::json& state) mutable { return factory.createLight(state, id); }), | |
| 152 | - groupList(stateCache, "groups", refreshDuration), | |
| 153 | - scheduleList(stateCache, "schedules", refreshDuration), | |
| 154 | - sceneList(stateCache, "scenes", refreshDuration), | |
| 155 | - sensorList(stateCache, "sensors", refreshDuration), | |
| 156 | - ruleList(stateCache, "rules", refreshDuration), | |
| 157 | - bridgeConfig(stateCache, refreshDuration) | |
| 151 | + int id, const nlohmann::json& state, const std::shared_ptr<APICache>& baseCache) mutable { | |
| 152 | + return factory.createLight(state, id, baseCache); | |
| 153 | + }), | |
| 154 | + groupList(stateCache, "groups", refreshDuration, sharedState), | |
| 155 | + scheduleList(stateCache, "schedules", refreshDuration, sharedState), | |
| 156 | + sceneList(stateCache, "scenes", refreshDuration, sharedState), | |
| 157 | + sensorList(stateCache, "sensors", refreshDuration, sharedState), | |
| 158 | + ruleList(stateCache, "rules", refreshDuration, sharedState), | |
| 159 | + bridgeConfig(stateCache, refreshDuration), | |
| 160 | + sharedState(sharedState) | |
| 158 | 161 | { } |
| 159 | 162 | |
| 160 | 163 | void Bridge::refresh() |
| ... | ... | @@ -304,13 +307,14 @@ void Bridge::setHttpHandler(std::shared_ptr<const IHttpHandler> handler) |
| 304 | 307 | { |
| 305 | 308 | http_handler = handler; |
| 306 | 309 | stateCache = std::make_shared<APICache>("", HueCommandAPI(ip, port, username, handler), refreshDuration); |
| 307 | - lightList = LightList(stateCache, "lights", refreshDuration, | |
| 308 | - [factory = LightFactory(stateCache->getCommandAPI(), refreshDuration)]( | |
| 309 | - int id, const nlohmann::json& state) mutable { return factory.createLight(state, id); }); | |
| 310 | - groupList = GroupList(stateCache, "groups", refreshDuration); | |
| 311 | - scheduleList = ScheduleList(stateCache, "schedules", refreshDuration); | |
| 312 | - sceneList = SceneList(stateCache, "scenes", refreshDuration); | |
| 313 | - sensorList = SensorList(stateCache, "sensors", refreshDuration); | |
| 310 | + lightList = LightList(stateCache, "lights", refreshDuration,sharedState, | |
| 311 | + [factory = LightFactory(stateCache->getCommandAPI(), refreshDuration)](int id, const nlohmann::json& state, | |
| 312 | + const std::shared_ptr<APICache>& baseCache) mutable { return factory.createLight(state, id, baseCache); }); | |
| 313 | + groupList = GroupList(stateCache, "groups", refreshDuration, sharedState); | |
| 314 | + scheduleList = ScheduleList(stateCache, "schedules", refreshDuration, sharedState); | |
| 315 | + sceneList = SceneList(stateCache, "scenes", refreshDuration, sharedState); | |
| 316 | + sensorList = SensorList(stateCache, "sensors", refreshDuration, sharedState); | |
| 317 | + ruleList = RuleList(stateCache, "rules", refreshDuration, sharedState); | |
| 314 | 318 | bridgeConfig = BridgeConfig(stateCache, refreshDuration); |
| 315 | 319 | stateCache->refresh(); |
| 316 | 320 | } | ... | ... |
src/Group.cpp
| ... | ... | @@ -4,6 +4,10 @@ |
| 4 | 4 | |
| 5 | 5 | namespace hueplusplus |
| 6 | 6 | { |
| 7 | +Group::Group(int id, const std::shared_ptr<APICache>& baseCache) | |
| 8 | + : id(id), state(baseCache, std::to_string(id), baseCache->getRefreshDuration()) | |
| 9 | +{ } | |
| 10 | + | |
| 7 | 11 | Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration) |
| 8 | 12 | : id(id), state("/groups/" + std::to_string(id), commands, refreshDuration) |
| 9 | 13 | { | ... | ... |
src/HueDeviceTypes.cpp
| ... | ... | @@ -67,41 +67,46 @@ LightFactory::LightFactory(const HueCommandAPI& commands, std::chrono::steady_cl |
| 67 | 67 | extendedColorTemperature(std::make_shared<ExtendedColorTemperatureStrategy>()), |
| 68 | 68 | simpleColorHue(std::make_shared<SimpleColorHueStrategy>()), |
| 69 | 69 | extendedColorHue(std::make_shared<ExtendedColorHueStrategy>()) |
| 70 | -{} | |
| 70 | +{ } | |
| 71 | 71 | |
| 72 | -Light LightFactory::createLight(const nlohmann::json& lightState, int id) | |
| 72 | +Light LightFactory::createLight(const nlohmann::json& lightState, int id, const std::shared_ptr<APICache>& baseCache) | |
| 73 | 73 | { |
| 74 | 74 | std::string type = lightState.value("type", ""); |
| 75 | 75 | // Ignore case |
| 76 | 76 | std::transform(type.begin(), type.end(), type.begin(), [](char c) { return std::tolower(c); }); |
| 77 | 77 | |
| 78 | + Light light = baseCache ? Light(id, baseCache) : Light(id, commands, nullptr, nullptr, nullptr, refreshDuration); | |
| 79 | + | |
| 78 | 80 | if (type == "on/off light" || type == "on/off plug-in unit") |
| 79 | 81 | { |
| 80 | - Light light(id, commands, nullptr, nullptr, nullptr, refreshDuration); | |
| 81 | 82 | light.colorType = ColorType::NONE; |
| 82 | 83 | return light; |
| 83 | 84 | } |
| 84 | - else if (type == "dimmable light" || type =="dimmable plug-in unit") | |
| 85 | + else if (type == "dimmable light" || type == "dimmable plug-in unit") | |
| 85 | 86 | { |
| 86 | - Light light(id, commands, simpleBrightness, nullptr, nullptr, refreshDuration); | |
| 87 | + light.setBrightnessStrategy(simpleBrightness); | |
| 87 | 88 | light.colorType = ColorType::NONE; |
| 88 | 89 | return light; |
| 89 | 90 | } |
| 90 | 91 | else if (type == "color temperature light") |
| 91 | 92 | { |
| 92 | - Light light(id, commands, simpleBrightness, simpleColorTemperature, nullptr, refreshDuration); | |
| 93 | + light.setBrightnessStrategy(simpleBrightness); | |
| 94 | + light.setColorTemperatureStrategy(simpleColorTemperature); | |
| 93 | 95 | light.colorType = ColorType::TEMPERATURE; |
| 94 | 96 | return light; |
| 95 | 97 | } |
| 96 | 98 | else if (type == "color light") |
| 97 | 99 | { |
| 98 | - Light light(id, commands, simpleBrightness, nullptr, simpleColorHue, refreshDuration); | |
| 100 | + light.setBrightnessStrategy(simpleBrightness); | |
| 101 | + light.setColorHueStrategy(simpleColorHue); | |
| 99 | 102 | light.colorType = getColorType(lightState, false); |
| 100 | 103 | return light; |
| 101 | 104 | } |
| 102 | 105 | else if (type == "extended color light") |
| 103 | 106 | { |
| 104 | - Light light(id, commands, simpleBrightness, extendedColorTemperature, extendedColorHue, refreshDuration); | |
| 107 | + light.setBrightnessStrategy(simpleBrightness); | |
| 108 | + light.setColorTemperatureStrategy(extendedColorTemperature); | |
| 109 | + light.setColorHueStrategy(extendedColorHue); | |
| 105 | 110 | light.colorType = getColorType(lightState, true); |
| 106 | 111 | return light; |
| 107 | 112 | } | ... | ... |
src/Light.cpp
| ... | ... | @@ -114,6 +114,9 @@ StateTransaction Light::transaction() |
| 114 | 114 | |
| 115 | 115 | Light::Light(int id, const HueCommandAPI& commands) : Light(id, commands, nullptr, nullptr, nullptr) { } |
| 116 | 116 | |
| 117 | +Light::Light(int id, const std::shared_ptr<APICache>& baseCache) : BaseDevice(id, baseCache), colorType(ColorType::NONE) | |
| 118 | +{ } | |
| 119 | + | |
| 117 | 120 | Light::Light(int id, const HueCommandAPI& commands, std::shared_ptr<const BrightnessStrategy> brightnessStrategy, |
| 118 | 121 | std::shared_ptr<const ColorTemperatureStrategy> colorTempStrategy, |
| 119 | 122 | std::shared_ptr<const ColorHueStrategy> colorHueStrategy, std::chrono::steady_clock::duration refreshDuration) |
| ... | ... | @@ -122,6 +125,5 @@ Light::Light(int id, const HueCommandAPI& commands, std::shared_ptr<const Bright |
| 122 | 125 | brightnessStrategy(std::move(brightnessStrategy)), |
| 123 | 126 | colorTemperatureStrategy(std::move(colorTempStrategy)), |
| 124 | 127 | colorHueStrategy(std::move(colorHueStrategy)) |
| 125 | -{ | |
| 126 | -} | |
| 128 | +{ } | |
| 127 | 129 | } // namespace hueplusplus | ... | ... |
src/Sensor.cpp
| ... | ... | @@ -230,6 +230,11 @@ bool Sensor::isPrimary() const |
| 230 | 230 | return primary.is_boolean() && primary.get<bool>(); |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | +Sensor::Sensor(int id, const std::shared_ptr<APICache>& baseCache) | |
| 234 | + : BaseDevice(id, baseCache) | |
| 235 | +{ } | |
| 236 | + | |
| 237 | + | |
| 233 | 238 | Sensor::Sensor(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration) |
| 234 | 239 | : BaseDevice(id, commands, "/sensors/", refreshDuration) |
| 235 | 240 | { } | ... | ... |
test/test_ResourceList.cpp
| ... | ... | @@ -32,6 +32,7 @@ using namespace testing; |
| 32 | 32 | class TestResource |
| 33 | 33 | { |
| 34 | 34 | public: |
| 35 | + TestResource(int id, std::shared_ptr<APICache> baseCache) {} | |
| 35 | 36 | TestResource(int id, HueCommandAPI api, std::chrono::steady_clock::duration refreshDuration) : id(id) { } |
| 36 | 37 | |
| 37 | 38 | void refresh(bool force = false) { } |
| ... | ... | @@ -47,6 +48,7 @@ public: |
| 47 | 48 | class TestStringResource |
| 48 | 49 | { |
| 49 | 50 | public: |
| 51 | + TestStringResource(const std::string& id, std::shared_ptr<APICache> baseCache) {} | |
| 50 | 52 | TestStringResource(const std::string& id, HueCommandAPI api, std::chrono::steady_clock::duration refreshDuration) |
| 51 | 53 | : id(id) |
| 52 | 54 | { } |
| ... | ... | @@ -122,8 +124,8 @@ TEST(ResourceList, get) |
| 122 | 124 | const nlohmann::json state = {{"resource", "state"}}; |
| 123 | 125 | const nlohmann::json response = {{std::to_string(id), state}}; |
| 124 | 126 | |
| 125 | - MockFunction<TestResource(int, const nlohmann::json&)> factory; | |
| 126 | - EXPECT_CALL(factory, Call(id, state)) | |
| 127 | + MockFunction<TestResource(int, const nlohmann::json&, const std::shared_ptr<APICache>&)> factory; | |
| 128 | + EXPECT_CALL(factory, Call(id, state, std::shared_ptr<APICache>())) | |
| 127 | 129 | .WillOnce(Return(TestResource(id, commands, std::chrono::steady_clock::duration::max()))); |
| 128 | 130 | |
| 129 | 131 | ResourceList<TestResource, int> list( |
| ... | ... | @@ -162,7 +164,7 @@ TEST(ResourceList, get) |
| 162 | 164 | } |
| 163 | 165 | { |
| 164 | 166 | ResourceList<TestResourceFactory, int> list(commands, path, std::chrono::steady_clock::duration::max(), |
| 165 | - [](int, const nlohmann::json&) { return TestResourceFactory(); }); | |
| 167 | + [](int, const nlohmann::json&, const std::shared_ptr<APICache>&) { return TestResourceFactory(); }); | |
| 166 | 168 | |
| 167 | 169 | const int id = 2; |
| 168 | 170 | const nlohmann::json response = {{std::to_string(id), {{"resource", "state"}}}}; | ... | ... |