Skip to content

Adding heated towel radiator element, AFD02#703

Merged
jasonacox merged 9 commits into
jasonacox:masterfrom
mintsoft:master
May 9, 2026
Merged

Adding heated towel radiator element, AFD02#703
jasonacox merged 9 commits into
jasonacox:masterfrom
mintsoft:master

Conversation

@mintsoft
Copy link
Copy Markdown
Contributor

The device I have is known as the AFD02 inside the SmartLife app, I've seen it also go by "102HET-RB02WF" for some reason.

I have been unable to find any documentation the Tuya DPS anywhere so it has been guessed-at by playing around with mine.

(10 for 1 hour, 15 for 90 minutes etc) so it seems like
minutes is the easiest representation to expose. It only
accepts 30 minute increments so we can enforce that also
@jasonacox-sam jasonacox-sam added the enhancement New feature or request label Apr 25, 2026
Comment thread tinytuya/Contrib/TowelRailHeaterDevice.py Outdated
@jasonacox-sam
Copy link
Copy Markdown
Collaborator

Hey @mintsoft! Thanks for contributing this — always great to see new device support for TinyTuya. 🎉

I reviewed the code and found a few things:

🔴 Syntax error (line 130)

if delay % 30 != 0
    return

Missing colon — should be if delay % 30 != 0:. This is the Pylint failure blocking CI.

🟡 Mode mismatch in set_operating_mode (line ~105)

The README documents the modes as "cold", "heat", "eco", and "auto", but the validation check uses "hot" instead of "heat":

if mode not in ("cold", "hot", "eco", "auto"):

Should be "heat" to match the README and what the device actually expects.

🟡 status_json() will crash if any DPS key is missing

If the device doesn't return all DPS keys (e.g., timer not active), status[self.DPS_TIMER] will raise a KeyError. Other Contrib devices handle this with .get() and defaults. Consider:

status.get(self.DPS_TIMER, 0)

🟡 Timer conversion comments are misleading

The comments say "Returns 10 for 1 hour" but duration * 6 means raw value 10 → 60 minutes (1 hour). The math is fine, but the inline comments could be clearer about which direction the conversion goes and what the raw unit represents.

🟡 set_target_temperature silently returns on bad input

Returning None on non-numeric input is fine, but consider raising a ValueError so callers know something went wrong. Minor preference.

💡 Minor style nits

  • Missing space after comma: "eco","auto""eco", "auto"
  • The is_float helper inside set_target_temperature could use isinstance(t, (int, float)) instead, but the try/except approach works too.

✅ What looks good

  • Class structure follows the Contrib pattern well
  • DPS constants are clean and documented
  • Default version 3.4 makes sense
  • README addition is clear and helpful
  • The celsius_to_tuya_temperature / tuya_temperature_to_celsius helpers are a nice touch

Fix the syntax error and the "hot""heat" mode mismatch and this is ready to merge. Nice first contribution!

Sam (Jason's AI assistant, reviewing on behalf of the TinyTuya project)

@jasonacox-sam
Copy link
Copy Markdown
Collaborator

Thanks @mintsoft — looks much cleaner now! 🎉

Both issues resolved:

  • ✅ Syntax error on line 134 fixed (if delay % 30 != 0:)
  • "hot" is correct for the device — good catch on my part getting that wrong. The README wording and the actual DPS value are two different things; you know the hardware.

The code looks good to me. Passing it to @jasonacox for final review and merge.

Comment thread tinytuya/Contrib/TowelRailHeaterDevice.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new community Contrib device module for a Tuya heated towel rail element (AFD02 / 102HET-RB02WF) and documents its usage in the Contrib README.

Changes:

  • Introduce TowelRailHeaterDevice with DPS mappings and helpers for temperature, mode, and timer control (default protocol version 3.4).
  • Extend tinytuya/Contrib/README.md with device description, mode mapping notes, and a usage example.
  • Minor README formatting tweak (language-tagged code fence) around the WiFiDualMeter example.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
tinytuya/Contrib/TowelRailHeaterDevice.py New device wrapper class providing typed-ish accessors/mutators for towel rail heater DPS.
tinytuya/Contrib/README.md Adds documentation and sample code for the new Contrib device.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tinytuya/Contrib/TowelRailHeaterDevice.py Outdated
Comment thread tinytuya/Contrib/TowelRailHeaterDevice.py Outdated
Comment thread tinytuya/Contrib/TowelRailHeaterDevice.py
Comment thread tinytuya/Contrib/TowelRailHeaterDevice.py Outdated
Comment thread tinytuya/Contrib/README.md Outdated
@jasonacox jasonacox merged commit f111b98 into jasonacox:master May 9, 2026
17 checks passed
@jasonacox
Copy link
Copy Markdown
Owner

Thanks @mintsoft !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants