Major improvements in v2.1:
- Fixed console settings matching to use DeviceName and template NAME fields
- Proper URL encoding for rules (handles # and = characters)
- Fixed rule enabling (Rule1 ON vs Rule1 4)
- Fixed MQTT FullTopic %20 prefix issue
- Added single-device diff (--diff DEVICE)
- Improved button timing (SetOption32=8 for 0.8s hold)
- Created Plug profile separate from switch settings
- Fixed SetOption verification and disabled to prevent device overload
- Added delays and retry logic for reliable rule enabling
- Rule{N} 4 command doesn't work reliably to enable rules
- Changed to use Rule{N} ON which works consistently
- Tested on firmware 15.0.1.3 - Rule1 ON successfully enables rule
- Fixes issue where rules were set but not enabled after script run
- SetOption73=0 disables button MQTT publishing
- Plug buttons are just local fallback when MQTT/WiFi down
- Removed SetOption32/40/53 - multi-press and hold not needed
- rule1 provides local toggle functionality
- No MQTT messages from plug buttons - they just work locally
- Plugs do have physical buttons that should work
- Added SetOption32=8 and SetOption40=0 for long press support
- Added rule1 for single press toggle
- Plugs can now: single press to toggle, long press sends HOLD to MQTT
- Other switches can use multi-press to control plugs remotely
- Omitted multi-press tuning options (SetOption4/13/19) - not needed for plugs
- Created new 'Plug' profile without button-specific settings
- Removed SetOption4, SetOption13, SetOption19, SetOption32, SetOption40
- Removed rule1 for button presses (plugs typically don't have buttons)
- Updated all plug devices to use 'Plug' instead of 'Traditional'
- Applies to: Gosund_WP5_Plug, Gosund_Plug, CloudFree_X10S_Plug, Sonoff_S31_PM_Plug
- SetOption32=40 required 4 second hold, too long for comfortable use
- SetOption32=8 requires 0.8 second hold, much more natural
- Also fixed SONOFF_ULTIMATE SetOption40 from 40 to 0 (no repeating)
- Enables long press to send MQTT HOLD action to Node-RED for area-wide light control
- Devices had FullTopic starting with %20 (URL-encoded space)
- This breaks MQTT topic publishing with invalid leading space
- Now detects %20 prefix and forces update even if normalized values match
- Properly URL-encodes all MQTT setting values when sending
- FullTopic %prefix%/%topic%/ now encoded as %25prefix%25%2F%25topic%25%2F
- Fixes MQTT topics showing as '%20stat/device/...' instead of 'stat/device/...'
- Add 0.5s delay before enabling rule to let device process rule content
- Use retry logic for rule enable command (3 attempts with 1s delay)
- Change failed enable from warning to error and fail the command
- Ensures rules are both set AND enabled for switches to work
- DeviceName comes from template's NAME field (e.g., 'Treatlife SS02')
- Config keys use different names (e.g., 'TreatLife_SW_SS02S')
- Now falls back to checking template NAME if key doesn't match
- Fixes issue where devices with template-based names weren't getting console settings
- Both console_settings and device_diff use same matching logic
- Changed from simple space replacement to full URL encoding using quote()
- Rules contain # and = characters that must be encoded
- # was being treated as URL fragment, truncating rule commands
- Now encodes # as %23, = as %3D, spaces as %20, etc.
- Fixes issue where rules weren't being applied correctly to devices
- Modified --diff to accept 1 or 2 device arguments
- With 1 device: compares device config vs expected config from file
- With 2 devices: compares devices to each other (existing behavior)
- Shows which SetOptions and Rules don't match configuration
- Normalizes ON/OFF vs 1/0 for proper comparison
- Helps diagnose why console settings aren't applying correctly
- Verification was doubling the number of HTTP requests per setting
- Devices were refusing connections due to request overload
- Trust command success based on response, don't verify separately
- Fixes connection refused and timeout errors
- Wait 0.5s after sending command before first verification
- Retry verification once with 0.5s delay if first attempt fails
- Increase delay between commands from 0.3s to 0.5s
- Add delay after enabling rules
- Prevents false verification failures by giving device time to process
- Avoids overwhelming device with rapid command sequences
- Changed from using Hostname base (e.g., 'KitchenBar') to DeviceName (e.g., 'TreatLife_SW_SS02S')
- DeviceName matches the template names in device_list configuration
- This fixes issue where console settings weren't being applied correctly
- Devices were not matching any templates due to hostname vs device type mismatch
- Now uses exact match first, then case-insensitive fallback
- Changed SetOption32 from 8 to 40 in SONOFF_ULTIMATE profile
- This fixes button timing issues where multiple presses were required
- KitchenMain (Traditional profile) was already using 40 and working correctly
- KitchenBar (SONOFF_ULTIMATE profile) had 8 and required multiple presses
- Both profiles now use SetOption32=40 (4 second hold time)
- Display rule fields side-by-side in columns like other sections
- Makes it easier to compare State, Once, Length, Free, Rules, etc.
- Consistent formatting with rest of report
- Remove extra lines between section headers and content
- Add blank lines only after sections for better readability
- Add _print_rule_differences() method to display rules in row format
- Rules show device names as rows with detailed rule info below each
- More space-efficient report layout
Enhanced readability with table-style columnar output
Changes:
- Converted vertical list format to columnar table format
- First column: Parameter name
- Second column: Device 1 value
- Third column: Device 2 value
- Added header row with device names
- Auto-adjusts column widths based on content
- Truncates very long values (>60 chars) with "..."
- Maintains section separation (Firmware, Network, MQTT, etc.)
Before:
SetOption32:
KitchenMain = 40
KitchenBar = 8
After:
Parameter KitchenMain-3040 KitchenBar-7845
--------------- -------------------- --------------------
SetOption32 40 8
Much easier to scan and compare values side-by-side!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Performance Improvement: Query both devices simultaneously
Changes:
- Added ThreadPoolExecutor to device_diff.py compare_devices()
- Both devices are now queried in parallel (max 2 workers)
- Each device queries ~150+ SetOptions independently
- Roughly 2x faster than sequential queries
Before: ~30 seconds (sequential)
After: ~15 seconds (parallel)
The parallel approach significantly improves user experience when comparing
devices, especially when querying all SetOptions (0-150) and Rules.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
New Feature: Device configuration comparison tool for diagnostics
Usage:
python TasmotaManager.py --diff DEVICE1 DEVICE2
Features:
- Queries all SetOptions (0-150) from both devices
- Compares firmware versions, network config, MQTT settings
- Shows Rule configurations and status
- Displays all differences in human-readable format
- Helps diagnose configuration issues between working/non-working devices
Files Added:
- device_diff.py: New DeviceComparison class with full status queries
Files Modified:
- TasmotaManager.py: Added --diff argument and comparison mode handler
Example:
python TasmotaManager.py --diff KitchenMain KitchenBar
This tool revealed that KitchenMain (working) and KitchenBar (problematic)
have significant SetOption differences including SetOption32, SetOption40,
and others that may affect button press behavior.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Root Cause: console_settings.py was using "Rule{N} 1" command which BOTH
enables the rule AND sets the Once flag to ON. The Once flag causes rules
to fire only one time and then stop, requiring multiple button presses
before the rule would work again.
Solution: Changed rule enablement from "Rule{N} 1" to "Rule{N} 4"
- Rule 1 = Enable rule + Set Once ON (WRONG)
- Rule 4 = Enable rule only (CORRECT)
- Rule 5 = Set Once ON only
- Rule 6 = Set Once OFF only
This allows rules to fire repeatedly on every button press, fixing the
issue where devices like KitchenBar required multiple presses.
Changes:
- console_settings.py line 190: Use Rule{N} 4 instead of Rule{N} 1
- Added detailed comments explaining Tasmota rule command behavior
- Reverted SetOption32 changes (was red herring, not the actual issue)
Tested on KitchenBar (192.168.8.244) - button now responds on every press.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Issue: Some Tasmota switches (e.g., KitchenBar) required multiple button
presses before responding, while others (e.g., KitchenMain) worked immediately.
Root Cause: SetOption32 was set to 8 (0.8 seconds) which creates too short
a time window for multi-press detection. This causes the device to sometimes
misinterpret single presses or require multiple attempts.
Solution: Changed SetOption32 from 8 to 40 (4.0 seconds) in both Traditional
and SONOFF_ULTIMATE console_set profiles. This matches the working devices
and provides a longer, more reliable detection window for single button presses
when using rule: "on button1#state=10 do power0 toggle endon"
SetOption32 controls the button hold time in 0.1s increments. A higher value
means the device waits longer to confirm it's a single press vs multi-press,
resulting in more reliable single-press detection.
Tested on KitchenBar (192.168.8.244) - button now responds reliably on first press.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major changes:
- Implement parallel device processing using ThreadPoolExecutor (10 workers)
- Add comprehensive error and warning tracking in ReportGenerator
- Fix MQTT configuration verification (query Topic/FullTopic directly)
- Improve console settings thread safety with locks
- Fix UniFi client for UniFi OS API endpoints
- Normalize FullTopic handling (strip URL-encoded spaces)
- Update network exclude patterns to support wildcards
- Add test_unifi_connection.py for debugging UniFi connectivity
Performance improvements:
- Process devices concurrently for faster execution
- Reduced verbose logging during parallel processing
Bug fixes:
- Handle deprecated.json format correctly (list vs dict)
- Fix exclude_patterns matching with partial string support
- Fix UniFi API authentication and endpoint paths for UniFi OS
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
UDM-SE uses UniFi OS which requires /proxy/network prefix for Network
application API endpoints. The legacy controller endpoints (/api/s/...)
return 404 on UniFi OS devices.
Changes:
- Updated get_clients() to use /proxy/network/api/s/{site}/stat/sta
- Updated get_devices() to use /proxy/network/api/s/{site}/stat/device
- Added comments explaining UniFi OS API structure
Fixes 404 errors when querying UniFi controller for devices
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The authentication endpoint /api/auth/login returns HTTP 200 with a different
JSON response format than data endpoints. UDM-SE (UniFi OS) does not include
the meta.rc field in authentication responses, causing false authentication
failures.
Changes:
- Added skip_meta_check parameter to _request_json() method
- Updated _login() to skip meta.rc validation for auth endpoint
- Added debug logging to show actual API responses for troubleshooting
Fixes authentication error: "UniFi API error: Unknown error"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Moved tasmota_manager_refactor_notes.md to docs/REFACTORING_NOTES.md
- Moved migrate_to_refactored.py to docs/ for future reference
- Moved GitWorkflowRefactor.sh to docs/ for future reference
- Renamed main.py to TasmotaManager.py for consistency with project name
- Updated pyproject.toml to reflect the new module name
- All functionality remains the same
- Created modular Python files (main, utils, discovery, configuration, console_settings, unknown_devices, reporting, unifi_client)
- Moved documentation files to docs/
- Moved data files to data/
- Removed old monolithic TasmotaManager.py and TasmotaManager_fixed.py
- Updated .gitignore and pyproject.toml
- All functionality preserved, command-line interface unchanged
Version: 2.0.0
- Removed blank entry that was causing empty parameter errors
- Fixes 'Verification failed for blank parameter' errors on all devices
- Issue discovered during testing and root cause identified in config
- Add 1-second delay after MQTT changes to allow device to process
- Only delays when MQTT settings were actually updated
- Prevents intermittent failures when applying console settings
- Device needs time to process MQTT reconnection before accepting new commands
- Add 0.5s delays after Template and Module commands for device processing
- Verify Module=0 (activation) in post-update verification, not just template
- Apply fixes to both template update and device name update code paths
- Enhanced logging for Module operations and verification
- Fixes issue where template was set but not activated, leaving device inoperable