Skip to content

Commit

Permalink
Merge pull request #2 from aderesh/feature/rate-limit-config
Browse files Browse the repository at this point in the history
introduced throttle and receive queue configurations
  • Loading branch information
aderesh authored May 25, 2024
2 parents d96270d + 914ad0f commit f2ba529
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,5 @@ There is a docker image aderesh/mqtt2kasa. Please see `docker-compose.yaml` for
### TODO

- Add support for the smart strip, so each 'child' can be controlled independently;
- Expose throttle config instead of hardcoded values;
- Improve documentation?!?
- Use strict yaml (https://hitchdev.com/strictyaml/)
15 changes: 15 additions & 0 deletions data/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ globals:
# kasa will monitor the current state of the device every
# poll interval, in seconds. You can override on a per device
poll_interval: 11
# throttle_rate_limit specifices `rate_limit` value of the throttler
# default value is `4`. `0` disables throttle
throttle_rate_limit: 4
# throttle_period specifies `period` value of the throttler
# default value is `60` seconds
throttle_period: 60
# receive_queue_size specfies command queue size
# Default value is `4`. `0` makes the queue and infinite queue
receive_queue_size: 4
locations:
# coffee maker. To turn it on, use mqtt publish
# topic: /coffee_maker/switch payload: on
Expand All @@ -39,6 +48,12 @@ locations:
alias: storage
poll_interval: 120
emeter_poll_interval: 600
# example where throttle parameters are specified
bedroom_lights:
host: 192.168.1.33
throttle_rate_limit: 10
throttle_period: 10 # seconds
receive_queue_size: 30
keep_alives:
# this is a very optional thing but can be useful. It will monitor a
# specific topic to determine if a device should be on or off. The
Expand Down
39 changes: 39 additions & 0 deletions mqtt2kasa/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,45 @@ def emeter_poll_interval(self, location_name):
or const.KASA_DEFAULT_EMETER_POLL_INTERVAL
)

def throttle_rate_limit(self, location_name):
locations = self._get_info().locations
if isinstance(locations, collections.abc.Mapping):
location_attributes = locations.get(location_name, {})
if "throttle_rate_limit" in location_attributes:
return float(location_attributes["throttle_rate_limit"])

cfg_globals = self._get_info().cfg_globals
if "throttle_rate_limit" in cfg_globals:
return float(cfg_globals["throttle_rate_limit"])

return float(const.KASA_DEFAULT_THROTTLE_RATE_LIMIT)

def throttle_period(self, location_name):
locations = self._get_info().locations
if isinstance(locations, collections.abc.Mapping):
location_attributes = locations.get(location_name, {})
if "throttle_period" in location_attributes:
return float(location_attributes["throttle_period"])

cfg_globals = self._get_info().cfg_globals
if "throttle_period" in cfg_globals:
return float(cfg_globals["throttle_period"])

return float(const.KASA_DEFAULT_THROTTLE_PERIOD)

def receive_queue_size(self, location_name):
locations = self._get_info().locations
if isinstance(locations, collections.abc.Mapping):
location_attributes = locations.get(location_name, {})
if "receive_queue_size" in location_attributes:
return float(location_attributes["receive_queue_size"])

cfg_globals = self._get_info().cfg_globals
if "receive_queue_size" in cfg_globals:
return float(cfg_globals["receive_queue_size"])

return float(const.KASA_DEFAULT_RECEIVE_QUEUE_SIZE)

@property
def locations(self):
return self._get_info().locations
Expand Down
3 changes: 3 additions & 0 deletions mqtt2kasa/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
KASA_DEFAULT_POLL_INTERVAL = 10 # [seconds]
KASA_DEFAULT_EMETER_POLL_INTERVAL = 0 # [seconds] 0 == disabled
KEEP_ALIVE_DEFAULT_TASK_INTERVAL = 1.5 # [seconds]
KASA_DEFAULT_THROTTLE_RATE_LIMIT = 4 # 0 == disabled
KASA_DEFAULT_THROTTLE_PERIOD = 60
KASA_DEFAULT_RECEIVE_QUEUE_SIZE = 4 # 0 == queue is disabled
14 changes: 12 additions & 2 deletions mqtt2kasa/kasa_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@

logger = log.getLogger()

class NoThrottler:
async def __aenter__(self):
return None

async def __aexit__(self, exc_type, exc, tb):
pass

class Kasa:
STATE_ON = "on"
Expand All @@ -27,8 +33,12 @@ def __init__(self, name: str, topic: str, config: dict):
self.alias = config.get("alias")
self.poll_interval = Cfg().poll_interval(name)
self.emeter_poll_interval = Cfg().emeter_poll_interval(name)
self.recv_q = asyncio.Queue(maxsize=4)
self.throttler = Throttler(rate_limit=4, period=60)
self.recv_q = asyncio.Queue(maxsize=Cfg().receive_queue_size(name))
rate_limit = Cfg().throttle_rate_limit(name)
if rate_limit > 0:
self.throttler = Throttler(rate_limit=Cfg().throttle_rate_limit(name), period=Cfg().throttle_period(name))
else:
self.throttler = NoThrottler()
self.curr_state = None
self.curr_brightness = None
self._device = None
Expand Down

0 comments on commit f2ba529

Please sign in to comment.