Merge pull request #6353 from shantur/tuya-mcu

Tuya mcu support
This commit is contained in:
Theo Arends 2019-09-05 10:03:02 +02:00 committed by GitHub
commit 2aedfc6a86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 310 additions and 77 deletions

View File

@ -444,6 +444,10 @@
#define D_CMND_LATITUDE "Latitude"
#define D_CMND_LONGITUDE "Longitude"
// Commands xdrv_16_tuyadimmer.ino
#define D_CMND_TUYA_MCU "TuyaMCU"
// Commands xdrv_23_zigbee.ino
#define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend"
#define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived"

View File

@ -307,7 +307,7 @@
// -- Optional modules ----------------------------
#define USE_BUZZER // Add support for a buzzer (+0k6 code)
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer
#define USE_TUYA_MCU // Add support for Tuya Serial MCU
#define TUYA_DIMMER_ID 0 // Default dimmer Id
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)

View File

@ -185,6 +185,14 @@ typedef struct {
uint32_t last_return_kWhtotal;
} EnergyUsage;
typedef struct {
uint8_t fnid = 0;
uint8_t dpid = 0;
} TuyaFnidDpidMap;
const uint8_t MAX_TUYA_FUNCTIONS = 16;
/*
struct SYSCFG {
unsigned long cfg_holder; // 000 Pre v6 header
@ -364,10 +372,9 @@ struct SYSCFG {
uint16_t web_refresh; // 7CC
char mems[MAX_RULE_MEMS][10]; // 7CE
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
uint8_t data8[32]; // E00
uint16_t data16[16]; // E20
TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes
uint8_t free_e20[448]; // E40
uint8_t free_e20[480]; // E20
// FFF last location
} Settings;

View File

@ -1096,6 +1096,41 @@ void SettingsDelta(void)
Settings.sbaudrate = Settings.ex_sbaudrate * 4;
}
if (Settings.version < 0x0606000A) {
uint8_t tuyaindex = 0;
if (Settings.param[P_TUYA_DIMMER_ID] > 0) {
Settings.tuya_fnid_map[tuyaindex].fnid = 21; //TUYA_MCU_FUNC_DIMMER; // Move Tuya Dimmer Id to Map
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_DIMMER_ID];
tuyaindex++;
} else if (Settings.flag3.tuya_disable_dimmer == 1) {
Settings.tuya_fnid_map[tuyaindex].fnid = 11; //TUYA_MCU_FUNC_REL1; // Create FnID for Switches
Settings.tuya_fnid_map[tuyaindex].dpid = 1;
tuyaindex++;
}
if (Settings.param[P_TUYA_RELAYS] > 0) {
for (uint8_t i = 0 ; i < Settings.param[P_TUYA_RELAYS]; i++) {
Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; //TUYA_MCU_FUNC_REL2+; // Create FnID for Switches
Settings.tuya_fnid_map[tuyaindex].dpid = i + 2;
tuyaindex++;
}
}
if (Settings.param[P_TUYA_POWER_ID] > 0) {
Settings.tuya_fnid_map[tuyaindex].fnid = 31; //TUYA_MCU_FUNC_POWER; // Move Tuya Power Id to Map
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_POWER_ID];
tuyaindex++;
}
if (Settings.param[P_TUYA_VOLTAGE_ID] > 0) {
Settings.tuya_fnid_map[tuyaindex].fnid = 33; //TUYA_MCU_FUNC_VOLTAGE; // Move Tuya Voltage Id to Map
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_VOLTAGE_ID];
tuyaindex++;
}
if (Settings.param[P_TUYA_CURRENT_ID] > 0) {
Settings.tuya_fnid_map[tuyaindex].fnid = 32; //TUYA_MCU_FUNC_CURRENT; // Move Tuya Current Id to Map
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_CURRENT_ID];
tuyaindex++;
}
}
Settings.version = VERSION;
SettingsSave(1);
}

View File

@ -85,7 +85,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
// -- Optional modules -------------------------
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer
#define USE_TUYA_MCU // Add support for Tuya Serial MCU
#ifndef TUYA_DIMMER_ID
#define TUYA_DIMMER_ID 0 // Default dimmer Id
#endif
@ -217,7 +217,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
//#ifndef USE_SONOFF_IFAN
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
//#endif
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
#undef ROTARY_V1 // Disable support for MI Desk Lamp
@ -345,7 +345,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
// -- Optional modules -------------------------
#undef USE_BUZZER // Disable support for a buzzer (+0k6 code)
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
#undef USE_DS18x20 // Disable Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code)
@ -436,7 +436,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
// -- Optional modules -------------------------
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
//#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
#undef ROTARY_V1 // Disable support for MI Desk Lamp
@ -517,7 +517,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
// -- Optional modules -------------------------
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
#undef ROTARY_V1 // Disable support for MI Desk Lamp

View File

@ -541,7 +541,7 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_SM16716_DAT, // SM16716 DATA
GPIO_SM16716_SEL, // SM16716 SELECT
#endif // USE_SM16716
#ifdef USE_TUYA_DIMMER
#ifdef USE_TUYA_MCU
GPIO_TUYA_TX, // Tuya Serial interface
GPIO_TUYA_RX, // Tuya Serial interface
#endif
@ -749,7 +749,7 @@ const uint8_t kModuleNiceList[] PROGMEM = {
OBI2,
MANZOKU_EU_4,
ESP_SWITCH, // Switch Devices
#ifdef USE_TUYA_DIMMER
#ifdef USE_TUYA_MCU
TUYA_DIMMER, // Dimmer Devices
#endif
#ifdef USE_ARMTRONIX_DIMMERS
@ -1728,7 +1728,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On )
0, 0, 0
},
{ "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer)
{ "Tuya MCU", // Tuya MCU device (ESP8266 w/ separate MCU)
// https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
GPIO_USER, // Virtual Button (controlled by MCU)
GPIO_USER, // GPIO01 MCU serial control

View File

@ -20,6 +20,6 @@
#ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_
const uint32_t VERSION = 0x06060009;
const uint32_t VERSION = 0x0606000A;
#endif // _SONOFF_VERSION_H_

View File

@ -661,7 +661,7 @@ void CmndSetoption(void)
IrReceiveUpdateThreshold();
break;
#endif
#ifdef USE_TUYA_DIMMER
#ifdef USE_TUYA_MCU
case P_TUYA_RELAYS:
case P_TUYA_POWER_ID:
case P_TUYA_CURRENT_ID:

View File

@ -171,7 +171,7 @@ void GetFeatures(void)
#ifdef USE_PCA9685
feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino
#endif
#if defined(USE_LIGHT) && defined(USE_TUYA_DIMMER)
#if defined(USE_LIGHT) && defined(USE_TUYA_MCU)
feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino
#endif
#ifdef USE_RC_SWITCH

View File

@ -1,5 +1,5 @@
/*
xdrv_16_tuyadimmer.ino - Tuya dimmer support for Sonoff-Tasmota
xdrv_16_tuyamcu.ino - Tuya MCU support for Sonoff-Tasmota
Copyright (C) 2019 digiblur, Joel Stein and Theo Arends
@ -18,7 +18,7 @@
*/
#ifdef USE_LIGHT
#ifdef USE_TUYA_DIMMER
#ifdef USE_TUYA_MCU
#define XDRV_16 16
#define XNRG_08 8
@ -61,10 +61,156 @@ struct TUYA {
int byte_counter = 0; // Index in serial receive buffer
} Tuya;
enum TuyaSupportedFunctions {
TUYA_MCU_FUNC_NONE,
TUYA_MCU_FUNC_SWT1 = 1, // Buttons
TUYA_MCU_FUNC_SWT2,
TUYA_MCU_FUNC_SWT3,
TUYA_MCU_FUNC_SWT4,
TUYA_MCU_FUNC_REL1 = 11, // Relays
TUYA_MCU_FUNC_REL2,
TUYA_MCU_FUNC_REL3,
TUYA_MCU_FUNC_REL4,
TUYA_MCU_FUNC_REL5,
TUYA_MCU_FUNC_REL6,
TUYA_MCU_FUNC_REL7,
TUYA_MCU_FUNC_REL8,
TUYA_MCU_FUNC_DIMMER = 21,
TUYA_MCU_FUNC_POWER = 31,
TUYA_MCU_FUNC_CURRENT,
TUYA_MCU_FUNC_VOLTAGE,
TUYA_MCU_FUNC_REL1_INV = 41, // Inverted Relays
TUYA_MCU_FUNC_REL2_INV,
TUYA_MCU_FUNC_REL3_INV,
TUYA_MCU_FUNC_REL4_INV,
TUYA_MCU_FUNC_REL5_INV,
TUYA_MCU_FUNC_REL6_INV,
TUYA_MCU_FUNC_REL7_INV,
TUYA_MCU_FUNC_REL8_INV,
TUYA_MCU_FUNC_LAST = 255
};
const char kTuyaCommand[] PROGMEM = "|" // No prefix
D_CMND_TUYA_MCU;
void (* const TuyaCommand[])(void) PROGMEM = {
&CmndTuyaMcu
};
/*
TuyaMcu fnid,dpid
*/
void CmndTuyaMcu(void) {
if (XdrvMailbox.data_len > 0) {
char *p;
uint8_t i = 0;
uint8_t parm[3] = { 0 };
for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) {
parm[i] = strtoul(str, nullptr, 0);
i++;
}
if (TuyaFuncIdValid(parm[0])) {
TuyaAddMcuFunc(parm[0], parm[1]);
restart_flag = 2;
} else {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]);
}
}
Response_P(PSTR("["));
bool added = false;
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].fnid != 0) {
if (added) {
ResponseAppend_P(PSTR(","));
}
ResponseAppend_P(PSTR("{\"fnId\":%d, \"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid);
added = true;
}
}
ResponseAppend_P(PSTR("]"));
}
/*********************************************************************************************\
* Internal Functions
\*********************************************************************************************/
void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) {
bool added = false;
if (fnId == 0 || dpId == 0) { // Delete entry
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) {
Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
Settings.tuya_fnid_map[i].dpid = 0;
break;
}
}
} else { // Add or update
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) {
if (!added) { // Update entry if exisiting entry or add
Settings.tuya_fnid_map[i].fnid = fnId;
Settings.tuya_fnid_map[i].dpid = dpId;
added = true;
} else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { // Remove existing entry if added to empty place
Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
Settings.tuya_fnid_map[i].dpid = 0;
}
}
}
}
UpdateDevices();
}
void UpdateDevices() {
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
uint8_t fnId = Settings.tuya_fnid_map[i].fnid;
if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) {
if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { //Relay
bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1);
} else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { // Inverted Relay
bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV);
}
}
}
}
inline bool TuyaFuncIdValid(uint8_t fnId) {
return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) ||
(fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) ||
fnId == TUYA_MCU_FUNC_DIMMER ||
(fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) ||
(fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV);
}
uint8_t TuyaGetFuncId(uint8_t dpid) {
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].dpid == dpid) {
return Settings.tuya_fnid_map[i].fnid;
}
}
return TUYA_MCU_FUNC_NONE;
}
uint8_t TuyaGetDpId(uint8_t fnId) {
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].fnid == fnId) {
return Settings.tuya_fnid_map[i].dpid;
}
}
return 0;
}
void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0)
{
uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF));
@ -131,7 +277,7 @@ bool TuyaSetPower(void)
int16_t source = XdrvMailbox.payload;
if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction
TuyaSendBool(active_device, bitRead(rpower, active_device-1));
TuyaSendBool(active_device, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1));
status = true;
}
return status;
@ -146,24 +292,26 @@ bool TuyaSetChannels(void)
void LightSerialDuty(uint8_t duty)
{
if (duty > 0 && !Tuya.ignore_dim && TuyaSerial) {
uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER);
if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) {
if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default
if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
}
if (Settings.flag3.tuya_disable_dimmer == 0) {
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
if (Tuya.new_dim != duty) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]);
TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid);
TuyaSendValue(dpid, duty);
}
}
} else {
} else if (dpid > 0) {
Tuya.ignore_dim = false; // reset flag
if (Settings.flag3.tuya_disable_dimmer == 0) {
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set
}
} else {
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); //
}
}
@ -189,6 +337,7 @@ void TuyaResetWifi(void)
void TuyaPacketProcess(void)
{
char scmnd[20];
uint8_t fnId = TUYA_MCU_FUNC_NONE;
switch (Tuya.buffer[3]) {
@ -201,24 +350,38 @@ void TuyaPacketProcess(void)
break;
case TUYA_CMD_STATE:
fnId = TuyaGetFuncId(Tuya.buffer[6]);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: FnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]);
// if (TuyaFuncIdValid(fnId)) {
if (Tuya.buffer[5] == 5) { // on/off packet
/*if ((power || Settings.light_dimmer > 0) && (power != Tuya.buffer[10])) {
ExecuteCommandPower(1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
}*/
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Device-%d --> MCU State: %s Current State:%s"),Tuya.buffer[6],Tuya.buffer[10]?"On":"Off",bitRead(power, Tuya.buffer[6]-1)?"On":"Off");
if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, Tuya.buffer[6]-1))) {
ExecuteCommandPower(Tuya.buffer[6], Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off");
if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) {
ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
}
} else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On");
if (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) {
ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10] ^ 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
}
} else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1));
if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) {
SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]);
SwitchHandler(1);
}
}
}
else if (Tuya.buffer[5] == 8) { // Long value packet
if (Settings.flag3.tuya_disable_dimmer == 0) {
if (!Settings.param[P_TUYA_DIMMER_ID]) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]);
Settings.param[P_TUYA_DIMMER_ID] = Tuya.buffer[6];
}
if (Settings.param[P_TUYA_DIMMER_ID] == Tuya.buffer[6]) {
if (fnId == TUYA_MCU_FUNC_DIMMER) {
// if (!Settings.param[P_TUYA_DIMMER_ID]) {
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]);
// Settings.param[P_TUYA_DIMMER_ID] = Tuya.buffer[6];
// }
// if (Settings.param[P_TUYA_DIMMER_ID] == Tuya.buffer[6]) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]);
Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100);
if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) {
@ -227,31 +390,32 @@ void TuyaPacketProcess(void)
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim );
ExecuteCommand(scmnd, SRC_SWITCH);
}
}
// }
}
#ifdef USE_ENERGY_SENSOR
if (Settings.param[P_TUYA_VOLTAGE_ID] == Tuya.buffer[6]) {
else if (fnId == TUYA_MCU_FUNC_VOLTAGE) {
Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Settings.param[P_TUYA_VOLTAGE_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
} else if (Settings.param[P_TUYA_CURRENT_ID] == Tuya.buffer[6]) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
} else if (fnId == TUYA_MCU_FUNC_CURRENT) {
Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Settings.param[P_TUYA_CURRENT_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
} else if (Settings.param[P_TUYA_POWER_ID] == Tuya.buffer[6]) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
} else if (fnId == TUYA_MCU_FUNC_POWER) {
Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Settings.param[P_TUYA_POWER_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) {
Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36;
EnergyUpdateToday();
}
Tuya.lastPowerCheckTime = Rtc.utc_time;
} else if (Settings.param[P_TUYA_DIMMER_ID] != Tuya.buffer[6]){
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Unknown ID=%d"), Tuya.buffer[6]);
}
#endif // USE_ENERGY_SENSOR
}
// } else {
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]);
// }
break;
case TUYA_CMD_WIFI_RESET:
@ -266,9 +430,9 @@ void TuyaPacketProcess(void)
break;
case TUYA_CMD_MCU_CONF:
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration"));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]);
if (Tuya.buffer[5] == 2) {
if (Tuya.buffer[5] == 2) { // Processing by ESP module mode
uint8_t led1_gpio = Tuya.buffer[6];
uint8_t key1_gpio = Tuya.buffer[7];
bool key1_set = false;
@ -307,21 +471,41 @@ bool TuyaModuleSelected(void)
Settings.my_gp.io[3] = GPIO_TUYA_RX;
restart_flag = 2;
}
if (Settings.flag3.tuya_disable_dimmer == 0) {
if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) {
TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID);
}
bool relaySet = false;
devices_present--;
for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) {
if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) ||
(Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) {
relaySet = true;
devices_present++;
}
}
if (!relaySet) {
TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1);
devices_present++;
SettingsSaveAll();
}
if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) {
light_type = LT_SERIAL1;
} else {
light_type = LT_BASIC;
}
UpdateDevices();
return true;
}
void TuyaInit(void)
{
devices_present += Settings.param[P_TUYA_RELAYS]; // SetOption41 - Add virtual relays if present
if (!Settings.param[P_TUYA_DIMMER_ID]) {
Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID;
}
Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE));
if (Tuya.buffer != nullptr) {
TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2);
@ -434,11 +618,11 @@ int Xnrg08(uint8_t function)
if (TUYA_DIMMER == my_module_type) {
if (FUNC_PRE_INIT == function) {
if (!energy_flg) {
if (Settings.param[P_TUYA_POWER_ID] != 0) {
if (Settings.param[P_TUYA_CURRENT_ID] == 0) {
if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) {
if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) {
Energy.current_available = false;
}
if (Settings.param[P_TUYA_VOLTAGE_ID] == 0) {
if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) {
Energy.voltage_available = false;
}
energy_flg = XNRG_08;
@ -486,10 +670,13 @@ bool Xdrv16(uint8_t function)
case FUNC_SET_CHANNELS:
result = TuyaSetChannels();
break;
case FUNC_COMMAND:
result = DecodeCommand(kTuyaCommand, TuyaCommand);
break;
}
}
return result;
}
#endif // USE_TUYA_DIMMER
#endif // USE_TUYA_MCU
#endif // USE_LIGHT