mirror of https://github.com/arendst/Tasmota.git
Add DALI command `DaliGroupSliders 0..16` to show GUI group sliders with feedback disabling `DaliLight`
This commit is contained in:
parent
deca4d9e06
commit
49d706f54c
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -3,12 +3,22 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## [Unreleased] - Development
|
||||
|
||||
## [14.3.0.3]
|
||||
## [14.3.0.4]
|
||||
### Added
|
||||
- Support for I2C over Serial, preliminary stub (#22388)
|
||||
- DALI command `DaliGroupSliders 0..16` to show GUI group sliders with feedback disabling `DaliLight`
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Removed
|
||||
|
||||
## [14.3.0.3] 20241031
|
||||
### Added
|
||||
- Support for I2C over Serial, preliminary stub (#22388)
|
||||
|
||||
### Changed
|
||||
- ESP32 Platform from 2024.10.30 to 2024.11.30, Framework (Arduino Core) from v3.1.0.241023 to v3.1.0.241030 and IDF to 5.3.1.241024 (#22384)
|
||||
- ESP32 LVGL library from v9.2.0 to v9.2.2 (#22385)
|
||||
|
@ -17,8 +27,6 @@ All notable changes to this project will be documented in this file.
|
|||
### Fixed
|
||||
- ESP32 Arduino Core IPv6 zones used by Matter (#22378)
|
||||
|
||||
### Removed
|
||||
|
||||
## [14.3.0.2] 20241030
|
||||
### Added
|
||||
- DALI command `DaliGear` to set max found gear to speed up scan response
|
||||
|
|
|
@ -114,13 +114,14 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
|||
|
||||
[Complete list](BUILDS.md) of available feature and sensors.
|
||||
|
||||
## Changelog v14.3.0.3
|
||||
## Changelog v14.3.0.4
|
||||
### Added
|
||||
- Command ``SetOption161 1`` to disable web page slider updates by commands
|
||||
- DALI support for short addresses (gear) and groups
|
||||
- DALI command `DaliGear` to set max found gear to speed up scan response
|
||||
- DALI command `DaliGroup` to add gear to groups
|
||||
- DALI command `DaliTarget` to set light control broadcast, group number or gear number
|
||||
- DALI command `DaliGroupSliders 0..16` to show GUI group sliders with feedback disabling `DaliLight`
|
||||
- DALI inverted signal configuration using GPIO DALI RX_i/TX_i
|
||||
- Support for I2C over Serial, preliminary stub [#22388](https://github.com/arendst/Tasmota/issues/22388)
|
||||
- Support for Shelly DALI Dimmer Gen3
|
||||
|
|
|
@ -195,7 +195,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t mqtt_disable_modbus : 1; // bit 12 (v13.3.0.5) - SetOption158 - (MQTT) Disable publish ModbusReceived MQTT messages (1), you must use event trigger rules instead
|
||||
uint32_t counter_both_edges : 1; // bit 13 (v13.3.0.5) - SetOption159 - (Counter) Enable counting on both rising and falling edge (1)
|
||||
uint32_t ld2410_use_pin : 1; // bit 14 (v14.3.0.2) - SetOption160 - (LD2410) Disable generate moving event by sensor report - use LD2410 out pin for events (1)
|
||||
uint32_t disable_slider_updates : 1; // bit 15 (v14.3.0.2) - SetOption161 - (Light) Disable slider updates (1)
|
||||
uint32_t disable_slider_updates : 1; // bit 15 (v14.3.0.2) - SetOption161 - (Light) Disable slider updates by commands (1)
|
||||
uint32_t spare16 : 1; // bit 16
|
||||
uint32_t spare17 : 1; // bit 17
|
||||
uint32_t spare18 : 1; // bit 18
|
||||
|
@ -260,15 +260,11 @@ typedef union {
|
|||
uint32_t spare16 : 1; // bit 16
|
||||
uint32_t spare17 : 1; // bit 17
|
||||
uint32_t spare18 : 1; // bit 18
|
||||
uint32_t spare19 : 1; // bit 19
|
||||
uint32_t spare20 : 1; // bit 20
|
||||
uint32_t spare21 : 1; // bit 21
|
||||
uint32_t spare22 : 1; // bit 22
|
||||
uint32_t spare23 : 1; // bit 23
|
||||
uint32_t FTP_Mode : 2; // bit 24, 25
|
||||
uint32_t tariff_forced : 2; // bit 26..27 (v12.4.0.2) - Energy forced tariff : 0=tariff change on time, 1|2=tariff forced
|
||||
uint32_t sunrise_dawn_angle : 2; // bits 28/29 (v12.1.1.4) -
|
||||
uint32_t temperature_set_res : 2; // bits 30/31 (v9.3.1.4) - (Tuya)
|
||||
uint32_t dali_group_sliders : 5; // bit 19.23 (v14.3.0.3) - (DALI) Number of group sliders 0 to 16
|
||||
uint32_t FTP_Mode : 2; // bit 24/25
|
||||
uint32_t tariff_forced : 2; // bit 26/27 (v12.4.0.2) - Energy forced tariff : 0=tariff change on time, 1|2=tariff forced
|
||||
uint32_t sunrise_dawn_angle : 2; // bit 28/29 (v12.1.1.4) -
|
||||
uint32_t temperature_set_res : 2; // bit 30/31 (v9.3.1.4) - (Tuya)
|
||||
};
|
||||
} SysMBitfield2;
|
||||
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
|
||||
#define TASMOTA_SHA_SHORT // Filled by Github sed
|
||||
|
||||
const uint32_t TASMOTA_VERSION = 0x0E030003; // 14.3.0.3
|
||||
const uint32_t TASMOTA_VERSION = 0x0E030004; // 14.3.0.4
|
||||
|
||||
#endif // _TASMOTA_VERSION_H_
|
||||
|
|
|
@ -1838,6 +1838,9 @@ void SettingsDelta(void) {
|
|||
if (Settings->version < 0x0E030002) { // 14.3.0.2
|
||||
Settings->sbflag1.dali_light = 1;
|
||||
}
|
||||
if (Settings->version < 0x0E030004) { // 14.3.0.4
|
||||
Settings->mbflag2.dali_group_sliders = 2;
|
||||
}
|
||||
|
||||
Settings->version = TASMOTA_VERSION;
|
||||
SettingsSave(1);
|
||||
|
|
|
@ -271,6 +271,9 @@ const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM =
|
|||
"<input id='sl%d' type='range' min='%d' max='%d' value='%d' onchange='lc(\"%c\",%d,value)'>"
|
||||
"</div>";
|
||||
|
||||
const char HTTP_MSG_SLIDER_UPDATE[] PROGMEM =
|
||||
"<img style='display:none;' src onerror=";
|
||||
|
||||
const char HTTP_MSG_RSTRT[] PROGMEM =
|
||||
"<br><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br>";
|
||||
|
||||
|
@ -1354,7 +1357,7 @@ void HandleRoot(void)
|
|||
WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE);
|
||||
#endif // ESP32
|
||||
WSContentButton(BUTTON_CONSOLE);
|
||||
#else
|
||||
#else // Not FIRMWARE_MINIMAL
|
||||
WSContentSpaceButton(BUTTON_CONFIGURATION);
|
||||
WSContentButton(BUTTON_INFORMATION);
|
||||
WSContentButton(BUTTON_FIRMWARE_UPGRADE);
|
||||
|
@ -1534,7 +1537,8 @@ bool HandleRootStatusRefresh(void)
|
|||
if (current_value != Web.slider[i]) {
|
||||
Web.slider[i] = current_value;
|
||||
// https://stackoverflow.com/questions/4057236/how-to-add-onload-event-to-a-div-element
|
||||
WSContentSend_P(PSTR("<img style='display:none;' src onerror=\"eb('sl%d').value='%d';\">"), i +1, current_value);
|
||||
WSContentSend_P(HTTP_MSG_SLIDER_UPDATE); // "<img style='display:none;' src onerror="
|
||||
WSContentSend_P(PSTR("\"eb('sl%d').value='%d';\">"), i +1, current_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
--------------------------------------------------------------------------------------------
|
||||
Version yyyymmdd Action Description
|
||||
--------------------------------------------------------------------------------------------
|
||||
1.1.0.0 20241031 update - Add GUI sliders with feedback when `DaliLight 0`
|
||||
- Add command `DaliGroupSliders 0..16` to show GUI sliders
|
||||
1.0.0.2 20241025 update - Fix GPIO detection
|
||||
- Fix ESP32(C3) transmit stability by disabling interrupts
|
||||
1.0.0.1 20241024 update - Change from signal invert defines to GPIO config DALI RX_i/DALI TX_i
|
||||
|
@ -264,6 +266,8 @@
|
|||
// Address type - Send as first byte
|
||||
#define DALI_BROADCAST_DP 0x00FE // 0b11111110 254 - Broadcast address
|
||||
|
||||
#define DALI_MAX_STORED 17 // Store broadcast and group states
|
||||
|
||||
#define DALI_TOPIC "DALI"
|
||||
#define D_PRFX_DALI "Dali"
|
||||
|
||||
|
@ -272,14 +276,16 @@ const char kDALICommands[] PROGMEM = D_PRFX_DALI "|" // Prefix
|
|||
#ifdef USE_LIGHT
|
||||
"|Light"
|
||||
#endif // USE_LIGHT
|
||||
"|Send|Query|Scan|Group|Gear";
|
||||
"|Send|Query|Scan|Group"
|
||||
"|GroupSliders|Gear";
|
||||
|
||||
void (* const DALICommand[])(void) PROGMEM = {
|
||||
&CmndDali, &CmndDaliPower, &CmndDaliDimmer, &CmndDaliTarget,
|
||||
#ifdef USE_LIGHT
|
||||
&CmndDaliLight,
|
||||
#endif // USE_LIGHT
|
||||
&CmndDaliSend, &CmndDaliQuery, &CmndDaliScan, &CmndDaliGroup, &CmndDaliGear };
|
||||
&CmndDaliSend, &CmndDaliQuery, &CmndDaliScan, &CmndDaliGroup,
|
||||
&CmndDaliGroupSliders, &CmndDaliGear };
|
||||
|
||||
struct DALI {
|
||||
uint32_t bit_cycles;
|
||||
|
@ -290,9 +296,13 @@ struct DALI {
|
|||
uint8_t max_short_address;
|
||||
uint8_t address;
|
||||
uint8_t command;
|
||||
uint8_t dimmer;
|
||||
uint8_t last_dimmer;
|
||||
uint8_t dimmer[DALI_MAX_STORED];
|
||||
uint8_t web_dimmer[DALI_MAX_STORED];
|
||||
uint8_t target;
|
||||
bool power;
|
||||
bool last_power;
|
||||
bool power[DALI_MAX_STORED];
|
||||
bool web_power[DALI_MAX_STORED];
|
||||
bool available;
|
||||
bool response;
|
||||
bool light_sync;
|
||||
|
@ -305,23 +315,23 @@ struct DALI {
|
|||
* DALI low level
|
||||
\*********************************************************************************************/
|
||||
|
||||
uint32_t DaliTarget2Address(uint32_t target) {
|
||||
uint32_t DaliTarget2Address(void) {
|
||||
// 1..64 = Short address
|
||||
// 101..116 = Group address
|
||||
// Others = Broadcast
|
||||
if ((target >= 1) && (target <= 64)) { // 1 .. 64
|
||||
target -= 1; // Short address
|
||||
target <<= 1;
|
||||
if ((Dali->target >= 1) && (Dali->target <= 64)) { // 1 .. 64
|
||||
Dali->target -= 1; // Short address
|
||||
Dali->target <<= 1;
|
||||
}
|
||||
else if ((target >= 101) && (target <= 116)) { // 101 .. 116
|
||||
target -= 101;
|
||||
target <<= 1;
|
||||
target |= 0x80; // Group address
|
||||
else if ((Dali->target >= 101) && (Dali->target <= 116)) { // 101 .. 116
|
||||
Dali->target -= 101;
|
||||
Dali->target <<= 1;
|
||||
Dali->target |= 0x80; // Group address
|
||||
}
|
||||
else { // Others
|
||||
target = DALI_BROADCAST_DP; // Broadcast address
|
||||
Dali->target = DALI_BROADCAST_DP; // Broadcast address
|
||||
}
|
||||
return target &0xFE; // Direct Arc Power Control command
|
||||
return Dali->target &0xFE; // Direct Arc Power Control command
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -336,6 +346,34 @@ uint32_t DaliAddress2Target(uint32_t adr) {
|
|||
}
|
||||
*/
|
||||
|
||||
uint32_t DaliSaveState(uint32_t adr, uint32_t cmd) {
|
||||
if (adr &0x01) { return 0; } // No address
|
||||
int index = -1;
|
||||
if (DALI_BROADCAST_DP == adr) { // Broadcast address
|
||||
index = 0;
|
||||
}
|
||||
adr >>= 1;
|
||||
if ((adr >= 0x40) && (adr <= 0x4F)) { // Group address 0 to 15
|
||||
index = adr -0x3F;
|
||||
}
|
||||
if (index >= 0) {
|
||||
Dali->last_power = Dali->power[index];
|
||||
Dali->power[index] = (cmd); // State
|
||||
if (Dali->power[index]) {
|
||||
Dali->last_dimmer = Dali->dimmer[index];
|
||||
Dali->dimmer[index] = cmd; // Value
|
||||
}
|
||||
if ((0 == index) && !Dali->power[0]) { // Only on Broadcast change to power Off
|
||||
for (uint32_t i = 0; i < DALI_MAX_STORED; i++) {
|
||||
Dali->power[i] = false; // Log all group power as Off when Broadcast is Off
|
||||
}
|
||||
}
|
||||
} else {
|
||||
index = 0; // Use broadcast
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void DaliEnableRxInterrupt(void) {
|
||||
Dali->available = false;
|
||||
attachInterrupt(Dali->pin_rx, DaliReceiveData, (Dali->invert_rx) ? RISING : FALLING);
|
||||
|
@ -508,13 +546,7 @@ void DaliSendData(uint32_t adr, uint32_t cmd) {
|
|||
|
||||
Dali->address = adr;
|
||||
Dali->command = cmd;
|
||||
if (DaliTarget2Address(Dali->target) == adr) {
|
||||
repeat = true;
|
||||
Dali->power = (cmd); // State
|
||||
if (Dali->power) {
|
||||
Dali->dimmer = cmd; // Value
|
||||
}
|
||||
}
|
||||
DaliSaveState(adr, cmd);
|
||||
|
||||
if (!repeat && (adr &0x01)) { // YAAAAAA1 Commands where user didn't set repeat
|
||||
if ((adr >= 0xA1) && (adr <= 0xFD)) { // Special commands
|
||||
|
@ -751,25 +783,28 @@ uint32_t DaliCommission(uint8_t init_arg) {
|
|||
|
||||
#ifdef USE_LIGHT
|
||||
DaliInitLight();
|
||||
uint32_t address = (Settings->sbflag1.dali_light) ? DaliTarget2Address(Dali->target) : DALI_BROADCAST_DP;
|
||||
DaliSendData(address, Dali->power); // Restore lights
|
||||
uint32_t address = (Settings->sbflag1.dali_light) ? DaliTarget2Address() : DALI_BROADCAST_DP;
|
||||
DaliSendData(address, Dali->power[0]); // Restore lights
|
||||
#else
|
||||
DaliSendData(DALI_BROADCAST_DP, Dali->power); // Restore lights
|
||||
DaliSendData(DALI_BROADCAST_DP, Dali->power[0]); // Restore lights
|
||||
#endif // USE_LIGHT
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void ResponseAppendDali(void) {
|
||||
uint8_t dimmer = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
||||
ResponseAppend_P(PSTR("\"DALI\":{\"Power\":\"%s\",\"Dimmer\":%d,\"Address\":%d,\"Command\":%d}"),
|
||||
GetStateText(Dali->power), dimmer, Dali->address, Dali->command);
|
||||
void ResponseAppendDali(uint32_t index) {
|
||||
char number[12];
|
||||
uint8_t dimmer = changeUIntScale(Dali->dimmer[index], 0, 254, 0, 100);
|
||||
ResponseAppend_P(PSTR("\"DALI\":{\"Power%s\":\"%s\",\"Dimmer%s\":%d,\"Address\":%d,\"Command\":%d}"),
|
||||
(0==index)?"":itoa(index+100, number, 10), GetStateText(Dali->power[index]),
|
||||
(0==index)?"":itoa(index+100, number, 10), dimmer,
|
||||
Dali->address, Dali->command);
|
||||
}
|
||||
|
||||
void ResponseDali(void) {
|
||||
void ResponseDali(uint32_t index) {
|
||||
Response_P(PSTR("{"));
|
||||
ResponseAppendDali();
|
||||
ResponseAppendDali(index);
|
||||
ResponseJsonEnd();
|
||||
}
|
||||
|
||||
|
@ -787,45 +822,32 @@ void DaliLoop(void) {
|
|||
|
||||
Dali->address = Dali->received_dali_data >> 8;
|
||||
Dali->command = Dali->received_dali_data;
|
||||
uint32_t index = DaliSaveState(Dali->address, Dali->command); // Update dimmer and power
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
bool show_response = true;
|
||||
if (DaliTarget2Address(Dali->target) == Dali->address) {
|
||||
uint8_t dimmer_old = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
||||
uint8_t power_old = Dali->power;
|
||||
Dali->power = (Dali->command); // State
|
||||
if (Dali->power) {
|
||||
Dali->dimmer = Dali->command; // Value
|
||||
}
|
||||
#ifdef USE_LIGHT
|
||||
if (DaliTarget2Address() == Dali->address) {
|
||||
if (Settings->sbflag1.dali_light) { // DaliLight 1
|
||||
uint8_t dimmer_new = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
||||
if (power_old != Dali->power) {
|
||||
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, SRC_SWITCH);
|
||||
ExecuteCommandPower(LightDevice(), Dali->power[index], SRC_SWITCH);
|
||||
}
|
||||
else if (dimmer_old != dimmer_new) {
|
||||
else if (dim_old != dim_new) {
|
||||
char scmnd[20];
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), dimmer_new);
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), dim_new);
|
||||
Dali->light_sync = true; // Block local loop
|
||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||
}
|
||||
show_response = false;
|
||||
}
|
||||
}
|
||||
#endif // USE_LIGHT
|
||||
if (show_response) {
|
||||
ResponseDali();
|
||||
ResponseDali(index);
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_PRFX_DALI));
|
||||
}
|
||||
#else
|
||||
if (DaliTarget2Address(Dali->target) == Dali->address) {
|
||||
Dali->power = (Dali->command); // State
|
||||
if (Dali->power) {
|
||||
Dali->dimmer = Dali->command; // Value
|
||||
}
|
||||
}
|
||||
ResponseDali();
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_PRFX_DALI));
|
||||
#endif // USE_LIGHT
|
||||
|
||||
Dali->available = false;
|
||||
}
|
||||
|
@ -850,7 +872,7 @@ bool DaliSetChannels(void) {
|
|||
} else {
|
||||
uint8_t value = ((uint8_t*)XdrvMailbox.data)[0];
|
||||
if (255 == value) { value = 254; } // Max Dali value
|
||||
DaliSendData(DaliTarget2Address(Dali->target), value);
|
||||
DaliSendData(DaliTarget2Address(), value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -900,7 +922,10 @@ bool DaliInit(void) {
|
|||
#endif // DALI_DEBUG
|
||||
|
||||
Dali->max_short_address = 64;
|
||||
Dali->dimmer = DALI_INIT_STATE;
|
||||
for (uint32_t i = 0; i < DALI_MAX_STORED; i++) {
|
||||
Dali->dimmer[i] = DALI_INIT_STATE;
|
||||
}
|
||||
|
||||
// Manchester twice 1200 bps = 2400 bps = 417 (protocol 416.76 +/- 10%) us
|
||||
Dali->bit_cycles = ESP.getCpuFreqMHz() * 1000000 / 2400;
|
||||
|
||||
|
@ -983,7 +1008,7 @@ void CmndDali(void) {
|
|||
}
|
||||
DaliJsonParse();
|
||||
}
|
||||
ResponseDali();
|
||||
ResponseDali(0);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
@ -1010,15 +1035,19 @@ void CmndDaliPower(void) {
|
|||
// DaliPower0 0..254 - Broadcast control (= DaliPower)
|
||||
// DaliPower1 0..254 - Short address 0 control
|
||||
// DaliPower3 0..254 - Short address 2 control
|
||||
uint32_t index = 0; // Broadcast
|
||||
if ((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116)) {
|
||||
index = XdrvMailbox.index - 100; // Group1 to 16
|
||||
}
|
||||
if (((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= 64)) ||
|
||||
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 254)) {
|
||||
if (XdrvMailbox.payload <= 2) {
|
||||
if (2 == XdrvMailbox.payload) {
|
||||
XdrvMailbox.payload = (Dali->power) ? 0 : 1;
|
||||
XdrvMailbox.payload = (Dali->power[index]) ? 0 : 1;
|
||||
}
|
||||
if (1 == XdrvMailbox.payload) {
|
||||
XdrvMailbox.payload = Dali->dimmer;
|
||||
XdrvMailbox.payload = Dali->dimmer[index];
|
||||
}
|
||||
}
|
||||
uint32_t DALIaddr = DALI_BROADCAST_DP;
|
||||
|
@ -1031,7 +1060,7 @@ void CmndDaliPower(void) {
|
|||
DaliSendData(DALIaddr, XdrvMailbox.payload);
|
||||
}
|
||||
}
|
||||
ResponseDali();
|
||||
ResponseDali(index);
|
||||
}
|
||||
|
||||
void CmndDaliDimmer(void) {
|
||||
|
@ -1039,6 +1068,10 @@ void CmndDaliDimmer(void) {
|
|||
// DaliDimmer0 0..100 - Broadcast set power off or dimmer state
|
||||
// DaliDimmer1 0..100 - Short address 0 set power off or dimmer state
|
||||
// DaliDimmer3 0..100 - Short address 2 set power off or dimmer state
|
||||
uint32_t index = 0; // Broadcast
|
||||
if ((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116)) {
|
||||
index = XdrvMailbox.index - 100; // Group1 to 16
|
||||
}
|
||||
if (((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= 64)) ||
|
||||
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||
|
@ -1053,7 +1086,7 @@ void CmndDaliDimmer(void) {
|
|||
DaliSendData(DALIaddr, dimmer);
|
||||
}
|
||||
}
|
||||
ResponseDali();
|
||||
ResponseDali(index);
|
||||
}
|
||||
|
||||
void CmndDaliGroup(void) {
|
||||
|
@ -1169,13 +1202,23 @@ void CmndDaliScan(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void CmndDaliGroupSliders(void) {
|
||||
// DaliGroupSliders 0..16 - Disable light controls and add group sliders
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 16)) {
|
||||
Settings->sbflag1.dali_light = 0; // Disable DaliLight
|
||||
Settings->mbflag2.dali_group_sliders = XdrvMailbox.payload;
|
||||
TasmotaGlobal.restart_flag = 2; // Restart to update GUI
|
||||
}
|
||||
ResponseCmndNumber(Settings->mbflag2.dali_group_sliders);
|
||||
}
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
void CmndDaliLight(void) {
|
||||
// DaliLight 0 - Disable light controls
|
||||
// DaliLight 1 - Enable light controls
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
Settings->sbflag1.dali_light = XdrvMailbox.payload &1;
|
||||
TasmotaGlobal.restart_flag = 2;
|
||||
TasmotaGlobal.restart_flag = 2; // Restart to update GUI
|
||||
}
|
||||
ResponseCmndStateText(Settings->sbflag1.dali_light);
|
||||
}
|
||||
|
@ -1185,10 +1228,86 @@ void CmndDaliLight(void) {
|
|||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_MSG_SLIDER_DALI[] PROGMEM =
|
||||
"<tr>"
|
||||
"<td style='width:15%%'><button id='k75%d' style='background:#%06x;' onclick='la(\"&k75=%d\");'>%s%s</button></td>"
|
||||
"<td style='width:85%%'><div class='r' style='background-image:linear-gradient(to right,#000,#FFF);'>"
|
||||
"<input id='i75%d' type='range' min='1' max='100' value='%d' onchange='lc(\"i\",75%d,value)'></div></td>"
|
||||
"</tr>";
|
||||
|
||||
void DaliWebAddMainSlider(void) {
|
||||
WSContentSend_P(HTTP_TABLE100);
|
||||
char number[12];
|
||||
uint32_t max_sliders = 1 + Settings->mbflag2.dali_group_sliders;
|
||||
for (uint32_t i = 0; i < max_sliders; i++) {
|
||||
Dali->web_dimmer[i] = Dali->dimmer[i];
|
||||
Dali->web_power[i] = Dali->power[i];
|
||||
WSContentSend_P(HTTP_MSG_SLIDER_DALI, // Brightness - Black to White
|
||||
i, // k75<i>
|
||||
WebColor((Dali->web_power[i])?COL_BUTTON:COL_BACKGROUND),
|
||||
i, // k75=<i>
|
||||
(0==i)?"B":"G", // B (Broadcast) or G1 to G16 (Group)
|
||||
(0==i)?"":itoa(i, number, 10),
|
||||
i, // i75<i>
|
||||
changeUIntScale(Dali->web_dimmer[i], 0, 254, 0, 100),
|
||||
i // i75<i>
|
||||
);
|
||||
}
|
||||
WSContentSend_P(PSTR("</table>"));
|
||||
}
|
||||
|
||||
void DaliWebGetArg(void) {
|
||||
char tmp[8]; // WebGetArg numbers only
|
||||
char svalue[32]; // Command and number parameter
|
||||
char webindex[8]; // WebGetArg name
|
||||
|
||||
uint32_t index;
|
||||
uint32_t max_sliders = 1 + Settings->mbflag2.dali_group_sliders;
|
||||
for (uint32_t i = 0; i < max_sliders; i++) {
|
||||
snprintf_P(webindex, sizeof(webindex), PSTR("i75%d"), i);
|
||||
WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent
|
||||
if (strlen(tmp)) {
|
||||
index = i;
|
||||
if (index > 0) { index += 100; } // Group
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("DaliDimmer%d %s"), index, tmp);
|
||||
ExecuteWebCommand(svalue);
|
||||
}
|
||||
}
|
||||
WebGetArg(PSTR("k75"), tmp, sizeof(tmp));
|
||||
if (strlen(tmp)) {
|
||||
index = atoi(tmp);
|
||||
if (index > 0) { index += 100; } // Group
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("DaliPower%d 2"), index);
|
||||
ExecuteWebCommand(svalue);
|
||||
}
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void DaliShow(bool json) {
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
ResponseAppendDali();
|
||||
ResponseAppendDali(0);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
uint32_t max_sliders = 1 + Settings->mbflag2.dali_group_sliders;
|
||||
for (uint32_t i = 0; i < max_sliders; i++) {
|
||||
if (Dali->power[i] != Dali->web_power[i]) {
|
||||
Dali->web_power[i] = Dali->power[i];
|
||||
WSContentSend_P(HTTP_MSG_SLIDER_UPDATE); // "<img style='display:none;' src onerror="
|
||||
WSContentSend_P(PSTR("\"eb('k75%d').style='background:#%06x;';\">"),
|
||||
i, WebColor((Dali->web_power[i])?COL_BUTTON:COL_BACKGROUND));
|
||||
WSContentSeparator(3); // Don't print separator on next WSContentSeparator(1)
|
||||
}
|
||||
if (Dali->dimmer[i] != Dali->web_dimmer[i]) {
|
||||
Dali->web_dimmer[i] = Dali->dimmer[i];
|
||||
WSContentSend_P(HTTP_MSG_SLIDER_UPDATE); // "<img style='display:none;' src onerror="
|
||||
WSContentSend_P(PSTR("\"eb('i75%d').value='%d';\">"),
|
||||
i, changeUIntScale(Dali->web_dimmer[i], 0, 254, 0, 100));
|
||||
WSContentSeparator(3); // Don't print separator on next WSContentSeparator(1)
|
||||
}
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1220,7 +1339,19 @@ bool Xdrv75(uint32_t function) {
|
|||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_SENSOR:
|
||||
DaliShow(false);
|
||||
if (!Settings->sbflag1.dali_light) { // DaliLight 0
|
||||
DaliShow(false);
|
||||
}
|
||||
break;
|
||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||
if (!Settings->sbflag1.dali_light) { // DaliLight 0
|
||||
DaliWebAddMainSlider();
|
||||
}
|
||||
break;
|
||||
case FUNC_WEB_GET_ARG:
|
||||
if (!Settings->sbflag1.dali_light) { // DaliLight 0
|
||||
DaliWebGetArg();
|
||||
}
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_COMMAND:
|
||||
|
|
Loading…
Reference in New Issue