Several KASA devices seem to have pretty strict buffer size limitations on incoming/outgoing data transfers.
Testing on KL125-US and HL103 has shown that sending a request size larger than about ~768 bytes will immediately crash the device. Additionally, a query that generates a response larger than ~4096 bytes will crash the KL125-US. I was unable to generate such a large response to test the HL103.
The KL125-US will only return such large queries when its monthly usage stats have been populated. This means that a new bulb would work fine, but after a month of data collection the bulb would break the 4K limit and start to crash.
To work around this issue, an estimated worst-case response size is calculated before sending a request by summing up all modules estimated response size. If the estimated size is greater than the device's max_response_payload_size then the query will be split into multiple queries.
This PR implements splitting queries expected to have large responses and also removes the module 'skip list' which was a previous workaround to the crash (which worked by simply reducing the number of modules queried, which prevented the overflow) since it is no longer necessary.
This PR does not attempt to address the "input buffer size limit." Thus far this limit has not been an issue.
* Add plumbing for passing credentials as far as discovery
* Pass credentials to Smart devices
* Rename authentication exception
* Fix tests failure due to test_json_output leaving echo as nop
* Fix test_credentials test
* Do not print credentials, fix echo function bug and improve get type parameter
* Add device class constructor test
* Add comment for echo handling and move assignment
* Mark mocked fixtures as such
* Use consistent filenames including the swver
* Remove executable bit
* Remove duplicate KL130(US)
* Remove unnecessary mocks where we have real ones available
* Fix filenames in tests
* Make hue, saturation and color_temp optional for smartbulbpresets
* Adjust bulb preset attributes for effect mode
* Don't send None values on save_preset
* Add tests for save_preset payloads
* Add module support & modularize existing query
This creates a base to expose more features on the supported devices.
At the moment, the most visible change is that each update cycle gets information from all available modules:
* Basic system info
* Cloud (new)
* Countdown (new)
* Antitheft (new)
* Schedule (new)
* Time (existing, implements the time/timezone handling)
* Emeter (existing, partially separated from smartdevice)
* Fix imports
* Fix linting
* Use device host instead of alias in module repr
* Add property to list available modules, print them in cli state report
* usage: fix the get_realtime query
* separate usage from schedule to avoid multi-inheritance
* Fix module querying
* Add is_supported property to modules
* Ensure state is restored when turning back on
Fixes https://github.com/home-assistant/core/issues/69039
* Update kasa/tests/test_bulb.py
Co-authored-by: Teemu R. <tpr@iki.fi>
Co-authored-by: Teemu R. <tpr@iki.fi>
* bulb: allow set_hsv without v, add fallback ct range
* add ColorTempRange and HSV named tuples
* add a fallback color temp range if unknown, log a warning
* set_hsv: the value is now optional
* Fix tests, change fallback range to 2700-5000
* Preliminary support for light strips
* Add color temperature range and cleanup, thanks to @darkoppressor
* Use lightstrip instead of {led,light}strip consistently everywhere
* The cli flag is now --lightstrip
* add apidocs
* Add fixture file for KL430
Signed-off-by: Kevin Wells <darkoppressor@gmail.com>
* Add discovery support, expose effect and length of the strip
* use set_light_state instead of transition_light_state
* Add tests for lightstrip
* add doctests
* Add KL430 to supported devices in README
Co-authored-by: Kevin Wells <darkoppressor@gmail.com>
* Add ignore_default to lights to allow setting to specific light state, force bulb on when changing the settings, allow defining brightness for set_color_temp, add a couple of new API methods
* Fix and simplify transition_light_state to make tests pass
* Add doctests to SmartBulb
* Add SmartDevice doctests, cleanup README.md
* add doctests for smartplug and smartstrip
* add discover doctests
* Fix bulb mock
* add smartdimmer doctests
* add sphinx-generated docs, cleanup readme a bit
* remove sphinx-click as it does not work with asyncclick
* in preparation for rtd hooking, move doc deps to be separate from dev deps
* pytestmark needs to be applied separately for each and every file, this fixes the tests
* use pathlib for resolving relative paths
* Skip discovery doctest on python3.7
The code is just fine, but some reason the mocking behaves differently between 3.7 and 3.8.
The latter seems to accept a discrete object for asyncio.run where the former expects a coroutine..
* Move tests to device-type specific test files to make improvements more approachable
* protocol: remove the port parameter from query, as there are no other known ports, fix docstrings
* Revise docstrings, remove superfluous information and remove unused methods ({set,get_icon} and set_time)
* cli: indent device output to make it more easily readable when having multiple devices
* remove adjust flake8 ignores (we have no setup.py anymore)
* pyproject: include cli tool to coverage, add config for interrogate (docstring coverage)
* bulb: raise exception on color_temp error cases instead of returning zero values
* improve bulb tests, simplify conftest
* strip: rename plugs property to children and move it to smartdevice
* Optimize I/O access
A single update() will now fetch information from all interesting modules,
including the current device state and the emeter information.
In practice, this will allow dropping the number of I/O reqs per homeassistant update cycle to 1,
which is paramount at least for bulbs which are very picky about sequential accesses.
This can be further extend to other modules/methods, if needed.
Currently fetched data:
* sysinfo
* realtime, today's and this months emeter stats
New properties:
* emeter_realtime: return the most recent emeter information, update()-version of get_emeter_realtime()
* emeter_today: returning today's energy consumption
* emeter_this_month: same for this month
Other changes:
* Accessing @requires_update properties will cause SmartDeviceException if the device has not ever been update()d
* Fix __repr__ for devices that haven't been updated
* Smartbulb uses now the state data from get_sysinfo instead of separately querying the bulb service
* SmartStrip's state_information no longer lists onsince for separate plugs
* The above mentioned properties are now printed out by cli
* Simplify is_on handling for bulbs
* remove implicit updates, return device responses for actions, update README.md instructions. fixes#61
* Convert to use poetry and pyproject.toml, update README
* add some resources for contributors
* minor adjustments
* ci: separate tests from linting, run using poetry
* add pytest-mock to dev requirements
* combine running tests and reporting to codecov
* generate both xml and html coverage reports
* add codecov to dev dependencies
The cache was useful trick when the property accesses caused I/O,
which is unnecessary now as dev.update() does explicitly cache results until its called again.
* All child device handling is moved out from the main smartdevice class, which simplifies the code.
* This will also cleanup the constructors as only the subdevices require the ID and the parent reference.
* SmartStripPlug offers SmartPlug like interface, but does not allow separate updates
* Trying to update() on the children will cause a warning.
* do not update inside __repr__
* Convert discovery to asyncio
* Use asyncio.DatagramProtocol
* Cleanup parameters, no more positional arguments
Closes#7
* Remove sync interface
* This requires #13 to be merged. Closes#12.
* Converts cli to use asyncio.run() where needed.
* The children from smartstrips is being initialized during the first update call.
* Convert on and off commands to use asyncio.run
* conftest: do the initial update automatically for the device, cleans up tests a bit
* return subdevices alias for strip plugs, remove sync from docstrings
* Make tests pass using pytest-asyncio
* Simplify tests and use pytest-asyncio.
* Removed the emeter tests for child devices, as this information do not seem to exist (based on the dummy sysinfo data). Can be added again if needed.
* Remove sync from docstrings.
* Fix incorrect type hint
* Add type hints and some docstrings to discovery