diff --git a/include/hueplusplus/APICache.h b/include/hueplusplus/APICache.h
index 55c9766..c1ffbf4 100644
--- a/include/hueplusplus/APICache.h
+++ b/include/hueplusplus/APICache.h
@@ -45,19 +45,19 @@ public:
//! \throws HueException when response contained no body
//! \throws HueAPIResponseException when response contains an error
//! \throws nlohmann::json::parse_error when response could not be parsed
- void Refresh();
+ void refresh();
//! \brief Get cached value, refresh if necessary.
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contained no body
//! \throws HueAPIResponseException when response contains an error
//! \throws nlohmann::json::parse_error when response could not be parsed
- nlohmann::json& GetValue();
+ nlohmann::json& getValue();
//! \brief Get cached value, does not refresh.
- const nlohmann::json& GetValue() const;
+ const nlohmann::json& getValue() const;
//! \brief Get duration between refreshes.
- std::chrono::steady_clock::duration GetRefreshDuration() const;
+ std::chrono::steady_clock::duration getRefreshDuration() const;
private:
std::string path;
diff --git a/include/hueplusplus/Group.h b/include/hueplusplus/Group.h
index 7ac73d6..648ab5d 100644
--- a/include/hueplusplus/Group.h
+++ b/include/hueplusplus/Group.h
@@ -34,67 +34,250 @@
namespace hueplusplus
{
+//! \brief Class for Groups of lights.
+//!
+//! Provides methods to control groups.
class Group
{
public:
+ //! Creates group with id
+ //! \param id Group id in the bridge
+ //! \param commands HueCommandAPI for requests
+ //! \param refreshDuration Time between refreshing the cached state.
Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration);
- virtual ~Group() = default;
+ //! \brief Refreshes internal cached state.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
+ void refresh();
- void Refresh();
+ //! \name General information
+ ///@{
+ //! \brief Get the group id.
int getId() const;
+
+ //! \brief Get the group name.
std::string getName() const;
+
+ //! \brief Get the group type.
+ //!
+ //! The type is specified on creation and cannot be changed.
+ //!
+ //! Possible types:
+ //! \li 0: Special group containing all lights, cannot be modified.
+ //! \li Luminaire, Lightsource: Automatically created groups for multisource luminaires.
+ //! \li LightGroup: Standard, user created group, not empty.
+ //! \li Room: User created room, has room type.
+ //! \li Entertainment: User created entertainment setup.
+ //! \li Zone: User created Zone.
std::string getType() const;
+
+ //! \brief Get lights in the group.
+ //! \returns Ids of the lights in the group.
std::vector getLightIds() const;
+ //! \brief Set group name.
+ //! \param name New name for the group.
+ //! Must be unique for all groups, otherwise a number is added.
void setName(const std::string& name);
+ //! \brief Set group lights.
+ //! \param ids New light ids. May or may not be empty depending on type.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
void setLights(const std::vector& ids);
- // Only for type room
+ //! \brief Get room type, only for type room.
+ //! \returns Room type/class of the group.
std::string getRoomType() const;
+ //! \brief Set room type, only for type room.
+ //! \param type New room class, case sensitive.
+ //! Only specific values are allowed.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
void setRoomType(const std::string& type);
- // Only for type luminaire
+ //! \brief Get luminaire model id, only for type luminaire.
+ //! \returns Unique id for the hardware model.
std::string getModelId() const;
- // For luminaire or lightsource
+
+ //! \brief Get luminaire model id, only for type luminaire or lightsource.
+ //! \returns Unique id in AA:BB:CC:DD format for luminaire groups
+ //! or AA:BB:CC:DD-XX for Lightsource groups.
std::string getUniqueId() const;
+ //! \brief Get whether all lights are on.
+ //! \returns true when all lights are on.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
bool getAllOn();
+
+ //! \brief Get whether all lights are on.
+ //! \returns true when all lights are on.
+ //! \note Does not refresh the state.
bool getAllOn() const;
+
+ //! \brief Get whether any light is on.
+ //! \returns true when any light is on.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
bool getAnyOn();
+
+ //! \brief Get whether any light is on.
+ //! \returns true when any light is on.
+ //! \note Does not refresh the state.
bool getAnyOn() const;
+ ///@}
+ //! \name Query Action
+ //! The action is the state of one light in the group.
+ //! It can be accessed using these methods.
+ ///@{
+
+ //! \brief Get on state of one light in the group.
+ //! \returns True if the light is on.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
bool getActionOn();
+
+ //! \brief Get on state of one light in the group.
+ //! \returns True if the light is on.
+ //! \note Does not refresh the state.
bool getActionOn() const;
+
+ //! \brief Get hue and saturation of one light in the group.
+ //! \returns Pair of hue, saturation.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
std::pair getActionHueSaturation();
+
+ //! \brief Get hue and saturation of one light in the group.
+ //! \returns Pair of hue, saturation.
+ //! \note Does not refresh the state.
std::pair getActionHueSaturation() const;
+
+ //! \brief Get brightness of one light in the group.
+ //! \returns Brightness (0-254).
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
unsigned int getActionBrightness();
+
+ //! \brief Get brightness of one light in the group.
+ //! \returns Brightness (0-254).
+ //! \note Does not refresh the state.
unsigned int getActionBrightness() const;
+
+ //! \brief Get color temperature of one light in the group.
+ //! \returns Color temperature in mired.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
unsigned int getActionColorTemperature();
+
+ //! \brief Get color temperature of one light in the group.
+ //! \returns Color temperature in mired.
+ //! \note Does not refresh the state.
unsigned int getActionColorTemperature() const;
+
+ //! \brief Get color coordinates of one light in the group.
+ //! \returns Pair of x and y color coordinates.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
std::pair getActionColorXY();
+
+ //! \brief Get color coordinates of one light in the group.
+ //! \returns Pair of x and y color coordinates.
+ //! \note Does not refresh the state.
std::pair getActionColorXY() const;
+
+ //! \brief Get color mode of one light in the group.
+ //!
+ //! The color mode is the currently used way to specify the color (hs,ct or xy).
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
std::string getActionColorMode();
+
+ //! \brief Get color mode of one light in the group.
+ //!
+ //! The color mode is the currently used way to specify the color (hs,ct or xy).
+ //! \note Does not refresh the state.
std::string getActionColorMode() const;
+ ///@}
+
+ //! \name Change lights
+ ///@{
+
+ //! \brief Create a transaction for this group.
+ //!
+ //! The transaction can be used to change more than one value in one request.
+ //!
+ //! Example usage: \code
+ //! group.transaction().setBrightness(240).setColorHue(5000).commit();
+ //! \endcode
StateTransaction transaction();
+ //! \brief Convenience function to turn lights on.
+ //! \see StateTransaction::setOn
void setOn(bool on, uint8_t transition = 4);
+ //! \brief Convenience function to set brightness.
+ //! \see StateTransaction::setBrightness
void setBrightness(uint8_t brightness, uint8_t transition = 4);
+ //! \brief Convenience function to set hue and saturation.
+ //! \see StateTransaction::setColorHue
+ //! \see StateTransaction::setColorSaturation
void setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition = 4);
+ //! \brief Convenience function to set color xy.
+ //! \see StateTransaction::setColorXY
void setColorXY(float x, float y, uint8_t transition = 4);
+ //! \brief Convenience function to set color temperature.
+ //! \see StateTransaction::setColorTemperature
void setColorTemperature(unsigned int mired, uint8_t transition = 4);
+ //! \brief Convenience function to set color loop.
+ //! \see StateTransaction::setColorLoop
void setColorLoop(bool on, uint8_t transition = 4);
- void incrementBrightness(int increment, uint8_t transition = 4);
- void incrementSaturation(int increment, uint8_t transition = 4);
- void incrementHue(int increment, uint8_t transition = 4);
- void incrementColorTemperature(int increment, uint8_t transition = 4);
- void incrementColorXY(float incX, float incY, uint8_t transition = 4);
+
+ //! \brief Recall scene for the group.
+ //!
+ //! Scenes are saved configurations for the lights in a group.
+ //! \param scene Scene name.
void setScene(const std::string& scene);
+ ///@}
+
protected:
- nlohmann::json SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo);
+ //! \brief Utility function to send a put request to the group.
+ //!
+ //! \param request The request to send
+ //! \param subPath A path that is appended to the uri, note it should always start with a slash ("/")
+ //! \param fileInfo FileInfo from calling function for exception details.
+ //! \returns The parsed reply
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
+ nlohmann::json sendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo);
protected:
int id;
@@ -102,17 +285,54 @@ protected:
HueCommandAPI commands;
};
+//! \brief Parameters necessary for creating a new Group.
+//!
+//! Provides static functions for each group type that can be created by the user.
+//! \note These are not all types that Group::getType() can return,
+//! because some types cannot be created manually.
class CreateGroup
{
public:
+ //! \brief Create a LightGroup.
+ //!
+ //! LightGroup is the default type for groups. Empty LightGroups will be deleted.
+ //! \param lights List of light ids, must not be empty.
+ //! \param name Name of the new group, optional.
static CreateGroup LightGroup(const std::vector& lights, const std::string& name = "");
+ //! \brief Create a Room group.
+ //!
+ //! Rooms can have a room class and can be empty. Every light can only be in one room.
+ //! \param lights List of light ids, may be empty.
+ //! \param name Name of the room, optional.
+ //! \param roomType Class of the room (case sensitive), optional.
+ //! Refer to Hue developer documentation for a list of possible room classes.
static CreateGroup Room(
const std::vector& lights, const std::string& name = "", const std::string& roomType = "");
+ //! \brief Create an Entertainment group.
+ //!
+ //! The lights are used in an entertainment setup and can have relative positions.
+ //! The group can be empty.
+ //! \param lights List of light ids, may be empty.
+ //! \param name Name of the group, optional.
static CreateGroup Entertainment(const std::vector& lights, const std::string& name = "");
+ //! \brief Create a Zone.
+ //!
+ //! Zones can be empty, a light can be in multiple zones.
+ //! \param lights List of light ids, may be empty.
+ //! \param name Name of the Zone, optional.
+ static CreateGroup Zone(const std::vector& lights, const std::string& name = "");
+
+ //! \brief Get request to create the group.
+ //! \returns JSON request for a POST to create the new group
nlohmann::json getRequest() const;
protected:
+ //! \brief Protected constructor, should not be called directly.
+ //! \param lights List of light ids for the group.
+ //! \param name Name of the group, empty for default name.
+ //! \param type Type of the group, empty for default type.
+ //! \param roomType Room class if type is room, empty for default class or if type is not room.
CreateGroup(
const std::vector& lights, const std::string& name, const std::string& type, const std::string& roomType);
diff --git a/include/hueplusplus/Hue.h b/include/hueplusplus/Hue.h
index 1fcb581..ad63a10 100644
--- a/include/hueplusplus/Hue.h
+++ b/include/hueplusplus/Hue.h
@@ -112,7 +112,9 @@ private:
std::shared_ptr http_handler;
};
-//! Hue class
+//! \brief Hue class for a bridge.
+//!
+//! This is the main class used to interact with the Hue bridge.
class Hue
{
friend class HueFinder;
@@ -123,11 +125,15 @@ public:
//! \param ip IP address in dotted decimal notation like "192.168.2.1"
//! \param port Port of the hue bridge
//! \param username String that specifies the username that is used to control
- //! the bridge. This needs to be acquired in \ref requestUsername
+ //! the bridge. Can be left empty and acquired in \ref requestUsername.
//! \param handler HttpHandler for communication with the bridge
+ //! \param refreshDuration Time between refreshing the cached state.
Hue(const std::string& ip, const int port, const std::string& username, std::shared_ptr handler,
std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10));
+ //! \name Configuration
+ ///@{
+
//! \brief Function to get the ip address of the hue bridge
//!
//! \return string containing ip
@@ -165,6 +171,16 @@ public:
//! "192.168.2.1:8080"
void setPort(const int port);
+ //! \brief Function that sets the HttpHandler and updates the HueCommandAPI.
+ //!
+ //! The HttpHandler and HueCommandAPI are used for bridge communication
+ //! \param handler a HttpHandler of type \ref IHttpHandler
+ void setHttpHandler(std::shared_ptr handler);
+
+ ///@}
+ //! \name Lights
+ ///@{
+
//! \brief Function that returns a \ref HueLight of specified id
//!
//! \param id Integer that specifies the ID of a Hue light
@@ -186,11 +202,6 @@ public:
//! \throws nlohmann::json::parse_error when response could not be parsed
bool removeLight(int id);
- //! \brief Function that returns all light types that are associated with this bridge
- //!
- //! \return A map mapping light id's to light types for every light
- // const std::map& getAllLightTypes();
-
//! \brief Function that returns all lights that are associated with this
//! bridge
//!
@@ -202,8 +213,6 @@ public:
std::vector> getAllLights();
//! \brief Function that tells whether a given light id represents an existing light
- //!
- //! Calls refreshState to update the local bridge state
//! \param id Id of a light to check for existance
//! \return Bool that is true when a light with the given id exists and false when not
//! \throws std::system_error when system or socket operations fail
@@ -221,15 +230,67 @@ public:
//! when not
bool lightExists(int id) const;
+ ///@}
+ //! \name Groups
+ ///@{
+
+ //! \brief Get all groups that exist on this bridge.
+ //! \return A vector of references to every Group.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contains no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
std::vector> getAllGroups();
+ //! \brief Get group specified by id.
+ //! \param id ID of the group.
+ //! \returns Group that can be controlled.
+ //! \note Every bridge has a special group 0 which contains all lights
+ //! and is not visible to getAllGroups().
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when id does not exist
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
Group& getGroup(int id);
+
+ //! \brief Remove a group from the bridge.
+ //! \param id ID of the group.
+ //! \returns true on success.
+ //! \brief Remove a group from the bridge.
+ //! \param id ID of the group.
+ //! \returns true on success.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contains no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
bool removeGroup(int id);
+
+ //! \brief Checks whether a group exists.
+ //! \param id ID of the group.
+ //! \returns true when the group exists.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contains no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
bool groupExists(int id);
+
+ //! \brief Checks whether a group exists.
+ //! \param id ID of the group.
+ //! \returns true when the group exists.
+ //! \note Does not refresh the cached state.
bool groupExists(int id) const;
+ //! \brief Create a new group.
+ //! \param params CreateGroup parameters for the new group.
+ //! \returns The new group id or 0 if failed.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contains no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
int createGroup(const CreateGroup& params);
+ ///@}
+
//! \brief Const function that returns the picture name of a given light id
//!
//! \note This will not update the local state of the bridge.
@@ -249,16 +310,6 @@ public:
//! string
std::string getPictureOfModel(const std::string& model_id) const;
- //! \brief Function that sets the HttpHandler and updates the HueCommandAPI.
- //!
- //! The HttpHandler and HueCommandAPI are used for bridge communication
- //! \param handler a HttpHandler of type \ref IHttpHandler
- void setHttpHandler(std::shared_ptr handler)
- {
- http_handler = std::move(handler);
- commands = HueCommandAPI(ip, port, username, http_handler);
- }
-
private:
std::string ip; //!< IP-Address of the hue bridge in dotted decimal notation
//!< like "192.168.2.1"
diff --git a/include/hueplusplus/HueCommandAPI.h b/include/hueplusplus/HueCommandAPI.h
index 1cb6cb6..0706a7e 100644
--- a/include/hueplusplus/HueCommandAPI.h
+++ b/include/hueplusplus/HueCommandAPI.h
@@ -65,48 +65,59 @@ public:
//! This function will block until at least \ref minDelay has passed to any previous request
//! \param path API request path (appended after /api/{username})
//! \param request Request to the api, may be empty
+ //! \param fileInfo File information for thrown exceptions.
//! \returns The return value of the underlying \ref IHttpHandler::PUTJson call
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contains no body
//! \throws HueAPIResponseException when response contains an error
- nlohmann::json PUTRequest(const std::string& path, const nlohmann::json& request) const;
nlohmann::json PUTRequest(const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const;
+ //! \overload
+ nlohmann::json PUTRequest(const std::string& path, const nlohmann::json& request) const;
//! \brief Sends a HTTP GET request to the bridge and returns the response
//!
//! This function will block until at least \ref minDelay has passed to any previous request
//! \param path API request path (appended after /api/{username})
//! \param request Request to the api, may be empty
+ //! \param fileInfo File information for thrown exceptions.
//! \returns The return value of the underlying \ref IHttpHandler::GETJson call
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contains no body
//! \throws HueAPIResponseException when response contains an error
- nlohmann::json GETRequest(const std::string& path, const nlohmann::json& request) const;
+ //! \throws nlohmann::json::parse_error when response could not be parsed
nlohmann::json GETRequest(const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const;
+ //! \overload
+ nlohmann::json GETRequest(const std::string& path, const nlohmann::json& request) const;
//! \brief Sends a HTTP DELETE request to the bridge and returns the response
//!
//! This function will block until at least \ref minDelay has passed to any previous request
//! \param path API request path (appended after /api/{username})
//! \param request Request to the api, may be empty
+ //! \param fileInfo File information for thrown exceptions.
//! \returns The return value of the underlying \ref IHttpHandler::DELETEJson call
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contains no body
//! \throws HueAPIResponseException when response contains an error
- nlohmann::json DELETERequest(const std::string& path, const nlohmann::json& request) const;
+ //! \throws nlohmann::json::parse_error when response could not be parsed
nlohmann::json DELETERequest(const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const;
+ //! \overload
+ nlohmann::json DELETERequest(const std::string& path, const nlohmann::json& request) const;
//! \brief Sends a HTTP POST request to the bridge and returns the response
//!
//! This function will block until at least \ref minDelay has passed to any previous request
//! \param path API request path (appended after /api/{username})
//! \param request Request to the api, may be empty
+ //! \param fileInfo File information for thrown exceptions.
//! \returns The return value of the underlying \ref IHttpHandler::POSTJson call
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contains no body
//! \throws HueAPIResponseException when response contains an error
- nlohmann::json POSTRequest(const std::string& path, const nlohmann::json& request) const;
+ //! \throws nlohmann::json::parse_error when response could not be parsed
nlohmann::json POSTRequest(const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const;
+ //! \overload
+ nlohmann::json POSTRequest(const std::string& path, const nlohmann::json& request) const;
private:
struct TimeoutData
diff --git a/include/hueplusplus/HueException.h b/include/hueplusplus/HueException.h
index 79e0313..974eec5 100644
--- a/include/hueplusplus/HueException.h
+++ b/include/hueplusplus/HueException.h
@@ -30,7 +30,7 @@
namespace hueplusplus
{
-//! \brief Contains information about error location, use CURRENT_FILE_INFO to create
+//! \brief Contains information about error location, use \ref CURRENT_FILE_INFO to create
struct FileInfo
{
//! \brief Current file name from __FILE__. Empty if unknown
diff --git a/include/hueplusplus/HueExceptionMacro.h b/include/hueplusplus/HueExceptionMacro.h
index 843b651..36888d3 100644
--- a/include/hueplusplus/HueExceptionMacro.h
+++ b/include/hueplusplus/HueExceptionMacro.h
@@ -22,6 +22,8 @@
#include "HueException.h"
+//! \def CURRENT_FILE_INFO
+//! \brief Creates the FileInfo for the current line.
#ifndef CURRENT_FILE_INFO
#define CURRENT_FILE_INFO (::hueplusplus::FileInfo{__FILE__, __LINE__, __func__})
#endif
\ No newline at end of file
diff --git a/include/hueplusplus/HueLight.h b/include/hueplusplus/HueLight.h
index 9f6138f..2b5b4b5 100644
--- a/include/hueplusplus/HueLight.h
+++ b/include/hueplusplus/HueLight.h
@@ -92,9 +92,9 @@ enum class ColorType
GAMUT_C_TEMPERATURE
};
+//! \brief Class for Hue Light fixtures
//!
-//! Class for Hue Light fixtures
-//!
+//! Provides methods to query and control lights.
class HueLight
{
friend class Hue;
@@ -109,40 +109,8 @@ public:
//! \brief std dtor
~HueLight() = default;
- //! \brief Function that turns the light on.
- //!
- //! \param transition Optional parameter to set the transition from current state to new, standard is 4 = 400ms
- //! \return true on success
- //! \throws std::system_error when system or socket operations fail
- //! \throws HueException when response contained no body
- //! \throws HueAPIResponseException when response contains an error
- //! \throws nlohmann::json::parse_error when response could not be parsed
- virtual bool On(uint8_t transition = 4);
-
- //! \brief Function that turns the light off.
- //!
- //! \param transition Optional parameter to set the transition from current state to new, standard is 4 = 400ms
- //! \return Bool that is true on success
- //! \throws std::system_error when system or socket operations fail
- //! \throws HueException when response contained no body
- //! \throws HueAPIResponseException when response contains an error
- //! \throws nlohmann::json::parse_error when response could not be parsed
- virtual bool Off(uint8_t transition = 4);
-
- //! \brief Function to check whether a light is on or off
- //!
- //! \return Bool that is true, when the light is on and false, when off
- //! \throws std::system_error when system or socket operations fail
- //! \throws HueException when response contained no body
- //! \throws HueAPIResponseException when response contains an error
- //! \throws nlohmann::json::parse_error when response could not be parsed
- virtual bool isOn();
-
- //! \brief Const function to check whether a light is on or off
- //!
- //! \note This will not refresh the light state
- //! \return Bool that is true, when the light is on and false, when off
- virtual bool isOn() const;
+ //! \name General information
+ ///@{
//! \brief Const function that returns the id of this light
//!
@@ -169,6 +137,15 @@ public:
//! \return String containig the name of the light
virtual std::string getName() const;
+ //! \brief Function that sets the name of the light
+ //!
+ //! \return Bool that is true on success
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
+ virtual bool setName(const std::string& name);
+
//! \brief Const function that returns the modelid of the light
//!
//! \return String conatining the modelid
@@ -213,14 +190,44 @@ public:
//! \return String containing the software version
virtual std::string getSwVersion() const;
- //! \brief Function that sets the name of the light
+ ///@}
+ //! \name Light state
+ ///@{
+
+ //! \brief Function that turns the light on.
//!
+ //! \param transition Optional parameter to set the transition from current state to new, standard is 4 = 400ms
+ //! \return true on success
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
+ virtual bool On(uint8_t transition = 4);
+
+ //! \brief Function that turns the light off.
+ //!
+ //! \param transition Optional parameter to set the transition from current state to new, standard is 4 = 400ms
//! \return Bool that is true on success
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contained no body
//! \throws HueAPIResponseException when response contains an error
//! \throws nlohmann::json::parse_error when response could not be parsed
- virtual bool setName(const std::string& name);
+ virtual bool Off(uint8_t transition = 4);
+
+ //! \brief Function to check whether a light is on or off
+ //!
+ //! \return Bool that is true, when the light is on and false, when off
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
+ virtual bool isOn();
+
+ //! \brief Const function to check whether a light is on or off
+ //!
+ //! \note This will not refresh the light state
+ //! \return Bool that is true, when the light is on and false, when off
+ virtual bool isOn() const;
//! \brief Const function that returns the color type of the light.
//!
@@ -677,8 +684,25 @@ public:
return false;
};
+ //! \brief Create a transaction for this light.
+ //!
+ //! The transaction can be used to change more than one value in one request.
+ //! Only use the functions supported by the current light type.
+ //!
+ //! Example usage: \code
+ //! light.transaction().setBrightness(240).setColorHue(5000).commit();
+ //! \endcode
virtual StateTransaction transaction();
+ ///@}
+
+ //! \brief Refreshes internal cached state.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contained no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
+ virtual void refresh();
+
protected:
//! \brief Protected ctor that is used by \ref Hue class.
//!
@@ -696,6 +720,8 @@ protected:
//! \param brightnessStrategy Strategy for brightness. May be nullptr.
//! \param colorTempStrategy Strategy for color temperature. May be nullptr.
//! \param colorHueStrategy Strategy for color hue/saturation. May be nullptr.
+ //! \param refreshDuration Time between refreshing the cached state.
+ //! Can be 0 to always refresh, or steady_clock::duration::max() to never refresh.
//! \throws std::system_error when system or socket operations fail
//! \throws HueException when response contained no body
//! \throws HueAPIResponseException when response contains an error
@@ -742,7 +768,6 @@ protected:
//! \brief Utility function to send a put request to the light.
//!
- //! \throws nlohmann::json::parse_error if the reply could not be parsed
//! \param request A nlohmann::json aka the request to send
//! \param subPath A path that is appended to the uri, note it should always start with a slash ("/")
//! \param fileInfo FileInfo from calling function for exception details.
@@ -751,11 +776,11 @@ protected:
//! \throws HueException when response contained no body
//! \throws HueAPIResponseException when response contains an error
//! \throws nlohmann::json::parse_error when response could not be parsed
- virtual nlohmann::json SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo);
+ virtual nlohmann::json sendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo);
protected:
int id; //!< holds the id of the light
- APICache state; //!< holds the current state of the light updated by \ref refreshState
+ APICache state; //!< holds the current state of the light
ColorType colorType; //!< holds the \ref ColorType of the light
std::shared_ptr
diff --git a/include/hueplusplus/StateTransaction.h b/include/hueplusplus/StateTransaction.h
index 3839cd0..469d7de 100644
--- a/include/hueplusplus/StateTransaction.h
+++ b/include/hueplusplus/StateTransaction.h
@@ -31,31 +31,120 @@
namespace hueplusplus
{
+//! \brief Transaction class which can be used for either light or group state.
+//!
+//! This is intended to be used in-line, all calls are chained until a \ref commit() call.
+//! \code
+//! light.transaction().setOn(true).setBrightness(29).setColorHue(3000).setColorSaturation(128).commit();
+//! \endcode
class StateTransaction
{
public:
+ //! \brief Creates a StateTransaction to a group or light state
+ //! \param commands HueCommandAPI for making requests
+ //! \param path Path to which the final PUT request is made (without username)
+ //! \param currentState JSON object with the current state to check whether changes are needed.
+ //! Pass an empty object to always include all requests (for groups, because individual lights might be different).
StateTransaction(const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState);
+ //! \brief Deleted copy constructor, do not store StateTransaction in a variable.
StateTransaction(const StateTransaction&) = delete;
StateTransaction(StateTransaction&&) = default;
+ //! \brief Commit transaction and make request.
+ //! \returns true on success or when no change was requested.
+ //! \note After changing the state of a HueLight or Group,
+ //! refresh() must be called if the updated values are needed immediately.
+ //! \throws std::system_error when system or socket operations fail
+ //! \throws HueException when response contains no body
+ //! \throws HueAPIResponseException when response contains an error
+ //! \throws nlohmann::json::parse_error when response could not be parsed
bool commit() &&;
+ //! \brief Turn light on or off.
+ //! \param on true for on, false for off
+ //! \returns This transaction for chaining calls
StateTransaction&& setOn(bool on) &&;
+ //! \brief Set light brightness.
+ //! \param brightness Brightness from 0 = off to 254 = fully lit.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have brightness control.
+ //! \note Brightness 0 will also turn off the light if nothing else is specified,
+ //! any other value will also turn on the light.
StateTransaction&& setBrightness(uint8_t brightness) &&;
+ //! \brief Set light hue.
+ //! \param hue Color hue from 0 to 65535
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
+ //! \note Will also turn on the light if nothing else is specified
StateTransaction&& setColorHue(uint16_t hue) &&;
+ //! \brief Set light saturation.
+ //! \param saturation Color saturation from 0 to 254
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
+ //! \note Will also turn on the light if nothing else is specified
StateTransaction&& setColorSaturation(uint8_t saturation) &&;
+ //! \brief Set light color in xy space.
+ //! \param x x coordinate in CIE color space
+ //! \param y y coordinate in CIE color space
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
+ //! \note Will also turn on the light if nothing else is specified
StateTransaction&& setColorXY(float x, float y) &&;
+ //! \brief Set light color temperature.
+ //! \param mired Color temperature in mired from 153 to 500
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have color temperature control.
+ //! \note Will also turn on the light if nothing else is specified
StateTransaction&& setColorTemperature(unsigned int mired) &&;
+ //! \brief Enables or disables color loop.
+ //! \param on true to enable, false to disable color loop.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
+ //! \note Will also turn on the light if nothing else is specified
StateTransaction&& setColorLoop(bool on) &&;
+ //! \brief Increment/Decrement brightness.
+ //! \param increment Brightness change from -254 to 254.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have brightness control.
StateTransaction&& incrementBrightness(int increment) &&;
+ //! \brief Increment/Decrement saturaction.
+ //! \param increment Saturation change from -254 to 254.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
StateTransaction&& incrementSaturation(int increment) &&;
+ //! \brief Increment/Decrement hue.
+ //! \param increment Hue change from -65535 to 65535.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
StateTransaction&& incrementHue(int increment) &&;
+ //! \brief Increment/Decrement color temperature.
+ //! \param increment Color temperature change in mired from -65535 to 65535.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have color temperature control.
StateTransaction&& incrementColorTemperature(int increment) &&;
+ //! \brief Increment/Decrement color xy.
+ //! \param xInc x color coordinate change from -0.5 to 0.5.
+ //! \param yInc y color coordinate change from -0.5 to 0.5.
+ //! \returns This transaction for chaining calls
+ //! \note If this transaction is for a light, the light needs to have rgb color control.
StateTransaction&& incrementColorXY(float xInc, float yInc) &&;
+ //! \brief Set transition time for the request.
+ //! \param transition Transition time in 100ms, default for any request is 400ms.
+ //! \returns This transaction for chaining calls
+ //! \note The transition only applies to the current request.
+ //! A request without any changes only containing a transition is pointless and is not sent.
StateTransaction&& setTransition(uint16_t transition) &&;
+ //! \brief Trigger an alert.
+ //!
+ //! The light performs one breathe cycle.
+ //! \returns This transaction for chaining calls
StateTransaction&& alert() &&;
+ //! \brief Trigger a long alert (15s).
+ //! \returns This transaction for chaining calls
StateTransaction&& longAlert() &&;
+ //! \brief Stop an ongoing long alert.
+ //! \returns This transaction for chaining calls
StateTransaction&& stopAlert() &&;
protected:
diff --git a/src/APICache.cpp b/src/APICache.cpp
index 74d627f..35a3b1b 100644
--- a/src/APICache.cpp
+++ b/src/APICache.cpp
@@ -28,13 +28,13 @@ hueplusplus::APICache::APICache(
: path(path), commands(commands), refreshDuration(refresh), lastRefresh(std::chrono::steady_clock::duration::zero())
{}
-void hueplusplus::APICache::Refresh()
+void hueplusplus::APICache::refresh()
{
value = commands.GETRequest(path, nlohmann::json::object(), CURRENT_FILE_INFO);
lastRefresh = std::chrono::steady_clock::now();
}
-nlohmann::json& hueplusplus::APICache::GetValue()
+nlohmann::json& hueplusplus::APICache::getValue()
{
using clock = std::chrono::steady_clock;
// Explicitly check for zero in case refreshDuration is duration::max()
@@ -42,7 +42,7 @@ nlohmann::json& hueplusplus::APICache::GetValue()
if (lastRefresh.time_since_epoch().count() == 0 || refreshDuration.count() < 0)
{
// No value set yet
- Refresh();
+ refresh();
}
// Check if nextRefresh would overflow (assumes lastRefresh is not negative, which it should not be).
// If addition would overflow, do not refresh
@@ -51,18 +51,18 @@ nlohmann::json& hueplusplus::APICache::GetValue()
clock::time_point nextRefresh = lastRefresh + refreshDuration;
if (clock::now() >= nextRefresh)
{
- Refresh();
+ refresh();
}
}
return value;
}
-const nlohmann::json& hueplusplus::APICache::GetValue() const
+const nlohmann::json& hueplusplus::APICache::getValue() const
{
return value;
}
-std::chrono::steady_clock::duration hueplusplus::APICache::GetRefreshDuration() const
+std::chrono::steady_clock::duration hueplusplus::APICache::getRefreshDuration() const
{
return refreshDuration;
}
diff --git a/src/ExtendedColorHueStrategy.cpp b/src/ExtendedColorHueStrategy.cpp
index 2cce861..67be19e 100644
--- a/src/ExtendedColorHueStrategy.cpp
+++ b/src/ExtendedColorHueStrategy.cpp
@@ -33,7 +33,7 @@ namespace hueplusplus
bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
@@ -116,7 +116,7 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue
bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
@@ -199,7 +199,7 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const
bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
diff --git a/src/ExtendedColorTemperatureStrategy.cpp b/src/ExtendedColorTemperatureStrategy.cpp
index edaf804..c6a438b 100644
--- a/src/ExtendedColorTemperatureStrategy.cpp
+++ b/src/ExtendedColorTemperatureStrategy.cpp
@@ -36,7 +36,7 @@ bool ExtendedColorTemperatureStrategy::setColorTemperature(
unsigned int mired, uint8_t transition, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
nlohmann::json request = nlohmann::json::object();
if (transition != 4)
{
@@ -65,7 +65,7 @@ bool ExtendedColorTemperatureStrategy::setColorTemperature(
return true;
}
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
+ nlohmann::json reply = light.sendPutRequest(request, "/state", CURRENT_FILE_INFO);
// Check whether request was successful
return utils::validateReplyForLight(request, reply, light.id);
@@ -74,7 +74,7 @@ bool ExtendedColorTemperatureStrategy::setColorTemperature(
bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
diff --git a/src/Group.cpp b/src/Group.cpp
index 21e04e9..4c42353 100644
--- a/src/Group.cpp
+++ b/src/Group.cpp
@@ -7,12 +7,12 @@ namespace hueplusplus
Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
: id(id), state("/groups/" + std::to_string(id), commands, refreshDuration), commands(commands)
{
- state.Refresh();
+ state.refresh();
}
-void Group::Refresh()
+void Group::refresh()
{
- state.Refresh();
+ state.refresh();
}
int Group::getId() const
@@ -22,17 +22,17 @@ int Group::getId() const
std::string Group::getName() const
{
- return state.GetValue().at("name").get();
+ return state.getValue().at("name").get();
}
std::string Group::getType() const
{
- return state.GetValue().at("type").get();
+ return state.getValue().at("type").get();
}
std::vector Group::getLightIds() const
{
- const nlohmann::json& lights = state.GetValue().at("lights");
+ const nlohmann::json& lights = state.getValue().at("lights");
std::vector ids;
ids.reserve(lights.size());
for (const nlohmann::json& id : lights)
@@ -45,8 +45,8 @@ std::vector Group::getLightIds() const
void Group::setName(const std::string& name)
{
nlohmann::json request = {{"name", name}};
- SendPutRequest(request, "", CURRENT_FILE_INFO);
- Refresh();
+ sendPutRequest(request, "", CURRENT_FILE_INFO);
+ refresh();
}
void Group::setLights(const std::vector& ids)
@@ -56,86 +56,86 @@ void Group::setLights(const std::vector& ids)
{
lights.push_back(std::to_string(id));
}
- SendPutRequest({{"lights", lights}}, "", CURRENT_FILE_INFO);
- Refresh();
+ sendPutRequest({{"lights", lights}}, "", CURRENT_FILE_INFO);
+ refresh();
}
bool Group::getAllOn()
{
- return state.GetValue().at("state").at("all_on").get();
+ return state.getValue().at("state").at("all_on").get();
}
bool Group::getAllOn() const
{
- return state.GetValue().at("state").at("all_on").get();
+ return state.getValue().at("state").at("all_on").get();
}
bool Group::getAnyOn()
{
- return state.GetValue().at("state").at("any_on").get();
+ return state.getValue().at("state").at("any_on").get();
}
bool Group::getAnyOn() const
{
- return state.GetValue().at("state").at("any_on").get();
+ return state.getValue().at("state").at("any_on").get();
}
bool Group::getActionOn()
{
- return state.GetValue().at("action").at("on").get();
+ return state.getValue().at("action").at("on").get();
}
bool Group::getActionOn() const
{
- return state.GetValue().at("action").at("on").get();
+ return state.getValue().at("action").at("on").get();
}
std::pair Group::getActionHueSaturation()
{
- const nlohmann::json& action = state.GetValue().at("action");
+ const nlohmann::json& action = state.getValue().at("action");
return std::make_pair(action.at("hue").get(), action.at("sat").get());
}
std::pair Group::getActionHueSaturation() const
{
- const nlohmann::json& action = state.GetValue().at("action");
+ const nlohmann::json& action = state.getValue().at("action");
return std::make_pair(action.at("hue").get(), action.at("sat").get());
}
unsigned int Group::getActionBrightness()
{
- return state.GetValue().at("action").at("bri").get();
+ return state.getValue().at("action").at("bri").get();
}
unsigned int Group::getActionBrightness() const
{
- return state.GetValue().at("action").at("bri").get();
+ return state.getValue().at("action").at("bri").get();
}
unsigned int Group::getActionColorTemperature()
{
- return state.GetValue().at("action").at("ct").get();
+ return state.getValue().at("action").at("ct").get();
}
unsigned int Group::getActionColorTemperature() const
{
- return state.GetValue().at("action").at("ct").get();
+ return state.getValue().at("action").at("ct").get();
}
std::pair Group::getActionColorXY()
{
- const nlohmann::json& xy = state.GetValue().at("action").at("xy");
+ const nlohmann::json& xy = state.getValue().at("action").at("xy");
return std::pair(xy[0].get(), xy[1].get());
}
std::pair Group::getActionColorXY() const
{
- const nlohmann::json& xy = state.GetValue().at("action").at("xy");
+ const nlohmann::json& xy = state.getValue().at("action").at("xy");
return std::pair(xy[0].get(), xy[1].get());
}
std::string Group::getActionColorMode()
{
- return state.GetValue().at("action").at("colormode").get();
+ return state.getValue().at("action").at("colormode").get();
}
std::string Group::getActionColorMode() const
{
- return state.GetValue().at("action").at("colormode").get();
+ return state.getValue().at("action").at("colormode").get();
}
StateTransaction Group::transaction()
@@ -174,60 +174,35 @@ void Group::setColorLoop(bool on, uint8_t transition)
transaction().setColorLoop(on).setTransition(transition);
}
-void Group::incrementBrightness(int increment, uint8_t transition)
-{
- transaction().incrementBrightness(increment).setTransition(transition).commit();
-}
-
-void Group::incrementSaturation(int increment, uint8_t transition)
-{
- transaction().incrementSaturation(increment).setTransition(transition).commit();
-}
-
-void Group::incrementHue(int increment, uint8_t transition)
-{
- transaction().incrementHue(increment).setTransition(transition).commit();
-}
-
-void Group::incrementColorTemperature(int increment, uint8_t transition)
-{
- transaction().incrementColorTemperature(increment).setTransition(transition).commit();
-}
-
-void Group::incrementColorXY(float incX, float incY, uint8_t transition)
-{
- transaction().incrementColorXY(incX, incY).setTransition(transition).commit();
-}
-
void Group::setScene(const std::string& scene)
{
- SendPutRequest({{"scene", scene}}, "/action", CURRENT_FILE_INFO);
+ sendPutRequest({{"scene", scene}}, "/action", CURRENT_FILE_INFO);
}
-nlohmann::json Group::SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo)
+nlohmann::json Group::sendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo)
{
return commands.PUTRequest("/groups/" + std::to_string(id) + subPath, request, std::move(fileInfo));
}
std::string Group::getRoomType() const
{
- return state.GetValue().at("class").get();
+ return state.getValue().at("class").get();
}
void Group::setRoomType(const std::string& type)
{
- SendPutRequest({{"class", type}}, "", CURRENT_FILE_INFO);
- Refresh();
+ sendPutRequest({{"class", type}}, "", CURRENT_FILE_INFO);
+ refresh();
}
std::string Group::getModelId() const
{
- return state.GetValue().at("modelid").get();
+ return state.getValue().at("modelid").get();
}
std::string Group::getUniqueId() const
{
- return state.GetValue().at("uniqueid").get();
+ return state.getValue().at("uniqueid").get();
}
CreateGroup CreateGroup::LightGroup(const std::vector& lights, const std::string& name)
@@ -245,6 +220,11 @@ CreateGroup CreateGroup::Entertainment(const std::vector& lights, const std
return CreateGroup(lights, name, "Entertainment", "");
}
+CreateGroup CreateGroup::Zone(const std::vector& lights, const std::string& name)
+{
+ return CreateGroup(lights, name, "Zone", "");
+}
+
nlohmann::json CreateGroup::getRequest() const
{
nlohmann::json lightStrings = nlohmann::json::array();
diff --git a/src/Hue.cpp b/src/Hue.cpp
index 488541a..0eae5e0 100644
--- a/src/Hue.cpp
+++ b/src/Hue.cpp
@@ -190,7 +190,7 @@ std::string Hue::requestUsername()
username = jsonUser.get();
// Update commands with new username and ip
commands = HueCommandAPI(ip, port, username, http_handler);
- stateCache = APICache("", commands, stateCache.GetRefreshDuration());
+ stateCache = APICache("", commands, stateCache.getRefreshDuration());
std::cout << "Success! Link button was pressed!\n";
std::cout << "Username is \"" << username << "\"\n";
break;
@@ -230,10 +230,10 @@ HueLight& Hue::getLight(int id)
auto pos = lights.find(id);
if (pos != lights.end())
{
- pos->second.state.Refresh();
+ pos->second.state.refresh();
return pos->second;
}
- const nlohmann::json& lightsCache = stateCache.GetValue()["lights"];
+ const nlohmann::json& lightsCache = stateCache.getValue()["lights"];
if (!lightsCache.count(std::to_string(id)))
{
std::cerr << "Error in Hue getLight(): light with id " << id << " is not valid\n";
@@ -261,7 +261,7 @@ bool Hue::removeLight(int id)
std::vector> Hue::getAllLights()
{
// No reference because getLight may invalidate it
- nlohmann::json lightsState = stateCache.GetValue()["lights"];
+ nlohmann::json lightsState = stateCache.getValue()["lights"];
for (auto it = lightsState.begin(); it != lightsState.end(); ++it)
{
getLight(std::stoi(it.key()));
@@ -276,7 +276,7 @@ std::vector> Hue::getAllLights()
std::vector> Hue::getAllGroups()
{
- nlohmann::json groupsState = stateCache.GetValue().at("groups");
+ nlohmann::json groupsState = stateCache.getValue().at("groups");
for (auto it = groupsState.begin(); it != groupsState.end(); ++it)
{
getGroup(std::stoi(it.key()));
@@ -295,16 +295,16 @@ Group& Hue::getGroup(int id)
auto pos = groups.find(id);
if (pos != groups.end())
{
- pos->second.Refresh();
+ pos->second.refresh();
return pos->second;
}
- const nlohmann::json& groupsCache = stateCache.GetValue()["groups"];
+ const nlohmann::json& groupsCache = stateCache.getValue()["groups"];
if (!groupsCache.count(std::to_string(id)))
{
std::cerr << "Error in Hue getGroup(): group with id " << id << " is not valid\n";
throw HueException(CURRENT_FILE_INFO, "Group id is not valid");
}
- return groups.emplace(id, Group(id, commands, stateCache.GetRefreshDuration())).first->second;
+ return groups.emplace(id, Group(id, commands, stateCache.getRefreshDuration())).first->second;
}
bool Hue::removeGroup(int id)
@@ -326,7 +326,7 @@ bool Hue::groupExists(int id)
{
return true;
}
- if (stateCache.GetValue()["groups"].count(std::to_string(id)))
+ if (stateCache.getValue()["groups"].count(std::to_string(id)))
{
return true;
}
@@ -340,7 +340,7 @@ bool Hue::groupExists(int id) const
{
return true;
}
- if (stateCache.GetValue()["groups"].count(std::to_string(id)))
+ if (stateCache.getValue()["groups"].count(std::to_string(id)))
{
return true;
}
@@ -365,7 +365,7 @@ bool Hue::lightExists(int id)
{
return true;
}
- if (stateCache.GetValue()["lights"].count(std::to_string(id)))
+ if (stateCache.getValue()["lights"].count(std::to_string(id)))
{
return true;
}
@@ -379,7 +379,7 @@ bool Hue::lightExists(int id) const
{
return true;
}
- if (stateCache.GetValue()["lights"].count(std::to_string(id)))
+ if (stateCache.getValue()["lights"].count(std::to_string(id)))
{
return true;
}
@@ -520,4 +520,11 @@ std::string Hue::getPictureOfModel(const std::string& model_id) const
}
return ret;
}
+
+void Hue::setHttpHandler(std::shared_ptr handler)
+{
+ http_handler = handler;
+ commands = HueCommandAPI(ip, port, username, handler);
+ stateCache = APICache("", commands, stateCache.getRefreshDuration());
+}
} // namespace hueplusplus
diff --git a/src/HueDeviceTypes.cpp b/src/HueDeviceTypes.cpp
index 362f177..f8d69ce 100644
--- a/src/HueDeviceTypes.cpp
+++ b/src/HueDeviceTypes.cpp
@@ -30,42 +30,42 @@ namespace hueplusplus
{
namespace
{
-const std::set getGamutBTypes()
+const std::set& getGamutBTypes()
{
static const std::set c_EXTENDEDCOLORLIGHT_GAMUTB_TYPES
= {"LCT001", "LCT002", "LCT003", "LCT007", "LLM001"};
return c_EXTENDEDCOLORLIGHT_GAMUTB_TYPES;
};
-const std::set getGamutCTypes()
+const std::set& getGamutCTypes()
{
static const std::set c_EXTENDEDCOLORLIGHT_GAMUTC_TYPES
= {"LCT010", "LCT011", "LCT012", "LCT014", "LCT015", "LCT016", "LLC020", "LST002"};
return c_EXTENDEDCOLORLIGHT_GAMUTC_TYPES;
}
-const std::set getGamutATypes()
+const std::set& getGamutATypes()
{
static const std::set c_EXTENDEDCOLORLIGHT_GAMUTA_TYPES
= {"LST001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", "LLC013", "LLC014"};
return c_EXTENDEDCOLORLIGHT_GAMUTA_TYPES;
}
-const std::set getNoColorTypes()
+const std::set& getNoColorTypes()
{
static const std::set c_DIMMABLELIGHT_NO_COLOR_TYPES
= {"LWB004", "LWB006", "LWB007", "LWB010", "LWB014", "LDF001", "LDF002", "LDD001", "LDD002", "MWM001"};
return c_DIMMABLELIGHT_NO_COLOR_TYPES;
}
-const std::set getNonDimmableTypes()
+const std::set& getNonDimmableTypes()
{
static const std::set c_NON_DIMMABLE_TYPES
= {"Plug 01"};
return c_NON_DIMMABLE_TYPES;
}
-const std::set getTemperatureLightTypes()
+const std::set& getTemperatureLightTypes()
{
static const std::set c_TEMPERATURELIGHT_TYPES
= {"LLM010", "LLM011", "LLM012", "LTW001", "LTW004", "LTW010", "LTW011", "LTW012", "LTW013", "LTW014", "LTW015",
diff --git a/src/HueLight.cpp b/src/HueLight.cpp
index 52294ef..46239c0 100644
--- a/src/HueLight.cpp
+++ b/src/HueLight.cpp
@@ -44,12 +44,12 @@ bool HueLight::Off(uint8_t transition)
bool HueLight::isOn()
{
- return state.GetValue().at("state").at("on").get();
+ return state.getValue().at("state").at("on").get();
}
bool HueLight::isOn() const
{
- return state.GetValue().at("state").at("on").get();
+ return state.getValue().at("state").at("on").get();
}
int HueLight::getId() const
@@ -59,60 +59,60 @@ int HueLight::getId() const
std::string HueLight::getType() const
{
- return state.GetValue()["type"].get();
+ return state.getValue()["type"].get();
}
std::string HueLight::getName()
{
- return state.GetValue()["name"].get();
+ return state.getValue()["name"].get();
}
std::string HueLight::getName() const
{
- return state.GetValue()["name"].get();
+ return state.getValue()["name"].get();
}
std::string HueLight::getModelId() const
{
- return state.GetValue()["modelid"].get();
+ return state.getValue()["modelid"].get();
}
std::string HueLight::getUId() const
{
- return state.GetValue().value("uniqueid", std::string());
+ return state.getValue().value("uniqueid", std::string());
}
std::string HueLight::getManufacturername() const
{
- return state.GetValue().value("manufacturername", std::string());
+ return state.getValue().value("manufacturername", std::string());
}
std::string HueLight::getProductname() const
{
- return state.GetValue().value("productname", std::string());
+ return state.getValue().value("productname", std::string());
}
std::string HueLight::getLuminaireUId() const
{
- return state.GetValue().value("luminaireuniqueid", std::string());
+ return state.getValue().value("luminaireuniqueid", std::string());
}
std::string HueLight::getSwVersion()
{
- return state.GetValue()["swversion"].get();
+ return state.getValue()["swversion"].get();
}
std::string HueLight::getSwVersion() const
{
- return state.GetValue()["swversion"].get();
+ return state.getValue()["swversion"].get();
}
bool HueLight::setName(const std::string& name)
{
nlohmann::json request = nlohmann::json::object();
request["name"] = name;
- nlohmann::json reply = SendPutRequest(request, "/name", CURRENT_FILE_INFO);
- state.Refresh();
+ nlohmann::json reply = sendPutRequest(request, "/name", CURRENT_FILE_INFO);
+ state.refresh();
// Check whether request was successful (returned name is not necessarily the actually set name)
// If it already exists, a number is added, if it is too long to be returned, "Updated" is returned
@@ -141,7 +141,12 @@ bool HueLight::alert()
StateTransaction HueLight::transaction()
{
- return StateTransaction(commands, "/lights/" + std::to_string(id) + "/state", state.GetValue().at("state"));
+ return StateTransaction(commands, "/lights/" + std::to_string(id) + "/state", state.getValue().at("state"));
+}
+
+void HueLight::refresh()
+{
+ state.refresh();
}
HueLight::HueLight(int id, const HueCommandAPI& commands) : HueLight(id, commands, nullptr, nullptr, nullptr) {}
@@ -157,10 +162,10 @@ HueLight::HueLight(int id, const HueCommandAPI& commands, std::shared_ptr();
+ return light.state.getValue()["state"]["bri"].get();
}
unsigned int SimpleBrightnessStrategy::getBrightness(const HueLight& light) const
{
- return light.state.GetValue()["state"]["bri"].get();
+ return light.state.getValue()["state"]["bri"].get();
}
} // namespace hueplusplus
diff --git a/src/SimpleColorHueStrategy.cpp b/src/SimpleColorHueStrategy.cpp
index a153a3d..a2e1f06 100644
--- a/src/SimpleColorHueStrategy.cpp
+++ b/src/SimpleColorHueStrategy.cpp
@@ -86,7 +86,7 @@ bool SimpleColorHueStrategy::setColorLoop(bool on, HueLight& light) const
bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
@@ -146,7 +146,7 @@ bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLi
bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
@@ -206,7 +206,7 @@ bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const
bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "hs")
@@ -266,25 +266,26 @@ bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight&
std::pair SimpleColorHueStrategy::getColorHueSaturation(HueLight& light) const
{
// Save value, so there are no inconsistent results if it is refreshed between two calls
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
return std::make_pair(state["hue"].get(), state["sat"].get());
}
std::pair SimpleColorHueStrategy::getColorHueSaturation(const HueLight& light) const
{
- return std::make_pair(light.state.GetValue()["state"]["hue"].get(), light.state.GetValue()["state"]["sat"].get());
+ return std::make_pair(light.state.getValue()["state"]["hue"].get(),
+ light.state.getValue()["state"]["sat"].get());
}
std::pair SimpleColorHueStrategy::getColorXY(HueLight& light) const
{
// Save value, so there are no inconsistent results if it is refreshed between two calls
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
return std::make_pair(state["xy"][0].get(), state["xy"][1].get());
}
std::pair SimpleColorHueStrategy::getColorXY(const HueLight& light) const
{
- return std::make_pair(light.state.GetValue()["state"]["xy"][0].get(), light.state.GetValue()["state"]["xy"][1].get());
+ return std::make_pair(light.state.getValue()["state"]["xy"][0].get(), light.state.getValue()["state"]["xy"][1].get());
}
/*bool SimpleColorHueStrategy::pointInTriangle(float pointx, float pointy, float
x0, float y0, float x1, float y1, float x2, float y2)
diff --git a/src/SimpleColorTemperatureStrategy.cpp b/src/SimpleColorTemperatureStrategy.cpp
index 9da0e98..bcc9f47 100644
--- a/src/SimpleColorTemperatureStrategy.cpp
+++ b/src/SimpleColorTemperatureStrategy.cpp
@@ -40,7 +40,7 @@ bool SimpleColorTemperatureStrategy::setColorTemperature(unsigned int mired, uin
bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
+ const nlohmann::json& state = light.state.getValue()["state"];
std::string cType = state["colormode"].get();
bool on = state["on"].get();
if (cType == "ct")
@@ -74,11 +74,11 @@ bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLig
unsigned int SimpleColorTemperatureStrategy::getColorTemperature(HueLight& light) const
{
- return light.state.GetValue()["state"]["ct"].get();
+ return light.state.getValue()["state"]["ct"].get();
}
unsigned int SimpleColorTemperatureStrategy::getColorTemperature(const HueLight& light) const
{
- return light.state.GetValue()["state"]["ct"].get();
+ return light.state.getValue()["state"]["ct"].get();
}
} // namespace hueplusplus
diff --git a/src/StateTransaction.cpp b/src/StateTransaction.cpp
index 05f10e0..d165297 100644
--- a/src/StateTransaction.cpp
+++ b/src/StateTransaction.cpp
@@ -42,18 +42,18 @@ bool StateTransaction::commit() &&
{
if (!request.count("on"))
{
- if (request.value("bri", 254) == 0 && state.value("on", true))
- {
- // Turn off if brightness is 0
- request["on"] = false;
- }
- else if (!state.value("on", false)
+ if (!state.value("on", false)
&& (request.value("bri", 0) != 0 || request.count("effect") || request.count("hue")
|| request.count("sat") || request.count("xy") || request.count("ct")))
{
// Turn on if it was turned off
request["on"] = true;
}
+ else if(request.value("bri", 254) == 0 && state.value("on", true))
+ {
+ // Turn off if brightness is 0
+ request["on"] = false;
+ }
}
nlohmann::json reply = commands.PUTRequest(path, request, CURRENT_FILE_INFO);
diff --git a/test/mocks/mock_HueLight.h b/test/mocks/mock_HueLight.h
index 63f35f5..cb1e048 100644
--- a/test/mocks/mock_HueLight.h
+++ b/test/mocks/mock_HueLight.h
@@ -43,7 +43,7 @@ public:
// Set refresh duration to max, so random refreshes do not hinder the test setups
}
- nlohmann::json& getState() { return state.GetValue(); }
+ nlohmann::json& getState() { return state.getValue(); }
MOCK_METHOD1(On, bool(uint8_t transition));
@@ -125,7 +125,7 @@ public:
MOCK_METHOD1(setColorLoop, bool(bool on));
- MOCK_METHOD3(SendPutRequest,
+ MOCK_METHOD3(sendPutRequest,
nlohmann::json(const nlohmann::json& request, const std::string& subPath, hueplusplus::FileInfo fileInfo));
};
diff --git a/test/test_APICache.cpp b/test/test_APICache.cpp
index c673cc8..ef1e1c7 100644
--- a/test/test_APICache.cpp
+++ b/test/test_APICache.cpp
@@ -29,28 +29,28 @@
using namespace hueplusplus;
-TEST(APICache, GetRefreshDuration)
+TEST(APICache, getRefreshDuration)
{
auto handler = std::make_shared();
HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
{
std::chrono::steady_clock::duration refresh = std::chrono::seconds(20);
APICache cache("", commands, refresh);
- EXPECT_EQ(refresh, cache.GetRefreshDuration());
+ EXPECT_EQ(refresh, cache.getRefreshDuration());
}
{
std::chrono::steady_clock::duration refresh = std::chrono::seconds(0);
APICache cache("", commands, refresh);
- EXPECT_EQ(refresh, cache.GetRefreshDuration());
+ EXPECT_EQ(refresh, cache.getRefreshDuration());
}
{
std::chrono::steady_clock::duration refresh = std::chrono::steady_clock::duration::max();
APICache cache("", commands, refresh);
- EXPECT_EQ(refresh, cache.GetRefreshDuration());
+ EXPECT_EQ(refresh, cache.getRefreshDuration());
}
}
-TEST(APICache, Refresh)
+TEST(APICache, refresh)
{
using namespace ::testing;
auto handler = std::make_shared();
@@ -62,7 +62,7 @@ TEST(APICache, Refresh)
EXPECT_CALL(*handler,
GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.WillOnce(Return(nlohmann::json::object()));
- cache.Refresh();
+ cache.refresh();
Mock::VerifyAndClearExpectations(handler.get());
}
{
@@ -73,13 +73,13 @@ TEST(APICache, Refresh)
"/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(2)
.WillRepeatedly(Return(nlohmann::json::object()));
- cache.Refresh();
- cache.Refresh();
+ cache.refresh();
+ cache.refresh();
Mock::VerifyAndClearExpectations(handler.get());
}
}
-TEST(APICache, GetValue)
+TEST(APICache, getValue)
{
using namespace ::testing;
auto handler = std::make_shared();
@@ -94,8 +94,8 @@ TEST(APICache, GetValue)
GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(2)
.WillRepeatedly(Return(value));
- EXPECT_EQ(value, cache.GetValue());
- EXPECT_EQ(value, cache.GetValue());
+ EXPECT_EQ(value, cache.getValue());
+ EXPECT_EQ(value, cache.getValue());
Mock::VerifyAndClearExpectations(handler.get());
}
// Only refresh once
@@ -106,8 +106,8 @@ TEST(APICache, GetValue)
EXPECT_CALL(*handler,
GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.WillOnce(Return(value));
- EXPECT_EQ(value, cache.GetValue());
- EXPECT_EQ(value, cache.GetValue());
+ EXPECT_EQ(value, cache.getValue());
+ EXPECT_EQ(value, cache.getValue());
Mock::VerifyAndClearExpectations(handler.get());
}
// No refresh with const
@@ -118,7 +118,7 @@ TEST(APICache, GetValue)
EXPECT_CALL(*handler,
GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(0);
- EXPECT_EQ(nullptr, cache.GetValue());
+ EXPECT_EQ(nullptr, cache.getValue());
Mock::VerifyAndClearExpectations(handler.get());
}
}
\ No newline at end of file
diff --git a/test/test_ExtendedColorTemperatureStrategy.cpp b/test/test_ExtendedColorTemperatureStrategy.cpp
index e0bf3f9..f57e001 100644
--- a/test/test_ExtendedColorTemperatureStrategy.cpp
+++ b/test/test_ExtendedColorTemperatureStrategy.cpp
@@ -56,7 +56,7 @@ TEST(ExtendedColorTemperatureStrategy, setColorTemperature)
prep_ret[2] = nlohmann::json::object();
prep_ret[2]["success"] = nlohmann::json::object();
prep_ret[2]["success"]["/lights/1/state/ct"] = 155;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(test_light, sendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["colormode"] = "ct";
test_light.getState()["state"]["on"] = true;
@@ -67,11 +67,11 @@ TEST(ExtendedColorTemperatureStrategy, setColorTemperature)
EXPECT_EQ(true, ExtendedColorTemperatureStrategy().setColorTemperature(155, 6, test_light));
prep_ret[2]["success"]["/lights/1/state/ct"] = 153;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(test_light, sendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
EXPECT_EQ(true, ExtendedColorTemperatureStrategy().setColorTemperature(0, 6, test_light));
prep_ret[2]["success"]["/lights/1/state/ct"] = 500;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(test_light, sendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
EXPECT_EQ(true, ExtendedColorTemperatureStrategy().setColorTemperature(600, 6, test_light));
}