blob: fbfcdda48284a12e2790f27cfa81f66b25474e29 [file] [log] [blame]
/*
*
* 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 <imgui.h>
#include <math.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-enums.h>
#include <app/clusters/level-control/level-control.h>
#include <app/clusters/on-off-server/on-off-server.h>
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<float>(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())
{
EmberAfStatus status = OnOffServer::Instance().setOnOffValue(
mEndpointId, mTargetLightIsOn.Value() ? OnOff::Commands::On::Id : OnOff::Commands::Off::Id,
false /* initiatedByLevelChange */);
if (status != EMBER_ZCL_STATUS_SUCCESS)
{
ChipLogError(AppServer, "Failed to set on/off value: %d", 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::LevelControlOptions::kExecuteIfOff);
data.optionsOverride.Set(LevelControl::LevelControlOptions::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 == EMBER_ZCL_COLOR_MODE_CURRENT_HUE_AND_CURRENT_SATURATION)
? "Hue/Saturation"
: (mColorMode == EMBER_ZCL_COLOR_MODE_CURRENT_X_AND_CURRENT_Y)
? "X/Y"
: (mColorMode == EMBER_ZCL_COLOR_MODE_COLOR_TEMPERATURE) ? "Temperature/Mireds" : "UNKNOWN";
ImGui::Text("Mode: %s", mode);
if (mColorMode == EMBER_ZCL_COLOR_MODE_CURRENT_HUE_AND_CURRENT_SATURATION)
{
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 == EMBER_ZCL_COLOR_MODE_CURRENT_X_AND_CURRENT_Y)
{
ImGui::Text("Current X: %d", mColorX);
ImGui::Text("Current Y: %d", mColorY);
}
else if (mColorMode == EMBER_ZCL_COLOR_MODE_COLOR_TEMPERATURE)
{
ImGui::Text("Color Temperature Mireds: %d", mColorTemperatureMireds);
}
ImGui::Unindent();
ImGui::End();
}
} // namespace Windows
} // namespace Ui
} // namespace example