Zigbee support for Tuya Moes devices

This commit is contained in:
Stephan Hadinger 2020-10-11 19:41:23 +02:00
parent 2c6ee9cd95
commit 5b25d9cc83
4 changed files with 314 additions and 181 deletions

View File

@ -148,6 +148,12 @@ public:
} }
return 0; return 0;
} }
uint16_t get16BigEndian(const size_t offset) const {
if (offset < len() - 1) {
return _buf->buf[offset+1] | (_buf->buf[offset] << 8);
}
return 0;
}
uint32_t get32(const size_t offset) const { uint32_t get32(const size_t offset) const {
if (offset < len() - 3) { if (offset < len() - 3) {
return _buf->buf[offset] | (_buf->buf[offset+1] << 8) | return _buf->buf[offset] | (_buf->buf[offset+1] << 8) |
@ -155,6 +161,13 @@ public:
} }
return 0; return 0;
} }
int32_t get32IBigEndian(const size_t offset) const {
if (offset < len() - 3) {
return _buf->buf[offset+3] | (_buf->buf[offset+2] << 8) |
(_buf->buf[offset+1] << 16) | (_buf->buf[offset] << 24);
}
return 0;
}
uint64_t get64(const size_t offset) const { uint64_t get64(const size_t offset) const {
if (offset < len() - 7) { if (offset < len() - 7) {
return (uint64_t)_buf->buf[offset] | ((uint64_t)_buf->buf[offset+1] << 8) | return (uint64_t)_buf->buf[offset] | ((uint64_t)_buf->buf[offset+1] << 8) |

View File

@ -272,7 +272,7 @@ const char Z_strings[] PROGMEM =
"ControlSequenceOfOperation" "\x00" "ControlSequenceOfOperation" "\x00"
"SystemMode" "\x00" "SystemMode" "\x00"
"TRVMode" "\x00" "TRVMode" "\x00"
"SetValvePosition" "\x00" "ValvePosition" "\x00"
"EurotronicErrors" "\x00" "EurotronicErrors" "\x00"
"CurrentTemperatureSetPoint" "\x00" "CurrentTemperatureSetPoint" "\x00"
"ThSetpoint" "\x00" "ThSetpoint" "\x00"
@ -361,6 +361,26 @@ const char Z_strings[] PROGMEM =
"PersistentMemoryWrites" "\x00" "PersistentMemoryWrites" "\x00"
"LastMessageLQI" "\x00" "LastMessageLQI" "\x00"
"LastMessageRSSI" "\x00" "LastMessageRSSI" "\x00"
"TuyaScheduleWorkdays" "\x00"
"TuyaScheduleHolidays" "\x00"
"TuyaChildLock" "\x00"
"TuyaWindowDetection" "\x00"
"TuyaValveDetection" "\x00"
"TuyaAutoLock" "\x00"
"TuyaTempTarget" "\x00"
"TuyaBattery" "\x00"
"TuyaMinTemp" "\x00"
"TuyaMaxTemp" "\x00"
"TuyaBoostTime" "\x00"
"TuyaComfortTemp" "\x00"
"TuyaEcoTemp" "\x00"
"TuyaValvePosition" "\x00"
"TuyaAwayTemp" "\x00"
"TuyaAwayDays" "\x00"
"TuyaPreset" "\x00"
"TuyaFanMode" "\x00"
"TuyaForceMode" "\x00"
"TuyaWeekSelect" "\x00"
"Identify" "\x00" "Identify" "\x00"
"xxxx" "\x00" "xxxx" "\x00"
"IdentifyQuery" "\x00" "IdentifyQuery" "\x00"
@ -651,184 +671,204 @@ enum Z_offsets {
Zo_ControlSequenceOfOperation = 3427, Zo_ControlSequenceOfOperation = 3427,
Zo_SystemMode = 3454, Zo_SystemMode = 3454,
Zo_TRVMode = 3465, Zo_TRVMode = 3465,
Zo_SetValvePosition = 3473, Zo_ValvePosition = 3473,
Zo_EurotronicErrors = 3490, Zo_EurotronicErrors = 3487,
Zo_CurrentTemperatureSetPoint = 3507, Zo_CurrentTemperatureSetPoint = 3504,
Zo_ThSetpoint = 3534, Zo_ThSetpoint = 3531,
Zo_TempTarget = 3545, Zo_TempTarget = 3542,
Zo_Hue = 3556, Zo_Hue = 3553,
Zo_Sat = 3560, Zo_Sat = 3557,
Zo_RemainingTime = 3564, Zo_RemainingTime = 3561,
Zo_X = 3578, Zo_X = 3575,
Zo_Y = 3580, Zo_Y = 3577,
Zo_DriftCompensation = 3582, Zo_DriftCompensation = 3579,
Zo_CompensationText = 3600, Zo_CompensationText = 3597,
Zo_CT = 3617, Zo_CT = 3614,
Zo_ColorMode = 3620, Zo_ColorMode = 3617,
Zo_NumberOfPrimaries = 3630, Zo_NumberOfPrimaries = 3627,
Zo_Primary1X = 3648, Zo_Primary1X = 3645,
Zo_Primary1Y = 3658, Zo_Primary1Y = 3655,
Zo_Primary1Intensity = 3668, Zo_Primary1Intensity = 3665,
Zo_Primary2X = 3686, Zo_Primary2X = 3683,
Zo_Primary2Y = 3696, Zo_Primary2Y = 3693,
Zo_Primary2Intensity = 3706, Zo_Primary2Intensity = 3703,
Zo_Primary3X = 3724, Zo_Primary3X = 3721,
Zo_Primary3Y = 3734, Zo_Primary3Y = 3731,
Zo_Primary3Intensity = 3744, Zo_Primary3Intensity = 3741,
Zo_WhitePointX = 3762, Zo_WhitePointX = 3759,
Zo_WhitePointY = 3774, Zo_WhitePointY = 3771,
Zo_ColorPointRX = 3786, Zo_ColorPointRX = 3783,
Zo_ColorPointRY = 3799, Zo_ColorPointRY = 3796,
Zo_ColorPointRIntensity = 3812, Zo_ColorPointRIntensity = 3809,
Zo_ColorPointGX = 3833, Zo_ColorPointGX = 3830,
Zo_ColorPointGY = 3846, Zo_ColorPointGY = 3843,
Zo_ColorPointGIntensity = 3859, Zo_ColorPointGIntensity = 3856,
Zo_ColorPointBX = 3880, Zo_ColorPointBX = 3877,
Zo_ColorPointBY = 3893, Zo_ColorPointBY = 3890,
Zo_ColorPointBIntensity = 3906, Zo_ColorPointBIntensity = 3903,
Zo_Illuminance = 3927, Zo_Illuminance = 3924,
Zo_IlluminanceMinMeasuredValue = 3939, Zo_IlluminanceMinMeasuredValue = 3936,
Zo_IlluminanceMaxMeasuredValue = 3967, Zo_IlluminanceMaxMeasuredValue = 3964,
Zo_IlluminanceTolerance = 3995, Zo_IlluminanceTolerance = 3992,
Zo_IlluminanceLightSensorType = 4016, Zo_IlluminanceLightSensorType = 4013,
Zo_IlluminanceLevelStatus = 4043, Zo_IlluminanceLevelStatus = 4040,
Zo_IlluminanceTargetLevel = 4066, Zo_IlluminanceTargetLevel = 4063,
Zo_Temperature = 4089, Zo_Temperature = 4086,
Zo_TemperatureMinMeasuredValue = 4101, Zo_TemperatureMinMeasuredValue = 4098,
Zo_TemperatureMaxMeasuredValue = 4129, Zo_TemperatureMaxMeasuredValue = 4126,
Zo_TemperatureTolerance = 4157, Zo_TemperatureTolerance = 4154,
Zo_Pressure = 4178, Zo_Pressure = 4175,
Zo_PressureMinMeasuredValue = 4187, Zo_PressureMinMeasuredValue = 4184,
Zo_PressureMaxMeasuredValue = 4212, Zo_PressureMaxMeasuredValue = 4209,
Zo_PressureTolerance = 4237, Zo_PressureTolerance = 4234,
Zo_PressureScaledValue = 4255, Zo_PressureScaledValue = 4252,
Zo_PressureMinScaledValue = 4275, Zo_PressureMinScaledValue = 4272,
Zo_PressureMaxScaledValue = 4298, Zo_PressureMaxScaledValue = 4295,
Zo_PressureScaledTolerance = 4321, Zo_PressureScaledTolerance = 4318,
Zo_PressureScale = 4345, Zo_PressureScale = 4342,
Zo_SeaPressure = 4359, Zo_SeaPressure = 4356,
Zo_FlowRate = 4371, Zo_FlowRate = 4368,
Zo_FlowMinMeasuredValue = 4380, Zo_FlowMinMeasuredValue = 4377,
Zo_FlowMaxMeasuredValue = 4401, Zo_FlowMaxMeasuredValue = 4398,
Zo_FlowTolerance = 4422, Zo_FlowTolerance = 4419,
Zo_Humidity = 4436, Zo_Humidity = 4433,
Zo_HumidityMinMeasuredValue = 4445, Zo_HumidityMinMeasuredValue = 4442,
Zo_HumidityMaxMeasuredValue = 4470, Zo_HumidityMaxMeasuredValue = 4467,
Zo_HumidityTolerance = 4495, Zo_HumidityTolerance = 4492,
Zo_Occupancy = 4513, Zo_Occupancy = 4510,
Zo_OccupancySensorType = 4523, Zo_OccupancySensorType = 4520,
Zo_ZoneState = 4543, Zo_ZoneState = 4540,
Zo_ZoneType = 4553, Zo_ZoneType = 4550,
Zo_ZoneStatus = 4562, Zo_ZoneStatus = 4559,
Zo_CurrentSummDelivered = 4573, Zo_CurrentSummDelivered = 4570,
Zo_CompanyName = 4594, Zo_CompanyName = 4591,
Zo_MeterTypeID = 4606, Zo_MeterTypeID = 4603,
Zo_DataQualityID = 4618, Zo_DataQualityID = 4615,
Zo_CustomerName = 4632, Zo_CustomerName = 4629,
Zo_Model = 4645, Zo_Model = 4642,
Zo_PartNumber = 4651, Zo_PartNumber = 4648,
Zo_ProductRevision = 4662, Zo_ProductRevision = 4659,
Zo_SoftwareRevision = 4678, Zo_SoftwareRevision = 4675,
Zo_UtilityName = 4695, Zo_UtilityName = 4692,
Zo_POD = 4707, Zo_POD = 4704,
Zo_AvailablePower = 4711, Zo_AvailablePower = 4708,
Zo_PowerThreshold = 4726, Zo_PowerThreshold = 4723,
Zo_RMSVoltage = 4741, Zo_RMSVoltage = 4738,
Zo_RMSCurrent = 4752, Zo_RMSCurrent = 4749,
Zo_ActivePower = 4763, Zo_ActivePower = 4760,
Zo_NumberOfResets = 4775, Zo_NumberOfResets = 4772,
Zo_PersistentMemoryWrites = 4790, Zo_PersistentMemoryWrites = 4787,
Zo_LastMessageLQI = 4813, Zo_LastMessageLQI = 4810,
Zo_LastMessageRSSI = 4828, Zo_LastMessageRSSI = 4825,
Zo_Identify = 4844, Zo_TuyaScheduleWorkdays = 4841,
Zo_xxxx = 4853, Zo_TuyaScheduleHolidays = 4862,
Zo_IdentifyQuery = 4858, Zo_TuyaChildLock = 4883,
Zo_AddGroup = 4872, Zo_TuyaWindowDetection = 4897,
Zo_xxxx00 = 4881, Zo_TuyaValveDetection = 4917,
Zo_ViewGroup = 4888, Zo_TuyaAutoLock = 4936,
Zo_GetGroup = 4898, Zo_TuyaTempTarget = 4949,
Zo_01xxxx = 4907, Zo_TuyaBattery = 4964,
Zo_GetAllGroups = 4914, Zo_TuyaMinTemp = 4976,
Zo_00 = 4927, Zo_TuyaMaxTemp = 4988,
Zo_RemoveGroup = 4930, Zo_TuyaBoostTime = 5000,
Zo_RemoveAllGroups = 4942, Zo_TuyaComfortTemp = 5014,
Zo_ViewScene = 4958, Zo_TuyaEcoTemp = 5030,
Zo_xxxxyy = 4968, Zo_TuyaValvePosition = 5042,
Zo_RemoveScene = 4975, Zo_TuyaAwayTemp = 5060,
Zo_RemoveAllScenes = 4987, Zo_TuyaAwayDays = 5073,
Zo_RecallScene = 5003, Zo_TuyaPreset = 5086,
Zo_GetSceneMembership = 5015, Zo_TuyaFanMode = 5097,
Zo_PowerOffEffect = 5034, Zo_TuyaForceMode = 5109,
Zo_xxyy = 5049, Zo_TuyaWeekSelect = 5123,
Zo_PowerOnRecall = 5054, Zo_Identify = 5138,
Zo_PowerOnTimer = 5068, Zo_xxxx = 5147,
Zo_xxyyyyzzzz = 5081, Zo_IdentifyQuery = 5152,
Zo_xx0A00 = 5092, Zo_AddGroup = 5166,
Zo_DimmerUp = 5099, Zo_xxxx00 = 5175,
Zo_00190200 = 5108, Zo_ViewGroup = 5182,
Zo_DimmerDown = 5117, Zo_GetGroup = 5192,
Zo_01190200 = 5128, Zo_01xxxx = 5201,
Zo_DimmerStop = 5137, Zo_GetAllGroups = 5208,
Zo_ResetAlarm = 5148, Zo_00 = 5221,
Zo_xxyyyy = 5159, Zo_RemoveGroup = 5224,
Zo_ResetAllAlarms = 5166, Zo_RemoveAllGroups = 5236,
Zo_xx000A00 = 5181, Zo_ViewScene = 5252,
Zo_HueSat = 5190, Zo_xxxxyy = 5262,
Zo_xxyy0A00 = 5197, Zo_RemoveScene = 5269,
Zo_Color = 5206, Zo_RemoveAllScenes = 5281,
Zo_xxxxyyyy0A00 = 5212, Zo_RecallScene = 5297,
Zo_xxxx0A00 = 5225, Zo_GetSceneMembership = 5309,
Zo_ShutterOpen = 5234, Zo_PowerOffEffect = 5328,
Zo_ShutterClose = 5246, Zo_xxyy = 5343,
Zo_ShutterStop = 5259, Zo_PowerOnRecall = 5348,
Zo_ShutterLift = 5271, Zo_PowerOnTimer = 5362,
Zo_xx = 5283, Zo_xxyyyyzzzz = 5375,
Zo_ShutterTilt = 5286, Zo_xx0A00 = 5386,
Zo_Shutter = 5298, Zo_DimmerUp = 5393,
Zo_DimmerMove = 5306, Zo_00190200 = 5402,
Zo_xx0A = 5317, Zo_DimmerDown = 5411,
Zo_DimmerStepUp = 5322, Zo_01190200 = 5422,
Zo_00xx0A00 = 5335, Zo_DimmerStop = 5431,
Zo_DimmerStepDown = 5344, Zo_ResetAlarm = 5442,
Zo_01xx0A00 = 5359, Zo_xxyyyy = 5453,
Zo_DimmerStep = 5368, Zo_ResetAllAlarms = 5460,
Zo_xx190A00 = 5379, Zo_xx000A00 = 5475,
Zo_01 = 5388, Zo_HueSat = 5484,
Zo_HueMove = 5391, Zo_xxyy0A00 = 5491,
Zo_xx19 = 5399, Zo_Color = 5500,
Zo_HueStepUp = 5404, Zo_xxxxyyyy0A00 = 5506,
Zo_HueStepDown = 5414, Zo_xxxx0A00 = 5519,
Zo_03xx0A00 = 5426, Zo_ShutterOpen = 5528,
Zo_HueStep = 5435, Zo_ShutterClose = 5540,
Zo_SatMove = 5443, Zo_ShutterStop = 5553,
Zo_SatStep = 5451, Zo_ShutterLift = 5565,
Zo_xx190A = 5459, Zo_xx = 5577,
Zo_ColorMove = 5466, Zo_ShutterTilt = 5580,
Zo_xxxxyyyy = 5476, Zo_Shutter = 5592,
Zo_ColorStep = 5485, Zo_DimmerMove = 5600,
Zo_ColorTempMoveUp = 5495, Zo_xx0A = 5611,
Zo_01xxxx000000000000 = 5511, Zo_DimmerStepUp = 5616,
Zo_ColorTempMoveDown = 5530, Zo_00xx0A00 = 5629,
Zo_03xxxx000000000000 = 5548, Zo_DimmerStepDown = 5638,
Zo_ColorTempMoveStop = 5567, Zo_01xx0A00 = 5653,
Zo_00xxxx000000000000 = 5585, Zo_DimmerStep = 5662,
Zo_ColorTempMove = 5604, Zo_xx190A00 = 5673,
Zo_xxyyyy000000000000 = 5618, Zo_01 = 5682,
Zo_ColorTempStepUp = 5637, Zo_HueMove = 5685,
Zo_01xxxx0A0000000000 = 5653, Zo_xx19 = 5693,
Zo_ColorTempStepDown = 5672, Zo_HueStepUp = 5698,
Zo_03xxxx0A0000000000 = 5690, Zo_HueStepDown = 5708,
Zo_ColorTempStep = 5709, Zo_03xx0A00 = 5720,
Zo_xxyyyy0A0000000000 = 5723, Zo_HueStep = 5729,
Zo_ArrowClick = 5742, Zo_SatMove = 5737,
Zo_ArrowHold = 5753, Zo_SatStep = 5745,
Zo_ArrowRelease = 5763, Zo_xx190A = 5753,
Zo_ZoneStatusChange = 5776, Zo_ColorMove = 5760,
Zo_xxxxyyzz = 5793, Zo_xxxxyyyy = 5770,
Zo_xxyyzzzz = 5802, Zo_ColorStep = 5779,
Zo_AddScene = 5811, Zo_ColorTempMoveUp = 5789,
Zo_xxyyyyzz = 5820, Zo_01xxxx000000000000 = 5805,
Zo_StoreScene = 5829, Zo_ColorTempMoveDown = 5824,
Zo_03xxxx000000000000 = 5842,
Zo_ColorTempMoveStop = 5861,
Zo_00xxxx000000000000 = 5879,
Zo_ColorTempMove = 5898,
Zo_xxyyyy000000000000 = 5912,
Zo_ColorTempStepUp = 5931,
Zo_01xxxx0A0000000000 = 5947,
Zo_ColorTempStepDown = 5966,
Zo_03xxxx0A0000000000 = 5984,
Zo_ColorTempStep = 6003,
Zo_xxyyyy0A0000000000 = 6017,
Zo_ArrowClick = 6036,
Zo_ArrowHold = 6047,
Zo_ArrowRelease = 6057,
Zo_ZoneStatusChange = 6070,
Zo_xxxxyyzz = 6087,
Zo_xxyyzzzz = 6096,
Zo_AddScene = 6105,
Zo_xxyyyyzz = 6114,
Zo_StoreScene = 6123,
}; };

View File

@ -120,6 +120,7 @@ enum Cx_cluster_short {
Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100, Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100,
Cx0101, Cx0102, Cx0201, Cx0300, Cx0400, Cx0401, Cx0402, Cx0403, Cx0101, Cx0102, Cx0201, Cx0300, Cx0400, Cx0401, Cx0402, Cx0403,
Cx0404, Cx0405, Cx0406, Cx0500, Cx0702, Cx0B01, Cx0B04, Cx0B05, Cx0404, Cx0405, Cx0406, Cx0500, Cx0702, Cx0B01, Cx0B04, Cx0B05,
CxEF00,
}; };
const uint16_t Cx_cluster[] PROGMEM = { const uint16_t Cx_cluster[] PROGMEM = {
@ -128,6 +129,7 @@ const uint16_t Cx_cluster[] PROGMEM = {
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100,
0x0101, 0x0102, 0x0201, 0x0300, 0x0400, 0x0401, 0x0402, 0x0403, 0x0101, 0x0102, 0x0201, 0x0300, 0x0400, 0x0401, 0x0402, 0x0403,
0x0404, 0x0405, 0x0406, 0x0500, 0x0702, 0x0B01, 0x0B04, 0x0B05, 0x0404, 0x0405, 0x0406, 0x0500, 0x0702, 0x0B01, 0x0B04, 0x0B05,
0xEF00,
}; };
uint16_t CxToCluster(uint8_t cx) { uint16_t CxToCluster(uint8_t cx) {
@ -453,7 +455,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
{ Zenum8, Cx0201, 0x001C, Z_(SystemMode), Cm1, 0 }, { Zenum8, Cx0201, 0x001C, Z_(SystemMode), Cm1, 0 },
// below is Eurotronic specific // below is Eurotronic specific
{ Zenum8, Cx0201, 0x4000, Z_(TRVMode), Cm1, 0 }, { Zenum8, Cx0201, 0x4000, Z_(TRVMode), Cm1, 0 },
{ Zuint8, Cx0201, 0x4001, Z_(SetValvePosition), Cm1, 0 }, { Zuint8, Cx0201, 0x4001, Z_(ValvePosition), Cm1, 0 },
{ Zuint8, Cx0201, 0x4002, Z_(EurotronicErrors), Cm1, 0 }, { Zuint8, Cx0201, 0x4002, Z_(EurotronicErrors), Cm1, 0 },
{ Zint16, Cx0201, 0x4003, Z_(CurrentTemperatureSetPoint), Cm_100, 0 }, { Zint16, Cx0201, 0x4003, Z_(CurrentTemperatureSetPoint), Cm_100, 0 },
// below are virtual attributes to simplify ZbData import/export // below are virtual attributes to simplify ZbData import/export
@ -578,6 +580,28 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
{ Zuint8, Cx0B05, 0x011C, Z_(LastMessageLQI), Cm1, 0 }, { Zuint8, Cx0B05, 0x011C, Z_(LastMessageLQI), Cm1, 0 },
{ Zuint8, Cx0B05, 0x011D, Z_(LastMessageRSSI), Cm1, 0 }, { Zuint8, Cx0B05, 0x011D, Z_(LastMessageRSSI), Cm1, 0 },
// Tuya Moes specific - 0xEF00
{ Zoctstr, CxEF00, 0x0070, Z_(TuyaScheduleWorkdays), Cm1, 0 },
{ Zoctstr, CxEF00, 0x0071, Z_(TuyaScheduleHolidays), Cm1, 0 },
{ Zuint8, CxEF00, 0x0107, Z_(TuyaChildLock), Cm1, 0 },
{ Zuint8, CxEF00, 0x0112, Z_(TuyaWindowDetection), Cm1, 0 },
{ Zuint8, CxEF00, 0x0114, Z_(TuyaValveDetection), Cm1, 0 },
{ Zuint8, CxEF00, 0x0174, Z_(TuyaAutoLock), Cm1, 0 },
{ Zint16, CxEF00, 0x0202, Z_(TuyaTempTarget), Cm_10, 0 },
{ Zint16, CxEF00, 0x0203, Z_(LocalTemperature), Cm_10, 0 }, // will be overwritten by actual LocalTemperature
{ Zuint8, CxEF00, 0x0215, Z_(TuyaBattery), Cm1, 0 }, // TODO check equivalent?
{ Zint32, CxEF00, 0x0266, Z_(TuyaMinTemp), Cm1, 0 },
{ Zint32, CxEF00, 0x0267, Z_(TuyaMaxTemp), Cm1, 0 },
{ Zint32, CxEF00, 0x0269, Z_(TuyaBoostTime), Cm1, 0 },
{ Zint32, CxEF00, 0x026B, Z_(TuyaComfortTemp), Cm1, 0 },
{ Zint32, CxEF00, 0x026C, Z_(TuyaEcoTemp), Cm1, 0 },
{ Zuint8, CxEF00, 0x026D, Z_(TuyaValvePosition), Cm1, 0 },
{ Zint32, CxEF00, 0x0272, Z_(TuyaAwayTemp), Cm1, 0 },
{ Zint32, CxEF00, 0x0275, Z_(TuyaAwayDays), Cm1, 0 },
{ Zuint8, CxEF00, 0x0404, Z_(TuyaPreset), Cm1, 0 },
{ Zuint8, CxEF00, 0x0405, Z_(TuyaFanMode), Cm1, 0 },
{ Zuint8, CxEF00, 0x046A, Z_(TuyaForceMode), Cm1, 0 },
{ Zuint8, CxEF00, 0x046F, Z_(TuyaWeekSelect), Cm1, 0 },
}; };
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -134,6 +134,8 @@ const Z_CommandConverter Z_Commands[] PROGMEM = {
{ Z_(RemoveAllScenes),0x0005, 0x03, 0x82, Z_(xxyyyy) }, // xx = status, yyyy = group id { Z_(RemoveAllScenes),0x0005, 0x03, 0x82, Z_(xxyyyy) }, // xx = status, yyyy = group id
{ Z_(StoreScene), 0x0005, 0x04, 0x82, Z_(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id { Z_(StoreScene), 0x0005, 0x04, 0x82, Z_(xxyyyyzz) }, // xx = status, yyyy = group id, zz = scene id
{ Z_(GetSceneMembership),0x0005, 0x06, 0x82,Z_(xxyyzzzz) }, // specific { Z_(GetSceneMembership),0x0005, 0x06, 0x82,Z_(xxyyzzzz) }, // specific
// Tuya - Moes specific
{ Z_(), 0xEF00, 0xFF, 0x83, Z_() }, // capture any command in 0xEF00 cluster
}; };
/*********************************************************************************************\ /*********************************************************************************************\
@ -330,7 +332,8 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster,
// Format: "0004<00": "00" = "<cluster><<cmd>": "<payload>" for commands to devices // Format: "0004<00": "00" = "<cluster><<cmd>": "<payload>" for commands to devices
char attrid_str[12]; char attrid_str[12];
snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd);
attr_list.addAttribute(attrid_str).setBuf(payload, 0, payload.len()); Z_attribute & attr_raw = attr_list.addAttribute(attrid_str);
attr_raw.setBuf(payload, 0, payload.len());
if (command_name) { if (command_name) {
// Now try to transform into a human readable format // Now try to transform into a human readable format
@ -410,6 +413,11 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster,
attr_list.addAttribute(PSTR("PowerOnTime"), true).setFloat(xyz.y / 10.0f); attr_list.addAttribute(PSTR("PowerOnTime"), true).setFloat(xyz.y / 10.0f);
attr_list.addAttribute(PSTR("PowerOffWait"), true).setFloat(xyz.z / 10.0f); attr_list.addAttribute(PSTR("PowerOffWait"), true).setFloat(xyz.z / 10.0f);
break; break;
case 0xEF000000 ... 0xEF0000FF: // any Tuya - Moes command
if (convertTuyaSpecificCluster(attr_list, cluster, cmd, direction, shortaddr, srcendpoint, payload)) {
attr_list.removeAttribute(&attr_raw); // remove raw command
}
break;
} }
} else { // general case } else { // general case
// do we send command with endpoint suffix // do we send command with endpoint suffix
@ -438,6 +446,54 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster,
} }
} }
//
// Tuya - MOES specifc cluster 0xEF00
// See https://medium.com/@dzegarra/zigbee2mqtt-how-to-add-support-for-a-new-tuya-based-device-part-2-5492707e882d
// and https://github.com/Koenkk/zigbee-herdsman-converters/blob/9f503d47d3df6a99d133b78d2b52aa5c701ddddf/converters/fromZigbee.js#L339
//
bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf) {
// uint8_t status = buf.get8(0);
// uint8_t transid = buf.get8(1);
uint16_t dp = buf.get16(2); // decode dp as 16 bits little endian - which is not big endian as mentioned in documentation
// uint8_t fn = buf.get8(4);
uint8_t len = buf.get8(5); // len of payload
if ((1 == cmd) || (2 == cmd)) { // attribute report or attribute response
// create a synthetic attribute with id 'dp'
Z_attribute & attr = attr_list.addAttribute(cluster, dp);
int32_t ival32 = -0x80000000;
if (1 == len) {
// 1 byte, convert as uint8_t
ival32 = buf.get8(6);
} else if (2 == len) {
ival32 = buf.get16BigEndian(6);
} else if (4 == len) {
// 4 bytes, convert as int32_t
ival32 = buf.get32IBigEndian(6);
}
if (ival32 != -0x80000000) {
// fix temperature coefficient
switch (dp) {
case 0x0202:
attr_list.addAttribute(0x0201, 0x0012).setInt(ival32 * 10); // OccupiedHeatingSetpoint
break;
case 0x0203:
attr_list.addAttribute(0x0201, 0x0000).setInt(ival32 * 10); // LocalTemperature
break;
case 0x026D:
attr_list.addAttribute(0x0201, 0x0008).setUInt(ival32); // PIHeatingDemand
break;
}
attr.setInt(ival32);
} else {
// add as raw buffer
attr.setBuf(buf, 6, len);
}
return true; // true = remove the original Tuya attribute
}
return false;
}
// Find the command details by command name // Find the command details by command name
// Only take commands outgoing, i.e. direction == 0 // Only take commands outgoing, i.e. direction == 0
// If not found: // If not found: