Commit 8bfb374147baa3244aa40045dc2d7a46c0ec1275

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 6e00e6d5

Implement HueLightFactory::getColorType, fix tests.

The color type is determined using the capabilities field on the light state. If that is not present, the hardcoded types are used.
include/hueplusplus/HueDeviceTypes.h
... ... @@ -33,12 +33,16 @@ namespace hueplusplus
33 33 class HueLightFactory
34 34 {
35 35 public:
36   - HueLightFactory(const HueCommandAPI& commands);
  36 + HueLightFactory(const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration);
37 37  
38 38 HueLight createLight(const nlohmann::json& lightState, int id);
39 39  
40 40 private:
  41 + ColorType getColorType(const nlohmann::json& lightState, bool hasCt) const;
  42 +
  43 +private:
41 44 HueCommandAPI commands;
  45 + std::chrono::steady_clock::duration refreshDuration;
42 46 std::shared_ptr<BrightnessStrategy> simpleBrightness;
43 47 std::shared_ptr<ColorTemperatureStrategy> simpleColorTemperature;
44 48 std::shared_ptr<ColorTemperatureStrategy> extendedColorTemperature;
... ...
include/hueplusplus/HueLight.h
... ... @@ -118,7 +118,13 @@ public:
118 118  
119 119 //! \brief Const function that returns the light type
120 120 //!
  121 + //! The type determines which functions the light has.
121 122 //! \return String containing the type
  123 + //! - "On/Off light": on/off
  124 + //! - "Dimmable light": on/off, brightness
  125 + //! - "Color light": on/off, brightness, color hue/sat/xy
  126 + //! - "Color temperature light": on/off, brightness, color temperature
  127 + //! - "Extended color light": on/off, brightness, color temperature, color hue/sat/xy
122 128 virtual std::string getType() const;
123 129  
124 130 //! \brief Function that returns the name of the light.
... ...
src/Hue.cpp
... ... @@ -137,7 +137,7 @@ Hue::Hue(const std::string&amp; ip, const int port, const std::string&amp; username,
137 137 http_handler(std::move(handler)),
138 138 commands(ip, port, username, http_handler),
139 139 stateCache("", commands, refreshDuration),
140   - lightFactory(commands)
  140 + lightFactory(commands, refreshDuration)
141 141 {}
142 142  
143 143 std::string Hue::getBridgeIP()
... ... @@ -179,9 +179,7 @@ std::string Hue::requestUsername()
179 179 // [{"success":{"username": "<username>"}}]
180 180 username = jsonUser.get<std::string>();
181 181 // Update commands with new username and ip
182   - commands = HueCommandAPI(ip, port, username, http_handler);
183   - stateCache = APICache("", commands, stateCache.getRefreshDuration());
184   - lightFactory = HueLightFactory(commands);
  182 + setHttpHandler(http_handler);
185 183 std::cout << "Success! Link button was pressed!\n";
186 184 std::cout << "Username is \"" << username << "\"\n";
187 185 break;
... ... @@ -523,6 +521,6 @@ void Hue::setHttpHandler(std::shared_ptr&lt;const IHttpHandler&gt; handler)
523 521 http_handler = handler;
524 522 commands = HueCommandAPI(ip, port, username, handler);
525 523 stateCache = APICache("", commands, stateCache.getRefreshDuration());
526   - lightFactory = HueLightFactory(commands);
  524 + lightFactory = HueLightFactory(commands, stateCache.getRefreshDuration());
527 525 }
528 526 } // namespace hueplusplus
... ...
src/HueDeviceTypes.cpp
... ... @@ -31,6 +31,7 @@
31 31 #include "hueplusplus/SimpleBrightnessStrategy.h"
32 32 #include "hueplusplus/SimpleColorHueStrategy.h"
33 33 #include "hueplusplus/SimpleColorTemperatureStrategy.h"
  34 +#include "hueplusplus/Utils.h"
