#include "Bridge.h" #include "HueDeviceTypes.h" #ifdef _WIN32 #include "WinHttpHandler.h" #else #include "LinHttpHandler.h" #endif #include "Detector.h" #include "LogManager.h" #include "PhilipsHueController.h" #include "PhilipsHueEntertainmentController.h" #include "RGBController_PhilipsHue.h" #include "RGBController_PhilipsHueEntertainment.h" #include "SettingsManager.h" /******************************************************************************************\ * * * DetectPhilipsHueControllers * * * * Detect Philips Hue lighting devices with RGB control * * * \******************************************************************************************/ void DetectPhilipsHueControllers(std::vector& rgb_controllers) { json hue_settings; /*-------------------------------------------------*\ | Create an HTTP handler | \*-------------------------------------------------*/ #ifdef _WIN32 using SystemHttpHandler = hueplusplus::WinHttpHandler; #else using SystemHttpHandler = hueplusplus::LinHttpHandler; #endif /*-------------------------------------------------*\ | Get Philips Hue settings from settings manager | \*-------------------------------------------------*/ hue_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("PhilipsHueDevices"); /*-------------------------------------------------*\ | Create a finder and find bridges | \*-------------------------------------------------*/ static hueplusplus::BridgeFinder finder(std::make_shared()); std::vector bridges;// = finder.findBridges(); /*-------------------------------------------------*\ | If no bridges were detected, manually add bridge | | IP and MAC (need to get these from file) | \*-------------------------------------------------*/ if(bridges.empty()) { if(hue_settings.contains("bridges")) { hueplusplus::BridgeFinder::BridgeIdentification ident; if(hue_settings["bridges"][0].contains("ip")) { ident.ip = hue_settings["bridges"][0]["ip"]; } if(hue_settings["bridges"][0].contains("mac")) { ident.mac = hue_settings["bridges"][0]["mac"]; } bridges.push_back(ident); } } /*-------------------------------------------------*\ | If no bridges were found, return, otherwise | | connect to the first bridge | \*-------------------------------------------------*/ if(bridges.empty()) { return; } else { /*-------------------------------------------------*\ | Check if a saved username exists | \*-------------------------------------------------*/ if(hue_settings.contains("bridges")) { /*-------------------------------------------------*\ | Add the username if it exists | \*-------------------------------------------------*/ if(hue_settings["bridges"][0].contains("username")) { finder.addUsername(bridges[0].mac, hue_settings["bridges"][0]["username"]); } /*-------------------------------------------------*\ | Add the client key if it exists | \*-------------------------------------------------*/ if(hue_settings["bridges"][0].contains("clientkey")) { finder.addClientKey(bridges[0].mac, hue_settings["bridges"][0]["clientkey"]); } } /*-------------------------------------------------*\ | If username was added, this should connect right | | away. If not, the user will have to push the | | connect button on the bridge. | \*-------------------------------------------------*/ try { static hueplusplus::Bridge bridge = finder.getBridge(bridges[0]); bridge.refresh(); /*-------------------------------------------------*\ | Check to see if we need to save the settings | | Settings need to be saved if either username or | | client key either do not exist or have changed | \*-------------------------------------------------*/ bool save_settings = false; bool use_entertainment = false; bool auto_connect = false; if(hue_settings.contains("bridges")) { if(hue_settings["bridges"][0].contains("username")) { if(hue_settings["bridges"][0]["username"] != bridge.getUsername()) { save_settings = true; } } else { save_settings = true; } if(hue_settings["bridges"][0].contains("clientkey")) { if(hue_settings["bridges"][0]["clientkey"] != bridge.getClientKey()) { use_entertainment = true; save_settings = true; } } else { save_settings = true; } } /*-------------------------------------------------*\ | Save the settings if needed | \*-------------------------------------------------*/ if(save_settings) { hue_settings["bridges"][0]["username"] = bridge.getUsername(); hue_settings["bridges"][0]["clientkey"] = bridge.getClientKey(); hue_settings["bridges"][0]["entertainment"] = use_entertainment; hue_settings["bridges"][0]["autoconnect"] = auto_connect; ResourceManager::get()->GetSettingsManager()->SetSettings("PhilipsHueDevices", hue_settings); ResourceManager::get()->GetSettingsManager()->SaveSettings(); } /*-------------------------------------------------*\ | Get entertainment mode settings | \*-------------------------------------------------*/ if(hue_settings["bridges"][0].contains("entertainment")) { use_entertainment = hue_settings["bridges"][0]["entertainment"]; } if(hue_settings["bridges"][0].contains("autoconnect")) { auto_connect = hue_settings["bridges"][0]["autoconnect"]; } /*-------------------------------------------------*\ | Get all groups from the bridge | \*-------------------------------------------------*/ if(use_entertainment) { std::vector groups = bridge.groups().getAll(); if(groups.size() > 0) { /*-------------------------------------------------*\ | Loop through all available groups and check to | | see if any are Entertainment groups | \*-------------------------------------------------*/ for(unsigned int group_idx = 0; group_idx < groups.size(); group_idx++) { if(groups[group_idx].getType() == "Entertainment") { PhilipsHueEntertainmentController* new_controller = new PhilipsHueEntertainmentController(bridge, groups[group_idx]); RGBController_PhilipsHueEntertainment* new_rgbcontroller = new RGBController_PhilipsHueEntertainment(new_controller); rgb_controllers.push_back(new_rgbcontroller); } } /*-------------------------------------------------*\ | Loop through RGB Controllers to find the first | | Entertainment group and Set it to "Connect", | | as only one Stream can be open at a time. | \*-------------------------------------------------*/ if(auto_connect) { for(unsigned int controller_idx = 0; controller_idx < rgb_controllers.size(); controller_idx++) { if(rgb_controllers[controller_idx]->description == "Philips Hue Entertainment Mode Device") { rgb_controllers[controller_idx]->SetMode(0); break; } } } } } /*-------------------------------------------------*\ | Get all lights from the bridge | \*-------------------------------------------------*/ else { std::vector lights = bridge.lights().getAll(); if(lights.size() > 0) { /*-------------------------------------------------*\ | Loop through all available lights and add those | | that have color (RGB) control capability | \*-------------------------------------------------*/ for(unsigned int light_idx = 0; light_idx < lights.size(); light_idx++) { if(lights[light_idx].hasColorControl()) { PhilipsHueController* new_controller = new PhilipsHueController(lights[light_idx], bridge.getBridgeIP()); RGBController_PhilipsHue* new_rgbcontroller = new RGBController_PhilipsHue(new_controller); rgb_controllers.push_back(new_rgbcontroller); } } } } } catch(const std::exception &e) { LOG_INFO("Exception occurred in Philips Hue detection: %s", e.what()); } } } /* DetectPhilipsHueControllers() */ REGISTER_DETECTOR("Philips Hue", DetectPhilipsHueControllers);