Releases: jasonacox/tinytuya
Release list
v1.20.0 - Monitor Reliability, Security & Bug Fixes
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 reportERR_TIMEOUT;received_wrong_cid_queuebounded.- Truncated frames raise
DecodeError;error_json()handles unknown codes;BulbDevicergb8 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)
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 — TheMonitorclass 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 stopSee 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:
PUTandDELETErequests now use the correct HTTP method instead of being downgraded toPOST. Fixes Cloud API calls that silently failed on certain endpoints via #717 by @vladulus. - BulbDevice fix:
set_brightness_percentage()andset_colourtemp_percentage()now calldetect_bulb()before readingvalue_max, preventingAttributeErroron 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
What's Changed
- Raise parse_header payload ceiling so large IR learn frames decode by @ostjen in #709
- core: Added
MAX_PAYLOAD_LENGTHconstant (default 1440 bytes) intinytuya/core/const.pyto replace the hardcoded 1000-byte ceiling inparse_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
What's Changed
devices.jsonformat: All loading paths (library, CLI, scanner, wizard, API server) now support both a flat[{...}]list and the{"devices": [{...}]}wrapped-dict format via a new centralizedload_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
RuntimeErroron undetectedcontrol_typeinsend_command()instead of silently failing by @jasonacox-sam in #698. - Contrib: New examples for
IRRemoteControlDeviceby @uzlonewolf in #699. - Contrib: Revert deprecated
Contrib/__init__.pyby @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.pymodule to keep__main__.pyfocused on argument parsing and dispatch by @uzlonewolf in #689. - CLI: New
monitorcommand — 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
versionsubcommand —tinytuya versionprints the installed TinyTuya version. - CLI: New
helpsubcommand —tinytuya helpprints a detailed usage summary with examples for all commands. Runningtinytuyawith no arguments also shows the full help. - CLI (
on,off,set,get,monitor):--idand--nameare now mutually exclusive and one is required (previously both were optional).--versionomitted 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
--keyis omitted and the key is not found indevices.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.
- If
New Contributors
- @jasonacox-sam made their first contribution in #695
Full Changelog: v1.17.6...v1.18.0
v1.17.6 - RFRemoteControlDevice Bug Fixes
What's Changed
- Contrib: Fix
RFRemoteControlDevice- three bugs that each independently causedrfstudy_sendcommands to be silently ignored by the device by @kongo09 in #684:rf_decode_button: fix missing()onbase64.b64decodecall — previously always returnedNone.send_command: build correctrfstudy_sendpayload (feqas int instead ofstudy_feqas string, addmode/ratefields, injectverinto each key dict); study/exit commands are unaffected.rf_send_button: do not forwardstudy_feqintofeq;feq=0tells 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
What's Changed
- Enhance command line interface with device control and listing commands by @jasonacox in #681
list– List all devices fromdevices.jsonas a formatted table (default) or JSON (--json).on/off– Turn a device switch on or off, with optional--dps Nto 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--dpsfor full status JSON or supply--dps Nto retrieve a single plain value.- All control commands accept
--id IDor--name NAMEto identify the target device. When--nameis used, the device ID is resolved via a case-insensitive lookup indevices.json. - Missing credentials (
--key,--ip,--version) are automatically filled in from the matchingdevices.jsonentry.
- Contrib: Add
SoriaInverterDeviceto support SORIA solar micro-inverters by @Markourai in #680 - Enhance
CoverDevicewith 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)
- Type 1:
- 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
- Major rewrite to support 8 different device command types with automatic detection (credit: @make-all):
- 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
- @sjhorn made their first contribution in #657
- @Andy-Voigt made their first contribution in #670
- @Markourai made their first contribution in #680
Full Changelog: v1.17.4...v1.17.5
v1.17.4 - Cloud Config
What's Changed
- Add
configFileoption to the Cloud constructor, allowing users to specify the config file location (default remains 'tinytuya.json') by @blackw1ng in #640
New Contributors
- @blackw1ng made their first contribution in #640
Full Changelog: v1.17.3...v1.17.4
v1.17.3 - Colorama Optional
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
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
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