34 35  
35 36 namespace hueplusplus
36 37 {
... ... @@ -56,32 +57,11 @@ const std::set&lt;std::string&gt;&amp; getGamutATypes()
56 57 = {"LST001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", "LLC013", "LLC014"};
57 58 return c_EXTENDEDCOLORLIGHT_GAMUTA_TYPES;
58 59 }
59   -
60   -const std::set<std::string>& getNoColorTypes()
61   -{
62   - static const std::set<std::string> c_DIMMABLELIGHT_NO_COLOR_TYPES
63   - = {"LWB004", "LWB006", "LWB007", "LWB010", "LWB014", "LDF001", "LDF002", "LDD001", "LDD002", "MWM001"};
64   - return c_DIMMABLELIGHT_NO_COLOR_TYPES;
65   -}
66   -
67   -const std::set<std::string>& getNonDimmableTypes()
68   -{
69   - static const std::set<std::string> c_NON_DIMMABLE_TYPES = {"Plug 01"};
70   - return c_NON_DIMMABLE_TYPES;
71   -}
72   -
73   -const std::set<std::string>& getTemperatureLightTypes()
74   -{
75   - static const std::set<std::string> c_TEMPERATURELIGHT_TYPES
76   - = {"LLM010", "LLM011", "LLM012", "LTW001", "LTW004", "LTW010", "LTW011", "LTW012", "LTW013", "LTW014", "LTW015",
77   - "LTP001", "LTP002", "LTP003", "LTP004", "LTP005", "LTD003", "LTF001", "LTF002", "LTC001", "LTC002",
78   - "LTC003", "LTC004", "LTC011", "LTC012", "LTD001", "LTD002", "LFF001", "LTT001", "LDT001"};
79   - return c_TEMPERATURELIGHT_TYPES;
80   -}
81 60 } // namespace
82 61  
83   -HueLightFactory::HueLightFactory(const HueCommandAPI& commands)
  62 +HueLightFactory::HueLightFactory(const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
84 63 : commands(commands),
  64 + refreshDuration(refreshDuration),
85 65 simpleBrightness(std::make_shared<SimpleBrightnessStrategy>()),
86 66 simpleColorHue(std::make_shared<SimpleColorHueStrategy>()),
87 67 extendedColorHue(std::make_shared<ExtendedColorHueStrategy>()),
... ... @@ -97,35 +77,81 @@ HueLight HueLightFactory::createLight(const nlohmann::json&amp; lightState, int id)
97 77  
98 78 if (type == "on/off light")
99 79 {
100   - HueLight light(id, commands, nullptr, nullptr, nullptr);
  80 + HueLight light(id, commands, nullptr, nullptr, nullptr, refreshDuration);
101 81 light.colorType = ColorType::NONE;
102 82 return light;
103 83 }
104 84 else if (type == "dimmable light")
105 85 {
106   - HueLight light(id, commands, simpleBrightness, nullptr, nullptr);
  86 + HueLight light(id, commands, simpleBrightness, nullptr, nullptr, refreshDuration);
107 87 light.colorType = ColorType::NONE;
108 88 return light;
109 89 }
110 90 else if (type == "color temperature light")
111 91 {
112   - HueLight light(id, commands, simpleBrightness, simpleColorTemperature, nullptr);
  92 + HueLight light(id, commands, simpleBrightness, simpleColorTemperature, nullptr, refreshDuration);
113 93 light.colorType = ColorType::TEMPERATURE;
114 94 return light;
115 95 }
116 96 else if (type == "color light")
117 97 {
118   - HueLight light(id, commands, simpleBrightness, nullptr, simpleColorHue);
119   - light.colorType = ColorType::GAMUT_A; // getColorType(state);
  98 + HueLight light(id, commands, simpleBrightness, nullptr, simpleColorHue, refreshDuration);
  99 + light.colorType = getColorType(lightState, false);
120 100 return light;
121 101 }
122 102 else if (type == "extended color light")
123 103 {
124   - HueLight light(id, commands, simpleBrightness, extendedColorTemperature, extendedColorHue);
125   - light.colorType = ColorType::GAMUT_B_TEMPERATURE; // getColorType(state);
  104 + HueLight light(id, commands, simpleBrightness, extendedColorTemperature, extendedColorHue, refreshDuration);
  105 + light.colorType = getColorType(lightState, true);
126 106 return light;
127 107 }
128 108 std::cerr << "Could not determine HueLight type:" << type << "!\n";
129 109 throw HueException(CURRENT_FILE_INFO, "Could not determine HueLight type!");
130 110 }
  111 +
  112 +ColorType HueLightFactory::getColorType(const nlohmann::json& lightState, bool hasCt) const
  113 +{
  114 + // Try to get color type via capabilities
  115 + const nlohmann::json& gamuttype = utils::safeGetMember(lightState, "capabilities", "control", "colorgamuttype");
  116 + if (gamuttype.is_string())
  117 + {
  118 + const std::string gamut = gamuttype.get<std::string>();
  119 + if (gamut == "A")
  120 + {
  121 + return hasCt ? ColorType::GAMUT_A_TEMPERATURE : ColorType::GAMUT_A;
  122 + }
  123 + else if (gamut == "B")
  124 + {
  125 + return hasCt ? ColorType::GAMUT_B_TEMPERATURE : ColorType::GAMUT_B;
  126 + }
  127 + else if (gamut == "C")
  128 + {
  129 + return hasCt ? ColorType::GAMUT_C_TEMPERATURE : ColorType::GAMUT_C;
  130 + }
  131 + else
  132 + {
  133 + // Only other type is "Other" which does not have an enum value
  134 + return ColorType::UNDEFINED;
  135 + }
  136 + }
  137 + else
  138 + {
  139 + // Old version without capabilities, fall back to hardcoded types
  140 + std::string modelid = lightState.at("modelid").get<std::string>();
  141 + if (getGamutATypes().count(modelid))
  142 + {
  143 + return hasCt ? ColorType::GAMUT_A_TEMPERATURE : ColorType::GAMUT_A;
  144 + }
  145 + else if (getGamutBTypes().count(modelid))
  146 + {
  147 + return hasCt ? ColorType::GAMUT_B_TEMPERATURE : ColorType::GAMUT_B;
  148 + }
  149 + else if (getGamutCTypes().count(modelid))
  150 + {
  151 + return hasCt ? ColorType::GAMUT_C_TEMPERATURE : ColorType::GAMUT_C;
  152 + }
  153 + std::cerr << "Could not determine HueLight color type:" << modelid << "!\n";
  154 + throw HueException(CURRENT_FILE_INFO, "Could not determine HueLight color type!");
  155 + }
  156 +}
