Fix and refactor DALI GUI multi controller sync
This commit is contained in:
parent
8feff1148a
commit
d716dec667
@ -799,7 +799,6 @@
|
||||
#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem)
|
||||
#endif
|
||||
#define USE_DALI // Add support for DALI gateway (+5k code)
|
||||
#define DALI_LIGHT_COLOR_SUPPORT // Add support for DALI DT8 RGBWAF color control (+0k7 code)
|
||||
#define USE_ESP32_TWAI // Add support for TWAI/CAN interface (+7k code)
|
||||
|
||||
#endif // FIRMWARE_TASMOTA32
|
||||
|
||||
@ -941,7 +941,6 @@
|
||||
//#define USE_WOOLIIS // Add support for Wooliis Hall Effect Coulometer or Battery capacity monitor (+1k6 code)
|
||||
//#define USE_DALI // Add support for DALI gateway (+7k6 code)
|
||||
// #define DALI_POWER_OFF_NO_FADE // Power off immediatly without fading (+0k1 code)
|
||||
// #define DALI_LIGHT_COLOR_SUPPORT // Add support for DALI DT8 RGBWAF color control (+0k7 code)
|
||||
// #define DALI_LIGHT_NO_READ_AFTER_WRITE // Use no DTR read-after-write for smooth color transitions saving 55ms / channel (-0k1 code)
|
||||
|
||||
// -- Power monitoring sensors --------------------
|
||||
|
||||
@ -65,6 +65,8 @@
|
||||
--------------------------------------------------------------------------------------------
|
||||
Version yyyymmdd Action Description
|
||||
--------------------------------------------------------------------------------------------
|
||||
1.5.0.0 20251206 update - Fix WAF GUI sync
|
||||
- Refactor GUI sync
|
||||
1.4.1.0 20251130 update - Add options to `DaliGear` and DaliGroup` to toggle specific outputs
|
||||
- Make max number of devices persistent to speed up scan response
|
||||
1.4.0.0 20251126 update - Change to TasmotaDali library
|
||||
@ -134,9 +136,7 @@
|
||||
#define DALI_TIMEOUT 20 // DALI backward frame receive timeout (ms) - Protocol = >7Te and <22Te (22 * 417us)
|
||||
#endif
|
||||
|
||||
//#define DALI_LIGHT_COLOR_SUPPORT // Support DALI DT8 RGBWAF
|
||||
//#define DALI_LIGHT_NO_READ_AFTER_WRITE // Use no DTR read-after-write for smooth color transitions (saves 55ms / channel)
|
||||
|
||||
//#define DALI_POWER_OFF_NO_FADE // Power off immediatly without fading
|
||||
|
||||
//#define DALI_DEBUG
|
||||
@ -162,6 +162,7 @@ typedef struct DliSettings_t {
|
||||
struct DALI {
|
||||
DliSettings_t Settings; // Persistent settings
|
||||
TasmotaDali *dali;
|
||||
uint32_t light_sync;
|
||||
uint8_t address;
|
||||
uint8_t command;
|
||||
uint8_t last_dimmer;
|
||||
@ -178,7 +179,6 @@ struct DALI {
|
||||
bool allow_light;
|
||||
bool last_power;
|
||||
bool power[DALI_MAX_STORED];
|
||||
bool light_sync;
|
||||
} *Dali = nullptr;
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -486,7 +486,6 @@ int DaliQueryExtendedVersionNumber(uint32_t adr, uint32_t device_type) {
|
||||
return DaliSendWaitResponse(adr | DALI_SELECTOR_BIT, 255); // DALI_xxx_QUERY_EXTENDED_VERSION_NUMBER
|
||||
}
|
||||
|
||||
#ifdef DALI_LIGHT_COLOR_SUPPORT
|
||||
uint32_t DaliQueryRGBWAF(uint32_t adr) {
|
||||
// https://www.dali-alliance.org/tech-notes/device-type-discovery.html
|
||||
uint32_t rgbwaf_channels = 0;
|
||||
@ -528,7 +527,6 @@ uint32_t DaliQueryRGBWAF(uint32_t adr) {
|
||||
}
|
||||
return rgbwaf_channels;
|
||||
}
|
||||
#endif // DALI_LIGHT_COLOR_SUPPORT
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
@ -713,6 +711,55 @@ void ResponseDali(uint32_t index) {
|
||||
|
||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
bool DaliLoopSync(uint32_t channels) {
|
||||
// Sync local light settings with DALI bus data
|
||||
if (!Dali->allow_light ||
|
||||
!Settings->sbflag1.dali_light || // DaliLight 1
|
||||
(DaliTarget2Address(Dali->Settings.target) != Dali->address)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Settings->save_data) {
|
||||
// Postpone save_data during fast color changes which results in exception 0 on ESP8266
|
||||
TasmotaGlobal.save_data_counter = 4;
|
||||
}
|
||||
|
||||
uint32_t rgb = 1; // RGB channel(s) present but not sure if powered ON
|
||||
uint32_t waf = (channels > 3) ? 1 : 0;
|
||||
for (uint32_t i = 0; i < channels; i++) {
|
||||
if (Dali->color[i] > 0) {
|
||||
if (i < 3) {
|
||||
rgb = 2; // At least one RGB channel is powered ON
|
||||
} else {
|
||||
waf = 2; // At least one WAF (CCT) channel is powered ON
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((2 == rgb) || (2 == waf)) {
|
||||
uint8_t color[LST_MAX] = {}; // Init as 0
|
||||
for (uint32_t i = 0; i < channels; i++) {
|
||||
if (i < 3) {
|
||||
color[i] = (2 == rgb) ? Dali->color[i] : Light.current_color[i];
|
||||
} else {
|
||||
color[i] = (2 == waf) ? Dali->color[i] : Light.current_color[i];
|
||||
}
|
||||
}
|
||||
Dali->light_sync = millis(); // Block local loop
|
||||
light_controller.changeChannels(color);
|
||||
}
|
||||
Dali->light_sync = millis(); // Block local loop
|
||||
ExecuteCommandPower(LightDevice(), (2 == rgb) ? 9 : 8, SRC_SWITCH);
|
||||
if (waf) {
|
||||
Dali->light_sync = millis(); // Block local loop
|
||||
ExecuteCommandPower(LightDevice() +1, (2 == waf) ? 9 : 8, SRC_SWITCH);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // USE_LIGHT
|
||||
|
||||
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
|
||||
|
||||
void DaliLoop(void) {
|
||||
while (Dali->dali->available()) {
|
||||
uint32_t queue = Dali->dali->available();
|
||||
@ -733,7 +780,6 @@ void DaliLoop(void) {
|
||||
Dali->command = frame.data &0xFF;
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef DALI_LIGHT_COLOR_SUPPORT
|
||||
if (DALI_102_SET_DTR0 == Dali->address) { Dali->dtr[0] = Dali->command; } // Might be Red / White
|
||||
else if (DALI_102_SET_DTR1 == Dali->address) { Dali->dtr[1] = Dali->command; } // Might be Green / Amber
|
||||
else if (DALI_102_SET_DTR2 == Dali->address) { Dali->dtr[2] = Dali->command; } // Might be Blue
|
||||
@ -742,7 +788,7 @@ void DaliLoop(void) {
|
||||
Dali->color[1] = Dali->dtr[1]; // Green
|
||||
Dali->color[2] = Dali->dtr[2]; // Blue
|
||||
}
|
||||
else if (DALI_209_SET_TEMPORARY_RGB_DIMLEVEL == Dali->command) {
|
||||
else if (DALI_209_SET_TEMPORARY_WAF_DIMLEVEL == Dali->command) {
|
||||
Dali->color[3] = Dali->dtr[0]; // Cold White
|
||||
Dali->color[4] = Dali->dtr[1]; // Warm White (Amber)
|
||||
}
|
||||
@ -750,55 +796,18 @@ void DaliLoop(void) {
|
||||
uint32_t channels = Dali->Settings.light_type -8;
|
||||
if ((Dali->target_rgbwaf > 0) && (channels > 0)) { // Color control
|
||||
Dali->address &= 0xFE; // Reset DALI_SELECTOR_BIT set
|
||||
if (Dali->allow_light && (DaliTarget2Address(Dali->Settings.target) == Dali->address)) {
|
||||
if (Settings->sbflag1.dali_light) { // DaliLight 1
|
||||
uint32_t any_color = 0;
|
||||
char scolors[20];
|
||||
scolors[0] = 0;
|
||||
for (uint32_t i = 0; i < channels; i++) {
|
||||
any_color += Dali->color[i];
|
||||
snprintf_P(scolors, sizeof(scolors), PSTR("%s%02X"), scolors, Dali->color[i]);
|
||||
}
|
||||
Dali->light_sync = true; // Block local loop
|
||||
if (any_color) {
|
||||
if (Settings->save_data) {
|
||||
// Postpone save_data during fast color changes which results in exception 0 on ESP8266
|
||||
TasmotaGlobal.save_data_counter = 4;
|
||||
}
|
||||
char scmnd[20];
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLOR " %s"), scolors);
|
||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||
} else {
|
||||
ExecuteCommandPower(LightDevice(), 0, SRC_SWITCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
DaliLoopSync(channels); // Sync local light settings with DALI bus data
|
||||
}
|
||||
} else
|
||||
#endif // DALI_LIGHT_COLOR_SUPPORT
|
||||
#endif // USE_LIGHT
|
||||
if (!(Dali->address & DALI_SELECTOR_BIT)) { // Address
|
||||
if (!(Dali->address & DALI_SELECTOR_BIT)) { // Address = DAPC command
|
||||
uint32_t index = DaliSaveState(Dali->address, Dali->command); // Update dimmer and power
|
||||
bool show_response = true;
|
||||
#ifdef USE_LIGHT
|
||||
if (Dali->allow_light && (DaliTarget2Address(Dali->Settings.target) == Dali->address)) {
|
||||
if (Settings->sbflag1.dali_light) { // DaliLight 1
|
||||
// Sync local light settings with DALI bus data
|
||||
uint8_t dim_old = changeUIntScale(Dali->last_dimmer, 0, 254, 0, 100);
|
||||
uint8_t dim_new = changeUIntScale(Dali->dimmer[index], 0, 254, 0, 100);
|
||||
if (Dali->last_power != Dali->power[index]) {
|
||||
Dali->light_sync = true; // Block local loop
|
||||
ExecuteCommandPower(LightDevice(), Dali->power[index], SRC_SWITCH);
|
||||
}
|
||||
else if (dim_old != dim_new) {
|
||||
char scmnd[20];
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), dim_new);
|
||||
Dali->light_sync = true; // Block local loop
|
||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||
}
|
||||
Dali->color[0] = Dali->command; // Contains "dimmer" value 0..254
|
||||
if (DaliLoopSync(1)) { // Sync local light settings with DALI bus data
|
||||
show_response = false;
|
||||
}
|
||||
}
|
||||
#endif // USE_LIGHT
|
||||
if (show_response) {
|
||||
ResponseDali(index);
|
||||
@ -828,16 +837,22 @@ bool DaliSetChannels(void) {
|
||||
if (Settings->sbflag1.dali_light) { // DaliLight 1
|
||||
Settings->light_fade = 0; // Use Dali fading
|
||||
Settings->light_correction = 0; // Use Dali light correction
|
||||
if (Dali->light_sync) { // Block local loop
|
||||
Dali->light_sync = false;
|
||||
} else {
|
||||
|
||||
uint8_t *cur_col = (uint8_t*)XdrvMailbox.data;
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: SetChannels Sync %d cur_col %02X %02X %02X %02X %02X"), Dali->light_sync, cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
||||
|
||||
if (Dali->light_sync) { // Block local loop
|
||||
uint32_t light_sync = Dali->light_sync;
|
||||
Dali->light_sync = 0;
|
||||
if (TimePassedSince(light_sync) < 200) { // Time it can take to call DaliSetChannels() from Dali received data
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// cur_col[0] = Red, cur_col[1] = Green, cur_col[2] = Blue, cur_col[3] = Cold = White, cur_col[4] = Warm = Amber
|
||||
for (uint32_t i = 0; i < 5; i++) {
|
||||
if (255 == cur_col[i]) { cur_col[i] = 254; } // Max Dali value
|
||||
}
|
||||
uint32_t adr = DaliTarget2Address(Dali->Settings.target);
|
||||
#ifdef DALI_LIGHT_COLOR_SUPPORT
|
||||
uint32_t channels = Dali->Settings.light_type -8;
|
||||
if ((Dali->target_rgbwaf > 0) && (channels > 0)) { // Color control
|
||||
adr |= DALI_SELECTOR_BIT; // Enable Selector bit
|
||||
@ -891,13 +906,11 @@ bool DaliSetChannels(void) {
|
||||
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
|
||||
DaliSendData(adr, DALI_209_SET_TEMPORARY_WAF_DIMLEVEL);
|
||||
}
|
||||
|
||||
#endif // DALI_LIGHT_NO_READ_AFTER_WRITE
|
||||
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
|
||||
DaliSendData(adr, DALI_209_ACTIVATE);
|
||||
return true;
|
||||
}
|
||||
#endif // DALI_LIGHT_COLOR_SUPPORT
|
||||
|
||||
#ifdef DALI_POWER_OFF_NO_FADE
|
||||
if (!cur_col[0]) {
|
||||
@ -907,7 +920,6 @@ bool DaliSetChannels(void) {
|
||||
#endif // DALI_POWER_OFF_NO_FADE
|
||||
DaliSendData(adr, cur_col[0]); // DAPC command - dim level
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // USE_LIGHT
|
||||
@ -970,7 +982,6 @@ bool DaliInit(uint32_t function) {
|
||||
UpdateDevicesPresent(1);
|
||||
|
||||
TasmotaGlobal.light_type = LT_W; // Single channel
|
||||
#ifdef DALI_LIGHT_COLOR_SUPPORT
|
||||
Dali->target_rgbwaf = DaliQueryRGBWAF(DaliTarget2Address(Dali->Settings.target));
|
||||
if (Dali->target_rgbwaf > 1) {
|
||||
TasmotaGlobal.light_type = Dali->Settings.light_type;
|
||||
@ -980,7 +991,6 @@ bool DaliInit(uint32_t function) {
|
||||
UpdateDevicesPresent(1); // We manage RGB and W separately, hence adding a device
|
||||
}
|
||||
}
|
||||
#endif // DALI_LIGHT_COLOR_SUPPORT
|
||||
|
||||
return true;
|
||||
#else
|
||||
@ -1090,9 +1100,7 @@ void CmndDaliTarget(void) {
|
||||
(XdrvMailbox.payload == 0)) {
|
||||
Dali->Settings.target = XdrvMailbox.payload;
|
||||
}
|
||||
#ifdef DALI_LIGHT_COLOR_SUPPORT
|
||||
Dali->target_rgbwaf = DaliQueryRGBWAF(DaliTarget2Address(Dali->Settings.target));
|
||||
#endif // DALI_LIGHT_COLOR_SUPPORT
|
||||
ResponseCmndNumber(Dali->Settings.target);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user