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
|
## [Unreleased] - Development
|
||||||
|
|
||||||
## [14.3.0.3]
|
## [14.3.0.4]
|
||||||
### Added
|
### 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
|
### Breaking Changed
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
## [14.3.0.3] 20241031
|
||||||
|
### Added
|
||||||
|
- Support for I2C over Serial, preliminary stub (#22388)
|
||||||
|
|
||||||
### Changed
|
### 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 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)
|
- 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
|
### Fixed
|
||||||
- ESP32 Arduino Core IPv6 zones used by Matter (#22378)
|
- ESP32 Arduino Core IPv6 zones used by Matter (#22378)
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
## [14.3.0.2] 20241030
|
## [14.3.0.2] 20241030
|
||||||
### Added
|
### Added
|
||||||
- DALI command `DaliGear` to set max found gear to speed up scan response
|
- 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.
|
[Complete list](BUILDS.md) of available feature and sensors.
|
||||||
|
|
||||||
## Changelog v14.3.0.3
|
## Changelog v14.3.0.4
|
||||||
### Added
|
### Added
|
||||||
- Command ``SetOption161 1`` to disable web page slider updates by commands
|
- Command ``SetOption161 1`` to disable web page slider updates by commands
|
||||||
- DALI support for short addresses (gear) and groups
|
- DALI support for short addresses (gear) and groups
|
||||||
- DALI command `DaliGear` to set max found gear to speed up scan response
|
- DALI command `DaliGear` to set max found gear to speed up scan response
|
||||||
- DALI command `DaliGroup` to add gear to groups
|
- DALI command `DaliGroup` to add gear to groups
|
||||||
- DALI command `DaliTarget` to set light control broadcast, group number or gear number
|
- 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
|
- 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 I2C over Serial, preliminary stub [#22388](https://github.com/arendst/Tasmota/issues/22388)
|
||||||
- Support for Shelly DALI Dimmer Gen3
|
- 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 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 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 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 spare16 : 1; // bit 16
|
||||||
uint32_t spare17 : 1; // bit 17
|
uint32_t spare17 : 1; // bit 17
|
||||||
uint32_t spare18 : 1; // bit 18
|
uint32_t spare18 : 1; // bit 18
|
||||||
|
@ -260,15 +260,11 @@ typedef union {
|
||||||
uint32_t spare16 : 1; // bit 16
|
uint32_t spare16 : 1; // bit 16
|
||||||
uint32_t spare17 : 1; // bit 17
|
uint32_t spare17 : 1; // bit 17
|
||||||
uint32_t spare18 : 1; // bit 18
|
uint32_t spare18 : 1; // bit 18
|
||||||
uint32_t spare19 : 1; // bit 19
|
uint32_t dali_group_sliders : 5; // bit 19.23 (v14.3.0.3) - (DALI) Number of group sliders 0 to 16
|
||||||
uint32_t spare20 : 1; // bit 20
|
uint32_t FTP_Mode : 2; // bit 24/25
|
||||||
uint32_t spare21 : 1; // bit 21
|
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 spare22 : 1; // bit 22
|
uint32_t sunrise_dawn_angle : 2; // bit 28/29 (v12.1.1.4) -
|
||||||
uint32_t spare23 : 1; // bit 23
|
uint32_t temperature_set_res : 2; // bit 30/31 (v9.3.1.4) - (Tuya)
|
||||||
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)
|
|
||||||
};
|
};
|
||||||
} SysMBitfield2;
|
} SysMBitfield2;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,6 @@
|
||||||
|
|
||||||
#define TASMOTA_SHA_SHORT // Filled by Github sed
|
#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_
|
#endif // _TASMOTA_VERSION_H_
|
||||||
|
|
|
@ -1838,6 +1838,9 @@ void SettingsDelta(void) {
|
||||||
if (Settings->version < 0x0E030002) { // 14.3.0.2
|
if (Settings->version < 0x0E030002) { // 14.3.0.2
|
||||||
Settings->sbflag1.dali_light = 1;
|
Settings->sbflag1.dali_light = 1;
|
||||||
}
|
}
|
||||||
|
if (Settings->version < 0x0E030004) { // 14.3.0.4
|
||||||
|
Settings->mbflag2.dali_group_sliders = 2;
|
||||||
|
}
|
||||||
|
|
||||||
Settings->version = TASMOTA_VERSION;
|
Settings->version = TASMOTA_VERSION;
|
||||||
SettingsSave(1);
|
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)'>"
|
"<input id='sl%d' type='range' min='%d' max='%d' value='%d' onchange='lc(\"%c\",%d,value)'>"
|
||||||
"</div>";
|
"</div>";
|
||||||
|
|
||||||
|
const char HTTP_MSG_SLIDER_UPDATE[] PROGMEM =
|
||||||
|
"<img style='display:none;' src onerror=";
|
||||||
|
|
||||||
const char HTTP_MSG_RSTRT[] PROGMEM =
|
const char HTTP_MSG_RSTRT[] PROGMEM =
|
||||||
"<br><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br>";
|
"<br><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br>";
|
||||||
|
|
||||||
|
@ -1354,7 +1357,7 @@ void HandleRoot(void)
|
||||||
WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE);
|
WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE);
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
WSContentButton(BUTTON_CONSOLE);
|
WSContentButton(BUTTON_CONSOLE);
|
||||||
#else
|
#else // Not FIRMWARE_MINIMAL
|
||||||
WSContentSpaceButton(BUTTON_CONFIGURATION);
|
WSContentSpaceButton(BUTTON_CONFIGURATION);
|
||||||
WSContentButton(BUTTON_INFORMATION);
|
WSContentButton(BUTTON_INFORMATION);
|
||||||
WSContentButton(BUTTON_FIRMWARE_UPGRADE);
|
WSContentButton(BUTTON_FIRMWARE_UPGRADE);
|
||||||
|
@ -1534,7 +1537,8 @@ bool HandleRootStatusRefresh(void)
|
||||||
if (current_value != Web.slider[i]) {
|
if (current_value != Web.slider[i]) {
|
||||||
Web.slider[i] = current_value;
|
Web.slider[i] = current_value;
|
||||||
// https://stackoverflow.com/questions/4057236/how-to-add-onload-event-to-a-div-element
|
// 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
|
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
|
1.0.0.2 20241025 update - Fix GPIO detection
|
||||||
- Fix ESP32(C3) transmit stability by disabling interrupts
|
- 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
|
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
|
// Address type - Send as first byte
|
||||||
#define DALI_BROADCAST_DP 0x00FE // 0b11111110 254 - Broadcast address
|
#define DALI_BROADCAST_DP 0x00FE // 0b11111110 254 - Broadcast address
|
||||||
|
|
||||||
|
#define DALI_MAX_STORED 17 // Store broadcast and group states
|
||||||
|
|
||||||
#define DALI_TOPIC "DALI"
|
#define DALI_TOPIC "DALI"
|
||||||
#define D_PRFX_DALI "Dali"
|
#define D_PRFX_DALI "Dali"
|
||||||
|
|
||||||
|
@ -272,14 +276,16 @@ const char kDALICommands[] PROGMEM = D_PRFX_DALI "|" // Prefix
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
"|Light"
|
"|Light"
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
||||||
"|Send|Query|Scan|Group|Gear";
|
"|Send|Query|Scan|Group"
|
||||||
|
"|GroupSliders|Gear";
|
||||||
|
|
||||||
void (* const DALICommand[])(void) PROGMEM = {
|
void (* const DALICommand[])(void) PROGMEM = {
|
||||||
&CmndDali, &CmndDaliPower, &CmndDaliDimmer, &CmndDaliTarget,
|
&CmndDali, &CmndDaliPower, &CmndDaliDimmer, &CmndDaliTarget,
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
&CmndDaliLight,
|
&CmndDaliLight,
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
||||||
&CmndDaliSend, &CmndDaliQuery, &CmndDaliScan, &CmndDaliGroup, &CmndDaliGear };
|
&CmndDaliSend, &CmndDaliQuery, &CmndDaliScan, &CmndDaliGroup,
|
||||||
|
&CmndDaliGroupSliders, &CmndDaliGear };
|
||||||
|
|
||||||
struct DALI {
|
struct DALI {
|
||||||
uint32_t bit_cycles;
|
uint32_t bit_cycles;
|
||||||
|
@ -290,9 +296,13 @@ struct DALI {
|
||||||
uint8_t max_short_address;
|
uint8_t max_short_address;
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
uint8_t command;
|
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;
|
uint8_t target;
|
||||||
bool power;
|
bool last_power;
|
||||||
|
bool power[DALI_MAX_STORED];
|
||||||
|
bool web_power[DALI_MAX_STORED];
|
||||||
bool available;
|
bool available;
|
||||||
bool response;
|
bool response;
|
||||||
bool light_sync;
|
bool light_sync;
|
||||||
|
@ -305,23 +315,23 @@ struct DALI {
|
||||||
* DALI low level
|
* DALI low level
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
uint32_t DaliTarget2Address(uint32_t target) {
|
uint32_t DaliTarget2Address(void) {
|
||||||
// 1..64 = Short address
|
// 1..64 = Short address
|
||||||
// 101..116 = Group address
|
// 101..116 = Group address
|
||||||
// Others = Broadcast
|
// Others = Broadcast
|
||||||
if ((target >= 1) && (target <= 64)) { // 1 .. 64
|
if ((Dali->target >= 1) && (Dali->target <= 64)) { // 1 .. 64
|
||||||
target -= 1; // Short address
|
Dali->target -= 1; // Short address
|
||||||
target <<= 1;
|
Dali->target <<= 1;
|
||||||
}
|
}
|
||||||
else if ((target >= 101) && (target <= 116)) { // 101 .. 116
|
else if ((Dali->target >= 101) && (Dali->target <= 116)) { // 101 .. 116
|
||||||
target -= 101;
|
Dali->target -= 101;
|
||||||
target <<= 1;
|
Dali->target <<= 1;
|
||||||
target |= 0x80; // Group address
|
Dali->target |= 0x80; // Group address
|
||||||
}
|
}
|
||||||
else { // Others
|
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) {
|
void DaliEnableRxInterrupt(void) {
|
||||||
Dali->available = false;
|
Dali->available = false;
|
||||||
attachInterrupt(Dali->pin_rx, DaliReceiveData, (Dali->invert_rx) ? RISING : FALLING);
|
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->address = adr;
|
||||||
Dali->command = cmd;
|
Dali->command = cmd;
|
||||||
if (DaliTarget2Address(Dali->target) == adr) {
|
DaliSaveState(adr, cmd);
|
||||||
repeat = true;
|
|
||||||
Dali->power = (cmd); // State
|
|
||||||
if (Dali->power) {
|
|
||||||
Dali->dimmer = cmd; // Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!repeat && (adr &0x01)) { // YAAAAAA1 Commands where user didn't set repeat
|
if (!repeat && (adr &0x01)) { // YAAAAAA1 Commands where user didn't set repeat
|
||||||
if ((adr >= 0xA1) && (adr <= 0xFD)) { // Special commands
|
if ((adr >= 0xA1) && (adr <= 0xFD)) { // Special commands
|
||||||
|
@ -751,25 +783,28 @@ uint32_t DaliCommission(uint8_t init_arg) {
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
DaliInitLight();
|
DaliInitLight();
|
||||||
uint32_t address = (Settings->sbflag1.dali_light) ? DaliTarget2Address(Dali->target) : DALI_BROADCAST_DP;
|
uint32_t address = (Settings->sbflag1.dali_light) ? DaliTarget2Address() : DALI_BROADCAST_DP;
|
||||||
DaliSendData(address, Dali->power); // Restore lights
|
DaliSendData(address, Dali->power[0]); // Restore lights
|
||||||
#else
|
#else
|
||||||
DaliSendData(DALI_BROADCAST_DP, Dali->power); // Restore lights
|
DaliSendData(DALI_BROADCAST_DP, Dali->power[0]); // Restore lights
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
void ResponseAppendDali(void) {
|
void ResponseAppendDali(uint32_t index) {
|
||||||
uint8_t dimmer = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
char number[12];
|
||||||
ResponseAppend_P(PSTR("\"DALI\":{\"Power\":\"%s\",\"Dimmer\":%d,\"Address\":%d,\"Command\":%d}"),
|
uint8_t dimmer = changeUIntScale(Dali->dimmer[index], 0, 254, 0, 100);
|
||||||
GetStateText(Dali->power), dimmer, Dali->address, Dali->command);
|
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("{"));
|
Response_P(PSTR("{"));
|
||||||
ResponseAppendDali();
|
ResponseAppendDali(index);
|
||||||
ResponseJsonEnd();
|
ResponseJsonEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,45 +822,32 @@ void DaliLoop(void) {
|
||||||
|
|
||||||
Dali->address = Dali->received_dali_data >> 8;
|
Dali->address = Dali->received_dali_data >> 8;
|
||||||
Dali->command = Dali->received_dali_data;
|
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;
|
bool show_response = true;
|
||||||
if (DaliTarget2Address(Dali->target) == Dali->address) {
|
#ifdef USE_LIGHT
|
||||||
uint8_t dimmer_old = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
if (DaliTarget2Address() == Dali->address) {
|
||||||
uint8_t power_old = Dali->power;
|
|
||||||
Dali->power = (Dali->command); // State
|
|
||||||
if (Dali->power) {
|
|
||||||
Dali->dimmer = Dali->command; // Value
|
|
||||||
}
|
|
||||||
if (Settings->sbflag1.dali_light) { // DaliLight 1
|
if (Settings->sbflag1.dali_light) { // DaliLight 1
|
||||||
uint8_t dimmer_new = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
uint8_t dim_old = changeUIntScale(Dali->last_dimmer, 0, 254, 0, 100);
|
||||||
if (power_old != Dali->power) {
|
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
|
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];
|
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
|
Dali->light_sync = true; // Block local loop
|
||||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||||
}
|
}
|
||||||
show_response = false;
|
show_response = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // USE_LIGHT
|
||||||
if (show_response) {
|
if (show_response) {
|
||||||
ResponseDali();
|
ResponseDali(index);
|
||||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_PRFX_DALI));
|
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;
|
Dali->available = false;
|
||||||
}
|
}
|
||||||
|
@ -850,7 +872,7 @@ bool DaliSetChannels(void) {
|
||||||
} else {
|
} else {
|
||||||
uint8_t value = ((uint8_t*)XdrvMailbox.data)[0];
|
uint8_t value = ((uint8_t*)XdrvMailbox.data)[0];
|
||||||
if (255 == value) { value = 254; } // Max Dali value
|
if (255 == value) { value = 254; } // Max Dali value
|
||||||
DaliSendData(DaliTarget2Address(Dali->target), value);
|
DaliSendData(DaliTarget2Address(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -900,7 +922,10 @@ bool DaliInit(void) {
|
||||||
#endif // DALI_DEBUG
|
#endif // DALI_DEBUG
|
||||||
|
|
||||||
Dali->max_short_address = 64;
|
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
|
// Manchester twice 1200 bps = 2400 bps = 417 (protocol 416.76 +/- 10%) us
|
||||||
Dali->bit_cycles = ESP.getCpuFreqMHz() * 1000000 / 2400;
|
Dali->bit_cycles = ESP.getCpuFreqMHz() * 1000000 / 2400;
|
||||||
|
|
||||||
|
@ -983,7 +1008,7 @@ void CmndDali(void) {
|
||||||
}
|
}
|
||||||
DaliJsonParse();
|
DaliJsonParse();
|
||||||
}
|
}
|
||||||
ResponseDali();
|
ResponseDali(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------*/
|
||||||
|
@ -1010,15 +1035,19 @@ void CmndDaliPower(void) {
|
||||||
// DaliPower0 0..254 - Broadcast control (= DaliPower)
|
// DaliPower0 0..254 - Broadcast control (= DaliPower)
|
||||||
// DaliPower1 0..254 - Short address 0 control
|
// DaliPower1 0..254 - Short address 0 control
|
||||||
// DaliPower3 0..254 - Short address 2 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)) ||
|
if (((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= 64)) ||
|
||||||
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 254)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 254)) {
|
||||||
if (XdrvMailbox.payload <= 2) {
|
if (XdrvMailbox.payload <= 2) {
|
||||||
if (2 == XdrvMailbox.payload) {
|
if (2 == XdrvMailbox.payload) {
|
||||||
XdrvMailbox.payload = (Dali->power) ? 0 : 1;
|
XdrvMailbox.payload = (Dali->power[index]) ? 0 : 1;
|
||||||
}
|
}
|
||||||
if (1 == XdrvMailbox.payload) {
|
if (1 == XdrvMailbox.payload) {
|
||||||
XdrvMailbox.payload = Dali->dimmer;
|
XdrvMailbox.payload = Dali->dimmer[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t DALIaddr = DALI_BROADCAST_DP;
|
uint32_t DALIaddr = DALI_BROADCAST_DP;
|
||||||
|
@ -1031,7 +1060,7 @@ void CmndDaliPower(void) {
|
||||||
DaliSendData(DALIaddr, XdrvMailbox.payload);
|
DaliSendData(DALIaddr, XdrvMailbox.payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponseDali();
|
ResponseDali(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndDaliDimmer(void) {
|
void CmndDaliDimmer(void) {
|
||||||
|
@ -1039,6 +1068,10 @@ void CmndDaliDimmer(void) {
|
||||||
// DaliDimmer0 0..100 - Broadcast set power off or dimmer state
|
// DaliDimmer0 0..100 - Broadcast set power off or dimmer state
|
||||||
// DaliDimmer1 0..100 - Short address 0 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
|
// 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)) ||
|
if (((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= 64)) ||
|
||||||
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||||
|
@ -1053,7 +1086,7 @@ void CmndDaliDimmer(void) {
|
||||||
DaliSendData(DALIaddr, dimmer);
|
DaliSendData(DALIaddr, dimmer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponseDali();
|
ResponseDali(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndDaliGroup(void) {
|
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
|
#ifdef USE_LIGHT
|
||||||
void CmndDaliLight(void) {
|
void CmndDaliLight(void) {
|
||||||
// DaliLight 0 - Disable light controls
|
// DaliLight 0 - Disable light controls
|
||||||
// DaliLight 1 - Enable light controls
|
// DaliLight 1 - Enable light controls
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
Settings->sbflag1.dali_light = XdrvMailbox.payload &1;
|
Settings->sbflag1.dali_light = XdrvMailbox.payload &1;
|
||||||
TasmotaGlobal.restart_flag = 2;
|
TasmotaGlobal.restart_flag = 2; // Restart to update GUI
|
||||||
}
|
}
|
||||||
ResponseCmndStateText(Settings->sbflag1.dali_light);
|
ResponseCmndStateText(Settings->sbflag1.dali_light);
|
||||||
}
|
}
|
||||||
|
@ -1185,10 +1228,86 @@ void CmndDaliLight(void) {
|
||||||
* Presentation
|
* 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) {
|
void DaliShow(bool json) {
|
||||||
if (json) {
|
if (json) {
|
||||||
ResponseAppend_P(PSTR(","));
|
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;
|
break;
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
case FUNC_WEB_SENSOR:
|
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;
|
break;
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
case FUNC_COMMAND:
|
case FUNC_COMMAND:
|
||||||
|
|
Loading…
Reference in New Issue