Hi Tuya team — I’ve found what looks like a bug in the enum strategy conversion that affects devices whose DP reports as a Python boolean (True/False) while the enumMappingMap keys are lowercase strings ("true"/"false"). This results in incorrect conversion and downstream integrations (e.g., Home Assistant) never receiving the “clear” state.
Affected file
tuya_sharing/strategy_repo/enum_.py
Current code:
if str(dp_value) in enum_mappings and "value" in enum_mappings[str(dp_value)]:
status_value = enum_mappings[str(dp_value)]["value"]
Real config snippet (from PIR motion DP)
For my PIR motion datapoint, the SDK conversion config contains:
{
"statusFormat": "{\"pir\":\"$\"}",
"enumMappingMap": {
"false": { "code": "pir", "value": "none" },
"true": { "code": "pir", "value": "pir" }
}
}
This means:
true => motion detected (pir)
false => clear (none)
Problem / root cause
When the device reports a boolean:
str(True) -> "True"
str(False) -> "False"
But enumMappingMap keys are "true" / "false" (lowercase).
So str(dp_value) in enum_mappings fails and the function falls back to convert_default_value(config_item).
In practice, this causes PIR motion to get stuck as "pir" even after the device reports False (clear), because the “clear” report isn’t mapped to "none".
Minimal reproduction
Call convert() with:
dp_item = ("pir", False)
config_item = { "statusFormat": "{"pir":"$"}", "enumMappingMap": {"false":{"code":"pir","value":"none"}, "true":{"code":"pir","value":"pir"}} }
Expected: ("pir", "none")
Actual: falls back to default and returns an incorrect value (in my case it stays "pir")
Best fix
Normalize boolean/string values before lookup (and optionally do a case-insensitive key fallback). For example:
key_raw = str(dp_value)
key_lc = key_raw.lower()
status_value = None
if key_raw in enum_mappings and "value" in enum_mappings[key_raw]:
status_value = enum_mappings[key_raw]["value"]
elif key_lc in enum_mappings and "value" in enum_mappings[key_lc]:
status_value = enum_mappings[key_lc]["value"]
if status_value is None:
status_value = convert_default_value(config_item)
This preserves backward compatibility for mappings that already use "True"/"False" while fixing mappings that use "true"/"false".
An even more robust approach is to normalize all mapping keys once with str(k).lower() and look up using a normalized key (or casefold()), but the above is the smallest safe change.
Suggested tests
Add tests covering:
enumMappingMap keys "true"/"false" with dp_value as True/False
enumMappingMap keys "True"/"False" (existing behavior remains)
Happy to provide additional logs or a PR if you confirm preferred contribution approach.
Hi Tuya team — I’ve found what looks like a bug in the enum strategy conversion that affects devices whose DP reports as a Python boolean (True/False) while the enumMappingMap keys are lowercase strings ("true"/"false"). This results in incorrect conversion and downstream integrations (e.g., Home Assistant) never receiving the “clear” state.
Affected file
tuya_sharing/strategy_repo/enum_.py
Current code:
Real config snippet (from PIR motion DP)
For my PIR motion datapoint, the SDK conversion config contains:
This means:
true => motion detected (pir)
false => clear (none)
Problem / root cause
When the device reports a boolean:
str(True) -> "True"
str(False) -> "False"
But enumMappingMap keys are "true" / "false" (lowercase).
So str(dp_value) in enum_mappings fails and the function falls back to convert_default_value(config_item).
In practice, this causes PIR motion to get stuck as "pir" even after the device reports False (clear), because the “clear” report isn’t mapped to "none".
Minimal reproduction
Call convert() with:
dp_item = ("pir", False)
config_item = { "statusFormat": "{"pir":"$"}", "enumMappingMap": {"false":{"code":"pir","value":"none"}, "true":{"code":"pir","value":"pir"}} }
Expected: ("pir", "none")
Actual: falls back to default and returns an incorrect value (in my case it stays "pir")
Best fix
Normalize boolean/string values before lookup (and optionally do a case-insensitive key fallback). For example:
This preserves backward compatibility for mappings that already use "True"/"False" while fixing mappings that use "true"/"false".
An even more robust approach is to normalize all mapping keys once with str(k).lower() and look up using a normalized key (or casefold()), but the above is the smallest safe change.
Suggested tests
Add tests covering:
enumMappingMap keys "true"/"false" with dp_value as True/False
enumMappingMap keys "True"/"False" (existing behavior remains)
Happy to provide additional logs or a PR if you confirm preferred contribution approach.