Skip to content

Commit 4bda3e1

Browse files
committed
Add DALI optional blink to DaliGear and DaliGroup
1 parent a305113 commit 4bda3e1

File tree

1 file changed

+70
-23
lines changed

1 file changed

+70
-23
lines changed

tasmota/tasmota_xdrv_driver/xdrv_75_dali.ino

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
--------------------------------------------------------------------------------------------
6666
Version yyyymmdd Action Description
6767
--------------------------------------------------------------------------------------------
68+
1.4.1.0 20251130 update - Add options to `DaliGear` and DaliGroup` to toggle specific outputs
69+
- Make max number of devices persistent to speed up scan response
6870
1.4.0.0 20251126 update - Change to TasmotaDali library
6971
1.3.0.4 20251123 update - Add send retry on collision detection
7072
- Prep DALI-2 24-bit transceive
@@ -154,12 +156,12 @@ typedef struct DliSettings_t {
154156
uint32_t crc32; // To detect file changes
155157
uint8_t target;
156158
uint8_t light_type;
159+
uint8_t max_gear;
157160
} DliSettings_t;
158161

159162
struct DALI {
160163
DliSettings_t Settings; // Persistent settings
161164
TasmotaDali *dali;
162-
uint8_t max_short_address;
163165
uint8_t address;
164166
uint8_t command;
165167
uint8_t last_dimmer;
@@ -199,15 +201,17 @@ bool DaliLoadData(void) {
199201
Dali->Settings.crc32 = root.getUInt(PSTR("Crc"), Dali->Settings.crc32);
200202
Dali->Settings.target = root.getUInt(PSTR("Target"), Dali->Settings.target);
201203
Dali->Settings.light_type = root.getUInt(PSTR("LightType"), Dali->Settings.light_type);
204+
Dali->Settings.max_gear = root.getUInt(PSTR("MaxGear"), Dali->Settings.max_gear);
202205

203206
return true;
204207
}
205208

206209
bool DaliSaveData(void) {
207-
Response_P(PSTR("{\"" XDRV_75_KEY "\":{\"Crc\":%u,\"Target\":%u,\"LightType\":%u}}"),
210+
Response_P(PSTR("{\"" XDRV_75_KEY "\":{\"Crc\":%u,\"Target\":%u,\"LightType\":%u,\"MaxGear\":%u}}"),
208211
Dali->Settings.crc32,
209212
Dali->Settings.target,
210-
Dali->Settings.light_type);
213+
Dali->Settings.light_type,
214+
Dali->Settings.max_gear);
211215

212216
return UfsJsonSettingsWrite(ResponseData());
213217
}
@@ -227,6 +231,7 @@ void DaliSettingsLoad(bool erase) {
227231
// *** Start init default values in case key is not found ***
228232
memset(&Dali->Settings, 0x00, sizeof(DliSettings_t));
229233
Dali->Settings.light_type = LT_RGB; // Default RGB channel
234+
Dali->Settings.max_gear = 64; // Default max supported short address
230235
// *** End Init default values ***
231236

232237
#ifndef USE_UFILESYS
@@ -527,20 +532,6 @@ uint32_t DaliQueryRGBWAF(uint32_t adr) {
527532

528533
/*-------------------------------------------------------------------------------------------*/
529534

530-
uint32_t DaliGearPresent(void) {
531-
uint32_t count = 0;
532-
for (uint32_t address = 0; address < Dali->max_short_address; address++) { // Scanning 64 addresses takes about 2500 ms
533-
uint32_t short_address = address << 1;
534-
if (DaliSendWaitResponse(short_address | DALI_SELECTOR_BIT, DALI_102_QUERY_CONTROL_GEAR_PRESENT, 20) >= 0) {
535-
count++;
536-
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Device %d at %d, short address %d"), count, address, short_address);
537-
}
538-
}
539-
return count;
540-
}
541-
542-
/*-------------------------------------------------------------------------------------------*/
543-
544535
void DaliInitLight(void) {
545536
// Taken from Shelly Dali Dimmer ;-)
546537
uint32_t adr = DALI_BROADCAST_DP | DALI_SELECTOR_BIT;
@@ -686,6 +677,19 @@ uint32_t DaliCommission(uint32_t init_arg, uint32_t max_count) {
686677
return cnt;
687678
}
688679

680+
/*-------------------------------------------------------------------------------------------*/
681+
682+
void DaliToggle(uint32_t adr, uint32_t *count) {
683+
static uint32_t interval = 0;
684+
685+
if (*count && TimeReached(interval)) {
686+
SetNextTimeInterval(interval, 600);
687+
(*count)--;
688+
DaliSendData(adr, (*count &1) ? 128 : 0); // Power toggle
689+
}
690+
delay(1);
691+
}
692+
689693
/*********************************************************************************************\
690694
* DALI Control Gear - Ballast or Sensor / Receiver
691695
*
@@ -933,7 +937,6 @@ bool DaliInit(uint32_t function) {
933937
if (!Dali) { return false; }
934938
DaliSettingsLoad(0);
935939

936-
Dali->max_short_address = 64;
937940
for (uint32_t i = 0; i < DALI_MAX_STORED; i++) {
938941
Dali->dimmer[i] = DALI_INIT_STATE;
939942
}
@@ -1154,10 +1157,20 @@ void CmndDaliDimmer(void) {
11541157
void CmndDaliGroup(void) {
11551158
// DaliGroup1 1,2 - Add device 1 and 2 to group 1
11561159
// DaliGroup1 -1,2 - Remove device 1 and 2 to group 1
1160+
// DaliGroup1 b - Blink group devices twice
11571161
if ((XdrvMailbox.index >= 1) && (XdrvMailbox.index <= 16)) {
11581162
uint32_t group = XdrvMailbox.index -1;
11591163
bool more = false;
11601164
char temp[200] = { 0 };
1165+
uint32_t tcount = 0;
1166+
uint32_t adr = DaliTarget2Address(group + 101);
1167+
if (XdrvMailbox.data_len) {
1168+
if ('b' == XdrvMailbox.data[0]) { // Blink devices
1169+
tcount = 4;
1170+
XdrvMailbox.data++;
1171+
XdrvMailbox.data_len--;
1172+
}
1173+
}
11611174
if (XdrvMailbox.data_len) {
11621175
uint32_t command = DALI_102_ADD_TO_GROUP0;
11631176
temp[0] = '+';
@@ -1184,6 +1197,7 @@ void CmndDaliGroup(void) {
11841197
DaliSendData((sa << 1) | DALI_SELECTOR_BIT, command);
11851198
}
11861199
}
1200+
while (tcount) { DaliToggle(adr, &tcount); }
11871201
ResponseCmndIdxChar(temp);
11881202
}
11891203
} else {
@@ -1193,7 +1207,8 @@ void CmndDaliGroup(void) {
11931207
command = DALI_102_QUERY_GROUPS_8_15;
11941208
bitmask = 1 << group - 8;
11951209
}
1196-
for (uint32_t sa = 0; sa < Dali->max_short_address; sa++) { // Scanning 64 addresses takes about 2500 ms
1210+
for (uint32_t sa = 0; sa < Dali->Settings.max_gear; sa++) { // Scanning 64 addresses takes about 2500 ms
1211+
if (tcount) { DaliToggle(adr, &tcount); }
11971212
int result = DaliSendWaitResponse((sa << 1) | DALI_SELECTOR_BIT, command, 20);
11981213
if ((result >= 0) && (result & bitmask)) {
11991214
snprintf_P(temp, sizeof(temp), PSTR("%s%s%d"), temp, (more)?",":"", sa +1);
@@ -1202,6 +1217,8 @@ void CmndDaliGroup(void) {
12021217
}
12031218
if (!strlen(temp)) {
12041219
snprintf_P(temp, sizeof(temp), PSTR("None"));
1220+
} else {
1221+
while (tcount) { DaliToggle(adr, &tcount); }
12051222
}
12061223
ResponseCmndIdxChar(temp);
12071224
}
@@ -1211,12 +1228,42 @@ void CmndDaliGroup(void) {
12111228
/*-------------------------------------------------------------------------------------------*/
12121229

12131230
void CmndDaliGear(void) {
1214-
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 64)) {
1215-
Dali->max_short_address = XdrvMailbox.payload;
1231+
// DaliGear[2] [<max_address>|<address>] - Scan bus for up to <max_address> devices and toggle output twice
1232+
// DaliGear - Scan bus for 64 devices taking around 2.5 sec
1233+
// DaliGear 15 - Scan bus for up to 15 devices
1234+
// DaliGear2 - Scan bus and toggle output twice
1235+
// DaliGear2 4 - Toggle output twice for device 4 only
1236+
uint32_t toggle_count = 0;
1237+
uint32_t start = 0;
1238+
uint32_t end = Dali->Settings.max_gear;
1239+
uint32_t payload = ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 64)) ? XdrvMailbox.payload : 0;
1240+
if (1 == XdrvMailbox.index) {
1241+
if (payload) {
1242+
end = payload;
1243+
Dali->Settings.max_gear = end;
1244+
}
1245+
}
1246+
else if (2 == XdrvMailbox.index) {
1247+
toggle_count = 4;
1248+
if (payload) {
1249+
start = payload -1;
1250+
end = payload;
1251+
}
1252+
}
1253+
char temp[200] = { 0 };
1254+
uint32_t count = 0;
1255+
for (uint32_t address = start; address < end; address++) { // Scanning 64 addresses takes about 2500 ms
1256+
uint32_t adr = address << 1;
1257+
uint32_t tcount = toggle_count;
1258+
if (DaliSendWaitResponse(adr | DALI_SELECTOR_BIT, DALI_102_QUERY_CONTROL_GEAR_PRESENT, 20) >= 0) {
1259+
snprintf_P(temp, sizeof(temp), PSTR("%s%s%d"), temp, (count)?",":"", address +1);
1260+
count++;
1261+
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Device %d at %d, short address %d"), count, address, adr);
1262+
while (tcount) { DaliToggle(adr, &tcount); }
1263+
}
12161264
}
1217-
uint32_t count = DaliGearPresent();
12181265
ResponseCmnd();
1219-
ResponseAppend_P(PSTR("%d,\"Present\":%d}"), Dali->max_short_address, count);
1266+
ResponseAppend_P(PSTR("%d,\"Present\":%d,\"Address\":[%s]}"), Dali->Settings.max_gear, count, temp);
12201267
}
12211268

12221269
/*-------------------------------------------------------------------------------------------*/

0 commit comments

Comments
 (0)