Integrating the Ropvacnic S1 into Home Assistant via LocalTuya
The Ropvacnic S1 is a Tuya-based robot vacuum. Getting it to work locally in Home Assistant requires some digging — the DP numbers aren't documented anywhere, and LocalTuya has a bug in its locate function. This guide documents everything I found.
Why local control? Faster response, no cloud dependency, works if Tuya servers go down. The device still sends data to Tuya's cloud, but Home Assistant commands go directly over your LAN.
Setup: Home Assistant OS 2026.3.4 · LocalTuya 5.2.3 · Protocol 3.4 · Region: Western America
Step 1 — Tuya IoT Platform Setup
Create an account at iot.tuya.com (not tuya.com — click "Developer Platform" at the bottom). Create a Cloud Project with these settings:
- Industry: Smart Home
- Development Method: Smart Home
- Data Center: Western America (for Canada/USA accounts)
Important: The Data Center must match your Tuya Smart app region. A mismatch causes a "Data center inconsistency" error when scanning the QR code.
Under Devices → Link Tuya App Account, scan the QR code with your Tuya Smart app. Then note:
- Access ID — from the Overview tab
- Access Secret — from the Overview tab
- UID — from the linked account (starts with
az...)
Step 2 — Discover DPs with tinytuya
A DP (Data Point) is a numbered channel that controls one specific function of the device. Install tinytuya on your computer to identify them all:
pip3 install tinytuya python3 -m tinytuya wizard # Enter your Access ID, Secret, UID and region (us) python3 -m tinytuya snapshot # Poll: Y → shows all live DP values
Complete DP Map — Ropvacnic S1
| DP | Code | Type | Values |
|---|---|---|---|
| 1 | switch | Boolean | true / false |
| 2 | switch_go | Boolean | true / false |
| 3 | mode | Enum | standby, random, wall_follow, spiral, chargego |
| 4 | direction_control | Enum | forward, backward, turn_left, turn_right, stop |
| 5 | status | Enum | standby, smart_clean, goto_charge, charging, charge_done, paused |
| 6 | residual_electricity | Integer | 0–100 (%) |
| 7 | clean_time | Integer | minutes |
| 9 | clean_area | Integer | m² |
| 13 | seek (locate) | Boolean | true / false |
| 14 | suction | Enum | gentle, normal, strong |
| 17 | edge_brush | Integer | 0–100 (%) |
| 18 | filter | Integer | 0–100 (%) |
| 20 | water_control | Enum | closed, low, middle, high |
Note: DP 13 (seek/locate) is not visible in the standard tinytuya output. It was found by brute-force testing DPs 10–16 using d.set_value(dp, True) and listening for the vacuum's beep.
Step 3 — LocalTuya Entity Configuration
Install LocalTuya via HACS, restart HA, then go to Settings → Devices & Services → Add Integration → LocalTuya.
Set Manual DPS to: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
Configure the entity with these values:
| Field | Value |
|---|---|
| ID (status DP) | 5 |
| Power DP (powergo_dp) | 1 |
| Mode DP | 3 |
| Battery DP | 6 |
| Fan Speed DP | 14 |
| Clean Time DP | 7 |
| Clean Area DP | 9 |
| Locate DP | 13 |
| Fault DP | (leave empty) |
| Idle Status | standby,sleep |
| Docked Status | charging,chargecompleted,charge_done |
| Returning Status | goto_charge |
| Modes list | standby,random,wall_follow,spiral,chargego |
| Return home mode | chargego |
| Fan speeds list | gentle,normal,strong |
| Pause state | paused |
| Stop status | standby |
Step 4 — Fix vacuum.py (LocalTuya bug)
LocalTuya 5.2.3 has a bug in async_locate — it sends an empty string "" instead of True, so the locate button does nothing. Fix it via the Terminal add-on:
sed -i 's/set_dp("", self._config\[CONF_LOCATE_DP\])/set_dp(True, self._config[CONF_LOCATE_DP])/g' \
/config/custom_components/localtuya/vacuum.py
# Verify
grep -A3 "async_locate" /config/custom_components/localtuya/vacuum.py
Step 5 — Fix config via Terminal (if GUI doesn't save)
The LocalTuya GUI sometimes doesn't persist certain changes (notably mode_dp and id). Edit the config file directly:
# Backup first! cp /config/.storage/core.config_entries \ /config/.storage/core.config_entries.backup # Status DP = 5 (reads DP 5 for state) sed -i 's/"id":1,"idle_status_value":"standby,sleep"/"id":5,"idle_status_value":"standby,sleep"/g' \ /config/.storage/core.config_entries # powergo_dp must be 1 (start/pause) sed -i 's/"powergo_dp":5/"powergo_dp":1/g' \ /config/.storage/core.config_entries # mode_dp = 3 (stop + return to base) sed -i 's/"mode_dp":0/"mode_dp":3/g' \ /config/.storage/core.config_entries # locate_dp = 13 sed -i 's/"locate_dp":0/"locate_dp":13/g' \ /config/.storage/core.config_entries # Remove fault_dp entirely (causes false errors) sed -i 's/,"fault_dp":[0-9]*//g' \ /config/.storage/core.config_entries
After edits, reload LocalTuya: Settings → Devices & Services → LocalTuya → 3 dots → Reload — no full restart needed.
Final Result
After completing all steps, the Ropvacnic S1 is fully controllable from Home Assistant with local-only communication:
- State correctly shows Docked, Cleaning, Returning, and Paused
- Start, Pause, Stop, and Return to Base all work
- Locate (beep) works after the vacuum.py fix
- Battery percentage displayed in real time
- Fan speed (gentle / normal / strong) selectable from HA
- Clean time and area tracked per session