/* * * Copyright (c) 2023 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "light.h" #include #include #include #include #include #include namespace example { namespace Ui { namespace Windows { namespace { using namespace chip::app::Clusters; using chip::app::DataModel::Nullable; ImVec4 HueSaturationToColor(float hueDegrees, float saturationPercent) { saturationPercent /= 100.0f; float x = saturationPercent * static_cast(1 - fabs(fmod(hueDegrees / 60, 2) - 1)); if (hueDegrees < 60) { return ImVec4(saturationPercent, x, 0, 1.0f); } if (hueDegrees < 120) { return ImVec4(x, saturationPercent, 0, 1.0f); } if (hueDegrees < 180) { return ImVec4(0, saturationPercent, x, 1.0f); } if (hueDegrees < 240) { return ImVec4(0, x, saturationPercent, 1.0f); } if (hueDegrees < 300) { return ImVec4(x, 0, saturationPercent, 1.0f); } return ImVec4(saturationPercent, 0, x, 1.0f); } } // namespace void Light::UpdateState() { if (mTargetLightIsOn.HasValue()) { chip::Protocols::InteractionModel::Status status = OnOffServer::Instance().setOnOffValue( mEndpointId, mTargetLightIsOn.Value() ? OnOff::Commands::On::Id : OnOff::Commands::Off::Id, false /* initiatedByLevelChange */); if (status != chip::Protocols::InteractionModel::Status::Success) { ChipLogError(AppServer, "Failed to set on/off value: %d", chip::to_underlying(status)); } mTargetLightIsOn.ClearValue(); } OnOff::Attributes::OnOff::Get(mEndpointId, &mLightIsOn); // Level Control if (mTargetLevel.HasValue()) { LevelControl::Commands::MoveToLevel::DecodableType data; data.level = mTargetLevel.Value(); data.optionsMask.Set(LevelControl::OptionsBitmap::kExecuteIfOff); data.optionsOverride.Set(LevelControl::OptionsBitmap::kExecuteIfOff); (void) LevelControlServer::MoveToLevel(mEndpointId, data); mTargetLevel.ClearValue(); } LevelControl::Attributes::CurrentLevel::Get(mEndpointId, mCurrentLevel); LevelControl::Attributes::MinLevel::Get(mEndpointId, &mMinLevel); LevelControl::Attributes::MaxLevel::Get(mEndpointId, &mMaxLevel); LevelControl::Attributes::RemainingTime::Get(mEndpointId, &mLevelRemainingTime10sOfSec); // Color control ColorControl::Attributes::ColorMode::Get(mEndpointId, &mColorMode); ColorControl::Attributes::CurrentHue::Get(mEndpointId, &mColorHue); ColorControl::Attributes::CurrentSaturation::Get(mEndpointId, &mColorSaturation); ColorControl::Attributes::CurrentX::Get(mEndpointId, &mColorX); ColorControl::Attributes::CurrentY::Get(mEndpointId, &mColorY); ColorControl::Attributes::ColorTemperatureMireds::Get(mEndpointId, &mColorTemperatureMireds); } void Light::Render() { ImGui::Begin("Light state"); ImGui::Text("Light on endpoint %d", mEndpointId); ImGui::Indent(); { bool uiValue = mLightIsOn; ImGui::Checkbox("Light is ON", &uiValue); if (uiValue != mLightIsOn) { mTargetLightIsOn.SetValue(uiValue); // schedule future update } } // bright yellow vs dark yellow on/off view ImGui::ColorButton("LightIsOn", mLightIsOn ? ImVec4(1.0f, 1.0f, 0.0f, 1.0f) : ImVec4(0.3f, 0.3f, 0.0f, 1.0f), 0 /* ImGuiColorEditFlags_* */, ImVec2(80, 80)); ImGui::Unindent(); ImGui::Text("Level Control:"); ImGui::Indent(); ImGui::Text("Remaining Time (1/10s): %d", mLevelRemainingTime10sOfSec); ImGui::Text("MIN Level: %d", mMinLevel); ImGui::Text("MAX Level: %d", mMaxLevel); if (mCurrentLevel.IsNull()) { ImGui::Text("Current Level: NULL"); } else { int uiValue = mCurrentLevel.Value(); ImGui::SliderInt("Current Level", &uiValue, mMinLevel, mMaxLevel); if (uiValue != mCurrentLevel.Value()) { mTargetLevel.SetValue(uiValue); // schedule future update } } ImGui::Unindent(); ImGui::Text("Color Control:"); ImGui::Indent(); const char * mode = // based on ColorMode attribute: spec 3.2.7.9 (mColorMode == ColorControl::ColorModeEnum::kCurrentHueAndCurrentSaturation) ? "Hue/Saturation" : (mColorMode == ColorControl::ColorModeEnum::kCurrentXAndCurrentY) ? "X/Y" : (mColorMode == ColorControl::ColorModeEnum::kColorTemperatureMireds) ? "Temperature/Mireds" : "UNKNOWN"; ImGui::Text("Mode: %s", mode); if (mColorMode == ColorControl::ColorModeEnum::kCurrentHueAndCurrentSaturation) { const float hueDegrees = (mColorHue * 360.0f) / 254.0f; const float saturationPercent = 100.0f * (mColorSaturation / 254.0f); ImGui::Text("Current Hue: %d (%f deg)", mColorHue, hueDegrees); ImGui::Text("Current Saturation: %d (%f %%)", mColorSaturation, saturationPercent); ImGui::ColorButton("LightColor", HueSaturationToColor(hueDegrees, saturationPercent), 0 /* ImGuiColorEditFlags_* */, ImVec2(80, 80)); } else if (mColorMode == ColorControl::ColorModeEnum::kCurrentXAndCurrentY) { ImGui::Text("Current X: %d", mColorX); ImGui::Text("Current Y: %d", mColorY); } else if (mColorMode == ColorControl::ColorModeEnum::kColorTemperatureMireds) { ImGui::Text("Color Temperature Mireds: %d", mColorTemperatureMireds); } ImGui::Unindent(); ImGui::End(); } } // namespace Windows } // namespace Ui } // namespace example