3dg1luk43/ha_washdata
GitHub: 3dg1luk43/ha_washdata
Stars: 934 | Forks: 25




[](https://ko-fi.com/3dg1luk43)
[](https://forms.gle/m6iGfP8QTasXWg5z7)
# WashData Integration
A Home Assistant custom component to monitor washing machines via smart sockets, learn power profiles, and estimate completion time using shape-correlation matching.
## ✨ Features
## 📘 Basic User Guide
Designed for new users to get up and running quickly.
## 1. Installation
### Option A: HACS (Recommended)
This integration is a default repository in HACS.
1. Click the button below to open the repository in HACS:
[](https://my.home-assistant.io/redirect/hacs_repository/?owner=3dg1luk43&repository=ha_washdata&category=integration)
2. Click **Download**.
3. Restart Home Assistant.
*Alternatively, open HACS > Integrations > Explore & Download Repositories > Search for "WashData".*
### Option B: Manual Installation
1. Download the `custom_components/ha_washdata` folder from the [latest release](https://github.com/3dg1luk43/ha_washdata/releases).
2. Copy it to your Home Assistant `custom_components` directory.
3. Restart Home Assistant.
## ⚡ Getting Started (The "Happy Path")
### 1. Initial Setup
1. Go to **Settings > Devices & Services** > **Add Integration** > **WashData**.
2. **Name**: Name your appliance (e.g., "Washing Machine").
3. **Device Type**: Select the type (Washer, Dryer, etc.) - this sets smart defaults for the internal logic.
4. **Power Sensor**: Select your smart plug's power entity (Watts). *Note: The system is now optimized for polling intervals of 30-60 seconds (defaults adjusted automatically).*
5. **Initial Profile (Optional)**: If you know your standard program (e.g. "Cotton"), create it now.
#### 💡 Tips for Zigbee2MQTT (Z2M) users
If you are using Zigbee2MQTT with smart plugs, ensure your device reporting is responsive enough for accurate matching:
- **Reporting Intervals**: Decrease the reporting intervals in Z2M (e.g., Min: 1s-10s, Max: 1200s).
- **Power Threshold**: Decrease the minimum updating threshold (e.g., from 5W to 1W or 2W) to ensure small power changes are captured promptly.
- *Note*: These changes may slightly increase Zigbee network traffic.
### 2. The Golden Rule: "Teach" the Integration
WashData **does not** come with pre-built profiles because every machine model is different. You must teach it what your cycles look like.
#### Option A: Manual "Record Mode" (Recommended)
This gives you the cleanest data.
1. Go to **Settings > Devices & Services > WashData > Configure**.
2. Open **Record Cycle (Manual)**, then start your machine.
3. When finished, go to **Manage Cycles** and find the recording.
4. Then open **Manage Profiles** and create a profile from that recording.
#### Option B: The Natural Way
If you prefer to just use it and label later:
1. **Run a Cycle**: Use your machine as normal. WashData will track it as an "Unknown" cycle.
2. **Label It**: After the cycle finishes:
- Go to **Manage Cycles** (via the Configure button or the Tile Card).
- Find the recent "Unknown" cycle.
- Open **Manage Profiles**, click **Create Profile**, name it (e.g., "Cotton 40"), and Save.
3. **Repeat**: Do this for your 2-3 most common programs.
### 3. Profile Granularity - How Detailed Should Profiles Be?
WashData matches cycles using **power-consumption shape, cycle duration, and total energy** - not temperature or spin-speed settings directly. This affects how granular your profile library should be.
#### What will be reliably auto-detected
Programs with clearly different durations or power patterns are always distinguished well:
| Example pair | Why it works |
| :--- | :--- |
| Quick Wash (~20 min) vs Cotton (~3 h) | Huge duration gap - no ambiguity |
| Wash-only vs Wash+Dry | Drying adds 100–200 min and significant extra energy |
| Cotton vs Delicates | Different agitation/heating patterns and often different durations |
#### Temperature and spin-speed variants
Programs that differ **only** in temperature or spin speed (e.g. Cotton 40°C vs Cotton 60°C) often produce similar power shapes and durations. The matcher will attempt to distinguish them using correlation and energy differences, but:
- On first run the system may assign the wrong variant - **use the Learning Feedbacks menu to correct it**.
- With a few confirmed corrections the system learns; 3–5 corrections per variant pair is usually enough.
- If your machine's power draw barely changes between temperatures, the variants may remain hard to distinguish automatically. In that case, selecting the program manually via the Program Selector dropdown remains reliable.
#### Practical advice for washer-dryer combos
Create **separate profiles** for every wash+dry combination you use regularly (e.g. "Cotton 40°C Wash", "Cotton 40°C + Cupboard Dry"). The drying phase adds so much duration and energy that wash-only vs wash+dry is one of the easiest distinctions for the matcher to make.
Start with a small set of your most-used and most-different programs, then add temperature/spin variants gradually as you accumulate history.
### 4. Verification & Learning
Once profiles are created, WashData starts **matching** new cycles automatically.
- **Feedback**: If a match is found but confidence is moderate, you may get a "Verify Cycle" notification.
- **Refinement**: Go to **Configure > Learning Feedbacks** to Confirm or Correct the detection.
- **Self-Improving**: Confirming a cycle helps the system refine its duration models.
## 🔧 Troubleshooting & Tuning
If "Auto-Detect" isn't working perfectly, use **Advanced Settings** to tune the logic for your specific machine.
| Problem | Likely Cause | Solution |
| :--- | :--- | :--- |
| **Cycle Starts Too Early** | Smart plug reports brief power spikes during boot/standby. | **Increase `Start Energy Threshold`** (e.g., to `2 Wh`). This forces the machine to consume actual energy before stating "Running". |
| **Cycle Ends Too Early** | Machine pauses (soaking) or has long low-power intervals. | **Increase `Off Delay`**. Give it more time (e.g. 5 mins) to wait before deciding the cycle is truly finished. |
| **False "Ghost" Cycles** | High-power usage at the very end (e.g. anti-crease or pump-out) triggers a new start. | **Increase `Minimum Off Gap`** (e.g. to `120s`). Forces a mandatory cooldown period between cycles. |
| **"Unknown" Matches** | Your profiles are too strict or variance is high. | **Increase `Duration Tolerance`** (e.g. `0.25`). Allows ±25% duration difference when matching. |
| **Notifications Too Late** | You want to know *before* it finishes. | **Set `Notify Before End Minutes`** (e.g. `5`). Get an alert 5 minutes before the estimated finish time. |
| **Persistent 'Running' State** | Integration stays locked to a long profile after a short cycle diverged. | **Adjust Matching Stability Thresholds** in `const.py`. Divergence detection now automatically reverts to "Detecting..." if confidence drops below 60% of the peak score. |
### Suggested Settings Sensor: What To Do
WashData exposes a diagnostic sensor: `sensor._suggested_settings`.
- `0` means there are currently no actionable recommendations.
- `> 0` means recommendations are ready to review.
When this sensor is above 0:
1. Go to **Settings > Devices & Services > WashData > Configure > Advanced Settings**.
2. Enable **Apply Suggested Values**.
3. Review the change summary step.
4. Confirm to stage values, then save only the changes you agree with.
Suggested values are optional and are never forced automatically.
### 🏷️ Phase Catalog & Assignment
Phases are descriptive labels for distinct power stages within a cycle (e.g., "Pre-Wash", "Heating", "Spin").
- **Manage Phase Catalog**: Go to **Configure > Manage Phase Catalog** to add, edit, or remove phase labels for each device type.
- **Assign Phases to a Profile**: In **Manage Profiles**, select **Assign Phase Ranges** and use the phase range editor to map time regions to phase labels.
- Phases are scoped to your device type - only relevant phases appear in the assignment dialog.
## 📊 Documentation & References
- 📗 **[IMPLEMENTATION.md](IMPLEMENTATION.md)** - Deep dive into NumPy matching, State Machine logic, and Learning algorithms.
- 🧪 **[TESTING.md](TESTING.md)** - How to test with the virtual socket.
### Entities Provided
- **`sensor._state`**: Current status (Idle / Running / Detecting... / Clean).
- **`sensor._program`**: Best-matched profile name.
- **`sensor._time_remaining`**: Smart countdown (locks during high-variance phases).
- **`sensor._total_duration`**: Total predicted duration (Elapsed + Remaining). Ideal for `timer-bar-card`.
- **`sensor._cycle_progress`**: 0–100% (resets after unload timeout).
- **`sensor._cycle_count`**: Total completed cycles stored — use in automations to schedule maintenance by cycle count.
- **`sensor._current_phase`**: Active cycle phase label (e.g. "Rinsing", "Spin").
- **`sensor._pump_runs_today`**: *(Pump device type only)* Completed pump cycles in a rolling 24-hour window.
- **`binary_sensor._running`**: Simple on/off running state.
- **`button._pause_cycle`**: Pause the active cycle (available while Running/Starting/Ending and not already paused).
- **`button._resume_cycle`**: Resume a user-paused cycle.
- **`button._force_end_cycle`**: Force-terminate a stuck cycle.
- **`switch._auto_maintenance`**: Toggle nightly database cleanup.
### Services
Most management is done via the **Interactive UI** (Configure > Manage Data), but services are available for automation:
- **`ha_washdata.export_config`**: Full JSON backup of all settings, profiles, and cycle history.
- **`ha_washdata.import_config`**: Restore from a JSON backup. Accepts regular WashData exports **and** HA diagnostics download files.
- **`ha_washdata.pause_cycle`**: Pause the active cycle programmatically (e.g. from an energy-tariff automation).
- **`ha_washdata.resume_cycle`**: Resume a user-paused cycle.
**`ha_washdata.record_start` / `record_stop`**:
Manually start/stop a recording. Useful for automations (e.g. triggering from a physical button or separate sensor).
service: ha_washdata.record_start
data:
device_id: "washer_device_id"
- `ha_washdata.label_cycle`: Assign a profile to a cycle in history programmatically.
### Events
WashData fires the following events on the Home Assistant event bus, suitable as automation triggers (e.g. `platform: event`, `event_type: ha_washdata_cycle_ended`). All three events are gated by the **Fire Events** toggle in the Notifications options page (default: on); disable it to suppress them globally without touching automations.
#### `ha_washdata_cycle_started`
Fired immediately when a cycle is detected (i.e. when the state machine first leaves `OFF`). The profile match has typically not run yet, so `program` is usually `"detecting..."` or `"unknown"` at this point; use `ha_washdata_cycle_ended` if you need the resolved profile name.
event_type: ha_washdata_cycle_started
data:
entry_id: 01KR1WGJYHJBTT5MEGS0VRXC4D # config-entry id, stable across restarts
device_name: Waschmaschine # the integration title you configured
device_type: washing_machine # washing_machine | dryer | washer_dryer | dishwasher | air_fryer | bread_maker | pump | other
program: "detecting..." # may resolve to a profile name later in the cycle
start_time: "2026-05-09T07:43:08.626640+02:00"
#### `ha_washdata_cycle_ended`
Fired once the cycle has fully terminated and been written to history. Carries the full cycle record minus the raw power trace (`power_data`, `debug_data`, `power_trace` are stripped to stay under Home Assistant's 32 KB event payload limit; fetch them via the diagnostics download if you need the samples).
event_type: ha_washdata_cycle_ended
data:
entry_id: 01KR1WGJYHJBTT5MEGS0VRXC4D
device_name: WashingMachine
program: "40°C / 1200rpm / cotton" # resolved profile name, or "unknown" if no match
duration: 13784.144562 # seconds (float)
start_time: "2026-05-09T07:43:08.626640+02:00"
end_time: "2026-05-09T11:32:52.771202+02:00"
cycle_data:
id: db87b5b60b2e # 12-char hex, stable cycle identifier
start_time: "2026-05-09T07:43:08.626640+02:00"
end_time: "2026-05-09T11:32:52.771202+02:00"
duration: 13784.144562 # seconds (float)
max_power: 2063 # watts (peak observed in the cycle)
energy_wh: 1564.04 # integrated energy over the cycle
status: completed # completed | aborted | timeout
termination_reason: timeout # off_delay | smart_termination | timeout | force_end | zombie | ghost_suppressed
profile_name: null # null when no profile was matched
sampling_interval: 43 # mean seconds between power readings
device_type: washing_machine
signature: # feature vector used for matching
duration: 13784.1
total_energy: 1564.04
max_power: 2063
event_density: 0
time_to_first_high: 1416.1
high_phase_ratio: 0.149
p05: 17 # 5th-percentile power (W)
p25: 38
p50: 91
p75: 203
p95: 2024.8
#### `ha_washdata_pump_stuck`
*(Pump device type only.)* Fired once when an active pump cycle exceeds the configured stuck-pump duration. Useful for sump-pit, condensate, or borehole-pump alarms.
event_type: ha_washdata_pump_stuck
data:
entry_id: 01KR1WGJYHJBTT5MEGS0VRXC4D
device: Sumppumpe # the integration title (note: legacy key name)
elapsed_seconds: 1830 # how long the pump had been running
threshold_seconds: 1800 # the configured stuck-pump threshold
### 🤝 Contribute Training Data
The more real-world cycle data WashData has, the smarter its detection becomes - across different appliance brands, ages, and programs.
If you'd like to help, you can submit a diagnostics export directly from Home Assistant. It takes less than 2 minutes and requires no technical knowledge.
**How to export:**
1. Open Home Assistant and go to** Settings → Devices & Services**
2. Find your **WashData** integration and click on it
3. Open device you want to submit data for
4. Navigate left, to **"Device info"** section
5. Select **"Download diagnostics"**
6. A .json file will be downloaded to your device
➡️ **[Submit your data here](https://forms.gle/m6iGfP8QTasXWg5z7)**
All contributions are used solely to improve the WashData integration.
### Supported Languages
🇬🇧 English • 🇨🇿 Čeština • 🇩🇰 Dansk • 🇩🇪 Deutsch • 🇬🇷 Ελληνικά • 🇪🇸 Español • 🇪🇪 Eesti • 🇫🇮 Suomi • 🇫🇷 Français • 🇭🇷 Hrvatski • 🇭🇺 Magyar • 🇮🇹 Italiano • 🇯🇵 日本語 • 🇱🇹 Lietuvių • 🇱🇻 Latviešu • 🇳🇴 Norsk • 🇳🇱 Nederlands • 🇧🇪 Nederlands (BE) • 🇵🇱 Polski • 🇵🇹 Português • 🇷🇴 Română • 🇸🇰 Slovenčina • 🇸🇮 Slovenščina • 🇷🇸 Srpski • 🇸🇪 Svenska • 🇺🇦 Українська • 🇨🇳 简体中文
## License
Non-commercial use only. See [LICENSE](LICENSE) file.