/*-----------------------------------------*\ | RGBController_PhilipsHueEntertainment.cpp| | | | Generic RGB Interface for Philips Hue | | Entertainment Mode | | | | Adam Honse (CalcProgrammer1) 11/7/2020 | \*-----------------------------------------*/ #include "RGBController_PhilipsHueEntertainment.h" #include "ResourceManager.h" using namespace std::chrono_literals; /**------------------------------------------------------------------*\ @name Philips Hue Entertainment @category Light @type Network @save :x: @direct :white_check_mark: @effects :x: @detectors DetectPhilipsHueControllers @comment \*-------------------------------------------------------------------*/ RGBController_PhilipsHueEntertainment::RGBController_PhilipsHueEntertainment(PhilipsHueEntertainmentController* controller_ptr) { controller = controller_ptr; name = controller->GetManufacturer() + " " + controller->GetName(); type = DEVICE_TYPE_LIGHT; version = controller->GetVersion(); description = "Philips Hue Entertainment Mode Device"; serial = controller->GetUniqueID(); location = controller->GetLocation(); mode Direct; Direct.name = "Direct"; Direct.value = 0; Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Disconnected; Disconnected.name = "Disconnected"; Disconnected.value = 1; Disconnected.flags = 0; Disconnected.color_mode = MODE_COLORS_NONE; modes.push_back(Disconnected); SetupZones(); /*-----------------------------------------------------------------------------------------------------*\ | The Philips Hue Entertainment Mode only supports one stream at a time. So we must start Disconnected. | | https://developers.meethue.com/develop/hue-entertainment/philips-hue-entertainment-api/ | \*-----------------------------------------------------------------------------------------------------*/ active_mode = 1; /*-----------------------------------------------------*\ | The Philips Hue Entertainment Mode requires a packet | | within 10 seconds of sending the lighting change in | | order to not exit entertainment mode. Start a thread | | to continuously send a packet every 5s | \*-----------------------------------------------------*/ KeepaliveThreadRunning = true; KeepaliveThread = new std::thread(&RGBController_PhilipsHueEntertainment::KeepaliveThreadFunction, this); } void RGBController_PhilipsHueEntertainment::SetupZones() { zone led_zone; led_zone.name = "RGB Light"; led_zone.type = ZONE_TYPE_SINGLE; led_zone.leds_min = controller->GetNumLEDs(); led_zone.leds_max = controller->GetNumLEDs(); led_zone.leds_count = controller->GetNumLEDs(); led_zone.matrix_map = NULL; zones.push_back(led_zone); for(unsigned int led_idx = 0; led_idx < controller->GetNumLEDs(); led_idx++) { led new_led; new_led.name = "RGB Light"; leds.push_back(new_led); } SetupColors(); } void RGBController_PhilipsHueEntertainment::ResizeZone(int /*zone*/, int /*new_size*/) { /*---------------------------------------------------------*\ | This device does not support resizing zones | \*---------------------------------------------------------*/ } void RGBController_PhilipsHueEntertainment::DeviceUpdateLEDs() { last_update_time = std::chrono::steady_clock::now(); if(active_mode == 0) { controller->SetColor(&colors[0]); } } void RGBController_PhilipsHueEntertainment::UpdateZoneLEDs(int /*zone*/) { DeviceUpdateLEDs(); } void RGBController_PhilipsHueEntertainment::UpdateSingleLED(int /*led*/) { DeviceUpdateLEDs(); } void RGBController_PhilipsHueEntertainment::DeviceUpdateMode() { if(active_mode == 0) { std::vector rgb_controllers = ResourceManager::get()->GetRGBControllers(); for(unsigned int controller_idx = 0; controller_idx < rgb_controllers.size(); controller_idx++) { if(rgb_controllers[controller_idx] != this && rgb_controllers[controller_idx]->description == "Philips Hue Entertainment Mode Device" && rgb_controllers[controller_idx]->active_mode == 0) { rgb_controllers[controller_idx]->SetMode(1); } } controller->Connect(); } else { controller->Disconnect(); } } void RGBController_PhilipsHueEntertainment::KeepaliveThreadFunction() { while(KeepaliveThreadRunning) { if(active_mode == 0) { if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::seconds(5)) { UpdateLEDs(); } } std::this_thread::sleep_for(1s); } }