Enhance DaliDT8 and Bridge: add support for RGBW, RGBCW, and RGBWAF operations, including temporary dim levels and control handling
Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -117,6 +117,10 @@ enum class BridgeOperation {
|
||||
dt1GetRatedDuration = 77,
|
||||
dt1GetExtendedVersion = 78,
|
||||
dt1GetEmergencyDeviceType = 79,
|
||||
setColourRGBW = 80,
|
||||
setColourRGBCW = 81,
|
||||
setColourRGBWAF = 82,
|
||||
setTemporaryRGBWAFDimLevels = 83,
|
||||
};
|
||||
|
||||
enum class BridgeValueEncoding {
|
||||
|
||||
@@ -60,10 +60,13 @@ struct SceneColorReport {
|
||||
int colorTypeValue = 0;
|
||||
std::vector<double> xy;
|
||||
std::optional<int> colorTemperature;
|
||||
std::vector<int> rgbwaf;
|
||||
std::optional<int> rgbwafControl;
|
||||
|
||||
ColorType colorType() const { return ColorType(colorTypeValue); }
|
||||
bool hasXy() const { return xy.size() == 2; }
|
||||
bool hasColorTemperature() const { return colorTemperature.has_value(); }
|
||||
bool hasRgbwaf() const { return rgbwaf.size() == 6; }
|
||||
};
|
||||
|
||||
struct Dt8LevelColorReport {
|
||||
@@ -71,16 +74,21 @@ struct Dt8LevelColorReport {
|
||||
int colorTypeValue = 0;
|
||||
std::vector<double> xy;
|
||||
std::optional<int> colorTemperature;
|
||||
std::vector<int> rgbwaf;
|
||||
std::optional<int> rgbwafControl;
|
||||
|
||||
ColorType colorType() const { return ColorType(colorTypeValue); }
|
||||
bool hasXy() const { return xy.size() == 2; }
|
||||
bool hasColorTemperature() const { return colorTemperature.has_value(); }
|
||||
bool hasRgbwaf() const { return rgbwaf.size() == 6; }
|
||||
};
|
||||
|
||||
enum class Dt8SceneStoreColorMode {
|
||||
disabled,
|
||||
colorTemperature,
|
||||
rgb,
|
||||
rgbw,
|
||||
rgbcw,
|
||||
};
|
||||
|
||||
class DaliDT8 {
|
||||
@@ -113,6 +121,8 @@ class DaliDT8 {
|
||||
bool setTemporaryRGBDimLevels(int a, int r, int g, int b);
|
||||
bool setTemporaryWAFDimLevels(int a, int w, int amber, int freecolour);
|
||||
bool setTemporaryRGBWAFControl(int a, int control);
|
||||
bool setTemporaryRGBWAFDimLevels(int a, int r, int g, int b, int w, int amber,
|
||||
int freecolour, int control);
|
||||
bool setTemporaryColourMask(int a);
|
||||
bool copyReportToTemporary(int a);
|
||||
|
||||
@@ -129,6 +139,10 @@ class DaliDT8 {
|
||||
std::optional<int> getColourRaw(int a, int type);
|
||||
std::vector<double> getColour(int a);
|
||||
bool setColourRGB(int addr, int r, int g, int b);
|
||||
bool setColourRGBW(int addr, int r, int g, int b, int w);
|
||||
bool setColourRGBCW(int addr, int r, int g, int b, int coolWhite, int warmWhite);
|
||||
bool setColourRGBWAF(int addr, int r, int g, int b, int w, int amber, int freecolour,
|
||||
int control = -1);
|
||||
std::vector<int> getColourRGB(int a);
|
||||
|
||||
bool activateTemporaryColour(int a);
|
||||
@@ -189,6 +203,8 @@ class DaliDT8 {
|
||||
bool storeSceneSnapshot(int address, int scene, int brightness,
|
||||
Dt8SceneStoreColorMode colorMode = Dt8SceneStoreColorMode::disabled,
|
||||
int colorTemperature = 0, int red = 0, int green = 0, int blue = 0,
|
||||
int white = 0, int amber = 0, int freecolour = 255,
|
||||
int rgbwafControl = -1,
|
||||
int gateway = -1);
|
||||
bool storePowerOnLevelSnapshot(int address, int level);
|
||||
bool storeSystemFailureLevelSnapshot(int address, int level);
|
||||
@@ -208,6 +224,7 @@ class DaliDT8 {
|
||||
|
||||
private:
|
||||
std::optional<Dt8LevelColorReport> buildLevelColorReport(int a, std::optional<int> level);
|
||||
std::vector<int> getReportRGBWAF(int a);
|
||||
|
||||
DaliBase& base_;
|
||||
};
|
||||
|
||||
+69
-1
@@ -680,9 +680,13 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
|
||||
case BridgeOperation::setColorTemperatureRaw:
|
||||
case BridgeOperation::setColourXY:
|
||||
case BridgeOperation::setColourRGB:
|
||||
case BridgeOperation::setColourRGBW:
|
||||
case BridgeOperation::setColourRGBCW:
|
||||
case BridgeOperation::setColourRGBWAF:
|
||||
case BridgeOperation::setTemporaryColourTemperature:
|
||||
case BridgeOperation::setTemporaryColourXY:
|
||||
case BridgeOperation::setTemporaryRGBDimLevels:
|
||||
case BridgeOperation::setTemporaryRGBWAFDimLevels:
|
||||
case BridgeOperation::setTemporaryColourMask:
|
||||
case BridgeOperation::activateTemporaryColour:
|
||||
case BridgeOperation::copyReportToTemporary: {
|
||||
@@ -724,6 +728,43 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
|
||||
return result;
|
||||
}
|
||||
result.ok = dt8_.setColourRGB(address.value(), r.value(), g.value(), b.value());
|
||||
} else if (operation == BridgeOperation::setColourRGBW) {
|
||||
const auto r = intParam(request, {"red", "r"});
|
||||
const auto g = intParam(request, {"green", "g"});
|
||||
const auto b = intParam(request, {"blue", "b"});
|
||||
const auto w = intParam(request, {"white", "w"});
|
||||
if (!r.has_value() || !g.has_value() || !b.has_value() || !w.has_value()) {
|
||||
result.error = "missing rgbw";
|
||||
return result;
|
||||
}
|
||||
result.ok = dt8_.setColourRGBW(address.value(), r.value(), g.value(), b.value(), w.value());
|
||||
} else if (operation == BridgeOperation::setColourRGBCW) {
|
||||
const auto r = intParam(request, {"red", "r"});
|
||||
const auto g = intParam(request, {"green", "g"});
|
||||
const auto b = intParam(request, {"blue", "b"});
|
||||
const auto cw = intParam(request, {"coolWhite", "cool_white", "cw", "white", "w"});
|
||||
const auto ww = intParam(request, {"warmWhite", "warm_white", "ww", "amber", "a"});
|
||||
if (!r.has_value() || !g.has_value() || !b.has_value() || !cw.has_value() ||
|
||||
!ww.has_value()) {
|
||||
result.error = "missing rgbcw";
|
||||
return result;
|
||||
}
|
||||
result.ok = dt8_.setColourRGBCW(address.value(), r.value(), g.value(), b.value(),
|
||||
cw.value(), ww.value());
|
||||
} else if (operation == BridgeOperation::setColourRGBWAF) {
|
||||
const auto r = intParam(request, {"red", "r"});
|
||||
const auto g = intParam(request, {"green", "g"});
|
||||
const auto b = intParam(request, {"blue", "b"});
|
||||
const auto w = intParam(request, {"white", "w"});
|
||||
if (!r.has_value() || !g.has_value() || !b.has_value() || !w.has_value()) {
|
||||
result.error = "missing rgbwaf";
|
||||
return result;
|
||||
}
|
||||
result.ok = dt8_.setColourRGBWAF(
|
||||
address.value(), r.value(), g.value(), b.value(), w.value(),
|
||||
intParam(request, {"amber", "a"}).value_or(255),
|
||||
intParam(request, {"freecolour", "freeColor", "f"}).value_or(255),
|
||||
intParam(request, {"control", "rgbwafControl", "rgbwaf_control"}).value_or(-1));
|
||||
} else if (operation == BridgeOperation::setTemporaryColourTemperature) {
|
||||
const auto value = intParam(request, {"colorTemperature", "colourTemperature", "kelvin", "value"});
|
||||
if (!value.has_value()) {
|
||||
@@ -749,6 +790,20 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
|
||||
return result;
|
||||
}
|
||||
result.ok = dt8_.setTemporaryRGBDimLevels(address.value(), r.value(), g.value(), b.value());
|
||||
} else if (operation == BridgeOperation::setTemporaryRGBWAFDimLevels) {
|
||||
const auto r = intParam(request, {"red", "r"});
|
||||
const auto g = intParam(request, {"green", "g"});
|
||||
const auto b = intParam(request, {"blue", "b"});
|
||||
const auto w = intParam(request, {"white", "w"});
|
||||
if (!r.has_value() || !g.has_value() || !b.has_value() || !w.has_value()) {
|
||||
result.error = "missing rgbwaf";
|
||||
return result;
|
||||
}
|
||||
result.ok = dt8_.setTemporaryRGBWAFDimLevels(
|
||||
address.value(), r.value(), g.value(), b.value(), w.value(),
|
||||
intParam(request, {"amber", "a"}).value_or(255),
|
||||
intParam(request, {"freecolour", "freeColor", "f"}).value_or(255),
|
||||
intParam(request, {"control", "rgbwafControl", "rgbwaf_control"}).value_or(0x3F));
|
||||
} else if (operation == BridgeOperation::setTemporaryColourMask) {
|
||||
result.ok = dt8_.setTemporaryColourMask(address.value());
|
||||
} else if (operation == BridgeOperation::activateTemporaryColour) {
|
||||
@@ -773,8 +828,17 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
|
||||
mode = Dt8SceneStoreColorMode::colorTemperature;
|
||||
} else if (modeName == "rgb") {
|
||||
mode = Dt8SceneStoreColorMode::rgb;
|
||||
} else if (modeName == "rgbw") {
|
||||
mode = Dt8SceneStoreColorMode::rgbw;
|
||||
} else if (modeName == "rgbcw" || modeName == "rgb_cw") {
|
||||
mode = Dt8SceneStoreColorMode::rgbcw;
|
||||
} else if (intParam(request, {"colorTemperature", "colourTemperature"}).has_value()) {
|
||||
mode = Dt8SceneStoreColorMode::colorTemperature;
|
||||
} else if (intParam(request, {"coolWhite", "cool_white", "cw"}).has_value() ||
|
||||
intParam(request, {"warmWhite", "warm_white", "ww", "amber"}).has_value()) {
|
||||
mode = Dt8SceneStoreColorMode::rgbcw;
|
||||
} else if (intParam(request, {"white", "w"}).has_value()) {
|
||||
mode = Dt8SceneStoreColorMode::rgbw;
|
||||
} else if (intParam(request, {"red", "r"}).has_value()) {
|
||||
mode = Dt8SceneStoreColorMode::rgb;
|
||||
}
|
||||
@@ -782,7 +846,11 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
|
||||
address.value(), scene.value(), brightness.value(), mode,
|
||||
intParam(request, {"colorTemperature", "colourTemperature"}).value_or(0),
|
||||
intParam(request, {"red", "r"}).value_or(0), intParam(request, {"green", "g"}).value_or(0),
|
||||
intParam(request, {"blue", "b"}).value_or(0));
|
||||
intParam(request, {"blue", "b"}).value_or(0),
|
||||
intParam(request, {"white", "w", "coolWhite", "cool_white", "cw"}).value_or(0),
|
||||
intParam(request, {"amber", "a", "warmWhite", "warm_white", "ww"}).value_or(0),
|
||||
intParam(request, {"freecolour", "freeColor", "f"}).value_or(255),
|
||||
intParam(request, {"control", "rgbwafControl", "rgbwaf_control"}).value_or(-1));
|
||||
break;
|
||||
}
|
||||
case BridgeOperation::storeDt8PowerOnLevelSnapshot:
|
||||
|
||||
@@ -358,12 +358,20 @@ const char* bridgeOperationToString(BridgeOperation operation) {
|
||||
return "set_colour_xy";
|
||||
case BridgeOperation::setColourRGB:
|
||||
return "set_colour_rgb";
|
||||
case BridgeOperation::setColourRGBW:
|
||||
return "set_colour_rgbw";
|
||||
case BridgeOperation::setColourRGBCW:
|
||||
return "set_colour_rgbcw";
|
||||
case BridgeOperation::setColourRGBWAF:
|
||||
return "set_colour_rgbwaf";
|
||||
case BridgeOperation::setTemporaryColourTemperature:
|
||||
return "set_temporary_colour_temperature";
|
||||
case BridgeOperation::setTemporaryColourXY:
|
||||
return "set_temporary_colour_xy";
|
||||
case BridgeOperation::setTemporaryRGBDimLevels:
|
||||
return "set_temporary_rgb_dim_levels";
|
||||
case BridgeOperation::setTemporaryRGBWAFDimLevels:
|
||||
return "set_temporary_rgbwaf_dim_levels";
|
||||
case BridgeOperation::setTemporaryColourMask:
|
||||
return "set_temporary_colour_mask";
|
||||
case BridgeOperation::activateTemporaryColour:
|
||||
@@ -505,6 +513,9 @@ BridgeOperation bridgeOperationFromString(const std::string& value) {
|
||||
if (normalized == "set_color_temperature_raw") return BridgeOperation::setColorTemperatureRaw;
|
||||
if (normalized == "set_colour_xy" || normalized == "set_color_xy") return BridgeOperation::setColourXY;
|
||||
if (normalized == "set_colour_rgb" || normalized == "set_color_rgb") return BridgeOperation::setColourRGB;
|
||||
if (normalized == "set_colour_rgbw" || normalized == "set_color_rgbw") return BridgeOperation::setColourRGBW;
|
||||
if (normalized == "set_colour_rgbcw" || normalized == "set_color_rgbcw") return BridgeOperation::setColourRGBCW;
|
||||
if (normalized == "set_colour_rgbwaf" || normalized == "set_color_rgbwaf") return BridgeOperation::setColourRGBWAF;
|
||||
if (normalized == "set_temporary_colour_temperature" || normalized == "set_temporary_color_temperature") {
|
||||
return BridgeOperation::setTemporaryColourTemperature;
|
||||
}
|
||||
@@ -512,6 +523,7 @@ BridgeOperation bridgeOperationFromString(const std::string& value) {
|
||||
return BridgeOperation::setTemporaryColourXY;
|
||||
}
|
||||
if (normalized == "set_temporary_rgb_dim_levels") return BridgeOperation::setTemporaryRGBDimLevels;
|
||||
if (normalized == "set_temporary_rgbwaf_dim_levels") return BridgeOperation::setTemporaryRGBWAFDimLevels;
|
||||
if (normalized == "set_temporary_colour_mask" || normalized == "set_temporary_color_mask") {
|
||||
return BridgeOperation::setTemporaryColourMask;
|
||||
}
|
||||
|
||||
+64
-1
@@ -6,6 +6,10 @@
|
||||
#include <cmath>
|
||||
|
||||
namespace {
|
||||
constexpr int kRgbWControl = 0x0F;
|
||||
constexpr int kRgbCwControl = 0x1F;
|
||||
constexpr int kRgbWafControl = 0x3F;
|
||||
|
||||
int colourTempLimitQuerySelector(int limitType) {
|
||||
switch (limitType & 0xFF) {
|
||||
case 0:
|
||||
@@ -222,6 +226,12 @@ bool DaliDT8::setTemporaryRGBWAFControl(int a, int control) {
|
||||
base_.sendExtCmd(addr, DALI_CMD_DT8_SET_TEMPORARY_RGBWAF_CONTROL);
|
||||
}
|
||||
|
||||
bool DaliDT8::setTemporaryRGBWAFDimLevels(int a, int r, int g, int b, int w, int amber,
|
||||
int freecolour, int control) {
|
||||
return setTemporaryRGBDimLevels(a, r, g, b) && setTemporaryWAFDimLevels(a, w, amber, freecolour) &&
|
||||
setTemporaryRGBWAFControl(a, control);
|
||||
}
|
||||
|
||||
bool DaliDT8::setTemporaryColourMask(int a) {
|
||||
if (setTemporaryRGBDimLevels(a, 255, 255, 255)) return true;
|
||||
if (base_.setDTR(0xFF) && base_.setDTR1(0xFF) && base_.dtSelect(8) && base_.setDTRAsColourTemp(a)) {
|
||||
@@ -335,6 +345,21 @@ bool DaliDT8::setColourRGB(int addr, int r, int g, int b) {
|
||||
return setColour(addr, xy[0], xy[1]);
|
||||
}
|
||||
|
||||
bool DaliDT8::setColourRGBW(int addr, int r, int g, int b, int w) {
|
||||
return setColourRGBWAF(addr, r, g, b, w, 255, 255, kRgbWControl);
|
||||
}
|
||||
|
||||
bool DaliDT8::setColourRGBCW(int addr, int r, int g, int b, int coolWhite, int warmWhite) {
|
||||
return setColourRGBWAF(addr, r, g, b, coolWhite, warmWhite, 255, kRgbCwControl);
|
||||
}
|
||||
|
||||
bool DaliDT8::setColourRGBWAF(int addr, int r, int g, int b, int w, int amber, int freecolour,
|
||||
int control) {
|
||||
const int rgbwafControl = control < 0 ? kRgbWafControl : control;
|
||||
return setTemporaryRGBWAFDimLevels(addr, r, g, b, w, amber, freecolour, rgbwafControl) &&
|
||||
activateTemporaryColour(addr);
|
||||
}
|
||||
|
||||
std::vector<int> DaliDT8::getColourRGB(int a) {
|
||||
const auto xy = getColour(a);
|
||||
if (xy.empty()) return {};
|
||||
@@ -344,7 +369,8 @@ std::vector<int> DaliDT8::getColourRGB(int a) {
|
||||
|
||||
bool DaliDT8::storeSceneSnapshot(int address, int scene, int brightness,
|
||||
Dt8SceneStoreColorMode colorMode, int colorTemperature, int red,
|
||||
int green, int blue, int /*gateway*/) {
|
||||
int green, int blue, int white, int amber, int freecolour,
|
||||
int rgbwafControl, int /*gateway*/) {
|
||||
const int sceneBrightness = std::clamp(brightness, 0, 255);
|
||||
const int sceneIndex = std::clamp(scene, 0, 15);
|
||||
|
||||
@@ -363,6 +389,16 @@ bool DaliDT8::storeSceneSnapshot(int address, int scene, int brightness,
|
||||
if (!setTemporaryColourXY(address, xy[0], xy[1])) return false;
|
||||
break;
|
||||
}
|
||||
case Dt8SceneStoreColorMode::rgbw: {
|
||||
const int control = rgbwafControl < 0 ? kRgbWControl : rgbwafControl;
|
||||
if (!setTemporaryRGBWAFDimLevels(address, red, green, blue, white, 255, 255, control)) return false;
|
||||
break;
|
||||
}
|
||||
case Dt8SceneStoreColorMode::rgbcw: {
|
||||
const int control = rgbwafControl < 0 ? kRgbCwControl : rgbwafControl;
|
||||
if (!setTemporaryRGBWAFDimLevels(address, red, green, blue, white, amber, freecolour, control)) return false;
|
||||
break;
|
||||
}
|
||||
case Dt8SceneStoreColorMode::disabled:
|
||||
if (!setTemporaryColourMask(address)) return false;
|
||||
break;
|
||||
@@ -451,6 +487,21 @@ std::optional<int> DaliDT8::getReportFreecolourDimLevel(int a) { return getColou
|
||||
std::optional<int> DaliDT8::getReportRGBWAFControl(int a) { return getColourRaw(a, 239); }
|
||||
std::optional<int> DaliDT8::getReportColourType(int a) { return getColourRaw(a, 240); }
|
||||
|
||||
std::vector<int> DaliDT8::getReportRGBWAF(int a) {
|
||||
const auto red = getReportRedDimLevel(a);
|
||||
const auto green = getReportGreenDimLevel(a);
|
||||
const auto blue = getReportBlueDimLevel(a);
|
||||
const auto white = getReportWhiteDimLevel(a);
|
||||
const auto amber = getReportAmberDimLevel(a);
|
||||
const auto freecolour = getReportFreecolourDimLevel(a);
|
||||
if (!red.has_value() && !green.has_value() && !blue.has_value() && !white.has_value() &&
|
||||
!amber.has_value() && !freecolour.has_value()) {
|
||||
return {};
|
||||
}
|
||||
return {red.value_or(255), green.value_or(255), blue.value_or(255),
|
||||
white.value_or(255), amber.value_or(255), freecolour.value_or(255)};
|
||||
}
|
||||
|
||||
std::vector<double> DaliDT8::getReportColour(int a) {
|
||||
const auto x = getReportXRaw(a);
|
||||
const auto y = getReportYRaw(a);
|
||||
@@ -502,6 +553,12 @@ std::optional<SceneColorReport> DaliDT8::getSceneColorReport(int a, int sense, i
|
||||
return report;
|
||||
}
|
||||
|
||||
if (colorType.rgbWaf()) {
|
||||
report.rgbwaf = getReportRGBWAF(a);
|
||||
report.rgbwafControl = getReportRGBWAFControl(a);
|
||||
return report;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
@@ -529,6 +586,12 @@ std::optional<Dt8LevelColorReport> DaliDT8::buildLevelColorReport(int a, std::op
|
||||
return report;
|
||||
}
|
||||
|
||||
if (colorType.rgbWaf()) {
|
||||
report.rgbwaf = getReportRGBWAF(a);
|
||||
report.rgbwafControl = getReportRGBWAFControl(a);
|
||||
return report;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user