From c60ef2ccde217c8e58306471eb4c0317441f885a Mon Sep 17 00:00:00 2001 From: Tony Date: Fri, 29 May 2026 11:32:10 +0800 Subject: [PATCH] feat: Enhance DALI Gateway with RGBW and RGBCW support - Added support for RGBW and RGBCW color modes in the DALI Gateway. - Updated JSON color mode parsing to handle new color types. - Extended the StoreDt8SceneSnapshot function to include white, amber, and free color parameters. - Introduced new methods in DaliGatewayBridge for setting RGBW, RGBCW, and RGBWAF colors. - Modified KnxDaliChannel to send RGBW and RGBCW colors based on the color type. - Updated parameter types and definitions in the KNX product XML files to accommodate new color modes. - Enhanced README with migration details and validation instructions. Signed-off-by: Tony --- apps/gateway/main/Kconfig.projbuild | 2 +- .../dali_domain/include/dali_domain.hpp | 10 ++- components/dali_domain/src/dali_domain.cpp | 59 ++++++++++++++- .../gateway_bridge/src/gateway_bridge.cpp | 23 +++++- .../knx_dali_gw/include/dali_gateway_bridge.h | 5 ++ components/knx_dali_gw/include/knxprod.h | 10 ++- .../knxprod/DALI-GW-address.templ.xml | 52 +++++++++++++ .../knxprod/DALI-GW-group.share.xml | 25 +++++++ .../knxprod/DALI-GW-group.templ.xml | 52 +++++++++++++ .../knx_dali_gw/knxprod/DALI-GW-hcl.share.xml | 21 ++++++ .../knx_dali_gw/knxprod/DALI-GW-hcl.templ.xml | 36 +++++++++ .../knx_dali_gw/knxprod/DALI-GW.base.xml | 75 +++++++++++++++++++ .../knx_dali_gw/knxprod/DALI-GW.share.xml | 53 +++++++++++++ components/knx_dali_gw/knxprod/DALI-GW.xml | 28 +++++++ components/knx_dali_gw/knxprod/README.md | 48 ++++++++++++ .../knx_dali_gw/src/dali_gateway_bridge.cpp | 19 +++++ .../knx_dali_gw/src/knx_dali_channel.cpp | 40 ++++++++-- components/knx_dali_gw/src/knx_dali_channel.h | 2 +- components/knx_dali_gw/src/knx_dali_gw.cpp | 12 ++- 19 files changed, 554 insertions(+), 18 deletions(-) create mode 100644 components/knx_dali_gw/knxprod/DALI-GW-address.templ.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW-group.share.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW-group.templ.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW-hcl.share.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW-hcl.templ.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW.base.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW.share.xml create mode 100644 components/knx_dali_gw/knxprod/DALI-GW.xml create mode 100644 components/knx_dali_gw/knxprod/README.md diff --git a/apps/gateway/main/Kconfig.projbuild b/apps/gateway/main/Kconfig.projbuild index 526f5da..f3c0e60 100644 --- a/apps/gateway/main/Kconfig.projbuild +++ b/apps/gateway/main/Kconfig.projbuild @@ -1991,7 +1991,7 @@ config GATEWAY_KNX_OEM_APPLICATION_VERSION hex "KNX OEM application version" depends on GATEWAY_KNX_BRIDGE_SUPPORTED range 0x00 0xff - default 0x08 + default 0x09 help Application version advertised by the ETS-programmable KNX-DALI gateway application. Keep this in sync with MAIN_ApplicationVersion from the diff --git a/components/dali_domain/include/dali_domain.hpp b/components/dali_domain/include/dali_domain.hpp index e941787..99853f9 100644 --- a/components/dali_domain/include/dali_domain.hpp +++ b/components/dali_domain/include/dali_domain.hpp @@ -82,6 +82,8 @@ enum class DaliDt8SceneColorMode { kDisabled, kColorTemperature, kRgb, + kRgbw, + kRgbcw, }; struct DaliDomainSnapshot { @@ -158,7 +160,8 @@ class DaliDomainService { bool storeDt8SceneSnapshot(uint8_t gateway_id, int short_address, int scene, int brightness, DaliDt8SceneColorMode color_mode = DaliDt8SceneColorMode::kDisabled, int color_temperature = 0, int red = 0, int green = 0, - int blue = 0) const; + int blue = 0, int white = 0, int amber = 0, + int freecolour = 255, int rgbwaf_control = -1) const; bool storeDt8PowerOnLevelSnapshot(uint8_t gateway_id, int short_address, int level) const; bool storeDt8SystemFailureLevelSnapshot(uint8_t gateway_id, int short_address, int level) const; bool setBright(uint8_t gateway_id, int short_address, int brightness) const; @@ -166,6 +169,11 @@ class DaliDomainService { bool setColTemp(uint8_t gateway_id, int short_address, int kelvin) const; bool setColourRaw(uint8_t gateway_id, int raw_addr, int x, int y) const; bool setColourRGB(uint8_t gateway_id, int short_address, int r, int g, int b) const; + bool setColourRGBW(uint8_t gateway_id, int short_address, int r, int g, int b, int w) const; + bool setColourRGBCW(uint8_t gateway_id, int short_address, int r, int g, int b, + int cool_white, int warm_white) const; + bool setColourRGBWAF(uint8_t gateway_id, int short_address, int r, int g, int b, int w, + int amber, int freecolour, int control = -1) const; bool on(uint8_t gateway_id, int short_address) const; bool off(uint8_t gateway_id, int short_address) const; bool off(int short_address) const; diff --git a/components/dali_domain/src/dali_domain.cpp b/components/dali_domain/src/dali_domain.cpp index 2275304..0e2fd7a 100644 --- a/components/dali_domain/src/dali_domain.cpp +++ b/components/dali_domain/src/dali_domain.cpp @@ -107,12 +107,30 @@ void PutOptionalNumber(DaliDomainSnapshot& snapshot, const char* name, } } +template +void PutRgbwafReport(DaliDomainSnapshot& snapshot, const Report& report) { + if (!report.hasRgbwaf()) { + return; + } + snapshot.int_arrays["rgbwaf"] = report.rgbwaf; + snapshot.int_arrays["rgbw"] = {report.rgbwaf[0], report.rgbwaf[1], report.rgbwaf[2], report.rgbwaf[3]}; + snapshot.int_arrays["rgbcw"] = {report.rgbwaf[0], report.rgbwaf[1], report.rgbwaf[2], + report.rgbwaf[3], report.rgbwaf[4]}; + if (report.rgbwafControl.has_value()) { + snapshot.ints["rgbwafControl"] = report.rgbwafControl.value(); + } +} + Dt8SceneStoreColorMode ToDaliCppColorMode(DaliDt8SceneColorMode color_mode) { switch (color_mode) { case DaliDt8SceneColorMode::kColorTemperature: return Dt8SceneStoreColorMode::colorTemperature; case DaliDt8SceneColorMode::kRgb: return Dt8SceneStoreColorMode::rgb; + case DaliDt8SceneColorMode::kRgbw: + return Dt8SceneStoreColorMode::rgbw; + case DaliDt8SceneColorMode::kRgbcw: + return Dt8SceneStoreColorMode::rgbcw; case DaliDt8SceneColorMode::kDisabled: default: return Dt8SceneStoreColorMode::disabled; @@ -1099,6 +1117,7 @@ std::optional DaliDomainService::dt8SceneColorReport( if (report->hasXy()) { snapshot.number_arrays["xy"] = report->xy; } + PutRgbwafReport(snapshot, report.value()); return snapshot; } @@ -1122,6 +1141,7 @@ std::optional DaliDomainService::dt8PowerOnLevelColorReport( if (report->hasXy()) { snapshot.number_arrays["xy"] = report->xy; } + PutRgbwafReport(snapshot, report.value()); return snapshot; } @@ -1145,6 +1165,7 @@ std::optional DaliDomainService::dt8SystemFailureLevelColorR if (report->hasXy()) { snapshot.number_arrays["xy"] = report->xy; } + PutRgbwafReport(snapshot, report.value()); return snapshot; } @@ -1152,7 +1173,8 @@ bool DaliDomainService::storeDt8SceneSnapshot(uint8_t gateway_id, int short_addr int brightness, DaliDt8SceneColorMode color_mode, int color_temperature, int red, int green, - int blue) const { + int blue, int white, int amber, int freecolour, + int rgbwaf_control) const { const auto* channel = findChannelByGateway(gateway_id); if (channel == nullptr || channel->dali == nullptr) { return false; @@ -1160,7 +1182,8 @@ bool DaliDomainService::storeDt8SceneSnapshot(uint8_t gateway_id, int short_addr markBusActivity(gateway_id); return channel->dali->dt8.storeSceneSnapshot(short_address, scene, brightness, ToDaliCppColorMode(color_mode), color_temperature, - red, green, blue); + red, green, blue, white, amber, freecolour, + rgbwaf_control); } bool DaliDomainService::storeDt8PowerOnLevelSnapshot(uint8_t gateway_id, int short_address, @@ -1229,6 +1252,38 @@ bool DaliDomainService::setColourRGB(uint8_t gateway_id, int short_address, int return channel->dali->dt8.setColourRGB(short_address, r, g, b); } +bool DaliDomainService::setColourRGBW(uint8_t gateway_id, int short_address, int r, int g, + int b, int w) const { + const auto* channel = findChannelByGateway(gateway_id); + if (channel == nullptr || channel->dali == nullptr) { + return false; + } + markBusActivity(gateway_id); + return channel->dali->dt8.setColourRGBW(short_address, r, g, b, w); +} + +bool DaliDomainService::setColourRGBCW(uint8_t gateway_id, int short_address, int r, int g, + int b, int cool_white, int warm_white) const { + const auto* channel = findChannelByGateway(gateway_id); + if (channel == nullptr || channel->dali == nullptr) { + return false; + } + markBusActivity(gateway_id); + return channel->dali->dt8.setColourRGBCW(short_address, r, g, b, cool_white, warm_white); +} + +bool DaliDomainService::setColourRGBWAF(uint8_t gateway_id, int short_address, int r, int g, + int b, int w, int amber, int freecolour, + int control) const { + const auto* channel = findChannelByGateway(gateway_id); + if (channel == nullptr || channel->dali == nullptr) { + return false; + } + markBusActivity(gateway_id); + return channel->dali->dt8.setColourRGBWAF(short_address, r, g, b, w, amber, freecolour, + control); +} + bool DaliDomainService::on(uint8_t gateway_id, int short_address) const { const auto* channel = findChannelByGateway(gateway_id); if (channel == nullptr || channel->dali == nullptr) { diff --git a/components/gateway_bridge/src/gateway_bridge.cpp b/components/gateway_bridge/src/gateway_bridge.cpp index fe95e1d..9a7b9f7 100644 --- a/components/gateway_bridge/src/gateway_bridge.cpp +++ b/components/gateway_bridge/src/gateway_bridge.cpp @@ -1020,6 +1020,12 @@ DaliDt8SceneColorMode JsonColorMode(const cJSON* root) { if (item->valueint == 2) { return DaliDt8SceneColorMode::kRgb; } + if (item->valueint == 3) { + return DaliDt8SceneColorMode::kRgbw; + } + if (item->valueint == 4) { + return DaliDt8SceneColorMode::kRgbcw; + } return DaliDt8SceneColorMode::kDisabled; } if (!cJSON_IsString(item) || item->valuestring == nullptr) { @@ -1032,6 +1038,12 @@ DaliDt8SceneColorMode JsonColorMode(const cJSON* root) { if (mode == "rgb") { return DaliDt8SceneColorMode::kRgb; } + if (mode == "rgbw") { + return DaliDt8SceneColorMode::kRgbw; + } + if (mode == "rgbcw" || mode == "rgbWwCw" || mode == "rgb_cw") { + return DaliDt8SceneColorMode::kRgbcw; + } return DaliDt8SceneColorMode::kDisabled; } @@ -1049,6 +1061,15 @@ GatewayBridgeHttpResponse StoreDt8SceneSnapshot(DaliDomainService& domain, uint8 const int red = JsonIntAny(root, "red", "r").value_or(0); const int green = JsonIntAny(root, "green", "g").value_or(0); const int blue = JsonIntAny(root, "blue", "b").value_or(0); + const int white = JsonIntAny(root, "white", "w") + .value_or(JsonIntAny(root, "coolWhite", "cool_white") + .value_or(JsonInt(root, "cw").value_or(0))); + const int amber = JsonIntAny(root, "amber", "a") + .value_or(JsonIntAny(root, "warmWhite", "warm_white") + .value_or(JsonInt(root, "ww").value_or(0))); + const int freecolour = JsonIntAny(root, "freecolour", "freeColor").value_or(255); + const int rgbwaf_control = JsonIntAny(root, "rgbwafControl", "rgbwaf_control") + .value_or(JsonInt(root, "control").value_or(-1)); cJSON_Delete(root); if (!address.has_value() || !scene.has_value() || !brightness.has_value() || @@ -1057,7 +1078,7 @@ GatewayBridgeHttpResponse StoreDt8SceneSnapshot(DaliDomainService& domain, uint8 } if (!domain.storeDt8SceneSnapshot(gateway_id, address.value(), scene.value(), brightness.value(), color_mode, color_temperature, red, - green, blue)) { + green, blue, white, amber, freecolour, rgbwaf_control)) { return ErrorResponse(ESP_FAIL, "failed to store DT8 scene snapshot"); } return StoredSnapshotResponse(domain.dt8SceneColorReport(gateway_id, address.value(), diff --git a/components/knx_dali_gw/include/dali_gateway_bridge.h b/components/knx_dali_gw/include/dali_gateway_bridge.h index 98f2bfd..7de7ef9 100644 --- a/components/knx_dali_gw/include/dali_gateway_bridge.h +++ b/components/knx_dali_gw/include/dali_gateway_bridge.h @@ -76,6 +76,11 @@ class DaliGatewayBridge { bool setColourTemperature(int short_address, int kelvin) const; bool setColourRGB(int short_address, uint8_t r, uint8_t g, uint8_t b) const; + bool setColourRGBW(int short_address, uint8_t r, uint8_t g, uint8_t b, uint8_t w) const; + bool setColourRGBCW(int short_address, uint8_t r, uint8_t g, uint8_t b, + uint8_t cool_white, uint8_t warm_white) const; + bool setColourRGBWAF(int short_address, uint8_t r, uint8_t g, uint8_t b, uint8_t w, + uint8_t amber, uint8_t freecolour, uint8_t control) const; std::optional dt8StatusSnapshot(int short_address) const; std::optional dt8SceneColorReport(int short_address, int scene) const; diff --git a/components/knx_dali_gw/include/knxprod.h b/components/knx_dali_gw/include/knxprod.h index 24c8a36..299932d 100644 --- a/components/knx_dali_gw/include/knxprod.h +++ b/components/knx_dali_gw/include/knxprod.h @@ -1,6 +1,10 @@ #pragma once +#include + +#if __has_include("sdkconfig.h") #include "sdkconfig.h" +#endif #ifndef CONFIG_GATEWAY_KNX_OEM_MANUFACTURER_ID #define CONFIG_GATEWAY_KNX_OEM_MANUFACTURER_ID 0x00A4 @@ -11,12 +15,12 @@ #endif #ifndef CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION -#define CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION 0x08 +#define CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION 0x09 #endif // Minimal stub for knxprod.h — generated KNX product definitions. // The full file (1796 bytes of parameters, 1439 group objects) will be -// adapted in Phase 3 to use the gateway/knx API directly. +// replaced by the OpenKNXproducer-generated header. // Product identity #define MAIN_OpenKnxId (CONFIG_GATEWAY_KNX_OEM_MANUFACTURER_ID & 0xff) @@ -45,6 +49,8 @@ enum PT_ColorType : uint8_t { PT_colorType_RGB = 1, PT_colorType_TW = 2, PT_colorType_XYY = 3, + PT_colorType_RGBW = 4, + PT_colorType_RGBCW = 5, }; enum PT_ColorSpace : uint8_t { diff --git a/components/knx_dali_gw/knxprod/DALI-GW-address.templ.xml b/components/knx_dali_gw/knxprod/DALI-GW-address.templ.xml new file mode 100644 index 0000000..42873fc --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW-address.templ.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW-group.share.xml b/components/knx_dali_gw/knxprod/DALI-GW-group.share.xml new file mode 100644 index 0000000..7896f5b --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW-group.share.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW-group.templ.xml b/components/knx_dali_gw/knxprod/DALI-GW-group.templ.xml new file mode 100644 index 0000000..bbff296 --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW-group.templ.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW-hcl.share.xml b/components/knx_dali_gw/knxprod/DALI-GW-hcl.share.xml new file mode 100644 index 0000000..df05eda --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW-hcl.share.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW-hcl.templ.xml b/components/knx_dali_gw/knxprod/DALI-GW-hcl.templ.xml new file mode 100644 index 0000000..c9b20b3 --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW-hcl.templ.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW.base.xml b/components/knx_dali_gw/knxprod/DALI-GW.base.xml new file mode 100644 index 0000000..d05f397 --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW.base.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW.share.xml b/components/knx_dali_gw/knxprod/DALI-GW.share.xml new file mode 100644 index 0000000..3d73c77 --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW.share.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/knx_dali_gw/knxprod/DALI-GW.xml b/components/knx_dali_gw/knxprod/DALI-GW.xml new file mode 100644 index 0000000..f4319c7 --- /dev/null +++ b/components/knx_dali_gw/knxprod/DALI-GW.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/knx_dali_gw/knxprod/README.md b/components/knx_dali_gw/knxprod/README.md new file mode 100644 index 0000000..70bede3 --- /dev/null +++ b/components/knx_dali_gw/knxprod/README.md @@ -0,0 +1,48 @@ +# DALI-GW KNX Product XML + +This folder contains the gateway-owned OpenKNXproducer source for the REG1-Dali KNX-DALI gateway persona. + +The source migrates the legacy Kaenx Creator database from `temp/openknx/GW-REG1-Dali/DALI-GW.ae-manu` into the gateway component so the generated product database, generated `knxprod.h`, and ESP-IDF runtime can evolve together. + +Current migration targets: + +- Manufacturer/OpenKNX id: `0xA4` +- Application number: `0x01` +- Application version: `0x09` +- Mask: `MV-07B0` +- Order number: `REG1-Dali` +- Address channels: `64` +- Group channels: `16` +- HCL curves: `3` + +The existing color type values stay stable for compatibility: + +- `HSV = 0` +- `RGB = 1` +- `TW = 2` +- `XYY = 3` +- `RGBW = 4` +- `RGBCW = 5` + +RGBW is exposed with standard DPT `251.600` (`DPT_Colour_RGBW`). RGBCW uses the same RGBW payload shape and maps the white and amber DT8 RGBWAF channels as cool-white and warm-white levels at runtime because the local KNX master database does not define a standard RGBCW datapoint subtype. + +## Validation + +Run a well-formed XML check from the repository root: + +```sh +xmllint --noout gateway/components/knx_dali_gw/knxprod/*.xml +``` + +Generate the producer header and product database artifacts with: + +```sh +OpenKNXproducer create --NoXsd \ + -h /tmp/DALI-GW-knxprod.h \ + -o /tmp/DALI-GW.knxprod \ + gateway/components/knx_dali_gw/knxprod/DALI-GW.xml +``` + +In this workspace the producer validates the XML and writes `/tmp/DALI-GW-knxprod.h`. If the local producer installation does not have an ETS converter available it prints `No ETS found, skipped knxprod creation!` and omits the `.knxprod` archive while still exiting successfully. + +The generated header must stay synchronized with the runtime identity in `gateway/apps/gateway/main/Kconfig.projbuild` and `gateway/components/knx_dali_gw/src/knx_dali_gw.cpp`. \ No newline at end of file diff --git a/components/knx_dali_gw/src/dali_gateway_bridge.cpp b/components/knx_dali_gw/src/dali_gateway_bridge.cpp index 437c89e..525d4d4 100644 --- a/components/knx_dali_gw/src/dali_gateway_bridge.cpp +++ b/components/knx_dali_gw/src/dali_gateway_bridge.cpp @@ -207,6 +207,25 @@ bool DaliGatewayBridge::setColourRGB(int short_address, uint8_t r, uint8_t g, return dali_.setColourRGB(gateway_id_, short_address, r, g, b); } +bool DaliGatewayBridge::setColourRGBW(int short_address, uint8_t r, uint8_t g, + uint8_t b, uint8_t w) const { + return dali_.setColourRGBW(gateway_id_, short_address, r, g, b, w); +} + +bool DaliGatewayBridge::setColourRGBCW(int short_address, uint8_t r, uint8_t g, + uint8_t b, uint8_t cool_white, + uint8_t warm_white) const { + return dali_.setColourRGBCW(gateway_id_, short_address, r, g, b, cool_white, + warm_white); +} + +bool DaliGatewayBridge::setColourRGBWAF(int short_address, uint8_t r, uint8_t g, + uint8_t b, uint8_t w, uint8_t amber, + uint8_t freecolour, uint8_t control) const { + return dali_.setColourRGBWAF(gateway_id_, short_address, r, g, b, w, amber, + freecolour, control); +} + std::optional DaliGatewayBridge::dt8StatusSnapshot( int short_address) const { return dali_.dt8StatusSnapshot(gateway_id_, short_address); diff --git a/components/knx_dali_gw/src/knx_dali_channel.cpp b/components/knx_dali_gw/src/knx_dali_channel.cpp index 627600d..8380559 100644 --- a/components/knx_dali_gw/src/knx_dali_channel.cpp +++ b/components/knx_dali_gw/src/knx_dali_channel.cpp @@ -132,8 +132,25 @@ void KnxDaliChannel::setDimmState(uint8_t value, bool, bool) { void KnxDaliChannel::sendColor() { if (dali_ == nullptr) return; - dali_->setColourRGB(static_cast(index_), current_color_[0], - current_color_[1], current_color_[2]); + const auto color_type = is_group_ ? ParamGRP_colorType(index_) : ParamADR_colorType(index_); + switch (color_type) { + case PT_ColorType::PT_colorType_RGBW: + dali_->setColourRGBW(static_cast(index_), current_color_[0], current_color_[1], + current_color_[2], current_color_[3]); + break; + case PT_ColorType::PT_colorType_RGBCW: + dali_->setColourRGBCW(static_cast(index_), current_color_[0], current_color_[1], + current_color_[2], current_color_[3], current_color_[4]); + break; + case PT_ColorType::PT_colorType_RGB: + case PT_ColorType::PT_colorType_HSV: + case PT_ColorType::PT_colorType_XYY: + case PT_ColorType::PT_colorType_TW: + default: + dali_->setColourRGB(static_cast(index_), current_color_[0], current_color_[1], + current_color_[2]); + break; + } } // ---- KO Handlers ---- @@ -172,12 +189,21 @@ void KnxDaliChannel::koHandleLock(GroupObject& ko) { } void KnxDaliChannel::koHandleColor(GroupObject& ko) { - KNXValue val = ko.value(); - if (true) { - // RGB packed in float or raw bytes - // Simplified: store and send - sendColor(); + const auto color_type = is_group_ ? ParamGRP_colorType(index_) : ParamADR_colorType(index_); + uint8_t* data = ko.valueRef(); + if (data != nullptr) { + current_color_[0] = data[0]; + current_color_[1] = data[1]; + current_color_[2] = data[2]; + if (color_type == PT_ColorType::PT_colorType_RGBW || + color_type == PT_ColorType::PT_colorType_RGBCW) { + current_color_[3] = data[3]; + } + if (color_type == PT_ColorType::PT_colorType_RGBCW) { + current_color_[4] = data[4]; + } } + sendColor(); } } // namespace knx_dali_gw diff --git a/components/knx_dali_gw/src/knx_dali_channel.h b/components/knx_dali_gw/src/knx_dali_channel.h index 6e8bc6f..fa42113 100644 --- a/components/knx_dali_gw/src/knx_dali_channel.h +++ b/components/knx_dali_gw/src/knx_dali_channel.h @@ -77,7 +77,7 @@ class KnxDaliChannel { bool current_state_{false}; uint8_t current_step_{0}; bool current_is_locked_{false}; - uint8_t current_color_[4]{}; + uint8_t current_color_[6]{}; // HCL uint8_t hcl_curve_{255}; diff --git a/components/knx_dali_gw/src/knx_dali_gw.cpp b/components/knx_dali_gw/src/knx_dali_gw.cpp index 13cc5bb..8bbdac7 100644 --- a/components/knx_dali_gw/src/knx_dali_gw.cpp +++ b/components/knx_dali_gw/src/knx_dali_gw.cpp @@ -21,21 +21,27 @@ constexpr const char* kTag = "knx_dali_gw"; #define CONFIG_GATEWAY_KNX_OEM_APPLICATION_NUMBER 0x0001 #endif +#ifndef CONFIG_GATEWAY_KNX_OEM_HARDWARE_ID +#define CONFIG_GATEWAY_KNX_OEM_HARDWARE_ID 0xA401 +#endif + #ifndef CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION -#define CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION 0x08 +#define CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION 0x09 #endif constexpr uint16_t kKnxOemManufacturerId = static_cast(CONFIG_GATEWAY_KNX_OEM_MANUFACTURER_ID); constexpr uint16_t kKnxOemApplicationNumber = static_cast(CONFIG_GATEWAY_KNX_OEM_APPLICATION_NUMBER); +constexpr uint16_t kKnxOemHardwareId = + static_cast(CONFIG_GATEWAY_KNX_OEM_HARDWARE_ID); constexpr uint8_t kKnxOemApplicationVersion = static_cast(CONFIG_GATEWAY_KNX_OEM_APPLICATION_VERSION); constexpr uint8_t kKnxOemHardwareType[6] = { 0x00, 0x00, - static_cast(kKnxOemManufacturerId & 0xff), - static_cast(kKnxOemApplicationNumber & 0xff), + static_cast((kKnxOemHardwareId >> 8) & 0xff), + static_cast(kKnxOemHardwareId & 0xff), kKnxOemApplicationVersion, 0x00}; constexpr uint8_t kKnxOemProgramVersion[5] = {