131 157 } // namespace hueplusplus
... ...
test/test_Hue.cpp
... ... @@ -298,6 +298,7 @@ TEST(Hue, getLight)
298 298 EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
299 299  
300 300 // more coverage stuff
  301 + hue_bridge_state["lights"]["1"]["type"] = "Color light";
301 302 hue_bridge_state["lights"]["1"]["modelid"] = "LCT001";
302 303 EXPECT_CALL(
303 304 *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
... ... @@ -349,7 +350,7 @@ TEST(Hue, getLight)
349 350 EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
350 351 EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A);
351 352  
352   - hue_bridge_state["lights"]["1"]["modelid"] = "LWB004";
  353 + hue_bridge_state["lights"]["1"]["type"] = "Dimmable light";
353 354 EXPECT_CALL(
354 355 *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
355 356 .Times(1)
... ... @@ -366,7 +367,7 @@ TEST(Hue, getLight)
366 367 EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
367 368 EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);
368 369  
369   - hue_bridge_state["lights"]["1"]["modelid"] = "Plug 01";
  370 + hue_bridge_state["lights"]["1"]["type"] = "On/Off light";
370 371 EXPECT_CALL(
371 372 *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
372 373 .Times(1)
... ... @@ -383,7 +384,7 @@ TEST(Hue, getLight)
383 384 EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
384 385 EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);
385 386  
386   - hue_bridge_state["lights"]["1"]["modelid"] = "ABC000";
  387 + hue_bridge_state["lights"]["1"]["type"] = "unknown light type";
387 388 EXPECT_CALL(
388 389 *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
389 390 .Times(1)
... ...
test/test_HueLight.cpp
... ... @@ -103,7 +103,7 @@ protected:
103 103 hue_bridge_state["lights"]["3"]["swupdate"] = nlohmann::json::object();
104 104 hue_bridge_state["lights"]["3"]["swupdate"]["state"] = "noupdates";
105 105 hue_bridge_state["lights"]["3"]["swupdate"]["lastinstall"] = nullptr;
106   - hue_bridge_state["lights"]["3"]["type"] = "Color extended light";
  106 + hue_bridge_state["lights"]["3"]["type"] = "Extended color light";
107 107 hue_bridge_state["lights"]["3"]["name"] = "Hue lamp 3";
108 108 hue_bridge_state["lights"]["3"]["modelid"] = "LCT010";
109 109 hue_bridge_state["lights"]["3"]["manufacturername"] = "Philips";
... ... @@ -236,10 +236,10 @@ TEST_F(HueLightTest, getType)
236 236  
237 237 EXPECT_EQ("Dimmable light", ctest_light_1.getType());
238 238 EXPECT_EQ("Color light", ctest_light_2.getType());
239   - EXPECT_EQ("Color extended light", ctest_light_3.getType());
  239 + EXPECT_EQ("Extended color light", ctest_light_3.getType());
240 240 EXPECT_EQ("Dimmable light", test_light_1.getType());
241 241 EXPECT_EQ("Color light", test_light_2.getType());
242   - EXPECT_EQ("Color extended light", test_light_3.getType());
  242 + EXPECT_EQ("Extended color light", test_light_3.getType());
243 243 }
244 244  
245 245 TEST_F(HueLightTest, getName)
... ... @@ -406,10 +406,10 @@ TEST_F(HueLightTest, getColorType)
406 406  
407 407 EXPECT_EQ(ColorType::NONE, ctest_light_1.getColorType());
408 408 EXPECT_EQ(ColorType::GAMUT_A, ctest_light_2.getColorType());
409   - EXPECT_EQ(ColorType::GAMUT_C, ctest_light_3.getColorType());
  409 + EXPECT_EQ(ColorType::GAMUT_C_TEMPERATURE, ctest_light_3.getColorType());
410 410 EXPECT_EQ(ColorType::NONE, test_light_1.getColorType());
411 411 EXPECT_EQ(ColorType::GAMUT_A, test_light_2.getColorType());
412   - EXPECT_EQ(ColorType::GAMUT_C, test_light_3.getColorType());
  412 + EXPECT_EQ(ColorType::GAMUT_C_TEMPERATURE, test_light_3.getColorType());
413 413 }
414 414  
415 415 TEST_F(HueLightTest, KelvinToMired)
... ...