The problem
On two A-OK AM45 Plus Wi-Fi tubular motors (product_id b9oa3zocv4qq47iy, category cl), HA's cover state never updates current_position is frozen at 100 regardless of physical position.
The Tuya/SmartLife app reflects the motor position correctly in real time (including when driven by the RF remote), so the motor is reporting to the cloud as expected.
Debug logs show the firmware only pushes percent_control (dpId 2) changes over MQTT. percent_state (dpId 3) is exposed in status_range but is never emitted after startup. It is stuck at 0 forever.
The DeviceCategory.CL cover description at homeassistant/components/tuya/cover.py:89 prefers PERCENT_STATE via the tuple:
current_position=(DPCode.PERCENT_STATE, DPCode.PERCENT_CONTROL)
get_default_definition → DPCodeInvertedPercentageWrapper.find_dpcode binds the entity to percent_state at setup (it exists in status_range), so live percent_control pushes are ignored for position tracking. Inverted percent_state=0 renders as HA current_position=100, state=open . Which matches the existing snapshot for fixture cl_g1cp07dsqnbdbbki (same DP shape), so the integration is behaving as coded; the coded assumption just doesn't match this firmware.
Possibly related: #156543 (state not updating after close), #159800 (reversed position), unmerged #161223 (options flow to invert).
What version of Home Assistant Core has the issue?
core-2026.4.3
What was the last working version of Home Assistant Core?
No response
What type of installation are you running?
Home Assistant Container
Integration causing the issue
Tuya
Link to integration documentation on our website
Tuya
Diagnostics information
In the attached diagnostics dumps (for EstorIzquierdo and EstorDerecho. product_id b9oa3zocv4qq47iy). Both show:
status_range contains: percent_state, percent_control
status: control=stop, percent_control=100, percent_state=0,
work_state=opening, fault=0
HA entity state: state=open, current_position=100
last_changed: 2026-04-18T01:03:13
last_reported: 2026-04-18T11:30:09 (10+ h of heartbeats, no state change)
debug log captured while moving the right blind via RF remote between 13:48 and 13:50 local time
tuya-cf1a7e4f547fffeba5bbc377c439ee5a-AM45 Plus Wi-Fi Derecho-6074fbc7c44569a9fe04ec01b2aaadb1.json
tuya-cf1a7e4f547fffeba5bbc377c439ee5a-AM45 Plus Wi-Fi Izquierdo-f994c4879f5fe897bb501762be5e9b68.json
tuya-am45-debug.log
Example YAML snippet
Anything in the logs that might be useful for us?
Moving one blind with the RF remote produces only `control` and `percent_control` updates. Never `percent_state`:
Received update for device bfb511584971be8c8cfsby: {... percent_control: 100, percent_state: 0 ...} (updated properties: ['control'], dp_timestamps: {'control': 1776512980822})
Received update for device bfb511584971be8c8cfsby: {... percent_control: 99, percent_state: 0 ...} (updated properties: ['percent_control'], dp_timestamps: {'percent_control': 1776512980894})
Received update for device bfb511584971be8c8cfsby: {... percent_control: 99, percent_state: 0 ...} (updated properties: ['control'], dp_timestamps: {'control': 1776512987701})
Received update for device bfb511584971be8c8cfsby: {... percent_control: 75, percent_state: 0 ...} (updated properties: ['percent_control'], dp_timestamps: {'percent_control': 1776512987785})
Raw MQTT payloads confirm `dpId:3` never appears across the entire debug capture (zero occurrences); only `dpId:1` (control) and `dpId:2` (percent_control) are pushed.
Additional information
Suggested direction: for DeviceCategory.CL entities where percent_state is present in status_range but never reported via MQTT, the entity should either (a) fall back to percent_control, or (b) allow per-device override. A blanket flip of the tuple would break motors that do report percent_state reliably (e.g. snapshot cl_zah67ekd expects position derived from percent_state=52, not percent_control=100), so a naïve reorder isn't safe.
The problem
On two A-OK AM45 Plus Wi-Fi tubular motors (product_id
b9oa3zocv4qq47iy, categorycl), HA's cover state never updatescurrent_positionis frozen at 100 regardless of physical position.The Tuya/SmartLife app reflects the motor position correctly in real time (including when driven by the RF remote), so the motor is reporting to the cloud as expected.
Debug logs show the firmware only pushes
percent_control(dpId 2) changes over MQTT.percent_state(dpId 3) is exposed instatus_rangebut is never emitted after startup. It is stuck at0forever.The
DeviceCategory.CLcover description athomeassistant/components/tuya/cover.py:89prefersPERCENT_STATEvia the tuple:get_default_definition→DPCodeInvertedPercentageWrapper.find_dpcodebinds the entity topercent_stateat setup (it exists instatus_range), so livepercent_controlpushes are ignored for position tracking. Invertedpercent_state=0renders as HAcurrent_position=100,state=open. Which matches the existing snapshot for fixturecl_g1cp07dsqnbdbbki(same DP shape), so the integration is behaving as coded; the coded assumption just doesn't match this firmware.Possibly related: #156543 (state not updating after close), #159800 (reversed position), unmerged #161223 (options flow to invert).
What version of Home Assistant Core has the issue?
core-2026.4.3
What was the last working version of Home Assistant Core?
No response
What type of installation are you running?
Home Assistant Container
Integration causing the issue
Tuya
Link to integration documentation on our website
Tuya
Diagnostics information
In the attached diagnostics dumps (for EstorIzquierdo and EstorDerecho. product_id
b9oa3zocv4qq47iy). Both show:debug log captured while moving the right blind via RF remote between 13:48 and 13:50 local time
tuya-cf1a7e4f547fffeba5bbc377c439ee5a-AM45 Plus Wi-Fi Derecho-6074fbc7c44569a9fe04ec01b2aaadb1.json
tuya-cf1a7e4f547fffeba5bbc377c439ee5a-AM45 Plus Wi-Fi Izquierdo-f994c4879f5fe897bb501762be5e9b68.json
tuya-am45-debug.log
Example YAML snippet
Anything in the logs that might be useful for us?
Moving one blind with the RF remote produces only `control` and `percent_control` updates. Never `percent_state`: Received update for device bfb511584971be8c8cfsby: {... percent_control: 100, percent_state: 0 ...} (updated properties: ['control'], dp_timestamps: {'control': 1776512980822}) Received update for device bfb511584971be8c8cfsby: {... percent_control: 99, percent_state: 0 ...} (updated properties: ['percent_control'], dp_timestamps: {'percent_control': 1776512980894}) Received update for device bfb511584971be8c8cfsby: {... percent_control: 99, percent_state: 0 ...} (updated properties: ['control'], dp_timestamps: {'control': 1776512987701}) Received update for device bfb511584971be8c8cfsby: {... percent_control: 75, percent_state: 0 ...} (updated properties: ['percent_control'], dp_timestamps: {'percent_control': 1776512987785}) Raw MQTT payloads confirm `dpId:3` never appears across the entire debug capture (zero occurrences); only `dpId:1` (control) and `dpId:2` (percent_control) are pushed.Additional information
Suggested direction: for
DeviceCategory.CLentities wherepercent_stateis present instatus_rangebut never reported via MQTT, the entity should either (a) fall back topercent_control, or (b) allow per-device override. A blanket flip of the tuple would break motors that do reportpercent_statereliably (e.g. snapshotcl_zah67ekdexpects position derived frompercent_state=52, notpercent_control=100), so a naïve reorder isn't safe.