Skip to content

Releases: jasonacox/tinytuya

v1.20.0 - Monitor Reliability, Security & Bug Fixes

Choose a tag to compare

@jasonacox-sam jasonacox-sam released this 06 Jul 04:37
8512d83

v1.20.0 - Monitor Reliability, Security & Bug Fixes

Release rollup for PRs #722, #723, and #724.

Monitor (experimental) reliability

  • Monitor now owns reconnection. Monitored devices are forced to fail fast on send errors (socketRetryLimit = 0) so a broken connection can no longer block the reactor thread or silently open a replacement socket the selector never watches.
  • Heartbeat and queued-command send failures are detected and routed through the disconnect → auto-reconnect path.
  • Command dispatch is gated on selector registration state rather than device.socket, closing a reconnect handshake race.
  • stop() returns promptly via interruptible backoff wait; can no longer spawn duplicate connector threads.
  • Retry limits are restored on device remove/stop. Selector unregisters by stored fd.
  • Added first offline unit tests for Monitor (37 total, 1 skipped).

Session crypto hardening

  • AES-GCM nonces and v3.4/v3.5 session-key client nonce now use os.urandom — eliminates nonce/IV reuse.
  • 6699/GCM frames that fail authentication tag are rejected.

Bug fixes

  • Cloud token-refresh retry preserves query string; helpers return error dicts on failed/empty responses.
  • set_timer() selects timer DP numerically; timeout errors report ERR_TIMEOUT; received_wrong_cid_queue bounded.
  • Truncated frames raise DecodeError; error_json() handles unknown codes; BulbDevice rgb8 hue offset fixed.
  • Scanner no longer mutates caller dicts.

Full changelog: https://github.com/jasonacox/tinytuya/blob/master/RELEASE.md

v1.19.0 - Experimental Monitor Class (Multi-Device Single-Thread)

Choose a tag to compare

@jasonacox-sam jasonacox-sam released this 29 Jun 06:07
2b33c0e

What's New in v1.19.0

🧪 Experimental: New Monitor Class — Single-Thread Multi-Device Monitoring

Watch any number of Tuya devices on a single OS thread using selectors (select/poll/epoll). Callback-driven, no asyncio, no per-device threads, no new dependencies.

⚠️ Experimental — The Monitor class is new and the API may change. Try it out and share feedback in #713.

import tinytuya

def on_status(device, result):
    print(f"{device.id}: {result.get('dps', {})}")

def on_connect(device, error):
    print(f"{'CONNECTED' if not error else 'FAILED'}: {device.id}")

mon = tinytuya.Monitor(
    on_status=on_status,
    on_connect=on_connect,
    heartbeat_interval=12,
    auto_reconnect=True,
)

mon.add(tinytuya.OutletDevice(dev_id="abc123", address="10.0.1.99", local_key="key", version=3.3))
# add more devices...

mon.run()  # blocks; Ctrl-C to stop

See examples/monitor_example.py and examples/monitor_poll_example.py for full usage. Implements the proposal by @3735943886 via #712.


Other Changes

  • IPv6/NAT64 support: Device addresses now support IPv6 and NAT64. Fixes connection failures on IPv6-only or dual-stack networks via #718 by @Kasoo.
  • Cloud API fix: PUT and DELETE requests now use the correct HTTP method instead of being downgraded to POST. Fixes Cloud API calls that silently failed on certain endpoints via #717 by @vladulus.
  • BulbDevice fix: set_brightness_percentage() and set_colourtemp_percentage() now call detect_bulb() before reading value_max, preventing AttributeError on newly created instances via #714 by @jasonacox-sam.
  • Force Scan fix: Fixed Error in main loop: 'id' crash in the API server main loop via #715 by @mkerni.
  • Contrib: FloorFanDevice: New device class for Comfort Zone floor standing tower fan (CZTF423S) via #711 by @cmoates.

Full Changelog: v1.18.1...v1.19.0

v1.18.1 - IR Learn Frame Fix

Choose a tag to compare

@jasonacox jasonacox released this 29 May 06:25
a9dc7f4

