wizlight 2.1.0
wizlight: ^2.1.0 copied to clipboard
A dart package for controlling WiZ smart devices over UDP.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
2.1.0 - 2025-11-08 #
Added #
-
WiZ Smart Dial Switch Support (model 9290037923)
- New
WizDialclass for representing Smart Dial devices DialManagersingleton for receiving UDP broadcast events from dialsDialEventclass with complete event type mapping:- Rotation events (clockwise/counter-clockwise, stepped/discrete clicks)
- Dial button events (short press, long press)
- Scene button 1 events (short press, long press)
- Scene button 2 events (short press, long press)
DialEventTypeenum with 8 event types + unknown- Event parsing from 13-byte binary frames (base64-encoded)
- Simple callback-based API similar to
PushManager - Automatic event debouncing for button presses (250ms window)
- Prevents duplicate events from hardware bouncing
- Rotation events are not debounced for fast responsiveness
- Per-MAC and per-event-type filtering
- New
-
Testing Support for Smart Dial
FakeDialtest helper intest/helpers/fake_dial.dart- Comprehensive unit tests for event parsing (
test/dial_event_test.dart) - Integration tests for manager and event handling (
test/integration/dial_integration_test.dart) - Integration tests for debouncing behavior (
test/integration/dial_debounce_test.dart) - Test hooks:
DialManager.testListenPort,DialManager.resetForTesting()
-
Examples
example/smart_dial_monitor.dart- Monitor and display all dial eventsexample/dial_controlled_bulb.dart- Control bulb brightness/power/scenes with dial
-
Documentation
- Complete protocol analysis and implementation guide in
SMART_DIAL.md - Updated README.md with Smart Dial usage examples
- Complete protocol analysis and implementation guide in
Fixed #
- Corrected rotation direction mapping based on real hardware testing:
- 0x08 = counter-clockwise (was incorrectly mapped as clockwise)
- 0x09 = clockwise (was incorrectly mapped as counter-clockwise)
- Initial mapping was reversed during protocol reverse engineering
- All tests and examples updated to reflect correct behavior
Technical Notes #
- Smart Dial uses UDP port 38899 (same as bulb respond port) with method
syncAccEvt - Events are broadcast without requiring registration (unlike bulbs)
- Rotation is stepped (discrete clicks), not continuous degrees
- Each click sends exactly one event (0x08 = CCW, 0x09 = CW)
- Protocol fully reverse-engineered from real hardware captures
2.0.0 - 2025-11-07 #
Added #
-
Discovery Module (
lib/src/discovery.dart)- New
discoverBulbs()function that finds ALL devices on the network DiscoveredBulbclass with IP and MAC addressBulbRegistryfor collecting and deduplicating discovered bulbs- Matches Python's discovery behavior: keeps socket open for 5 seconds, sends repeated broadcasts
- Exported in public API for programmatic use
- New
-
Color Utilities (
lib/src/color_utils.dart)RGBColorclass for RGB color representation (0-255 range)HSVColorclass for HSV color representation (hue 0-360°, saturation/value 0-100%)rgbToHsv()- Convert RGB to HSV color spacehsvToRgb()- Convert HSV to RGB color spacehexToPercent()- Convert 0-255 hex values to 0-100 percentpercentToHex()- Convert 0-100 percent to 0-255 hex valueskelvinToRgb()- Convert color temperature (Kelvin) to RGB using blackbody approximation- 37 comprehensive unit tests with round-trip validation
-
Examples
example/color_demo.dart- Complete demo: discovery + push updates + RGB color cyclingexample/discover.dart- Discovery and basic controlexample/monitor_changes.dart- Long-running push update monitorexample/push_updates.dart- Push updates with programmatic testingexample/debug_push.dart- Debug version with detailed logging
-
Testing Improvements
- Test hooks in
PushManagerfor better testabilityPushManager.testListenPort- Override listen port (use 0 for any available port)PushManager.testSourceIp- Override source IP for localhost testingPushManager.resetForTesting()- Reset singleton state between tests
- All 15 timeout/retry integration tests now passing (100%)
- Test hooks in
Fixed #
-
Discovery Issues
- Fixed discovery only finding first device instead of all devices
- Discovery now keeps socket open for 5 seconds (matching Python)
- Discovery now sends repeated broadcasts every 1 second (matching Python)
- Discovery now collects and deduplicates all responses by MAC address
- CLI discovery output now matches Python format exactly
-
Push Manager Critical Bug
- Fixed source IP detection returning
0.0.0.0instead of actual local IP - Now uses
NetworkInterface.list()to find correct local IP on same subnet - Bulbs can now properly send push updates back to the monitoring application
- Push updates verified working with real WiZ devices
- Fixed source IP detection returning
-
BulbType Detection
- Fixed
whiteChannelsauto-detection always returning null - Now reads from
drvConfarray first (for firmware < 1.22) - Then overrides with model config values if available (firmware >= 1.22)
- Matches Python's dual-source reading logic exactly
- Fixed
-
Test Reliability
- Fixed 8 timeout/retry test failures
- Tests now properly handle exceptions and timeouts
- Reduced concurrent operations in stress tests (5 → 3)
- Increased test timeouts where appropriate (60s → 90s)
- Fixed push manager registration tests with proper test hooks
-
Compilation
- Fixed missing
import 'dart:convert'inwiz_control.dart
- Fixed missing
Changed #
-
Discovery Behavior
- Old:
Bulb.discover()returned single device as string - New:
discoverBulbs()returnsList<DiscoveredBulb>with all devices - CLI still works but now uses new discovery module internally
- Output format changed to match Python exactly
- Old:
-
Push Manager
- Source IP detection now more robust and accurate
- Better logging for troubleshooting connection issues
Verified #
- ✅ All features tested with real WiZ smart bulbs (2 devices)
- ✅ Discovery finds all devices on network
- ✅ Push updates receive real-time state changes
- ✅ RGB color control works (red, green, blue, yellow, cyan, magenta, white)
- ✅ Color temperature control works (2700K warm white tested)
- ✅ Output format matches Python implementation exactly
- ✅ All 15 timeout/retry integration tests passing
- ✅ All 40 bulb_type tests passing
- ✅ All 37 color_utils tests passing
1.0.0 - 2025-11-04 #
Added #
- Initial release of WizLight Dart package
- Complete port of wizlightcpp functionality to Dart
Bulbclass for controlling WiZ smart light bulbs- Device discovery via UDP broadcast
- Basic controls (on/off, reboot)
- Brightness control (0-100%)
- RGB color control (0-255 per channel)
- Color temperature control (1000-8000K)
- Scene selection (32 preset scenes)
- Animation speed control (0-100%)
- Device information queries (status, WiFi config, system config, user config)
UDPSocketclass for UDP communication with broadcast supportWizControlclass for command handling and CLI operations- CLI tool (
bin/wizlight.dart) with support for:- All bulb control commands
- Interactive and CLI modes
- Help and usage information
- Verbose logging option
- Comprehensive unit tests
- Input validation tests
- JSON request format tests
- Response parsing tests
- Command handling tests
- Example code demonstrating all features
- Full API documentation with Dartdoc comments
- README with detailed usage instructions
- MIT License
Features #
- Type Safety: Full null-safety support
- Input Validation: Range checking for all parameters
- Error Handling: Proper timeout and error handling
- Logging: Structured logging with configurable levels
- Cross-Platform: Works on all Dart-supported platforms
Documentation #
- Comprehensive README.md with examples
- API reference documentation
- Usage examples in
example/main.dart - Scene list reference
- Protocol details and troubleshooting guide
Testing #
- Unit tests for Bulb class
- Unit tests for WizControl class
- Request format validation tests
- Response parsing tests