From 2c8fa836922ccd9672dbafa8f8cd0d0ad8d67111 Mon Sep 17 00:00:00 2001 From: phyzical <5182053+phyzical@users.noreply.github.com> Date: Fri, 10 Jul 2026 18:29:23 +0800 Subject: [PATCH 01/14] add logic to use the correct state for multi switches --- src/lib/tuya.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 1618f9b9ffa4d..c4d65bdc33b84 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3315,8 +3315,10 @@ const tuyaTz = { return await tz.on_off.convertSet(entity, key, value, meta); } if (message.brightness != null) { + // If state includes state_l1 assume we need to use a custom lookup + const stateKey = Object.keys(state).find((k) => k.startsWith("state_")) ? "state_l" + entity.ID : "state"; // set brightness - if (state.state === "OFF") { + if (state[stateKey] === "OFF") { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } @@ -3328,7 +3330,7 @@ const tuyaTz = { {level, transtime: 100}, utils.getOptions(meta.mapped, entity), ); - return {state: {state: "ON", brightness}}; + return {state: {[stateKey]: "ON", brightness}}; } }, convertGet: async (entity, key, meta) => { From 83dc951c5a74b9c91daaf631f3401702a2c807be Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:33:22 +0000 Subject: [PATCH 02/14] [autofix.ci] apply automated fixes --- src/lib/tuya.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index c4d65bdc33b84..37d8b23360467 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3315,7 +3315,7 @@ const tuyaTz = { return await tz.on_off.convertSet(entity, key, value, meta); } if (message.brightness != null) { - // If state includes state_l1 assume we need to use a custom lookup + // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_")) ? "state_l" + entity.ID : "state"; // set brightness if (state[stateKey] === "OFF") { From fec5a6fabae9ab7f3d614e1cf70a6cddae1984ef Mon Sep 17 00:00:00 2001 From: phyzical <5182053+phyzical@users.noreply.github.com> Date: Fri, 10 Jul 2026 18:52:40 +0800 Subject: [PATCH 03/14] add logic to only trigger on when the brightness is unchanged to reduce zigbee commands --- src/lib/tuya.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index c4d65bdc33b84..250fbbd31a5ea 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3316,14 +3316,20 @@ const tuyaTz = { } if (message.brightness != null) { // If state includes state_l1 assume we need to use a custom lookup - const stateKey = Object.keys(state).find((k) => k.startsWith("state_")) ? "state_l" + entity.ID : "state"; - // set brightness - if (state[stateKey] === "OFF") { + const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? "state_l" + entity.ID : "state"; + const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? "brightness_l" + entity.ID : "brightness"; + + const brightness = utils.toNumber(message.brightness, "brightness"); + const brightnessUnchanged = utils.mapNumberRange(brightness, 0, 254, 0, 254) == state[brightnessKey]; + + // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya + if (state[stateKey] === "OFF" && brightnessUnchanged) { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } - const brightness = utils.toNumber(message.brightness, "brightness"); const level = utils.mapNumberRange(brightness, 0, 254, 0, 1000); + + // set brightness await entity.command<"genLevelCtrl", "moveToLevelTuya", TuyaGenLevelCtrl>( "genLevelCtrl", "moveToLevelTuya", From d2bad8b0cc39c1e5ffe17a06eb2c7f3fe5fb4590 Mon Sep 17 00:00:00 2001 From: phyzical <5182053+phyzical@users.noreply.github.com> Date: Fri, 10 Jul 2026 18:57:03 +0800 Subject: [PATCH 04/14] lint --- src/lib/tuya.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 250fbbd31a5ea..a0aa4ee5b40f2 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3316,11 +3316,11 @@ const tuyaTz = { } if (message.brightness != null) { // If state includes state_l1 assume we need to use a custom lookup - const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? "state_l" + entity.ID : "state"; - const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? "brightness_l" + entity.ID : "brightness"; + const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; + const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; const brightness = utils.toNumber(message.brightness, "brightness"); - const brightnessUnchanged = utils.mapNumberRange(brightness, 0, 254, 0, 254) == state[brightnessKey]; + const brightnessUnchanged = utils.mapNumberRange(brightness, 0, 254, 0, 254) === state[brightnessKey]; // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya if (state[stateKey] === "OFF" && brightnessUnchanged) { From 701cb7360e7c3c338274984fcb218618fa6800d1 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:59:16 +0000 Subject: [PATCH 05/14] [autofix.ci] apply automated fixes --- src/lib/tuya.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index a0aa4ee5b40f2..5157f8932a6b9 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3315,7 +3315,7 @@ const tuyaTz = { return await tz.on_off.convertSet(entity, key, value, meta); } if (message.brightness != null) { - // If state includes state_l1 assume we need to use a custom lookup + // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; From 73ccae882dd8f5eeb31c30653b29091ea5075642 Mon Sep 17 00:00:00 2001 From: Jack <5182053+phyzical@users.noreply.github.com> Date: Sat, 11 Jul 2026 18:09:50 +0800 Subject: [PATCH 06/14] Update tuya.ts Fix brightness lookups, as max brightness was always 1 behind max causing the force on work around never to fire --- src/lib/tuya.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 5157f8932a6b9..5c30d67dd8e60 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3318,16 +3318,18 @@ const tuyaTz = { // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; - + const minBrightness = state[`min_${brightnessKey}`]; + const maxBrightness = state[`max_${brightnessKey}`]; + const brightness = utils.toNumber(message.brightness, "brightness"); - const brightnessUnchanged = utils.mapNumberRange(brightness, 0, 254, 0, 254) === state[brightnessKey]; + const brightnessUnchanged = utils.mapNumberRange(brightness,minBrightness,maxBrightness, minBrightness,maxBrightness) === state[brightnessKey]; // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya if (state[stateKey] === "OFF" && brightnessUnchanged) { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } - const level = utils.mapNumberRange(brightness, 0, 254, 0, 1000); + const level = utils.mapNumberRange(brightness, minBrightness, maxBrightness, 0, 1000); // set brightness await entity.command<"genLevelCtrl", "moveToLevelTuya", TuyaGenLevelCtrl>( From b6832a1a35dcb0a3f3b84ac72f4318510c0fc175 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 10:10:32 +0000 Subject: [PATCH 07/14] [autofix.ci] apply automated fixes --- src/lib/tuya.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 5c30d67dd8e60..5b19f463dae2c 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3319,10 +3319,11 @@ const tuyaTz = { const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; const minBrightness = state[`min_${brightnessKey}`]; - const maxBrightness = state[`max_${brightnessKey}`]; - + const maxBrightness = state[`max_${brightnessKey}`]; + const brightness = utils.toNumber(message.brightness, "brightness"); - const brightnessUnchanged = utils.mapNumberRange(brightness,minBrightness,maxBrightness, minBrightness,maxBrightness) === state[brightnessKey]; + const brightnessUnchanged = + utils.mapNumberRange(brightness, minBrightness, maxBrightness, minBrightness, maxBrightness) === state[brightnessKey]; // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya if (state[stateKey] === "OFF" && brightnessUnchanged) { From b3e46baff56b0f0a175109a85586752b0a73b9e7 Mon Sep 17 00:00:00 2001 From: Jack <5182053+phyzical@users.noreply.github.com> Date: Sat, 11 Jul 2026 19:16:04 +0800 Subject: [PATCH 08/14] Adjust the brightness unchanged var --- src/lib/tuya.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 5b19f463dae2c..7f5febaf9fd76 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3318,19 +3318,17 @@ const tuyaTz = { // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; - const minBrightness = state[`min_${brightnessKey}`]; - const maxBrightness = state[`max_${brightnessKey}`]; - const brightness = utils.toNumber(message.brightness, "brightness"); + // we allow at most 1 incase its a rounding/ float precision issue const brightnessUnchanged = - utils.mapNumberRange(brightness, minBrightness, maxBrightness, minBrightness, maxBrightness) === state[brightnessKey]; + Math.abs(utils.mapNumberRange(brightness, 0, 254, 0, 254) - state[brightnessKey]) <= 1; // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya if (state[stateKey] === "OFF" && brightnessUnchanged) { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } - const level = utils.mapNumberRange(brightness, minBrightness, maxBrightness, 0, 1000); + const level = utils.mapNumberRange(brightness, 0, 254, 0, 1000); // set brightness await entity.command<"genLevelCtrl", "moveToLevelTuya", TuyaGenLevelCtrl>( From 1684356df68b7cf405d2add19f156b4194fb99f6 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 11:16:40 +0000 Subject: [PATCH 09/14] [autofix.ci] apply automated fixes --- src/lib/tuya.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 7f5febaf9fd76..78ce54a959907 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3320,8 +3320,7 @@ const tuyaTz = { const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; const brightness = utils.toNumber(message.brightness, "brightness"); // we allow at most 1 incase its a rounding/ float precision issue - const brightnessUnchanged = - Math.abs(utils.mapNumberRange(brightness, 0, 254, 0, 254) - state[brightnessKey]) <= 1; + const brightnessUnchanged = Math.abs(utils.mapNumberRange(brightness, 0, 254, 0, 254) - state[brightnessKey]) <= 1; // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya if (state[stateKey] === "OFF" && brightnessUnchanged) { From bd2899c24548f0ccb62ad414c2ac6e5ed96ed5ba Mon Sep 17 00:00:00 2001 From: phyzical <5182053+phyzical@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:07:46 +0800 Subject: [PATCH 10/14] Remove brightness unchanged logic as the on simply is always required --- src/lib/tuya.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 78ce54a959907..c9d5275c03596 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3317,15 +3317,7 @@ const tuyaTz = { if (message.brightness != null) { // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; - const brightnessKey = Object.keys(state).find((k) => k.startsWith("brightness_l1")) ? `brightness_l${entity.ID}` : "brightness"; const brightness = utils.toNumber(message.brightness, "brightness"); - // we allow at most 1 incase its a rounding/ float precision issue - const brightnessUnchanged = Math.abs(utils.mapNumberRange(brightness, 0, 254, 0, 254) - state[brightnessKey]) <= 1; - - // if the brightness is unchanged then we need to force it on due to weirdness with moveToLevelTuya - if (state[stateKey] === "OFF" && brightnessUnchanged) { - await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); - } const level = utils.mapNumberRange(brightness, 0, 254, 0, 1000); @@ -3336,6 +3328,11 @@ const tuyaTz = { {level, transtime: 100}, utils.getOptions(meta.mapped, entity), ); + + if (state[stateKey] === "OFF" ) { + await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); + } + return {state: {[stateKey]: "ON", brightness}}; } }, From 3c8e8eb745ba2b17de769f122c7bc594cc09bbca Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 07:08:34 +0000 Subject: [PATCH 11/14] [autofix.ci] apply automated fixes --- src/lib/tuya.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index c9d5275c03596..08b893d5e6d83 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3329,7 +3329,7 @@ const tuyaTz = { utils.getOptions(meta.mapped, entity), ); - if (state[stateKey] === "OFF" ) { + if (state[stateKey] === "OFF") { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } From dfee13cc51408bde7e3e79fa8d871c2a58f4cd91 Mon Sep 17 00:00:00 2001 From: Jack <5182053+phyzical@users.noreply.github.com> Date: Tue, 14 Jul 2026 10:13:53 +0800 Subject: [PATCH 12/14] Apply suggestions from code review will review again but i think the state key being returned is a mistake and there is translation occuring down the line and the only issue was the state check to turn on Co-authored-by: Jack <5182053+phyzical@users.noreply.github.com> --- src/lib/tuya.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 08b893d5e6d83..6f295e7ef0fae 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3315,6 +3315,11 @@ const tuyaTz = { return await tz.on_off.convertSet(entity, key, value, meta); } if (message.brightness != null) { + // turn on + if (state[stateKey] === "OFF") { + await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); + } + // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; const brightness = utils.toNumber(message.brightness, "brightness"); @@ -3329,11 +3334,7 @@ const tuyaTz = { utils.getOptions(meta.mapped, entity), ); - if (state[stateKey] === "OFF") { - await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); - } - - return {state: {[stateKey]: "ON", brightness}}; + return {state: {state: "ON", brightness}}; } }, convertGet: async (entity, key, meta) => { From c21add6369b285ee08b80698e4cf1f3f74465777 Mon Sep 17 00:00:00 2001 From: Jack <5182053+phyzical@users.noreply.github.com> Date: Tue, 14 Jul 2026 10:14:41 +0800 Subject: [PATCH 13/14] Apply suggestions from code review Co-authored-by: Jack <5182053+phyzical@users.noreply.github.com> --- src/lib/tuya.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index 6f295e7ef0fae..c5b8a31670635 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3315,13 +3315,13 @@ const tuyaTz = { return await tz.on_off.convertSet(entity, key, value, meta); } if (message.brightness != null) { + // If state includes state_l1 assume we need to use a custom lookup + const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; // turn on if (state[stateKey] === "OFF") { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } - // If state includes state_l1 assume we need to use a custom lookup - const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; const brightness = utils.toNumber(message.brightness, "brightness"); const level = utils.mapNumberRange(brightness, 0, 254, 0, 1000); From 6e1c88f76667328bd83cc7eb226b3742d7fa3f9e Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 02:15:14 +0000 Subject: [PATCH 14/14] [autofix.ci] apply automated fixes --- src/lib/tuya.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/tuya.ts b/src/lib/tuya.ts index c5b8a31670635..80e562dcd8635 100644 --- a/src/lib/tuya.ts +++ b/src/lib/tuya.ts @@ -3315,13 +3315,13 @@ const tuyaTz = { return await tz.on_off.convertSet(entity, key, value, meta); } if (message.brightness != null) { - // If state includes state_l1 assume we need to use a custom lookup + // If state includes state_l1 assume we need to use a custom lookup const stateKey = Object.keys(state).find((k) => k.startsWith("state_l1")) ? `state_l${entity.ID}` : "state"; // turn on if (state[stateKey] === "OFF") { await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity)); } - + const brightness = utils.toNumber(message.brightness, "brightness"); const level = utils.mapNumberRange(brightness, 0, 254, 0, 1000);