What's Changed

  • Raise parse_header payload ceiling so large IR learn frames decode by @ostjen in #709
  • core: Added MAX_PAYLOAD_LENGTH constant (default 1440 bytes) in tinytuya/core/const.py to replace the hardcoded 1000-byte ceiling in parse_header(). Enables local IR learn frame capture from devices with larger payloads such as AC IR blasters. Fixes #708 via #709 by @ostjen.
  • Adding heated towel radiator element, AFD02 by @mintsoft in #703

New Contributors

Full Changelog: v1.18.0...v1.18.1

v1.18.0 - Format Handling and UX Improvements

Choose a tag to compare

@jasonacox jasonacox released this 13 Apr 00:31

What's Changed

  • devices.json format: All loading paths (library, CLI, scanner, wizard, API server) now support both a flat [{...}] list and the {"devices": [{...}]} wrapped-dict format via a new centralized load_devicefile() helper. Fixes #532 via #700 by @uzlonewolf and @jasonacox.
  • API server: Added isRegistered() / deviceError() helpers to distinguish "Device offline" from "Device ID not found" in error responses.
  • Cloud: Preserve device mappings on transient Cloud API failure in getdevices() so a temporary outage no longer wipes the local device map by @jasonacox in #692.
  • IRRemoteControlDevice: Raise RuntimeError on undetected control_type in send_command() instead of silently failing by @jasonacox-sam in #698.
  • Contrib: New examples for IRRemoteControlDevice by @uzlonewolf in #699.
  • Contrib: Revert deprecated Contrib/__init__.py by @uzlonewolf in #686.
  • Docs: Clarify set_version() example — 3.3 is not the required version by @jasonacox-sam in #695.
  • Scanner: Improved messaging for devices with no IP address — now clearly indicates the device may be battery-powered or sleeping and that local control is not supported, instead of the generic "Error: No IP found" by @jasonacox in #689.
  • Wizard: When the Tuya Cloud API returns a "permission deny" error (or error code 1010), the wizard now prints a targeted hint suggesting the user check their IoT Core service subscription at https://iot.tuya.com by @jasonacox in #689.
  • README: Added troubleshooting notes clarifying battery-powered device limitations and warning against aggressive polling intervals that can cause devices to drop or reset their connection.
  • CLI: Refactored device-control functions into a new cli.py module to keep __main__.py focused on argument parsing and dispatch by @uzlonewolf in #689.
  • CLI: New monitor command — connects to a device with a persistent socket, prints the initial status, then listens for async updates with a heartbeat every 12 s and a full status refresh every 30 s by @uzlonewolf in #689.
  • CLI: New version subcommand — tinytuya version prints the installed TinyTuya version.
  • CLI: New help subcommand — tinytuya help prints a detailed usage summary with examples for all commands. Running tinytuya with no arguments also shows the full help.
  • CLI (on, off, set, get, monitor): --id and --name are now mutually exclusive and one is required (previously both were optional). --version omitted now triggers an auto-scan instead of silently defaulting to v3.3 by @uzlonewolf in #689.
  • CLI (on, off, set, get, monitor): Improved handling of device local keys that contain special shell characters ($, #, =, :, !) - re: #688 by @jasonacox in #689:
    • If --key is omitted and the key is not found in devices.json, the CLI now prompts interactively for the key. Input at a terminal prompt bypasses shell interpretation entirely, so no quoting or escaping is needed.
    • Added key length validation — Tuya local keys are always exactly 16 characters. If the resolved key is the wrong length (the most common symptom of a shell-escaping problem), a clear error is printed with platform-specific quoting tips for Linux/Mac and Windows CMD.

New Contributors

Full Changelog: v1.17.6...v1.18.0

v1.17.6 - RFRemoteControlDevice Bug Fixes

Choose a tag to compare

@jasonacox jasonacox released this 22 Feb 17:58

What's Changed

  • Contrib: Fix RFRemoteControlDevice - three bugs that each independently caused rfstudy_send commands to be silently ignored by the device by @kongo09 in #684:
    • rf_decode_button: fix missing () on base64.b64decode call — previously always returned None.
    • send_command: build correct rfstudy_send payload (feq as int instead of study_feq as string, add mode/rate fields, inject ver into each key dict); study/exit commands are unaffected.
    • rf_send_button: do not forward study_feq into feq; feq=0 tells the device to use the frequency embedded in the code itself.
  • Adds regression tests for all three fixes.

New Contributors

Full Changelog: v1.17.5...v1.17.6

v1.17.5

Choose a tag to compare

@jasonacox jasonacox released this 21 Feb 17:49
04264b7

What's Changed

  • Enhance command line interface with device control and listing commands by @jasonacox in #681
    • list – List all devices from devices.json as a formatted table (default) or JSON (--json).
    • on / off – Turn a device switch on or off, with optional --dps N to target a specific switch index (default: 1).
    • set – Write a value to a DPS index (--dps N --value VALUE). Value is parsed as JSON where possible (e.g. true, 123) and falls back to a plain string.
    • get – Read device status; omit --dps for full status JSON or supply --dps N to retrieve a single plain value.
    • All control commands accept --id ID or --name NAME to identify the target device. When --name is used, the device ID is resolved via a case-insensitive lookup in devices.json.
    • Missing credentials (--key, --ip, --version) are automatically filled in from the matching devices.json entry.
  • Contrib: Add SoriaInverterDevice to support SORIA solar micro-inverters by @Markourai in #680
  • Enhance CoverDevice with automatic command type detection by @jasonacox in #654
    • Major rewrite to support 8 different device command types with automatic detection (credit: @make-all):
      • Type 1: ["open", "close", "stop", "continue"] — Most curtains, blinds, roller shades (DEFAULT)
      • Type 2: [true, false] — Simple relays, garage doors, locks
      • Type 3: ["0", "1", "2"] — String-numeric position/state
      • Type 4: ["00", "01", "02", "03"] — Zero-prefixed numeric position/state
      • Type 5: ["fopen", "fclose"] — Directional binary (no stop)
      • Type 6: ["on", "off", "stop"] — Switch-lexicon
      • Type 7: ["up", "down", "stop"] — Vertical-motion (lifts, hoists)
      • Type 8: ["ZZ", "FZ", "STOP"] — Vendor-specific (Abalon-style, older standard)
    • Added continue_cover() method for device types that support it (Types 1 and 4)
    • Added set_cover_type(type_id) method to manually override auto-detection
  • Expand DPS detection ranges in XenonDevice to include missing values by @jasonacox in #674
  • Update Scanner: improved clarity on v3.4 and v3.5 device identification when unresponsive by @jasonacox in #672
  • Added star projector example by @Andy-Voigt in #670
  • Add Dart Flutter port of TinyTuya to README by @sjhorn in #657
  • Fix pylint CI workflow to run on pull requests as well as pushes, catching errors before merge

New Contributors

Full Changelog: v1.17.4...v1.17.5

v1.17.4 - Cloud Config

Choose a tag to compare

@jasonacox jasonacox released this 24 Aug 22:58
788911f

What's Changed

  • Add configFile option to the Cloud constructor, allowing users to specify the config file location (default remains 'tinytuya.json') by @blackw1ng in #640

New Contributors

Full Changelog: v1.17.3...v1.17.4

v1.17.3 - Colorama Optional

Choose a tag to compare

@jasonacox jasonacox released this 09 Aug 16:10
ad91c8e

What's Changed

  • This update makes the colorama dependency optional for the tinytuya library, allowing it to function without colorama while gracefully disabling color output. This will help with memory or dependency limited platforms. Update by @uzlonewolf in #637.

Full Changelog: v1.17.2...v1.17.3

v1.17.2 - BulbDevice

Choose a tag to compare

@jasonacox jasonacox released this 05 Jun 03:44

What's Changed

  • Add Singapore datacenter, update BulbDevice for non-bulb devices again by @uzlonewolf in #625

Full Changelog: v1.17.1...v1.17.2

v1.17.1 - Fix BulbDevice

Choose a tag to compare

@jasonacox jasonacox released this 31 May 18:07

What's Changed

  • Fix BulbDevice for non-bulb devices. This will allow BulbDevice to be used even for non-bulb devices, e.g. turn_on() & turn_off(), by @uzlonewolf in #620.

Full Changelog: v1.17.0...v1.17.1