hueplusplus 1.2.0
Loading...
Searching...
No Matches
ResourceList.h
Go to the documentation of this file.
1
22#ifndef INCLUDE_HUEPLUSPLUS_RESOURCE_LIST_H
23#define INCLUDE_HUEPLUSPLUS_RESOURCE_LIST_H
24
25#include <functional>
26#include <map>
27#include <string>
28#include <vector>
29
30#include "APICache.h"
31#include "HueException.h"
32#include "NewDeviceList.h"
33#include "Utils.h"
34
35namespace hueplusplus
36{
45template <typename Resource, typename IdT>
47{
48public:
49 using ResourceType = Resource;
50 using IdType = IdT;
51 static_assert(std::is_integral<IdType>::value || std::is_same<std::string, IdType>::value,
52 "IdType must be integral or string");
53
61 ResourceList(std::shared_ptr<APICache> baseCache, const std::string& cacheEntry,
62 std::chrono::steady_clock::duration refreshDuration, bool sharedState = false,
63 const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory
64 = nullptr)
65 : stateCache(std::make_shared<APICache>(baseCache, cacheEntry, refreshDuration)),
67 path(stateCache->getRequestPath() + '/'),
69 { }
76 ResourceList(const HueCommandAPI& commands, const std::string& path,
77 std::chrono::steady_clock::duration refreshDuration,
78 const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory
79 = nullptr)
80 : stateCache(std::make_shared<APICache>(path, commands, refreshDuration, nullptr)),
82 path(path + '/'),
83 sharedState(false)
84 { }
85
87 ResourceList(const ResourceList&) = delete;
90
92 void refresh() { stateCache->refresh(); }
93
96 void setRefreshDuration(std::chrono::steady_clock::duration refreshDuration)
97 {
98 stateCache->setRefreshDuration(refreshDuration);
99 }
100
107 std::vector<Resource> getAll()
108 {
109 nlohmann::json& state = stateCache->getValue();
110 std::vector<Resource> result;
111 result.reserve(state.size());
112 for (auto it = state.begin(); it != state.end(); ++it)
113 {
114 result.emplace_back(construct(maybeStoi(it.key()), it.value()));
115 }
116 return result;
117 }
118
126 Resource get(const IdType& id)
127 {
128 const nlohmann::json& state = stateCache->getValue();
129 std::string key = maybeToString(id);
130 if (!state.count(key))
131 {
132 throw HueException(FileInfo {__FILE__, __LINE__, __func__}, "Resource id is not valid");
133 }
134 return construct(id, state[key]);
135 }
136
144 bool exists(const IdType& id) { return stateCache->getValue().count(maybeToString(id)) != 0; }
145
151 bool exists(const IdType& id) const { return stateCache->getValue().count(maybeToString(id)) != 0; }
152
162 bool remove(const IdType& id)
163 {
164 std::string requestPath = path + maybeToString(id);
165 nlohmann::json result = stateCache->getCommandAPI().DELETERequest(
166 requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
167 bool success = utils::safeGetMember(result, 0, "success") == requestPath + " deleted";
168 return success;
169 }
170
171protected:
173 static IdType maybeStoi(const std::string& key) { return maybeStoi(key, std::is_integral<IdType> {}); }
174
176 static std::string maybeToString(const IdType& id) { return maybeToString(id, std::is_integral<IdType> {}); }
177
180 Resource construct(const IdType& id, const nlohmann::json& state)
181 {
182 return construct(id, state,
183 std::is_constructible<Resource, IdType, HueCommandAPI, std::chrono::steady_clock::duration,
184 const nlohmann::json&> {});
185 }
186
191
192private:
193 // Resource is constructible
194 Resource construct(const IdType& id, const nlohmann::json& state, std::true_type)
195 {
196 if (factory)
197 {
198 return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>());
199 }
200 else
201 {
202 if (sharedState)
203 {
204 return Resource(id, stateCache);
205 }
206 else
207 {
208 return Resource(id, stateCache->getCommandAPI(), stateCache->getRefreshDuration(), state);
209 }
210 }
211 }
212 // Resource is not constructible
213 Resource construct(const IdType& id, const nlohmann::json& state, std::false_type)
214 {
215 if (!factory)
216 {
217 throw HueException(FileInfo {__FILE__, __LINE__, __func__},
218 "Resource is not constructable with default parameters, but no factory given");
219 }
220 return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>());
221 }
222
223private:
224 static IdType maybeStoi(const std::string& key, std::true_type) { return std::stoi(key); }
225 static IdType maybeStoi(const std::string& key, std::false_type) { return key; }
226 static std::string maybeToString(IdType id, std::true_type) { return std::to_string(id); }
227 static std::string maybeToString(const IdType& id, std::false_type) { return id; }
228
229protected:
230 std::shared_ptr<APICache> stateCache;
231 std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)> factory;
232 std::string path;
234};
235
238template <typename Resource>
239class SearchableResourceList : public ResourceList<Resource, int>
240{
241public:
242 using ResourceList<Resource, int>::ResourceList;
243
248 void search(const std::vector<std::string>& deviceIds = {})
249 {
250 std::string requestPath = this->path;
251 // Remove trailing slash
252 requestPath.pop_back();
253 if (deviceIds.empty())
254 {
255 this->stateCache->getCommandAPI().POSTRequest(
256 requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
257 }
258 else
259 {
260 this->stateCache->getCommandAPI().POSTRequest(
261 requestPath, nlohmann::json {{"deviceid", deviceIds}}, FileInfo {__FILE__, __LINE__, __func__});
262 }
263 }
264
267 {
268 nlohmann::json response = this->stateCache->getCommandAPI().GETRequest(
269 this->path + "new", nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
270 return NewDeviceList::parse(response);
271 }
272
273protected:
278};
279
284template <typename BaseResourceList, typename CreateType>
285class CreateableResourceList : public BaseResourceList
286{
287public:
288 using BaseResourceList::BaseResourceList;
289
298 typename BaseResourceList::IdType create(const CreateType& params)
299 {
300 std::string requestPath = this->path;
301 // Remove slash
302 requestPath.pop_back();
303 nlohmann::json response = this->stateCache->getCommandAPI().POSTRequest(
304 requestPath, params.getRequest(), FileInfo {__FILE__, __LINE__, __func__});
305 nlohmann::json id = utils::safeGetMember(response, 0, "success", "id");
306 if (id.is_string())
307 {
308 std::string idStr = id.get<std::string>();
309 if (idStr.find(this->path) == 0)
310 {
311 idStr.erase(0, this->path.size());
312 }
313 this->stateCache->refresh();
314 return this->maybeStoi(idStr);
315 }
316 return typename BaseResourceList::IdType {};
317 }
318
319protected:
324};
325
330template <typename Resource, typename CreateType>
331class GroupResourceList : public CreateableResourceList<ResourceList<Resource, int>, CreateType>
332{
334
335public:
336 using Base::Base;
339 Resource get(const int& id)
340 {
341 const nlohmann::json& state = this->stateCache->getValue();
342 std::string key = this->maybeToString(id);
343 if (!state.count(key) && id != 0)
344 {
345 throw HueException(FileInfo {__FILE__, __LINE__, __func__}, "Resource id is not valid");
346 }
347 return this->construct(id, id == 0 ? nlohmann::json {nullptr} : state[key]);
348 }
351 bool exists(int id) const { return id == 0 || Base::exists(id); }
352
353protected:
358};
359} // namespace hueplusplus
360
361#endif
Caches API GET requests and refreshes regularly.
Definition APICache.h:38
Handles a ResourceList where Resources can be added by the user.
Definition ResourceList.h:286
BaseResourceList::IdType create(const CreateType &params)
Create a new resource.
Definition ResourceList.h:298
CreateableResourceList & operator=(CreateableResourceList &&)=default
Protected defaulted move assignment.
CreateableResourceList(CreateableResourceList &&)=default
Protected defaulted move constructor.
Handles a group list with the special group 0.
Definition ResourceList.h:332
Resource get(const int &id)
Get group, specially handles group 0.
Definition ResourceList.h:339
GroupResourceList & operator=(GroupResourceList &&)=default
Protected defaulted move assignment.
GroupResourceList(GroupResourceList &&)=default
Protected defaulted move constructor.
bool exists(int id) const
Get group, specially handles group 0.
Definition ResourceList.h:351
Definition HueCommandAPI.h:38
Exception class with file information. Base class of all custom exception classes.
Definition HueException.h:50
List of new devices found during the last scan.
Definition NewDeviceList.h:36
static NewDeviceList parse(const nlohmann::json &json)
Parse from json response.
Definition NewDeviceList.cpp:45
Handles a list of a certain API resource.
Definition ResourceList.h:47
ResourceList(ResourceList &&)=default
Protected defaulted move constructor.
ResourceList(const ResourceList &)=delete
Deleted copy constructor.
Resource ResourceType
Definition ResourceList.h:49
ResourceList(const HueCommandAPI &commands, const std::string &path, std::chrono::steady_clock::duration refreshDuration, const std::function< Resource(IdType, const nlohmann::json &, const std::shared_ptr< APICache > &)> &factory=nullptr)
Construct ResourceList with a separate cache and optional factory function.
Definition ResourceList.h:76
void refresh()
Refreshes internal state now.
Definition ResourceList.h:92
Resource get(const IdType &id)
Get resource specified by id.
Definition ResourceList.h:126
bool exists(const IdType &id) const
Checks whether resource with id exists.
Definition ResourceList.h:151
ResourceList(std::shared_ptr< APICache > baseCache, const std::string &cacheEntry, std::chrono::steady_clock::duration refreshDuration, bool sharedState=false, const std::function< Resource(IdType, const nlohmann::json &, const std::shared_ptr< APICache > &)> &factory=nullptr)
Construct ResourceList using a base cache and optional factory function.
Definition ResourceList.h:61
void setRefreshDuration(std::chrono::steady_clock::duration refreshDuration)
Sets custom refresh interval for this list and all resources created.
Definition ResourceList.h:96
std::vector< Resource > getAll()
Get all resources that exist.
Definition ResourceList.h:107
ResourceList & operator=(const ResourceList &)=delete
Deleted copy assignment.
IdT IdType
Definition ResourceList.h:50
ResourceList & operator=(ResourceList &&)=default
Protected defaulted move assignment.
Resource construct(const IdType &id, const nlohmann::json &state)
Constructs resource using factory or constructor, if available.
Definition ResourceList.h:180
static IdType maybeStoi(const std::string &key)
Calls std::stoi if IdType is int.
Definition ResourceList.h:173
bool sharedState
Definition ResourceList.h:233
std::shared_ptr< APICache > stateCache
Definition ResourceList.h:230
std::string path
Definition ResourceList.h:232
std::function< Resource(IdType, const nlohmann::json &, const std::shared_ptr< APICache > &)> factory
Definition ResourceList.h:231
bool remove(const IdType &id)
Removes the resource.
Definition ResourceList.h:162
static std::string maybeToString(const IdType &id)
Calls std::to_string if IdType is int.
Definition ResourceList.h:176
bool exists(const IdType &id)
Checks whether resource with id exists.
Definition ResourceList.h:144
Handles a ResourceList of physical devices which can be searched for.
Definition ResourceList.h:240
NewDeviceList getNewDevices() const
Get devices found in last search.
Definition ResourceList.h:266
void search(const std::vector< std::string > &deviceIds={})
Start search for new devices.
Definition ResourceList.h:248
SearchableResourceList(SearchableResourceList &&)=default
Protected defaulted move constructor.
SearchableResourceList & operator=(SearchableResourceList &&)=default
Protected defaulted move assignment.
nlohmann::json safeGetMember(const nlohmann::json &json, Paths &&... paths)
Returns the object/array member or null if it does not exist.
Definition Utils.h:92
Namespace for the hueplusplus library.
Definition Action.h:28
Contains information about error location, use CURRENT_FILE_INFO to create.
Definition HueException.h:35