mirror of https://github.com/arendst/Tasmota.git
Update changelogs
Add DALI short address and group support
This commit is contained in:
parent
e39f1cc83f
commit
4948b70acd
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -5,10 +5,13 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [14.3.0.1]
|
## [14.3.0.1]
|
||||||
### Added
|
### Added
|
||||||
|
- BLE track devices with RPA (#22300)
|
||||||
|
- DALI support for short addresses and groups
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- ESP32 platform update from 2024.09.30 to 2024.10.30 and Framework (Arduino Core) from v3.1.0.240926 to v3.1.0.241015 (#22299)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -30,11 +33,11 @@ All notable changes to this project will be documented in this file.
|
||||||
- Command ``DaliSend <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus
|
- Command ``DaliSend <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus
|
||||||
- Command ``DaliQuery <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus and wait up to DALI_TIMEOUT ms for response
|
- Command ``DaliQuery <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus and wait up to DALI_TIMEOUT ms for response
|
||||||
- Berry Serial `config` to change parity on-the-fly for RS-485 (#22285)
|
- Berry Serial `config` to change parity on-the-fly for RS-485 (#22285)
|
||||||
- Misubishi Electric HVAC Heat/Dry/Cool Auto operation mode (#22216)
|
- Mitsubishi Electric HVAC Heat/Dry/Cool Auto operation mode (#22216)
|
||||||
- Misubishi Electric HVAC Bridge to HomeBridge/Homekit locally (#22236)
|
- Mitsubishi Electric HVAC Bridge to HomeBridge/Homekit locally (#22236)
|
||||||
- Misubishi Electric HVAC Air Direction Control (#22241)
|
- Mitsubishi Electric HVAC Air Direction Control (#22241)
|
||||||
- Misubishi Electric HVAC prohibit function (#22269)
|
- Mitsubishi Electric HVAC prohibit function (#22269)
|
||||||
- Misubishi Electric HVAC compressor map and operation power and energy (#22290)
|
- Mitsubishi Electric HVAC compressor map and operation power and energy (#22290)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- ESP32 platform update from 2024.09.10 to 2024.09.30 and Framework (Arduino Core) from v3.0.5 to v3.1.0.240926 (#22203)
|
- ESP32 platform update from 2024.09.10 to 2024.09.30 and Framework (Arduino Core) from v3.0.5 to v3.1.0.240926 (#22203)
|
||||||
|
|
|
@ -116,10 +116,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
||||||
|
|
||||||
## Changelog v14.3.0.1
|
## Changelog v14.3.0.1
|
||||||
### Added
|
### Added
|
||||||
|
- DALI support for short addresses and groups
|
||||||
|
- BLE track devices with RPA [#22300](https://github.com/arendst/Tasmota/issues/22300)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- ESP32 platform update from 2024.09.30 to 2024.10.30 and Framework (Arduino Core) from v3.1.0.240926 to v3.1.0.241015 [#22299](https://github.com/arendst/Tasmota/issues/22299)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
Version yyyymmdd Action Description
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
|
0.1.0.7 20241017 update - Add command `DaliCommission 1|2` assigning short addresses
|
||||||
|
- Add command `DaliTarget 0, 1..64, 101..116` to select light control address
|
||||||
|
- Add command `DaliGroup1..16 +<devices>|-<devices>` to add/remove devices from group
|
||||||
|
- Extend commands `DaliPower` and `DaliDimmer` with index to control short address or group
|
||||||
|
- Remove non-functional MQTT interface
|
||||||
0.1.0.6 20241014 update - Fix received light command loop
|
0.1.0.6 20241014 update - Fix received light command loop
|
||||||
- Add send collision detection
|
- Add send collision detection
|
||||||
0.1.0.5 20241014 update - Add command `DaliSend [repeat]<address>,<command>`
|
0.1.0.5 20241014 update - Add command `DaliSend [repeat]<address>,<command>`
|
||||||
|
@ -43,6 +48,29 @@
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* DALI support for Tasmota
|
* DALI support for Tasmota
|
||||||
|
*
|
||||||
|
* Available commands:
|
||||||
|
* <first byte> = 0..255 or 0x00..0xFF + 256/0x100 for optional repeat (send twice)
|
||||||
|
* <second byte> = 0..255 or 0x00..0xFF - Both decimal and hexadecimal is supported
|
||||||
|
* <broadcast> = 0 - DALI default
|
||||||
|
* <device> = 1..64 - DALI short address + 1
|
||||||
|
* <group> = 101..116 - DALI group + 101
|
||||||
|
* DaliSend <first byte>,<second byte> - Execute DALI code and do not expect a DALI backward frame
|
||||||
|
* DaliQuery <first byte>,<second byte> - Execute DALI code and report result (DALI backward frame)
|
||||||
|
* DaliCommission 1|2 - Reset (0) or (1)/and commission device short addresses
|
||||||
|
* DaliGroup<1..16> [+]|-<device>,<device>... - Add(+) or Remove(-) devices to/from group
|
||||||
|
* DaliPower<broadcast>|<device>|<group> 0..254 - Control power (0 = Off, 1 = Last dimmer, 2 = Toggle, 3..254 = absolute light brightness)
|
||||||
|
* DaliDimmer<broadcast>|<device>|<group> 0..100 - Control dimmer (0 = Off, 1..100 = precentage of brightness)
|
||||||
|
* DaliWeb 0|1 - Enable Tasmota light control for DaliTarget device
|
||||||
|
* DaliTarget <broadcast>|<device>|<group> - Set Tasmota light control device (0, 1..64, 101..116)
|
||||||
|
*
|
||||||
|
* Address type Address byte
|
||||||
|
* ------------------ --------------------
|
||||||
|
* Broadcast address 1111111S
|
||||||
|
* 64 short address 0AAAAAAS
|
||||||
|
* 16 group address 100AAAAS
|
||||||
|
* Special command 101CCCC1 to 110CCCC1
|
||||||
|
* A = Address bit, S = 0 Direct Arc Power control, S = 1 Command, C = Special command
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
#define XDRV_75 75
|
#define XDRV_75 75
|
||||||
|
@ -71,18 +99,18 @@
|
||||||
#define D_PRFX_DALI "Dali"
|
#define D_PRFX_DALI "Dali"
|
||||||
|
|
||||||
const char kDALICommands[] PROGMEM = D_PRFX_DALI "|" // Prefix
|
const char kDALICommands[] PROGMEM = D_PRFX_DALI "|" // Prefix
|
||||||
"|" D_CMND_POWER
|
"|" D_CMND_POWER "|" D_CMND_DIMMER "|Target"
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
"|Web"
|
"|Web"
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
||||||
"|" D_CMND_DIMMER "|Send|Query" ;
|
"|Send|Query|Commission|Group";
|
||||||
|
|
||||||
void (* const DALICommand[])(void) PROGMEM = {
|
void (* const DALICommand[])(void) PROGMEM = {
|
||||||
&CmndDali, &CmndDaliPower,
|
&CmndDali, &CmndDaliPower, &CmndDaliDimmer, &CmndDaliTarget,
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
&CmndDaliWeb,
|
&CmndDaliWeb,
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
||||||
&CmndDaliDimmer, &CmndDaliSend, &CmndDaliQuery };
|
&CmndDaliSend, &CmndDaliQuery, &CmndDaliCommission, &CmndDaliGroup };
|
||||||
|
|
||||||
struct DALI {
|
struct DALI {
|
||||||
uint32_t bit_time;
|
uint32_t bit_time;
|
||||||
|
@ -92,6 +120,7 @@ struct DALI {
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
uint8_t dimmer;
|
uint8_t dimmer;
|
||||||
|
uint8_t target;
|
||||||
bool power;
|
bool power;
|
||||||
bool available;
|
bool available;
|
||||||
bool response;
|
bool response;
|
||||||
|
@ -102,6 +131,35 @@ struct DALI {
|
||||||
* DALI low level
|
* DALI low level
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
uint32_t DaliTarget2Address(uint32_t target) {
|
||||||
|
// 1..64 = Short address
|
||||||
|
// 101..116 = Group address
|
||||||
|
// Others = Broadcast
|
||||||
|
if ((target >= 1) && (target <= 64)) { // 1 .. 64
|
||||||
|
target -= 1; // Short address
|
||||||
|
target <<= 1;
|
||||||
|
}
|
||||||
|
else if ((target >= 101) && (target <= 116)) { // 101 .. 116
|
||||||
|
target -= 101;
|
||||||
|
target <<= 1;
|
||||||
|
target |= 0x80; // Group address
|
||||||
|
}
|
||||||
|
else { // Others
|
||||||
|
target = DALI_BROADCAST_DP; // Broadcast address
|
||||||
|
}
|
||||||
|
return target &0xFE; // Direct Arc Power Control command
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
uint32_t DaliAddress2Target(uint32_t adr) {
|
||||||
|
if (adr >= 254) { // 0b1111111S
|
||||||
|
return 0; // Broadcast address (0)
|
||||||
|
}
|
||||||
|
else if ((adr >= 128) && (adr <= 159)) { // 0b1000000S .. 0b1001111S
|
||||||
|
return (adr >> 1) +101; // Group address (101 .. 116)
|
||||||
|
}
|
||||||
|
return (adr >> 1) +1; // 0b0000000S .. 0b0111111S Short address (1 .. 64)
|
||||||
|
}
|
||||||
|
*/
|
||||||
void DaliEnableRxInterrupt(void) {
|
void DaliEnableRxInterrupt(void) {
|
||||||
Dali->available = false;
|
Dali->available = false;
|
||||||
attachInterrupt(Dali->pin_rx, DaliReceiveData, FALLING);
|
attachInterrupt(Dali->pin_rx, DaliReceiveData, FALLING);
|
||||||
|
@ -243,7 +301,7 @@ void DaliSendData(uint32_t adr, uint32_t cmd) {
|
||||||
|
|
||||||
Dali->address = adr;
|
Dali->address = adr;
|
||||||
Dali->command = cmd;
|
Dali->command = cmd;
|
||||||
if (DALI_BROADCAST_DP == adr) {
|
if (DaliTarget2Address(Dali->target) == adr) {
|
||||||
repeat = true;
|
repeat = true;
|
||||||
Dali->power = (cmd); // State
|
Dali->power = (cmd); // State
|
||||||
if (Dali->power) {
|
if (Dali->power) {
|
||||||
|
@ -263,6 +321,10 @@ void DaliSendData(uint32_t adr, uint32_t cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DALI_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: SendData Repeat %d, Adr 0x%02X, Cmd 0x%02x"), repeat, adr, cmd);
|
||||||
|
#endif // DALI_DEBUG
|
||||||
|
|
||||||
uint16_t send_dali_data = adr << 8 | cmd;
|
uint16_t send_dali_data = adr << 8 | cmd;
|
||||||
|
|
||||||
DaliDisableRxInterrupt();
|
DaliDisableRxInterrupt();
|
||||||
|
@ -289,13 +351,164 @@ int DaliSendWaitResponse(uint32_t adr, uint32_t cmd, uint32_t timeout) {
|
||||||
result = Dali->received_dali_data;
|
result = Dali->received_dali_data;
|
||||||
}
|
}
|
||||||
Dali->response = false;
|
Dali->response = false;
|
||||||
|
|
||||||
|
#ifdef DALI_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: SendWaitResponse result %d = 0x%04X"), result, result);
|
||||||
|
#endif // DALI_DEBUG
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaliPower(uint32_t val) {
|
/*********************************************************************************************\
|
||||||
DaliSendData(DALI_BROADCAST_DP, val);
|
* DALI commissioning short addresses
|
||||||
|
*
|
||||||
|
* Courtesy of https://github.com/qqqlab/DALI-Lighting-Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
// Query commands - Send as second byte
|
||||||
|
#define DALI_QUERY_STATUS 0x0090 // 144 - Returns "STATUS INFORMATION"
|
||||||
|
|
||||||
|
// Special commands - Send as first byte
|
||||||
|
#define DALI_TERMINATE 0x00A1 // 256 - Releases the INITIALISE state.
|
||||||
|
#define DALI_INITIALISE 0x01A5 // 258 REPEAT - Sets the slave to the INITIALISE status for15 minutes. Commands 259 to 270 are enabled only for a slave in this status.
|
||||||
|
#define DALI_RANDOMISE 0x01A7 // 259 REPEAT - Generates a random address.
|
||||||
|
#define DALI_COMPARE 0x00A9 // 260 - Is the random address smaller or equal to the search address?
|
||||||
|
#define DALI_WITHDRAW 0x00AB // 261 - Excludes slaves for which the random address and search address match from the Compare process.
|
||||||
|
#define DALI_SEARCHADDRH 0x00B1 // 264 - Specifies the higher 8 bits of the search address.
|
||||||
|
#define DALI_SEARCHADDRM 0x00B3 // 265 - Specifies the middle 8 bits of the search address.
|
||||||
|
#define DALI_SEARCHADDRL 0x00B5 // 266 - Specifies the lower 8 bits of the search address.
|
||||||
|
#define DALI_PROGRAM_SHORT_ADDRESS 0x00B7 // 267 - The slave shall store the received 6-bit address (AAA AAA) as a short address if it is selected.
|
||||||
|
|
||||||
|
void DaliSetSearchAddress(uint32_t adr) {
|
||||||
|
// Set search address
|
||||||
|
DaliSendData(DALI_SEARCHADDRH, adr>>16);
|
||||||
|
DaliSendData(DALI_SEARCHADDRM, adr>>8);
|
||||||
|
DaliSendData(DALI_SEARCHADDRL, adr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DaliSetSearchAddressDifference(uint32_t adr_new, uint32_t adr_current) {
|
||||||
|
// Set search address, but set only changed bytes (takes less time)
|
||||||
|
if ( (uint8_t)(adr_new>>16) != (uint8_t)(adr_current>>16) ) DaliSendData(DALI_SEARCHADDRH, adr_new>>16);
|
||||||
|
if ( (uint8_t)(adr_new>>8) != (uint8_t)(adr_current>>8) ) DaliSendData(DALI_SEARCHADDRM, adr_new>>8);
|
||||||
|
if ( (uint8_t)(adr_new) != (uint8_t)(adr_current) ) DaliSendData(DALI_SEARCHADDRL, adr_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaliCompare() {
|
||||||
|
// Is the random address smaller or equal to the search address?
|
||||||
|
// As more than one device can reply, the reply gets garbled
|
||||||
|
uint8_t retry = 2;
|
||||||
|
while (retry > 0) {
|
||||||
|
// Compare is true if we received any activity on the bus as reply.
|
||||||
|
// Sometimes the reply is not registered... so only accept retry times 'no reply' as a real false compare
|
||||||
|
int rv = DaliSendWaitResponse(DALI_COMPARE, 0x00);
|
||||||
|
if (rv == 0xFF) return true; // Yes reply
|
||||||
|
retry--;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DaliFindAddress(void) {
|
||||||
|
// Find addr with binary search
|
||||||
|
uint32_t adr = 0x800000;
|
||||||
|
uint32_t addsub = 0x400000;
|
||||||
|
uint32_t adr_last = adr;
|
||||||
|
DaliSetSearchAddress(adr);
|
||||||
|
|
||||||
|
while (addsub) {
|
||||||
|
DaliSetSearchAddressDifference(adr, adr_last);
|
||||||
|
adr_last = adr;
|
||||||
|
if (DaliCompare()) { // Returns true if searchadr > adr
|
||||||
|
adr -= addsub;
|
||||||
|
} else {
|
||||||
|
adr += addsub;
|
||||||
|
}
|
||||||
|
addsub >>= 1;
|
||||||
|
}
|
||||||
|
DaliSetSearchAddressDifference(adr, adr_last);
|
||||||
|
adr_last = adr;
|
||||||
|
if (!DaliCompare()) {
|
||||||
|
adr++;
|
||||||
|
DaliSetSearchAddressDifference(adr, adr_last);
|
||||||
|
}
|
||||||
|
return adr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaliProgramShortAddress(uint8_t shortadr) {
|
||||||
|
// The slave shall store the received 6-bit address (AAAAAA) as a short address if it is selected.
|
||||||
|
DaliSendData(DALI_PROGRAM_SHORT_ADDRESS, (shortadr << 1) | 0x01);
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Set short address %d"), shortadr +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DaliCommission(uint8_t init_arg) {
|
||||||
|
// init_arg=11111111 : all without short address
|
||||||
|
// init_arg=00000000 : all
|
||||||
|
// init_arg=0AAAAAA1 : only for this shortadr
|
||||||
|
// returns number of new short addresses assigned
|
||||||
|
DaliSendData(DALI_BROADCAST_DP, 0); // Turn all OFF
|
||||||
|
delay(100); // Need 100ms pause before starting commissioning
|
||||||
|
|
||||||
|
uint8_t arr[64];
|
||||||
|
uint32_t sa;
|
||||||
|
for (sa = 0; sa < 64; sa++) {
|
||||||
|
arr[sa] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start commissioning
|
||||||
|
DaliSendData(DALI_INITIALISE, init_arg);
|
||||||
|
DaliSendData(DALI_RANDOMISE, 0x00);
|
||||||
|
delay(100); // Need 100ms pause after RANDOMISE
|
||||||
|
|
||||||
|
// Find used short addresses (run always, seems to work better than without...)
|
||||||
|
for (sa = 0; sa < 64; sa++) {
|
||||||
|
int rv = DaliSendWaitResponse(sa << 1 | 1, DALI_QUERY_STATUS);
|
||||||
|
if (rv >= 0) {
|
||||||
|
if (init_arg != 0b00000000) {
|
||||||
|
arr[sa] = 1; // Remove address from list if not in "all" mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
while (true) { // Find random addresses and assign unused short addresses
|
||||||
|
uint32_t adr = DaliFindAddress();
|
||||||
|
if (adr > 0xffffff) { break; } // No more random addresses found -> exit
|
||||||
|
for (sa = 0; sa < 64; sa++) { // Find first unused short address
|
||||||
|
if (0 == arr[sa]) { break; }
|
||||||
|
}
|
||||||
|
if( sa >= 64) { break; } // All 64 short addresses assigned -> exit
|
||||||
|
arr[sa] = 1; // Mark short address as used
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
DaliProgramShortAddress(sa); // Assign short address
|
||||||
|
DaliSendData(DALI_WITHDRAW, 0x00); // Remove the device from the search
|
||||||
|
|
||||||
|
delay(1);
|
||||||
|
OsWatchLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
DaliSendData(DALI_TERMINATE, 0x00); // Terminate the DALI_INITIALISE command
|
||||||
|
|
||||||
|
for (sa = 0; sa < cnt; sa++) {
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Flash short address %d"), sa +1);
|
||||||
|
|
||||||
|
DaliSendData(sa << 1, 200); // Flash assigned lights
|
||||||
|
delay(1000);
|
||||||
|
OsWatchLoop();
|
||||||
|
DaliSendData(sa << 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* DALI group management
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
// Configuration commands - Send as second byte
|
||||||
|
#define DALI_ADD_TO_GROUP0 0x0060 // 96 - Adds the slave to Group XXXX.
|
||||||
|
#define DALI_REMOVE_FROM_GROUP0 0x0070 // 112 - Deletes the slave from Group XXXX.
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
|
|
||||||
void ResponseAppendDali(void) {
|
void ResponseAppendDali(void) {
|
||||||
|
@ -318,7 +531,7 @@ void DaliInput(void) {
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
bool show_response = true;
|
bool show_response = true;
|
||||||
if (DALI_BROADCAST_DP == Dali->address) {
|
if (DaliTarget2Address(Dali->target) == Dali->address) {
|
||||||
uint8_t dimmer_old = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
uint8_t dimmer_old = changeUIntScale(Dali->dimmer, 0, 254, 0, 100);
|
||||||
uint8_t power_old = Dali->power;
|
uint8_t power_old = Dali->power;
|
||||||
Dali->power = (Dali->command); // State
|
Dali->power = (Dali->command); // State
|
||||||
|
@ -345,7 +558,7 @@ void DaliInput(void) {
|
||||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_PRFX_DALI));
|
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_PRFX_DALI));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (DALI_BROADCAST_DP == Dali->address) {
|
if (DaliTarget2Address(Dali->target) == Dali->address) {
|
||||||
Dali->power = (Dali->command); // State
|
Dali->power = (Dali->command); // State
|
||||||
if (Dali->power) {
|
if (Dali->power) {
|
||||||
Dali->dimmer = Dali->command; // Value
|
Dali->dimmer = Dali->command; // Value
|
||||||
|
@ -366,7 +579,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
|
||||||
DaliPower(value);
|
DaliSendData(DaliTarget2Address(Dali->target), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -411,84 +624,6 @@ bool DaliInit(void) {
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Experimental - Not functioning
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
bool DaliMqtt(void) {
|
|
||||||
/*
|
|
||||||
XdrvMailbox.topic = topic;
|
|
||||||
XdrvMailbox.index = strlen(topic);
|
|
||||||
XdrvMailbox.data = (char*)data;
|
|
||||||
XdrvMailbox.data_len = data_len;
|
|
||||||
|
|
||||||
This won't work as there is currently no subscribe done
|
|
||||||
*/
|
|
||||||
char stopic[TOPSZ];
|
|
||||||
strncpy(stopic, XdrvMailbox.topic, TOPSZ);
|
|
||||||
XdrvMailbox.topic[TOPSZ - 1] = 0;
|
|
||||||
|
|
||||||
char *items[10];
|
|
||||||
char *p = stopic;
|
|
||||||
int cnt = 0;
|
|
||||||
do {
|
|
||||||
items[cnt] = strtok(p, "/");
|
|
||||||
cnt++;
|
|
||||||
p = nullptr;
|
|
||||||
} while (items[cnt - 1]);
|
|
||||||
cnt--; // represents the number of items
|
|
||||||
|
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Cnt %d, Topic '%s', Payload '%s'"), cnt, XdrvMailbox.topic, XdrvMailbox.data);
|
|
||||||
|
|
||||||
if (cnt < 3) { // not for us?
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("DLI: Cnt %d < 3"), cnt);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DALIindex = 0;
|
|
||||||
int ADRindex = 0;
|
|
||||||
int CMDindex = 0;
|
|
||||||
uint8_t DALIaddr = DALI_BROADCAST_DP;
|
|
||||||
|
|
||||||
if (strcasecmp_P(items[cnt - 3], PSTR(DALI_TOPIC)) != 0) { // dali
|
|
||||||
// cmnd
|
|
||||||
if (strcasecmp_P(items[cnt - 2], PSTR(DALI_TOPIC)) != 0) { // dali
|
|
||||||
// device
|
|
||||||
return false; // not for us
|
|
||||||
} else {
|
|
||||||
// cmnd/dali/percent
|
|
||||||
DALIindex = cnt - 2;
|
|
||||||
CMDindex = cnt - 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// dali/percent/2 20
|
|
||||||
DALIindex = cnt - 3;
|
|
||||||
CMDindex = cnt - 2;
|
|
||||||
ADRindex = cnt - 1;
|
|
||||||
DALIaddr = ((int)CharToFloat(items[ADRindex])) << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t level;
|
|
||||||
uint8_t value = (uint8_t)CharToFloat(XdrvMailbox.data);
|
|
||||||
if (strcasecmp_P(items[CMDindex], PSTR("percent")) == 0) {
|
|
||||||
// dali/percent/
|
|
||||||
float percent = (float)(254 * value * 0.01);
|
|
||||||
level = (uint8_t)percent;
|
|
||||||
}
|
|
||||||
else if (strcasecmp_P(items[CMDindex], PSTR("level")) == 0) {
|
|
||||||
level = value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
AddLog(LOG_LEVEL_INFO,PSTR("DLI: Command not recognized: %s"), items[CMDindex]);
|
|
||||||
return false; // not for us
|
|
||||||
}
|
|
||||||
|
|
||||||
AddLog(LOG_LEVEL_INFO,PSTR("DLI: Dali value %d on address %d"), value, DALIaddr);
|
|
||||||
DaliSendData(DALIaddr, level);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Commands
|
* Commands
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -548,11 +683,30 @@ void CmndDali(void) {
|
||||||
ResponseDali();
|
ResponseDali();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CmndDaliTarget(void) {
|
||||||
|
// DaliTarget - Set transmit target
|
||||||
|
// DaliTarget 0 - Set target to broadcast address
|
||||||
|
// DaliTarget 1..64 - Set target to short address
|
||||||
|
// DaliTarget 101..116 - Set target to group address
|
||||||
|
if (((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 64)) ||
|
||||||
|
((XdrvMailbox.payload >= 101) && (XdrvMailbox.payload <= 116)) ||
|
||||||
|
(XdrvMailbox.payload == 0)) {
|
||||||
|
Dali->target = XdrvMailbox.payload;
|
||||||
|
}
|
||||||
|
ResponseCmndNumber(Dali->target);
|
||||||
|
}
|
||||||
|
|
||||||
void CmndDaliPower(void) {
|
void CmndDaliPower(void) {
|
||||||
// DaliPower 0 - Power off
|
// DaliPower 0 - Broadcast power off
|
||||||
// DaliPower 1 - Power on to last dimmer state
|
// DaliPower 1 - Broadcast power on to last dimmer state
|
||||||
// DaliPower 2 - Toggle power off or last dimmer state
|
// DaliPower 2 - Broadcast toggle power off or last dimmer state
|
||||||
// DaliPower 3..254 - Equals DaliDimmer command
|
// DaliPower 3..254 - Broadcast equals DaliDimmer command
|
||||||
|
// DaliPower 0..254 - Broadcast control
|
||||||
|
// DaliPower0 0..254 - Broadcast control (= DaliPower)
|
||||||
|
// DaliPower1 0..254 - Short address 0 control
|
||||||
|
// DaliPower3 0..254 - Short address 2 control
|
||||||
|
if (((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= 64)) ||
|
||||||
|
((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) {
|
||||||
|
@ -562,23 +716,76 @@ void CmndDaliPower(void) {
|
||||||
XdrvMailbox.payload = Dali->dimmer;
|
XdrvMailbox.payload = Dali->dimmer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DaliPower(XdrvMailbox.payload);
|
uint32_t DALIaddr = DALI_BROADCAST_DP;
|
||||||
|
if (XdrvMailbox.index >= 101) {
|
||||||
|
DALIaddr = ((XdrvMailbox.index -101) << 1) | 0x80; // Group address
|
||||||
|
}
|
||||||
|
else if ((XdrvMailbox.index > 0) && XdrvMailbox.usridx) {
|
||||||
|
DALIaddr = (XdrvMailbox.index -1) << 1; // Short address
|
||||||
|
}
|
||||||
|
DaliSendData(DALIaddr, XdrvMailbox.payload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ResponseDali();
|
ResponseDali();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndDaliDimmer(void) {
|
void CmndDaliDimmer(void) {
|
||||||
// DaliDimmer 0..100 - Set power off or dimmer state
|
// DaliDimmer 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
|
||||||
|
// DaliDimmer3 0..100 - Short address 2 set power off or dimmer state
|
||||||
|
if (((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= 64)) ||
|
||||||
|
((XdrvMailbox.index >= 101) && (XdrvMailbox.index <= 116))) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||||
uint8_t dimmer = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 254);
|
uint8_t dimmer = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 254);
|
||||||
DaliPower(dimmer);
|
uint32_t DALIaddr = DALI_BROADCAST_DP;
|
||||||
|
if (XdrvMailbox.index >= 101) {
|
||||||
|
DALIaddr = ((XdrvMailbox.index -101) << 1) | 0x80; // Group address
|
||||||
|
}
|
||||||
|
else if ((XdrvMailbox.index > 0) && XdrvMailbox.usridx) {
|
||||||
|
DALIaddr = (XdrvMailbox.index -1) << 1; // Short address
|
||||||
|
}
|
||||||
|
DaliSendData(DALIaddr, dimmer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ResponseDali();
|
ResponseDali();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CmndDaliGroup(void) {
|
||||||
|
// DaliGroup1 1,2 - Add device 1 and 2 to group 1
|
||||||
|
// DaliGroup1 -1,2 - Remove device 1 and 2 to group 1
|
||||||
|
if ((XdrvMailbox.index >= 1) && (XdrvMailbox.index <= 16)) {
|
||||||
|
if (XdrvMailbox.data_len) {
|
||||||
|
uint32_t command = DALI_ADD_TO_GROUP0;
|
||||||
|
if ('+' == XdrvMailbox.data[0]) { // Add devices
|
||||||
|
XdrvMailbox.data++;
|
||||||
|
XdrvMailbox.data_len--;
|
||||||
|
}
|
||||||
|
else if ('-' == XdrvMailbox.data[0]) { // Remove devices
|
||||||
|
command = DALI_REMOVE_FROM_GROUP0;
|
||||||
|
XdrvMailbox.data++;
|
||||||
|
XdrvMailbox.data_len--;
|
||||||
|
}
|
||||||
|
uint32_t argc = ArgC(); // Number of devices
|
||||||
|
if (argc) {
|
||||||
|
command |= (XdrvMailbox.index -1);
|
||||||
|
uint32_t sas[argc];
|
||||||
|
ParseParameters(argc, sas);
|
||||||
|
for (uint32_t arg = 0; arg < argc; arg++) {
|
||||||
|
uint32_t sa = sas[arg] -1;
|
||||||
|
if (sa <= 63) {
|
||||||
|
DaliSendData(sa << 1 | 0x01, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResponseCmndDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CmndDaliSend(void) {
|
void CmndDaliSend(void) {
|
||||||
// Send command
|
// Send command
|
||||||
// Setting bit 8 will repeat command twice
|
// Setting bit 8 will repeat command once
|
||||||
// DaliSend 0x1a5,255 - DALI Initialise (send twice)
|
// DaliSend 0x1a5,255 - DALI Initialise (send twice)
|
||||||
uint32_t values[2] = { 0 };
|
uint32_t values[2] = { 0 };
|
||||||
uint32_t params = ParseParameters(2, values);
|
uint32_t params = ParseParameters(2, values);
|
||||||
|
@ -590,7 +797,7 @@ void CmndDaliSend(void) {
|
||||||
|
|
||||||
void CmndDaliQuery(void) {
|
void CmndDaliQuery(void) {
|
||||||
// Send command and return response or -1 (no response within DALI_TIMEOUT)
|
// Send command and return response or -1 (no response within DALI_TIMEOUT)
|
||||||
// Setting bit 8 will repeat command twice
|
// Setting bit 8 will repeat command once
|
||||||
// DaliQuery 0xff,0x90 - DALI Query status
|
// DaliQuery 0xff,0x90 - DALI Query status
|
||||||
// DaliQuery 0xff,144 - DALI Query status
|
// DaliQuery 0xff,144 - DALI Query status
|
||||||
uint32_t values[2] = { 0 };
|
uint32_t values[2] = { 0 };
|
||||||
|
@ -601,6 +808,20 @@ void CmndDaliQuery(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CmndDaliCommission(void) {
|
||||||
|
// Commission short addresses
|
||||||
|
// DaliCommission 1 - Reset and commission short addresses
|
||||||
|
// DaliCommission 2 - Commission unassigned short addresses
|
||||||
|
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 2)) {
|
||||||
|
uint32_t init_arg = 0x00; // Commission all
|
||||||
|
if (2 == XdrvMailbox.payload) {
|
||||||
|
init_arg = 0xFF; // Commission all without short addresses
|
||||||
|
}
|
||||||
|
int result = DaliCommission(init_arg);
|
||||||
|
ResponseCmndNumber(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
void CmndDaliWeb(void) {
|
void CmndDaliWeb(void) {
|
||||||
// DaliWeb 0 - Disable GUI light controls
|
// DaliWeb 0 - Disable GUI light controls
|
||||||
|
@ -639,9 +860,6 @@ bool Xdrv75(uint32_t function) {
|
||||||
case FUNC_LOOP:
|
case FUNC_LOOP:
|
||||||
DaliInput();
|
DaliInput();
|
||||||
break;
|
break;
|
||||||
case FUNC_MQTT_DATA:
|
|
||||||
result = DaliMqtt();
|
|
||||||
break;
|
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
case FUNC_SET_CHANNELS:
|
case FUNC_SET_CHANNELS:
|
||||||
result = DaliSetChannels();
|
result = DaliSetChannels();
|
||||||
|
|
Loading…
Reference in New Issue