Commit 8bfb374147baa3244aa40045dc2d7a46c0ec1275
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.
Showing
6 changed files
with
79 additions
and
44 deletions
include/hueplusplus/HueDeviceTypes.h
| @@ -33,12 +33,16 @@ namespace hueplusplus | @@ -33,12 +33,16 @@ namespace hueplusplus | ||
| 33 | class HueLightFactory | 33 | class HueLightFactory |
| 34 | { | 34 | { |
| 35 | public: | 35 | public: |
| 36 | - HueLightFactory(const HueCommandAPI& commands); | 36 | + HueLightFactory(const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration); |
| 37 | 37 | ||
| 38 | HueLight createLight(const nlohmann::json& lightState, int id); | 38 | HueLight createLight(const nlohmann::json& lightState, int id); |
| 39 | 39 | ||
| 40 | private: | 40 | private: |
| 41 | + ColorType getColorType(const nlohmann::json& lightState, bool hasCt) const; | ||
| 42 | + | ||
| 43 | +private: | ||
| 41 | HueCommandAPI commands; | 44 | HueCommandAPI commands; |
| 45 | + std::chrono::steady_clock::duration refreshDuration; | ||
| 42 | std::shared_ptr<BrightnessStrategy> simpleBrightness; | 46 | std::shared_ptr<BrightnessStrategy> simpleBrightness; |
| 43 | std::shared_ptr<ColorTemperatureStrategy> simpleColorTemperature; | 47 | std::shared_ptr<ColorTemperatureStrategy> simpleColorTemperature; |
| 44 | std::shared_ptr<ColorTemperatureStrategy> extendedColorTemperature; | 48 | std::shared_ptr<ColorTemperatureStrategy> extendedColorTemperature; |
include/hueplusplus/HueLight.h
| @@ -118,7 +118,13 @@ public: | @@ -118,7 +118,13 @@ public: | ||
| 118 | 118 | ||
| 119 | //! \brief Const function that returns the light type | 119 | //! \brief Const function that returns the light type |
| 120 | //! | 120 | //! |
| 121 | + //! The type determines which functions the light has. | ||
| 121 | //! \return String containing the type | 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 | virtual std::string getType() const; | 128 | virtual std::string getType() const; |
| 123 | 129 | ||
| 124 | //! \brief Function that returns the name of the light. | 130 | //! \brief Function that returns the name of the light. |
src/Hue.cpp
| @@ -137,7 +137,7 @@ Hue::Hue(const std::string& ip, const int port, const std::string& username, | @@ -137,7 +137,7 @@ Hue::Hue(const std::string& ip, const int port, const std::string& username, | ||
| 137 | http_handler(std::move(handler)), | 137 | http_handler(std::move(handler)), |
| 138 | commands(ip, port, username, http_handler), | 138 | commands(ip, port, username, http_handler), |
| 139 | stateCache("", commands, refreshDuration), | 139 | stateCache("", commands, refreshDuration), |
| 140 | - lightFactory(commands) | 140 | + lightFactory(commands, refreshDuration) |
| 141 | {} | 141 | {} |
| 142 | 142 | ||
| 143 | std::string Hue::getBridgeIP() | 143 | std::string Hue::getBridgeIP() |
| @@ -179,9 +179,7 @@ std::string Hue::requestUsername() | @@ -179,9 +179,7 @@ std::string Hue::requestUsername() | ||
| 179 | // [{"success":{"username": "<username>"}}] | 179 | // [{"success":{"username": "<username>"}}] |
| 180 | username = jsonUser.get<std::string>(); | 180 | username = jsonUser.get<std::string>(); |
| 181 | // Update commands with new username and ip | 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 | std::cout << "Success! Link button was pressed!\n"; | 183 | std::cout << "Success! Link button was pressed!\n"; |
| 186 | std::cout << "Username is \"" << username << "\"\n"; | 184 | std::cout << "Username is \"" << username << "\"\n"; |
| 187 | break; | 185 | break; |
| @@ -523,6 +521,6 @@ void Hue::setHttpHandler(std::shared_ptr<const IHttpHandler> handler) | @@ -523,6 +521,6 @@ void Hue::setHttpHandler(std::shared_ptr<const IHttpHandler> handler) | ||
| 523 | http_handler = handler; | 521 | http_handler = handler; |
| 524 | commands = HueCommandAPI(ip, port, username, handler); | 522 | commands = HueCommandAPI(ip, port, username, handler); |
| 525 | stateCache = APICache("", commands, stateCache.getRefreshDuration()); | 523 | stateCache = APICache("", commands, stateCache.getRefreshDuration()); |
| 526 | - lightFactory = HueLightFactory(commands); | 524 | + lightFactory = HueLightFactory(commands, stateCache.getRefreshDuration()); |
| 527 | } | 525 | } |
| 528 | } // namespace hueplusplus | 526 | } // namespace hueplusplus |
src/HueDeviceTypes.cpp
| @@ -31,6 +31,7 @@ | @@ -31,6 +31,7 @@ | ||
| 31 | #include "hueplusplus/SimpleBrightnessStrategy.h" | 31 | #include "hueplusplus/SimpleBrightnessStrategy.h" |
| 32 | #include "hueplusplus/SimpleColorHueStrategy.h" | 32 | #include "hueplusplus/SimpleColorHueStrategy.h" |
| 33 | #include "hueplusplus/SimpleColorTemperatureStrategy.h" | 33 | #include "hueplusplus/SimpleColorTemperatureStrategy.h" |
| 34 | +#include "hueplusplus/Utils.h" | ||
| 34 | 35 | ||
| 35 | namespace hueplusplus | 36 | namespace hueplusplus |
| 36 | { | 37 | { |
| @@ -56,32 +57,11 @@ const std::set<std::string>& getGamutATypes() | @@ -56,32 +57,11 @@ const std::set<std::string>& getGamutATypes() | ||
| 56 | = {"LST001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", "LLC013", "LLC014"}; | 57 | = {"LST001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012", "LLC013", "LLC014"}; |
| 57 | return c_EXTENDEDCOLORLIGHT_GAMUTA_TYPES; | 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 | } // namespace | 60 | } // namespace |
| 82 | 61 | ||
| 83 | -HueLightFactory::HueLightFactory(const HueCommandAPI& commands) | 62 | +HueLightFactory::HueLightFactory(const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration) |
| 84 | : commands(commands), | 63 | : commands(commands), |
| 64 | + refreshDuration(refreshDuration), | ||
| 85 | simpleBrightness(std::make_shared<SimpleBrightnessStrategy>()), | 65 | simpleBrightness(std::make_shared<SimpleBrightnessStrategy>()), |
| 86 | simpleColorHue(std::make_shared<SimpleColorHueStrategy>()), | 66 | simpleColorHue(std::make_shared<SimpleColorHueStrategy>()), |
| 87 | extendedColorHue(std::make_shared<ExtendedColorHueStrategy>()), | 67 | extendedColorHue(std::make_shared<ExtendedColorHueStrategy>()), |
| @@ -97,35 +77,81 @@ HueLight HueLightFactory::createLight(const nlohmann::json& lightState, int id) | @@ -97,35 +77,81 @@ HueLight HueLightFactory::createLight(const nlohmann::json& lightState, int id) | ||
| 97 | 77 | ||
| 98 | if (type == "on/off light") | 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 | light.colorType = ColorType::NONE; | 81 | light.colorType = ColorType::NONE; |
| 102 | return light; | 82 | return light; |
| 103 | } | 83 | } |
| 104 | else if (type == "dimmable light") | 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 | light.colorType = ColorType::NONE; | 87 | light.colorType = ColorType::NONE; |
| 108 | return light; | 88 | return light; |
| 109 | } | 89 | } |
| 110 | else if (type == "color temperature light") | 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 | light.colorType = ColorType::TEMPERATURE; | 93 | light.colorType = ColorType::TEMPERATURE; |
| 114 | return light; | 94 | return light; |
| 115 | } | 95 | } |
| 116 | else if (type == "color light") | 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 | return light; | 100 | return light; |
| 121 | } | 101 | } |
| 122 | else if (type == "extended color light") | 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 | return light; | 106 | return light; |
| 127 | } | 107 | } |
| 128 | std::cerr << "Could not determine HueLight type:" << type << "!\n"; | 108 | std::cerr << "Could not determine HueLight type:" << type << "!\n"; |
| 129 | throw HueException(CURRENT_FILE_INFO, "Could not determine HueLight type!"); | 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 | } // namespace hueplusplus | 157 | } // namespace hueplusplus |
test/test_Hue.cpp
| @@ -298,6 +298,7 @@ TEST(Hue, getLight) | @@ -298,6 +298,7 @@ TEST(Hue, getLight) | ||
| 298 | EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE); | 298 | EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE); |
| 299 | 299 | ||
| 300 | // more coverage stuff | 300 | // more coverage stuff |
| 301 | + hue_bridge_state["lights"]["1"]["type"] = "Color light"; | ||
| 301 | hue_bridge_state["lights"]["1"]["modelid"] = "LCT001"; | 302 | hue_bridge_state["lights"]["1"]["modelid"] = "LCT001"; |
| 302 | EXPECT_CALL( | 303 | EXPECT_CALL( |
| 303 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) | 304 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) |
| @@ -349,7 +350,7 @@ TEST(Hue, getLight) | @@ -349,7 +350,7 @@ TEST(Hue, getLight) | ||
| 349 | EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); | 350 | EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); |
| 350 | EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A); | 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 | EXPECT_CALL( | 354 | EXPECT_CALL( |
| 354 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) | 355 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) |
| 355 | .Times(1) | 356 | .Times(1) |
| @@ -366,7 +367,7 @@ TEST(Hue, getLight) | @@ -366,7 +367,7 @@ TEST(Hue, getLight) | ||
| 366 | EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); | 367 | EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); |
| 367 | EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE); | 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 | EXPECT_CALL( | 371 | EXPECT_CALL( |
| 371 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) | 372 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) |
| 372 | .Times(1) | 373 | .Times(1) |
| @@ -383,7 +384,7 @@ TEST(Hue, getLight) | @@ -383,7 +384,7 @@ TEST(Hue, getLight) | ||
| 383 | EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); | 384 | EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); |
| 384 | EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE); | 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 | EXPECT_CALL( | 388 | EXPECT_CALL( |
| 388 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) | 389 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) |
| 389 | .Times(1) | 390 | .Times(1) |
test/test_HueLight.cpp
| @@ -103,7 +103,7 @@ protected: | @@ -103,7 +103,7 @@ protected: | ||
| 103 | hue_bridge_state["lights"]["3"]["swupdate"] = nlohmann::json::object(); | 103 | hue_bridge_state["lights"]["3"]["swupdate"] = nlohmann::json::object(); |
| 104 | hue_bridge_state["lights"]["3"]["swupdate"]["state"] = "noupdates"; | 104 | hue_bridge_state["lights"]["3"]["swupdate"]["state"] = "noupdates"; |
| 105 | hue_bridge_state["lights"]["3"]["swupdate"]["lastinstall"] = nullptr; | 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 | hue_bridge_state["lights"]["3"]["name"] = "Hue lamp 3"; | 107 | hue_bridge_state["lights"]["3"]["name"] = "Hue lamp 3"; |
| 108 | hue_bridge_state["lights"]["3"]["modelid"] = "LCT010"; | 108 | hue_bridge_state["lights"]["3"]["modelid"] = "LCT010"; |
| 109 | hue_bridge_state["lights"]["3"]["manufacturername"] = "Philips"; | 109 | hue_bridge_state["lights"]["3"]["manufacturername"] = "Philips"; |
| @@ -236,10 +236,10 @@ TEST_F(HueLightTest, getType) | @@ -236,10 +236,10 @@ TEST_F(HueLightTest, getType) | ||
| 236 | 236 | ||
| 237 | EXPECT_EQ("Dimmable light", ctest_light_1.getType()); | 237 | EXPECT_EQ("Dimmable light", ctest_light_1.getType()); |
| 238 | EXPECT_EQ("Color light", ctest_light_2.getType()); | 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 | EXPECT_EQ("Dimmable light", test_light_1.getType()); | 240 | EXPECT_EQ("Dimmable light", test_light_1.getType()); |
| 241 | EXPECT_EQ("Color light", test_light_2.getType()); | 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 | TEST_F(HueLightTest, getName) | 245 | TEST_F(HueLightTest, getName) |
| @@ -406,10 +406,10 @@ TEST_F(HueLightTest, getColorType) | @@ -406,10 +406,10 @@ TEST_F(HueLightTest, getColorType) | ||
| 406 | 406 | ||
| 407 | EXPECT_EQ(ColorType::NONE, ctest_light_1.getColorType()); | 407 | EXPECT_EQ(ColorType::NONE, ctest_light_1.getColorType()); |
| 408 | EXPECT_EQ(ColorType::GAMUT_A, ctest_light_2.getColorType()); | 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 | EXPECT_EQ(ColorType::NONE, test_light_1.getColorType()); | 410 | EXPECT_EQ(ColorType::NONE, test_light_1.getColorType()); |
| 411 | EXPECT_EQ(ColorType::GAMUT_A, test_light_2.getColorType()); | 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 | TEST_F(HueLightTest, KelvinToMired) | 415 | TEST_F(HueLightTest, KelvinToMired) |