mirror of https://github.com/arendst/Tasmota.git
Merge pull request #4075 from digiblur/development
Initial Tuya Dimmer Support
This commit is contained in:
commit
cd9987111e
|
@ -208,7 +208,7 @@ enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, D
|
|||
|
||||
enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER };
|
||||
enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE };
|
||||
enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC};
|
||||
enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_SERIAL, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC};
|
||||
enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC};
|
||||
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
||||
|
||||
|
|
|
@ -200,6 +200,8 @@ char mqtt_data[MESSZ]; // MQTT publish buffer and web page
|
|||
char log_data[LOGSZ]; // Logging
|
||||
char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer
|
||||
String backlog[MAX_BACKLOG]; // Command backlog
|
||||
uint8_t tuya_new_dim = 0; // Tuya dimmer value temp
|
||||
boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
@ -350,6 +352,23 @@ void SetDevicePower(power_t rpower, int source)
|
|||
Serial.write('\n');
|
||||
Serial.flush();
|
||||
}
|
||||
else if (TUYA_DIMMER == Settings.module && source != SRC_SWITCH ) { // ignore to prevent loop from pushing state from faceplate interaction
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
Serial.write(0x55); // Tuya header 55AA
|
||||
Serial.write(0xAA);
|
||||
Serial.write(0x00); // version 00
|
||||
Serial.write(0x06); // Tuya command 06
|
||||
Serial.write(0x00);
|
||||
Serial.write(0x05); // following data length 0x05
|
||||
Serial.write(0x01); // relay number 1,2,3
|
||||
Serial.write(0x01);
|
||||
Serial.write(0x00);
|
||||
Serial.write(0x01);
|
||||
Serial.write(rpower); // status
|
||||
Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256
|
||||
Serial.flush();
|
||||
}
|
||||
else if (EXS_RELAY == Settings.module) {
|
||||
SetLatchingRelay(rpower, 1);
|
||||
}
|
||||
|
@ -2215,6 +2234,48 @@ void ArduinoOTAInit()
|
|||
|
||||
/********************************************************************************************/
|
||||
|
||||
void TuyaPacketProcess()
|
||||
{
|
||||
char scmnd[20];
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), serial_in_byte_counter);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat"));
|
||||
}
|
||||
if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet
|
||||
if (serial_in_buffer[10] == 0) {
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - Off State"));
|
||||
ExecuteCommandPower(1, 0, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
||||
} else
|
||||
{
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd - On State"));
|
||||
ExecuteCommandPower(1, 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
||||
}
|
||||
serial_in_byte_counter = 0;
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
}
|
||||
if (serial_in_byte_counter == 15 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 8) { // dim packet
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), serial_in_buffer[13]);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.));
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim );
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim );
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd );
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
tuya_ignore_dim = true;
|
||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||
serial_in_byte_counter = 0;
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
}
|
||||
if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd"));
|
||||
serial_in_byte_counter = 0;
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2");
|
||||
ExecuteCommand(scmnd, SRC_BUTTON);
|
||||
}
|
||||
}
|
||||
void SerialInput()
|
||||
{
|
||||
while (Serial.available()) {
|
||||
|
@ -2243,6 +2304,29 @@ void SerialInput()
|
|||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
* Tuya based Dimmer with Serial Communications to MCU dimmer
|
||||
\*-------------------------------------------------------------------------------------------*/
|
||||
if (TUYA_DIMMER == Settings.module) {
|
||||
if (serial_in_byte == '\x55') { // Start TUYA Packet
|
||||
if (serial_in_byte_counter > 0 && serial_in_byte_counter < 11) {
|
||||
TuyaPacketProcess();
|
||||
}
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55 Packet Start"));
|
||||
serial_in_byte_counter = 0;
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
// return; // test to see if we need this
|
||||
} else { // read additional packets from TUYA
|
||||
if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
serial_polling_window = millis();
|
||||
// return; // test to see if we need this
|
||||
} else {
|
||||
serial_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
if (XdrvCall(FUNC_SERIAL)) {
|
||||
|
@ -2252,33 +2336,33 @@ void SerialInput()
|
|||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data...
|
||||
serial_in_byte_counter = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
if (!Settings.flag.mqtt_serial) {
|
||||
if (isprint(serial_in_byte)) {
|
||||
if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
} else {
|
||||
serial_in_byte_counter = 0;
|
||||
}
|
||||
if (TUYA_DIMMER != Settings.module) {
|
||||
if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data...
|
||||
serial_in_byte_counter = 0;
|
||||
Serial.flush();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (serial_in_byte || Settings.flag.mqtt_serial_raw) {
|
||||
if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) &&
|
||||
((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
serial_polling_window = millis();
|
||||
} else {
|
||||
serial_polling_window = 0;
|
||||
break;
|
||||
if (!Settings.flag.mqtt_serial) {
|
||||
if (isprint(serial_in_byte)) {
|
||||
if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
} else {
|
||||
serial_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (serial_in_byte || Settings.flag.mqtt_serial_raw) {
|
||||
if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) &&
|
||||
((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits
|
||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
||||
serial_polling_window = millis();
|
||||
} else {
|
||||
serial_polling_window = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
* Sonoff SC 19200 baud serial interface
|
||||
\*-------------------------------------------------------------------------------------------*/
|
||||
|
@ -2307,23 +2391,34 @@ void SerialInput()
|
|||
}
|
||||
}
|
||||
|
||||
if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
if (!Settings.flag.mqtt_serial_raw) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\""));
|
||||
for (int i = 0; i < serial_in_byte_counter; i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data);
|
||||
if (TUYA_DIMMER == Settings.module && serial_in_byte_counter > 6 && (millis() > (serial_polling_window + SERIAL_POLLING))) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \""));
|
||||
for (int i = 0; i < serial_in_byte_counter; i++) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]);
|
||||
}
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
// XdrvRulesProcess();
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
TuyaPacketProcess();
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
serial_in_byte_counter = 0;
|
||||
} else {
|
||||
if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) {
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
if (!Settings.flag.mqtt_serial_raw) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\""));
|
||||
for (int i = 0; i < serial_in_byte_counter; i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data);
|
||||
}
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
// XdrvRulesProcess();
|
||||
serial_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void GpioSwitchPinMode(uint8_t index)
|
||||
|
@ -2465,6 +2560,11 @@ void GpioInit()
|
|||
devices_present = 0;
|
||||
baudrate = 19200;
|
||||
}
|
||||
else if (TUYA_DIMMER == Settings.module) {
|
||||
Settings.flag.mqtt_serial = 0;
|
||||
baudrate = 9600;
|
||||
light_type = LT_SERIAL;
|
||||
}
|
||||
else if (SONOFF_BN == Settings.module) { // PWM Single color led (White)
|
||||
light_type = LT_PWM1;
|
||||
}
|
||||
|
|
|
@ -241,6 +241,7 @@ enum SupportedModules {
|
|||
OBI,
|
||||
TECKIN,
|
||||
APLIC_WDP303075,
|
||||
TUYA_DIMMER,
|
||||
MAXMODULE };
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -418,7 +419,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
|
|||
AILIGHT, // Light Bulbs
|
||||
PHILIPS,
|
||||
WITTY, // Development Devices
|
||||
WEMOS
|
||||
WEMOS,
|
||||
TUYA_DIMMER
|
||||
};
|
||||
|
||||
// Default module settings
|
||||
|
@ -1133,6 +1135,15 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||
GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off)
|
||||
GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On )
|
||||
0, 0, 0
|
||||
},
|
||||
{ "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer)
|
||||
0,
|
||||
GPIO_TXD, // TX to dimmer MCU
|
||||
0,
|
||||
GPIO_RXD, // RX from dimmer MCU
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -343,6 +343,37 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut
|
|||
os_delay_us(12); // TStop > 12us.
|
||||
}
|
||||
|
||||
// *************** Tuya Dimmer Serial Comms
|
||||
void LightSerialDuty(uint8_t duty)
|
||||
{
|
||||
if (duty > 0 && !tuya_ignore_dim ) {
|
||||
if (duty < 25) {
|
||||
duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
||||
}
|
||||
Serial.write(0x55); // Tuya header 55AA
|
||||
Serial.write(0xAA);
|
||||
Serial.write(0x00); // version 00
|
||||
Serial.write(0x06); // Tuya command 06 - send order
|
||||
Serial.write(0x00);
|
||||
Serial.write(0x08); // following data length 0x08
|
||||
Serial.write(0x03); // dimmer id
|
||||
Serial.write(0x02); // type=value
|
||||
Serial.write(0x00); // length hi
|
||||
Serial.write(0x04); // length low
|
||||
Serial.write(0x00); //
|
||||
Serial.write(0x00); //
|
||||
Serial.write(0x00); //
|
||||
Serial.write( duty ); // dim value (0-255)
|
||||
Serial.write( byte(22 + duty) ); // checksum:sum of all bytes in packet mod 256
|
||||
Serial.flush();
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d"), duty);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
tuya_ignore_dim = false; // reset flag
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
}
|
||||
/********************************************************************************************/
|
||||
|
||||
void LightInit()
|
||||
|
@ -359,7 +390,7 @@ void LightInit()
|
|||
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
||||
}
|
||||
}
|
||||
if (LT_PWM1 == light_type) {
|
||||
if (LT_PWM1 == light_type || LT_SERIAL == light_type) {
|
||||
Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color
|
||||
}
|
||||
if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities
|
||||
|
@ -391,6 +422,9 @@ void LightInit()
|
|||
max_scheme = LS_MAX + WS2812_SCHEMES;
|
||||
}
|
||||
#endif // USE_WS2812 ************************************************************************
|
||||
else if (LT_SERIAL == light_type) {
|
||||
light_subtype = LST_SINGLE;
|
||||
}
|
||||
else {
|
||||
light_pdi_pin = pin[GPIO_DI];
|
||||
light_pdcki_pin = pin[GPIO_DCKI];
|
||||
|
@ -821,6 +855,9 @@ void LightAnimate()
|
|||
if (light_type > LT_WS2812) {
|
||||
LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
||||
}
|
||||
if (light_type == LT_SERIAL) {
|
||||
LightSerialDuty(cur_col[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue