/** \file Bridge.h Copyright Notice\n Copyright (C) 2017 Jan Rogall - developer\n Copyright (C) 2017 Moritz Wirger - developer\n This file is part of hueplusplus. hueplusplus is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. hueplusplus is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with hueplusplus. If not, see . **/ #ifndef INCLUDE_HUEPLUSPLUS_HUE_H #define INCLUDE_HUEPLUSPLUS_HUE_H #include #include #include #include #include #include "APICache.h" #include "BridgeConfig.h" #include "BrightnessStrategy.h" #include "ColorHueStrategy.h" #include "ColorTemperatureStrategy.h" #include "Group.h" #include "HueCommandAPI.h" #include "HueDeviceTypes.h" #include "IHttpHandler.h" #include "Light.h" #include "ResourceList.h" #include "Rule.h" #include "Scene.h" #include "Schedule.h" #include "Sensor.h" #include "SensorList.h" #include "Utils.h" #include //! \brief Namespace for the hueplusplus library namespace hueplusplus { // forward declarations class Bridge; //! //! Class to find all Hue bridges on the network and create usernames for them. //! class BridgeFinder { public: struct BridgeIdentification { std::string ip; int port = 80; std::string mac; }; public: //! \brief Constructor of BridgeFinder class //! //! \param handler HttpHandler of type \ref IHttpHandler for communication with the bridge BridgeFinder(std::shared_ptr handler); //! \brief Finds all bridges in the network and returns them. //! //! The user should be given the opportunity to select the correct one based on the mac address. //! \return vector containing ip and mac of all found bridges //! \throws std::system_error when system or socket operations fail //! \throws HueException when response contained no body std::vector findBridges() const; //! \brief Gets a Hue bridge based on its identification //! //! \param identification \ref BridgeIdentification that specifies a bridge //! \param sharedState Uses a single, shared cache for all objects on the bridge. //! \return \ref Bridge class object //! \throws std::system_error when system or socket operations fail //! \throws HueException when response contained no body or username could not be requested //! \throws HueAPIResponseException when response contains an error //! \throws nlohmann::json::parse_error when response could not be parsed Bridge getBridge(const BridgeIdentification& identification, bool sharedState = false); //! \brief Function that adds a username to the usernames map //! //! \param mac MAC address of Hue bridge //! \param username Username that is used to control the Hue bridge void addUsername(const std::string& mac, const std::string& username); //! \brief Function that adds a client key to the clientkeys map //! //! The client key is only needed for entertainment mode, otherwise it is optional. //! \param mac MAC address of Hue bridge //! \param clientkey Client key that is used to control the Hue bridge in entertainment mode void addClientKey(const std::string& mac, const std::string& clientkey); //! \brief Function that returns a map of mac addresses and usernames. //! //! Note these should be saved at the end and re-loaded with \ref addUsername //! next time, so only one username is generated per bridge. \returns A map //! mapping mac address to username for every bridge const std::map& getAllUsernames() const; //! \brief Normalizes mac address to plain hex number. //! \returns \p input without separators and whitespace, in lower case. static std::string normalizeMac(std::string input); private: //! \brief Parses mac address from description.xml //! //! \param description Content of description.xml file as returned by GET request. //! \returns Content of xml element \c serialNumber if description matches a Hue bridge, otherwise an empty //! string. static std::string parseDescription(const std::string& description); std::map usernames; //!< Maps all macs to usernames added by \ref //!< BridgeFinder::addUsername std::map clientkeys; //!< Maps all macs to clientkeys added by \ref //!< BridgeFinder::addClientKey std::shared_ptr http_handler; }; //! \brief Bridge class for a bridge. //! //! This is the main class used to interact with the Hue bridge. class Bridge { friend class BridgeFinder; public: using LightList = SearchableResourceList; using GroupList = GroupResourceList; using ScheduleList = CreateableResourceList, CreateSchedule>; using SceneList = CreateableResourceList, CreateScene>; using RuleList = CreateableResourceList, CreateRule>; public: //! \brief Constructor of Bridge class //! //! \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. Can be left empty and acquired in \ref requestUsername. //! \param handler HttpHandler for communication with the bridge //! \param clientkey Optional client key for streaming //! \param refreshDuration Time between refreshing the cached state. //! \param sharedState Uses a single, shared cache for all objects on the bridge. Bridge(const std::string& ip, const int port, const std::string& username, std::shared_ptr handler, const std::string& clientkey = "", std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10), bool sharedState = false); //! \brief Refreshes the bridge state. //! //! Should only be called rarely, as a full refresh is costly and usually not necessary. //! Instead refresh only the parts you are interested in or rely on periodic refreshes //! that happen automatically when calling non-const methods. //! \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(); //! \brief Sets refresh interval for the whole bridge state. //! \param refreshDuration The new minimum duration between refreshes. May be 0 or \ref c_refreshNever. //! //! Also sets refresh duration on all resource lists on the bridge, but not on already existing lights. //! The resource lists (such as lights()) can have their own durations, but those must be set after calling this function. void setRefreshDuration(std::chrono::steady_clock::duration refreshDuration); //! \brief Function to get the ip address of the hue bridge //! //! \return string containing ip std::string getBridgeIP() const; //! \brief Function to set stream mode to active for entertainment mode //! //! \return bool - whether stream request was successful bool startStreaming(std::string group_identifier); //! \brief Function to set stream mode to active for entertainment mode //! //! \return bool - whether stream request was successful bool stopStreaming(std::string group_identifier); //! \brief Function to get the port of the hue bridge //! //! \return integer containing port int getBridgePort() const; //! \brief Send a username request to the Hue bridge. //! //! Blocks for about 30 seconds and 5 seconds to prepare. //! It automatically sets the username variable according to the username received and returns the username //! received. This function should only be called once to acquire a username to control the bridge and the //! username should be saved for future use. \return username for API usage \throws std::system_error when //! system or socket operations fail \throws HueException when response contained no body \throws //! HueAPIResponseException when response contains an error except link button not pressed. \throws //! nlohmann::json::parse_error when response could not be parsed std::string requestUsername(); //! \brief Function that returns the username //! //! \return The username used for API access std::string getUsername() const; //! \brief Function that returns the client key //! //! \return The client key used for Entertainment Mode API access std::string getClientKey() const; //! \brief Function to set the ip address of this class representing a bridge //! //! \param ip String that specifies the ip in dotted decimal notation like "192.168.2.1" void setIP(const std::string& ip); //! \brief Function to set the port of this class representing a bridge //! //! \param port Integer that specifies the port of an address like //! "192.168.2.1:8080" void setPort(const int port); //! \brief Provides access to the configuration of the bridge. BridgeConfig& config(); //! \brief Provides access to the configuration of the bridge. //! \note Does not refresh state. const BridgeConfig& config() const; //! \brief Provides access to the Light%s on the bridge. LightList& lights(); //! \brief Provides access to the Light%s on the bridge. //! \note Does not refresh state. const LightList& lights() const; //! \brief Provides access to the Group%s on the bridge. GroupList& groups(); //! \brief Provides access to the Group%s on the bridge. //! \note Does not refresh state. const GroupList& groups() const; //! \brief Provides access to the Schedule%s on the bridge. ScheduleList& schedules(); //! \brief Provides access to the Schedule%s on the bridge. //! \note Does not refresh state. const ScheduleList& schedules() const; //! \brief Provides access to the Scene%s on the bridge. SceneList& scenes(); //! \brief Provides access to the Scene%s on the bridge. //! \note Does not refresh state. const SceneList& scenes() const; //! \brief Provides access to the Sensor%s on the bridge. SensorList& sensors(); //! \brief Provides access to the Sensor%s on the bridge. //! \note Does not refresh state. const SensorList& sensors() const; //! \brief Provides access to the Rule%s on the bridge. RuleList& rules(); //! \brief Provides access to the Rule%s on the bridge //! \note Does not refresh state. const RuleList& rules() const; private: //! \brief Function that sets the HttpHandler and updates the HueCommandAPI. //! \param handler a HttpHandler of type \ref IHttpHandler //! //! The HttpHandler and HueCommandAPI are used for bridge communication. //! Resetting the HttpHandler should only be done when the username is first set, //! before Bridge is used. //! Resets all caches and resource lists. void setHttpHandler(std::shared_ptr handler); private: std::string ip; //!< IP-Address of the hue bridge in dotted decimal notation //!< like "192.168.2.1" std::string username; //!< Username that is ussed to access the hue bridge std::string clientkey; //!< Client key that is used for entertainment mode int port; std::shared_ptr http_handler; //!< A IHttpHandler that is used to communicate with the //!< bridge std::chrono::steady_clock::duration refreshDuration; std::shared_ptr stateCache; detail::MakeCopyable lightList; detail::MakeCopyable groupList; detail::MakeCopyable scheduleList; detail::MakeCopyable sceneList; detail::MakeCopyable sensorList; detail::MakeCopyable ruleList; detail::MakeCopyable bridgeConfig; bool sharedState; }; } // namespace hueplusplus #endif