From dd22527979fd168ea86c4fe4779369d7567f135b Mon Sep 17 00:00:00 2001 From: yparitcher Date: Thu, 24 Aug 2023 20:25:16 -0400 Subject: [PATCH 01/17] rule: end options are optional --- kasa/modules/rulemodule.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index e73b2d03e..75c741736 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -41,8 +41,8 @@ class Rule(BaseModel): smin: int eact: Optional[Action] - etime_opt: TimeOption - emin: int + etime_opt: Optional[TimeOption] + emin: Optional[int] # Only on bulbs s_light: Optional[Dict] From 68007a7ced5d381974c89458969167f29c4b731b Mon Sep 17 00:00:00 2001 From: yparitcher Date: Thu, 24 Aug 2023 20:26:05 -0400 Subject: [PATCH 02/17] schedule: overall enable schedule --- kasa/cli.py | 9 +++++++++ kasa/modules/rulemodule.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kasa/cli.py b/kasa/cli.py index d2ac9589d..754775287 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -642,6 +642,15 @@ def _schedule_list(dev, type): return sched.rules +@schedule.command(name="enable") +@pass_dev +@click.argument("enable", type=click.BOOL) +async def _schedule_enable(dev, enable): + """Enable or disable schedule.""" + schedule = dev.modules["schedule"] + return await schedule.set_enabled(enable) + + @schedule.command(name="delete") @pass_dev @click.option("--id", type=str, required=True) diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 75c741736..c77c818fd 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -72,7 +72,7 @@ def rules(self) -> List[Rule]: async def set_enabled(self, state: bool): """Enable or disable the service.""" - return await self.call("set_overall_enable", state) + return await self.call("set_overall_enable", {"enable": 1 if state else 0}) async def delete_rule(self, rule: Rule): """Delete the given rule.""" From 0f0066451bcc9255a5193edc2429c379ac954e3b Mon Sep 17 00:00:00 2001 From: yparitcher Date: Thu, 24 Aug 2023 20:26:18 -0400 Subject: [PATCH 03/17] schedule: delete all --- kasa/cli.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kasa/cli.py b/kasa/cli.py index 754775287..d54f46e52 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -665,6 +665,14 @@ async def delete_rule(dev, id): echo(f"No rule with id {id} was found") +@schedule.command(name="delete_all") +@pass_dev +async def delete_all(dev): + """Delete all rules from device.""" + schedule = dev.modules["schedule"] + return await schedule.delete_all_rules() + + @cli.group(invoke_without_command=True) @click.pass_context async def presets(ctx): From ccd1756882b7cc089429dd3ad2f282fa589f3ea2 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Thu, 24 Aug 2023 23:20:49 -0400 Subject: [PATCH 04/17] rule: end options doc --- kasa/modules/rulemodule.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index c77c818fd..3963c555e 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -29,7 +29,8 @@ class TimeOption(Enum): class Rule(BaseModel): """Representation of a rule.""" - id: str + # not used when adding a rule + id: Optional[str] name: str enable: bool wday: List[int] @@ -40,7 +41,9 @@ class Rule(BaseModel): stime_opt: TimeOption smin: int + # end action eact: Optional[Action] + # will be None if the rule was created with etime_opt: -1 etime_opt: Optional[TimeOption] emin: Optional[int] From 8b51c76509b366fbbb21a2d712caafade7f7b31a Mon Sep 17 00:00:00 2001 From: yparitcher Date: Fri, 25 Aug 2023 00:21:37 -0400 Subject: [PATCH 05/17] schedule: fix list --- kasa/cli.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index d54f46e52..a556b4c57 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -630,14 +630,18 @@ async def schedule(dev): @schedule.command(name="list") @pass_dev +@click.option("--json", is_flag=True) @click.argument("type", default="schedule") -def _schedule_list(dev, type): +def _schedule_list(dev, json, type): """Return the list of schedule actions for the given type.""" sched = dev.modules[type] - for rule in sched.rules: - print(rule) - else: + if sched.rules == []: echo(f"No rules of type {type}") + for rule in sched.rules: + if json: + print(rule.json()) + else: + print(rule) return sched.rules From 37fda33ef8ae9b30fa88dfc1ada33cb3d3586d45 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Fri, 25 Aug 2023 00:22:09 -0400 Subject: [PATCH 06/17] schedule: doc --- kasa/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/kasa/cli.py b/kasa/cli.py index a556b4c57..fb750c9a9 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -674,6 +674,7 @@ async def delete_rule(dev, id): async def delete_all(dev): """Delete all rules from device.""" schedule = dev.modules["schedule"] + echo(f"Deleting all rules") return await schedule.delete_all_rules() From 2a3d29bff7d19dee54a9bff100ba6d17acb6a528 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Fri, 25 Aug 2023 02:37:00 -0400 Subject: [PATCH 07/17] schedule: add / edit rule (only plugs for now not switches) --- kasa/cli.py | 76 +++++++++++++++++++++++++++++++++++++- kasa/modules/rulemodule.py | 26 ++++++++----- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index fb750c9a9..e222fbdf3 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -38,6 +38,8 @@ def wrapper(message=None, *args, **kwargs): SmartStrip, ) +from kasa.modules import Rule + TYPE_TO_CLASS = { "plug": SmartPlug, "bulb": SmartBulb, @@ -652,7 +654,79 @@ def _schedule_list(dev, json, type): async def _schedule_enable(dev, enable): """Enable or disable schedule.""" schedule = dev.modules["schedule"] - return await schedule.set_enabled(enable) + return await schedule.set_enabled(1 if state else 0) + + +@schedule.command(name="add") +@pass_dev +@click.option("--name", type=str, required=True) +@click.option("--enable", type=click.BOOL, default=True, show_default=True) +@click.option("--repeat", type=click.BOOL, default=True, show_default=True) +@click.option("--wday", type=str, required=True) +@click.option("--sact", type=click.IntRange(-1, 2), default=None, required=True) +@click.option("--stime_opt", type=click.IntRange(-1, 2), default=None, required=True) +@click.option("--smin", type=click.IntRange(0, 1440), default=None, required=True) +@click.option("--eact", type=click.IntRange(-1, 2), default=-1) +@click.option("--etime_opt", type=click.IntRange(-1, 2), default=-1) +@click.option("--emin", type=click.IntRange(0, 1440), default=None) +async def add_rule(dev, + name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin +): + """Add rule to device.""" + schedule = dev.modules["schedule"] + #rule_to_add = Rule.parse_raw(rule) + rule_to_add = Rule(name=name, enable=enable, repeat=repeat, wday=list(map(int, wday.split(","))), sact=sact, stime_opt=stime_opt, smin=smin, eact=eact, etime_opt=etime_opt, emin=emin) + if rule_to_add: + echo(f"Adding rule") + return await schedule.add_rule(rule_to_add) + else: + echo(f"Invalid rule") + + +@schedule.command(name="edit") +@pass_dev +@click.option("--id", type=str, required=True) +@click.option("--name", type=str) +@click.option("--enable", type=click.BOOL) +@click.option("--repeat", type=click.BOOL) +@click.option("--wday", type=str) +@click.option("--sact", type=click.IntRange(-1, 2)) +@click.option("--stime_opt", type=click.IntRange(-1, 2)) +@click.option("--smin", type=click.IntRange(0, 1440)) +@click.option("--eact", type=click.IntRange(-1, 2)) +@click.option("--etime_opt", type=click.IntRange(-1, 2)) +@click.option("--emin", type=click.IntRange(0, 1440)) +async def edit_rule(dev, + id, name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin +): + """Edit rule from device.""" + schedule = dev.modules["schedule"] + rule_to_edit = next(filter(lambda rule: (rule.id == id), schedule.rules), None) + if rule_to_edit: + echo(f"Editing rule id {id}") + if name != None: + rule_to_edit.name = name + if enable != None: + rule_to_edit.enable = 1 if enable else 0 + if repeat != None: + rule_to_edit.repeat = 1 if repeat else 0 + if wday!= None: + rule_to_edit.wday = list(map(int, wday.split(","))) + if sact != None: + rule_to_edit.sact = sact + if stime_opt != None: + rule_to_edit.stime_opt = stime_opt + if smin != None: + rule_to_edit.smin = smin + if eact != None: + rule_to_edit.eact = eact + if etime_opt != None: + rule_to_edit.etime_opt = etime_opt + if emin != None: + rule_to_edit.emin = emin + return await schedule.edit_rule(rule_to_edit) + else: + echo(f"No rule with id {id} was found") @schedule.command(name="delete") diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 3963c555e..64f74ff66 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -1,5 +1,5 @@ """Base implementation for all rule-based modules.""" -import logging +import logging, json from enum import Enum from typing import Dict, List, Optional @@ -26,15 +26,15 @@ class TimeOption(Enum): AtSunset = 2 -class Rule(BaseModel): +class Rule(BaseModel, validate_assignment=True): """Representation of a rule.""" # not used when adding a rule id: Optional[str] name: str - enable: bool + enable: int wday: List[int] - repeat: bool + repeat: int # start action sact: Optional[Action] @@ -43,8 +43,8 @@ class Rule(BaseModel): # end action eact: Optional[Action] - # will be None if the rule was created with etime_opt: -1 - etime_opt: Optional[TimeOption] + # Required to submit, but the device will not return it if set to -1 + etime_opt: TimeOption = TimeOption.Disabled emin: Optional[int] # Only on bulbs @@ -55,7 +55,7 @@ class Rule(BaseModel): class RuleModule(Module): - """Base class for rule-based modules, such as countdown and antitheft.""" + """Base class for rule-based modules, such as antitheft, countdown and schedule.""" def query(self): """Prepare the query for rules.""" @@ -73,9 +73,17 @@ def rules(self) -> List[Rule]: _LOGGER.error("Unable to read rule list: %s (data: %s)", ex, self.data) return [] - async def set_enabled(self, state: bool): + async def set_enabled(self, state: int): """Enable or disable the service.""" - return await self.call("set_overall_enable", {"enable": 1 if state else 0}) + return await self.call("set_overall_enable", {"enable": state}) + + async def add_rule(self, rule: Rule): + """Add a new rule.""" + return await self.call("add_rule", json.loads(rule.json(exclude_none=True))) + + async def edit_rule(self, rule: Rule): + """Edit the given rule.""" + return await self.call("edit_rule", json.loads(rule.json(exclude_none=True))) async def delete_rule(self, rule: Rule): """Delete the given rule.""" From a1151fa9a66160b1d39810789cc4b0361d8506eb Mon Sep 17 00:00:00 2001 From: yparitcher Date: Fri, 25 Aug 2023 02:43:55 -0400 Subject: [PATCH 08/17] lint --- kasa/cli.py | 49 ++++++++++++++++++++++---------------- kasa/modules/rulemodule.py | 10 ++++++-- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index e222fbdf3..4f93e11ab 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -37,7 +37,6 @@ def wrapper(message=None, *args, **kwargs): SmartPlug, SmartStrip, ) - from kasa.modules import Rule TYPE_TO_CLASS = { @@ -669,18 +668,28 @@ async def _schedule_enable(dev, enable): @click.option("--eact", type=click.IntRange(-1, 2), default=-1) @click.option("--etime_opt", type=click.IntRange(-1, 2), default=-1) @click.option("--emin", type=click.IntRange(0, 1440), default=None) -async def add_rule(dev, - name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin +async def add_rule( + dev, name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin ): """Add rule to device.""" schedule = dev.modules["schedule"] - #rule_to_add = Rule.parse_raw(rule) - rule_to_add = Rule(name=name, enable=enable, repeat=repeat, wday=list(map(int, wday.split(","))), sact=sact, stime_opt=stime_opt, smin=smin, eact=eact, etime_opt=etime_opt, emin=emin) + rule_to_add = Rule( + name=name, + enable=enable, + repeat=repeat, + wday=list(map(int, wday.split(","))), + sact=sact, + stime_opt=stime_opt, + smin=smin, + eact=eact, + etime_opt=etime_opt, + emin=emin, + ) if rule_to_add: - echo(f"Adding rule") + echo("Adding rule") return await schedule.add_rule(rule_to_add) else: - echo(f"Invalid rule") + echo("Invalid rule") @schedule.command(name="edit") @@ -696,33 +705,33 @@ async def add_rule(dev, @click.option("--eact", type=click.IntRange(-1, 2)) @click.option("--etime_opt", type=click.IntRange(-1, 2)) @click.option("--emin", type=click.IntRange(0, 1440)) -async def edit_rule(dev, - id, name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin +async def edit_rule( + dev, id, name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin ): """Edit rule from device.""" schedule = dev.modules["schedule"] rule_to_edit = next(filter(lambda rule: (rule.id == id), schedule.rules), None) if rule_to_edit: echo(f"Editing rule id {id}") - if name != None: + if name is not None: rule_to_edit.name = name - if enable != None: + if enable is not None: rule_to_edit.enable = 1 if enable else 0 - if repeat != None: + if repeat is not None: rule_to_edit.repeat = 1 if repeat else 0 - if wday!= None: + if wday is not None: rule_to_edit.wday = list(map(int, wday.split(","))) - if sact != None: + if sact is not None: rule_to_edit.sact = sact - if stime_opt != None: + if stime_opt is not None: rule_to_edit.stime_opt = stime_opt - if smin != None: + if smin is not None: rule_to_edit.smin = smin - if eact != None: + if eact is not None: rule_to_edit.eact = eact - if etime_opt != None: + if etime_opt is not None: rule_to_edit.etime_opt = etime_opt - if emin != None: + if emin is not None: rule_to_edit.emin = emin return await schedule.edit_rule(rule_to_edit) else: @@ -748,7 +757,7 @@ async def delete_rule(dev, id): async def delete_all(dev): """Delete all rules from device.""" schedule = dev.modules["schedule"] - echo(f"Deleting all rules") + echo("Deleting all rules") return await schedule.delete_all_rules() diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 64f74ff66..34c012991 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -1,5 +1,6 @@ """Base implementation for all rule-based modules.""" -import logging, json +import json +import logging from enum import Enum from typing import Dict, List, Optional @@ -26,7 +27,7 @@ class TimeOption(Enum): AtSunset = 2 -class Rule(BaseModel, validate_assignment=True): +class Rule(BaseModel): """Representation of a rule.""" # not used when adding a rule @@ -50,6 +51,11 @@ class Rule(BaseModel, validate_assignment=True): # Only on bulbs s_light: Optional[Dict] + class Config: + """Rule Config.""" + + validate_assignment = True + _LOGGER = logging.getLogger(__name__) From af3b9994df6fcab3d4482e2ed42c6421ce747898 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sat, 26 Aug 2023 21:56:47 -0400 Subject: [PATCH 09/17] set timezone --- kasa/cli.py | 8 ++++++++ kasa/modules/time.py | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/kasa/cli.py b/kasa/cli.py index 4f93e11ab..7c7c17b83 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -570,6 +570,14 @@ async def time(dev): return res +@cli.command() +@click.argument("tz_index", type=int) +@pass_dev +async def set_timezone(dev, tz_index): + """Set the device timezone.""" + return await dev.modules["time"].set_timezone(tz_index) + + @cli.command() @click.option("--index", type=int, required=False) @click.option("--name", type=str, required=False) diff --git a/kasa/modules/time.py b/kasa/modules/time.py index d72e2d600..aa5e45f03 100644 --- a/kasa/modules/time.py +++ b/kasa/modules/time.py @@ -52,3 +52,7 @@ async def get_time(self): async def get_timezone(self): """Request timezone information from the device.""" return await self.call("get_timezone") + + async def set_timezone(self, tz_index): + """Request timezone information from the device.""" + return await self.call("set_timezone", {"index": tz_index}) From 178da08d15cc2125009f67330a13cfe14ad49e3a Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sat, 26 Aug 2023 22:01:26 -0400 Subject: [PATCH 10/17] doc --- kasa/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kasa/cli.py b/kasa/cli.py index 7c7c17b83..7c37538b8 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -574,7 +574,10 @@ async def time(dev): @click.argument("tz_index", type=int) @pass_dev async def set_timezone(dev, tz_index): - """Set the device timezone.""" + """Set the device timezone. + + See https://github.com/GadgetReactor/pyHS100/issues/53#issuecomment-296875129 for valid timezones + """ return await dev.modules["time"].set_timezone(tz_index) From cb5722faae4641b4e61a9a89cc37612fc61559e3 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sat, 26 Aug 2023 22:05:35 -0400 Subject: [PATCH 11/17] EnabledOption --- kasa/modules/rulemodule.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 34c012991..2d2139347 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -9,6 +9,13 @@ from .module import Module, merge +class EnabledOption(Enum): + """Integer enabled option.""" + + TurnOff = 0 + Enabled = 1 + + class Action(Enum): """Action to perform.""" @@ -33,9 +40,9 @@ class Rule(BaseModel): # not used when adding a rule id: Optional[str] name: str - enable: int + enable: EnabledOption wday: List[int] - repeat: int + repeat: EnabledOption # start action sact: Optional[Action] From 736fe2b6cdb457f0f940ac9a4d11fb44fb50f7e0 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sat, 26 Aug 2023 22:22:48 -0400 Subject: [PATCH 12/17] delete all fixes --- kasa/cli.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index 7c37538b8..98778ad43 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -763,13 +763,15 @@ async def delete_rule(dev, id): echo(f"No rule with id {id} was found") -@schedule.command(name="delete_all") +@schedule.command() @pass_dev -async def delete_all(dev): +@click.option("--prompt", type=click.BOOL, prompt=True, help="Are you sure?") +async def delete_all(dev, prompt): """Delete all rules from device.""" schedule = dev.modules["schedule"] - echo("Deleting all rules") - return await schedule.delete_all_rules() + if prompt: + echo("Deleting all rules") + return await schedule.delete_all_rules() @cli.group(invoke_without_command=True) From 4e46c97df50b8720336928504620bc679eb83cf3 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sat, 26 Aug 2023 23:36:57 -0400 Subject: [PATCH 13/17] rule: better modeling --- kasa/cli.py | 82 ++++++++++++++++++++++++-------------- kasa/modules/__init__.py | 9 +++-- kasa/modules/antitheft.py | 4 +- kasa/modules/countdown.py | 4 +- kasa/modules/rulemodule.py | 57 +++++++++++++++++--------- kasa/modules/schedule.py | 10 ++++- kasa/smartbulb.py | 4 +- 7 files changed, 113 insertions(+), 57 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index 98778ad43..2c408e6f6 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -37,7 +37,6 @@ def wrapper(message=None, *args, **kwargs): SmartPlug, SmartStrip, ) -from kasa.modules import Rule TYPE_TO_CLASS = { "plug": SmartPlug, @@ -576,7 +575,7 @@ async def time(dev): async def set_timezone(dev, tz_index): """Set the device timezone. - See https://github.com/GadgetReactor/pyHS100/issues/53#issuecomment-296875129 for valid timezones + See https://github.com/GadgetRend_actionor/pyHS100/issues/53#issuecomment-296875129 for valid timezones """ return await dev.modules["time"].set_timezone(tz_index) @@ -672,29 +671,41 @@ async def _schedule_enable(dev, enable): @click.option("--name", type=str, required=True) @click.option("--enable", type=click.BOOL, default=True, show_default=True) @click.option("--repeat", type=click.BOOL, default=True, show_default=True) -@click.option("--wday", type=str, required=True) -@click.option("--sact", type=click.IntRange(-1, 2), default=None, required=True) +@click.option("--days", type=str, required=True) +@click.option("--start-action", type=click.IntRange(-1, 2), default=None, required=True) @click.option("--stime_opt", type=click.IntRange(-1, 2), default=None, required=True) -@click.option("--smin", type=click.IntRange(0, 1440), default=None, required=True) -@click.option("--eact", type=click.IntRange(-1, 2), default=-1) +@click.option( + "--start-minutes", type=click.IntRange(0, 1440), default=None, required=True +) +@click.option("--end-action", type=click.IntRange(-1, 2), default=-1) @click.option("--etime_opt", type=click.IntRange(-1, 2), default=-1) -@click.option("--emin", type=click.IntRange(0, 1440), default=None) +@click.option("--end-minutes", type=click.IntRange(0, 1440), default=None) async def add_rule( - dev, name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin + dev, + name, + enable, + repeat, + days, + start_action, + stime_opt, + start_minutes, + end_action, + etime_opt, + end_minutes, ): """Add rule to device.""" schedule = dev.modules["schedule"] - rule_to_add = Rule( + rule_to_add = schedule.Rule( name=name, enable=enable, repeat=repeat, - wday=list(map(int, wday.split(","))), - sact=sact, + days=list(map(int, days.split(","))), + start_action=start_action, stime_opt=stime_opt, - smin=smin, - eact=eact, + start_minutes=start_minutes, + end_action=end_action, etime_opt=etime_opt, - emin=emin, + end_minutes=end_minutes, ) if rule_to_add: echo("Adding rule") @@ -709,15 +720,26 @@ async def add_rule( @click.option("--name", type=str) @click.option("--enable", type=click.BOOL) @click.option("--repeat", type=click.BOOL) -@click.option("--wday", type=str) -@click.option("--sact", type=click.IntRange(-1, 2)) +@click.option("--days", type=str) +@click.option("--start-action", type=click.IntRange(-1, 2)) @click.option("--stime_opt", type=click.IntRange(-1, 2)) -@click.option("--smin", type=click.IntRange(0, 1440)) -@click.option("--eact", type=click.IntRange(-1, 2)) +@click.option("--start-minutes", type=click.IntRange(0, 1440)) +@click.option("--end-action", type=click.IntRange(-1, 2)) @click.option("--etime_opt", type=click.IntRange(-1, 2)) -@click.option("--emin", type=click.IntRange(0, 1440)) +@click.option("--end-minutes", type=click.IntRange(0, 1440)) async def edit_rule( - dev, id, name, enable, repeat, wday, sact, stime_opt, smin, eact, etime_opt, emin + dev, + id, + name, + enable, + repeat, + days, + start_action, + stime_opt, + start_minutes, + end_action, + etime_opt, + end_minutes, ): """Edit rule from device.""" schedule = dev.modules["schedule"] @@ -730,20 +752,20 @@ async def edit_rule( rule_to_edit.enable = 1 if enable else 0 if repeat is not None: rule_to_edit.repeat = 1 if repeat else 0 - if wday is not None: - rule_to_edit.wday = list(map(int, wday.split(","))) - if sact is not None: - rule_to_edit.sact = sact + if days is not None: + rule_to_edit.wday = list(map(int, days.split(","))) + if start_action is not None: + rule_to_edit.sact = start_action if stime_opt is not None: rule_to_edit.stime_opt = stime_opt - if smin is not None: - rule_to_edit.smin = smin - if eact is not None: - rule_to_edit.eact = eact + if start_minutes is not None: + rule_to_edit.smin = start_minutes + if end_action is not None: + rule_to_edit.eact = end_action if etime_opt is not None: rule_to_edit.etime_opt = etime_opt - if emin is not None: - rule_to_edit.emin = emin + if end_minutes is not None: + rule_to_edit.emin = end_minutes return await schedule.edit_rule(rule_to_edit) else: echo(f"No rule with id {id} was found") diff --git a/kasa/modules/__init__.py b/kasa/modules/__init__.py index 8ad5088d5..e6d3043e9 100644 --- a/kasa/modules/__init__.py +++ b/kasa/modules/__init__.py @@ -6,8 +6,8 @@ from .emeter import Emeter from .module import Module from .motion import Motion -from .rulemodule import Rule, RuleModule -from .schedule import Schedule +from .rulemodule import BulbScheduleRule, CountdownRule, RuleModule, ScheduleRule +from .schedule import BulbSchedule, Schedule from .time import Time from .usage import Usage @@ -19,9 +19,12 @@ "Emeter", "Module", "Motion", - "Rule", + "CountdownRule", + "ScheduleRule", + "BulbScheduleRule", "RuleModule", "Schedule", + "BulbSchedule", "Time", "Usage", ] diff --git a/kasa/modules/antitheft.py b/kasa/modules/antitheft.py index c885a70c2..06ebd51b4 100644 --- a/kasa/modules/antitheft.py +++ b/kasa/modules/antitheft.py @@ -1,5 +1,5 @@ """Implementation of the antitheft module.""" -from .rulemodule import RuleModule +from .rulemodule import RuleModule, ScheduleRule class Antitheft(RuleModule): @@ -7,3 +7,5 @@ class Antitheft(RuleModule): This shares the functionality among other rule-based modules. """ + + Rule = ScheduleRule diff --git a/kasa/modules/countdown.py b/kasa/modules/countdown.py index 9f3e59c16..eacc0702b 100644 --- a/kasa/modules/countdown.py +++ b/kasa/modules/countdown.py @@ -1,6 +1,8 @@ """Implementation for the countdown timer.""" -from .rulemodule import RuleModule +from .rulemodule import CountdownRule, RuleModule class Countdown(RuleModule): """Implementation of countdown module.""" + + Rule = CountdownRule diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 2d2139347..72871c72f 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -4,7 +4,7 @@ from enum import Enum from typing import Dict, List, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Field from .module import Module, merge @@ -34,34 +34,50 @@ class TimeOption(Enum): AtSunset = 2 -class Rule(BaseModel): +class BaseRule(BaseModel): """Representation of a rule.""" # not used when adding a rule id: Optional[str] name: str enable: EnabledOption - wday: List[int] + + class Config: + """Rule Config.""" + + validate_assignment = True + allow_population_by_field_name = True + + +class CountdownRule(BaseRule): + """Representation of a countdown rule.""" + + delay: int + act: EnabledOption = Field(alias="action") + + +class ScheduleRule(BaseRule): + """Representation of a schedule rule.""" + + wday: List[int] = Field(alias="days") repeat: EnabledOption # start action - sact: Optional[Action] - stime_opt: TimeOption - smin: int + sact: Optional[Action] = Field(alias="start_action") + stime_opt: TimeOption = Field(alias="start?") + smin: int = Field(alias="start_minutes", ge=0, le=1440) # end action - eact: Optional[Action] + eact: Optional[Action] = Field(alias="end_action") # Required to submit, but the device will not return it if set to -1 - etime_opt: TimeOption = TimeOption.Disabled - emin: Optional[int] + etime_opt: TimeOption = Field(default=TimeOption.Disabled, alias="end?") + emin: Optional[int] = Field(alias="end_minutes", ge=0, le=1440) - # Only on bulbs - s_light: Optional[Dict] - class Config: - """Rule Config.""" +class BulbScheduleRule(BaseRule): + """Representation of a bulb schedule rule.""" - validate_assignment = True + s_light: Optional[Dict] = Field(alias="lights") _LOGGER = logging.getLogger(__name__) @@ -70,17 +86,20 @@ class Config: class RuleModule(Module): """Base class for rule-based modules, such as antitheft, countdown and schedule.""" + Rule = BaseRule + def query(self): """Prepare the query for rules.""" q = self.query_for_command("get_rules") return merge(q, self.query_for_command("get_next_action")) @property - def rules(self) -> List[Rule]: + def rules(self) -> List[BaseRule]: """Return the list of rules for the service.""" try: return [ - Rule.parse_obj(rule) for rule in self.data["get_rules"]["rule_list"] + self.Rule.parse_obj(rule) + for rule in self.data["get_rules"]["rule_list"] ] except Exception as ex: _LOGGER.error("Unable to read rule list: %s (data: %s)", ex, self.data) @@ -90,15 +109,15 @@ async def set_enabled(self, state: int): """Enable or disable the service.""" return await self.call("set_overall_enable", {"enable": state}) - async def add_rule(self, rule: Rule): + async def add_rule(self, rule: BaseRule): """Add a new rule.""" return await self.call("add_rule", json.loads(rule.json(exclude_none=True))) - async def edit_rule(self, rule: Rule): + async def edit_rule(self, rule: BaseRule): """Edit the given rule.""" return await self.call("edit_rule", json.loads(rule.json(exclude_none=True))) - async def delete_rule(self, rule: Rule): + async def delete_rule(self, rule: BaseRule): """Delete the given rule.""" return await self.call("delete_rule", {"id": rule.id}) diff --git a/kasa/modules/schedule.py b/kasa/modules/schedule.py index 62371692b..b67e86cfe 100644 --- a/kasa/modules/schedule.py +++ b/kasa/modules/schedule.py @@ -1,6 +1,14 @@ """Schedule module implementation.""" -from .rulemodule import RuleModule +from .rulemodule import BulbScheduleRule, RuleModule, ScheduleRule class Schedule(RuleModule): """Implements the scheduling interface.""" + + Rule = ScheduleRule + + +class BulbSchedule(RuleModule): + """Implements the scheduling interface.""" + + Rule = BulbScheduleRule diff --git a/kasa/smartbulb.py b/kasa/smartbulb.py index 1d6ba31e3..c0ad21e06 100644 --- a/kasa/smartbulb.py +++ b/kasa/smartbulb.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, Field, root_validator -from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage +from .modules import Antitheft, BulbSchedule, Cloud, Countdown, Emeter, Time, Usage from .smartdevice import DeviceType, SmartDevice, SmartDeviceException, requires_update @@ -202,7 +202,7 @@ class SmartBulb(SmartDevice): def __init__(self, host: str, *, port: Optional[int] = None) -> None: super().__init__(host=host, port=port) self._device_type = DeviceType.Bulb - self.add_module("schedule", Schedule(self, "smartlife.iot.common.schedule")) + self.add_module("schedule", BulbSchedule(self, "smartlife.iot.common.schedule")) self.add_module("usage", Usage(self, "smartlife.iot.common.schedule")) self.add_module("antitheft", Antitheft(self, "smartlife.iot.common.anti_theft")) self.add_module("time", Time(self, "smartlife.iot.common.timesetting")) From 11c408da7de05931a40e339ea38eb71de8736426 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sat, 26 Aug 2023 23:56:53 -0400 Subject: [PATCH 14/17] untested: add bulb rule items --- kasa/modules/__init__.py | 9 ++++++++- kasa/modules/antitheft.py | 4 ++-- kasa/modules/rulemodule.py | 28 ++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/kasa/modules/__init__.py b/kasa/modules/__init__.py index e6d3043e9..eedcc0dfa 100644 --- a/kasa/modules/__init__.py +++ b/kasa/modules/__init__.py @@ -6,7 +6,13 @@ from .emeter import Emeter from .module import Module from .motion import Motion -from .rulemodule import BulbScheduleRule, CountdownRule, RuleModule, ScheduleRule +from .rulemodule import ( + AntitheftRule, + BulbScheduleRule, + CountdownRule, + RuleModule, + ScheduleRule, +) from .schedule import BulbSchedule, Schedule from .time import Time from .usage import Usage @@ -19,6 +25,7 @@ "Emeter", "Module", "Motion", + "AntitheftRule", "CountdownRule", "ScheduleRule", "BulbScheduleRule", diff --git a/kasa/modules/antitheft.py b/kasa/modules/antitheft.py index 06ebd51b4..0dae2e19b 100644 --- a/kasa/modules/antitheft.py +++ b/kasa/modules/antitheft.py @@ -1,5 +1,5 @@ """Implementation of the antitheft module.""" -from .rulemodule import RuleModule, ScheduleRule +from .rulemodule import AntitheftRule, RuleModule class Antitheft(RuleModule): @@ -8,4 +8,4 @@ class Antitheft(RuleModule): This shares the functionality among other rule-based modules. """ - Rule = ScheduleRule + Rule = AntitheftRule diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 72871c72f..7442b932a 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -2,7 +2,7 @@ import json import logging from enum import Enum -from typing import Dict, List, Optional +from typing import List, Optional from pydantic import BaseModel, Field @@ -34,6 +34,13 @@ class TimeOption(Enum): AtSunset = 2 +class BulbModeOption(Enum): + """Bulb mode.""" + + Customize = "customize_preset" + Last = "last_status" + + class BaseRule(BaseModel): """Representation of a rule.""" @@ -74,10 +81,27 @@ class ScheduleRule(BaseRule): emin: Optional[int] = Field(alias="end_minutes", ge=0, le=1440) +class BulbRule(BaseRule): + """Representation of a bulb schedule rule.""" + + saturation: int = Field(ge=0, le=100) + hue: int = Field(ge=0, le=360) + brightness: int = Field(ge=0, le=100) + color_temp: int = Field(ge=2500, le=9000) + mode: BulbModeOption + on_off: EnabledOption + + class BulbScheduleRule(BaseRule): """Representation of a bulb schedule rule.""" - s_light: Optional[Dict] = Field(alias="lights") + s_light: BulbRule = Field(alias="lights") + + +class AntitheftRule(BaseRule): + """Representation of a antitheft rule.""" + + frequency: int = Field(ge=1, le=10) _LOGGER = logging.getLogger(__name__) From 3da18e3c66f48e319158bd28d921f7cc8493dc93 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sun, 27 Aug 2023 00:00:45 -0400 Subject: [PATCH 15/17] sun name --- kasa/cli.py | 28 ++++++++++++++-------------- kasa/modules/rulemodule.py | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index 2c408e6f6..b1a86750b 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -673,12 +673,12 @@ async def _schedule_enable(dev, enable): @click.option("--repeat", type=click.BOOL, default=True, show_default=True) @click.option("--days", type=str, required=True) @click.option("--start-action", type=click.IntRange(-1, 2), default=None, required=True) -@click.option("--stime_opt", type=click.IntRange(-1, 2), default=None, required=True) +@click.option("--start-sun", type=click.IntRange(-1, 2), default=None, required=True) @click.option( "--start-minutes", type=click.IntRange(0, 1440), default=None, required=True ) @click.option("--end-action", type=click.IntRange(-1, 2), default=-1) -@click.option("--etime_opt", type=click.IntRange(-1, 2), default=-1) +@click.option("--end-sun", type=click.IntRange(-1, 2), default=-1) @click.option("--end-minutes", type=click.IntRange(0, 1440), default=None) async def add_rule( dev, @@ -687,10 +687,10 @@ async def add_rule( repeat, days, start_action, - stime_opt, + start_sun, start_minutes, end_action, - etime_opt, + end_sun, end_minutes, ): """Add rule to device.""" @@ -701,10 +701,10 @@ async def add_rule( repeat=repeat, days=list(map(int, days.split(","))), start_action=start_action, - stime_opt=stime_opt, + start_sun=start_sun, start_minutes=start_minutes, end_action=end_action, - etime_opt=etime_opt, + end_sun=end_sun, end_minutes=end_minutes, ) if rule_to_add: @@ -722,10 +722,10 @@ async def add_rule( @click.option("--repeat", type=click.BOOL) @click.option("--days", type=str) @click.option("--start-action", type=click.IntRange(-1, 2)) -@click.option("--stime_opt", type=click.IntRange(-1, 2)) +@click.option("--start-sun", type=click.IntRange(-1, 2)) @click.option("--start-minutes", type=click.IntRange(0, 1440)) @click.option("--end-action", type=click.IntRange(-1, 2)) -@click.option("--etime_opt", type=click.IntRange(-1, 2)) +@click.option("--end-sun", type=click.IntRange(-1, 2)) @click.option("--end-minutes", type=click.IntRange(0, 1440)) async def edit_rule( dev, @@ -735,10 +735,10 @@ async def edit_rule( repeat, days, start_action, - stime_opt, + start_sun, start_minutes, end_action, - etime_opt, + end_sun, end_minutes, ): """Edit rule from device.""" @@ -756,14 +756,14 @@ async def edit_rule( rule_to_edit.wday = list(map(int, days.split(","))) if start_action is not None: rule_to_edit.sact = start_action - if stime_opt is not None: - rule_to_edit.stime_opt = stime_opt + if start_sun is not None: + rule_to_edit.stime_opt = start_sun if start_minutes is not None: rule_to_edit.smin = start_minutes if end_action is not None: rule_to_edit.eact = end_action - if etime_opt is not None: - rule_to_edit.etime_opt = etime_opt + if end_sun is not None: + rule_to_edit.etime_opt = end_sun if end_minutes is not None: rule_to_edit.emin = end_minutes return await schedule.edit_rule(rule_to_edit) diff --git a/kasa/modules/rulemodule.py b/kasa/modules/rulemodule.py index 7442b932a..232f5bc74 100644 --- a/kasa/modules/rulemodule.py +++ b/kasa/modules/rulemodule.py @@ -71,13 +71,13 @@ class ScheduleRule(BaseRule): # start action sact: Optional[Action] = Field(alias="start_action") - stime_opt: TimeOption = Field(alias="start?") + stime_opt: TimeOption = Field(alias="start_sun") smin: int = Field(alias="start_minutes", ge=0, le=1440) # end action eact: Optional[Action] = Field(alias="end_action") # Required to submit, but the device will not return it if set to -1 - etime_opt: TimeOption = Field(default=TimeOption.Disabled, alias="end?") + etime_opt: TimeOption = Field(default=TimeOption.Disabled, alias="end_sun") emin: Optional[int] = Field(alias="end_minutes", ge=0, le=1440) From acf041ad72508fa6b61b028b1452022bcf817c85 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sun, 27 Aug 2023 00:44:41 -0400 Subject: [PATCH 16/17] document timezones: Shoild we move the list somwhere else? --- kasa/cli.py | 678 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 674 insertions(+), 4 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index b1a86750b..feb5247d4 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -570,14 +570,684 @@ async def time(dev): @cli.command() -@click.argument("tz_index", type=int) +@click.option("--list", is_flag=True) +@click.argument("index", type=int, required=False) @pass_dev -async def set_timezone(dev, tz_index): +async def set_timezone(dev, list, index): """Set the device timezone. - See https://github.com/GadgetRend_actionor/pyHS100/issues/53#issuecomment-296875129 for valid timezones + pass --list to see valid timezones """ - return await dev.modules["time"].set_timezone(tz_index) + if list: + timezones = [ + { + "index": 0, + "zone_str": "(UTC-12:00) International Date Line West", + "tz_str": "12", + "dst_offset": 0, + }, + { + "index": 1, + "zone_str": "(UTC-11:00) Coordinated Universal Time-11", + "tz_str": "11", + "dst_offset": 0, + }, + { + "index": 2, + "zone_str": "(UTC-10:00) Hawaii", + "tz_str": "HST10", + "dst_offset": 0, + }, + { + "index": 3, + "zone_str": "(UTC-09:00) Alaska", + "tz_str": "AKST9AKDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 4, + "zone_str": "(UTC-08:00) Baja California", + "tz_str": "PST8PDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 5, + "zone_str": "(UTC-08:00) Pacific Standard Time (US & Canada)", + "tz_str": "PST8", + "dst_offset": 0, + }, + { + "index": 6, + "zone_str": "(UTC-08:00) Pacific Daylight Time (US & Canada)", + "tz_str": "PST8PDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 7, + "zone_str": "(UTC-07:00) Arizona", + "tz_str": "MST7", + "dst_offset": 0, + }, + { + "index": 8, + "zone_str": "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "tz_str": "MST7MDT,M4.1.0,M10.5.0", + "dst_offset": 60, + }, + { + "index": 9, + "zone_str": "(UTC-07:00) Mountain Standard Time (US & Canada)", + "tz_str": "MST7", + "dst_offset": 0, + }, + { + "index": 10, + "zone_str": "(UTC-07:00) Mountain Daylight Time (US & Canada)", + "tz_str": "MST7MDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 11, + "zone_str": "(UTC-06:00) Central America", + "tz_str": "CST6", + "dst_offset": 0, + }, + { + "index": 12, + "zone_str": "(UTC-06:00) Central Standard Time (US & Canada)", + "tz_str": "CST6", + "dst_offset": 0, + }, + { + "index": 13, + "zone_str": "(UTC-06:00) Central Daylight Time (US & Canada)", + "tz_str": "CST6CDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 14, + "zone_str": "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + "tz_str": "CST6CDT,M4.1.0,M10.5.0", + "dst_offset": 60, + }, + { + "index": 15, + "zone_str": "(UTC-06:00) Saskatchewan", + "tz_str": "6", + "dst_offset": 0, + }, + { + "index": 16, + "zone_str": "(UTC-05:00) Bogota, Lima, Quito, Rio Branco", + "tz_str": "COT5", + "dst_offset": 0, + }, + { + "index": 17, + "zone_str": "(UTC-05:00) Eastern Standard Time (US & Canada)", + "tz_str": "EST5", + "dst_offset": 0, + }, + { + "index": 18, + "zone_str": "(UTC-05:00) Eastern Daylight Time (US & Canada)", + "tz_str": "EST5EDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 19, + "zone_str": "(UTC-05:00) Indiana (East)", + "tz_str": "EST5EDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 20, + "zone_str": "(UTC-04:30) Caracas", + "tz_str": "VET4:30", + "dst_offset": 0, + }, + { + "index": 21, + "zone_str": "(UTC-04:00) Asuncion", + "tz_str": "PYT4PYST,M10.1.0/0,M3.4.0/0", + "dst_offset": 60, + }, + { + "index": 22, + "zone_str": "(UTC-04:00) Atlantic Standard Time (Canada)", + "tz_str": "AST4", + "dst_offset": 0, + }, + { + "index": 23, + "zone_str": "(UTC-04:00) Atlantic Daylight Time (Canada)", + "tz_str": "AST4ADT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 24, + "zone_str": "(UTC-04:00) Cuiaba", + "tz_str": "AMT4AMST,M10.3.0/0,M2.3.0/0", + "dst_offset": 60, + }, + { + "index": 25, + "zone_str": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "tz_str": "BOT4", + "dst_offset": 0, + }, + { + "index": 26, + "zone_str": "(UTC-04:00) Santiago", + "tz_str": "AMT4AMST,M10.3.0/0,M2.3.0/0", + "dst_offset": 60, + }, + { + "index": 27, + "zone_str": "(UTC-03:30) Newfoundland", + "tz_str": "NST3:30NDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 28, + "zone_str": "(UTC-03:00) Brasilia", + "tz_str": "BRT3BRST,M10.3.0/0,M2.3.0/0", + "dst_offset": 60, + }, + { + "index": 29, + "zone_str": "(UTC-03:00) Buenos Aires", + "tz_str": "3", + "dst_offset": 0, + }, + { + "index": 30, + "zone_str": "(UTC-03:00) Cayenne, Fortaleza", + "tz_str": "3", + "dst_offset": 0, + }, + { + "index": 31, + "zone_str": "(UTC-03:00) Greenland", + "tz_str": "PMST3PMDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 32, + "zone_str": "(UTC-03:00) Montevideo", + "tz_str": "UYT3UYST,M10.1.0,M3.2.0", + "dst_offset": 60, + }, + { + "index": 33, + "zone_str": "(UTC-03:00) Salvador", + "tz_str": "3", + "dst_offset": 0, + }, + { + "index": 34, + "zone_str": "(UTC-02:00) Coordinated Universal Time-02", + "tz_str": "2", + "dst_offset": 0, + }, + { + "index": 35, + "zone_str": "(UTC-01:00) Azores", + "tz_str": "AZOT1AZOST,M3.5.0/0,M10.5.0/1", + "dst_offset": 60, + }, + { + "index": 36, + "zone_str": "(UTC-01:00) Cabo Verde Is.", + "tz_str": "CVT1", + "dst_offset": 0, + }, + { + "index": 37, + "zone_str": "(UTC) Casablanca", + "tz_str": "WET0WEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 38, + "zone_str": "(UTC) Coordinated Universal Time", + "tz_str": "GMT0", + "dst_offset": 0, + }, + { + "index": 39, + "zone_str": "(UTC) Dublin, Edinburgh, Lisbon, London", + "tz_str": "GMT0BST,M3.5.0/1,M10.5.0", + "dst_offset": 60, + }, + { + "index": 40, + "zone_str": "(UTC) Monrovia, Reykjavik", + "tz_str": "GMT0", + "dst_offset": 0, + }, + { + "index": 41, + "zone_str": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 42, + "zone_str": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 43, + "zone_str": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 44, + "zone_str": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 45, + "zone_str": "(UTC+01:00) West Central Africa", + "tz_str": "WAT-1", + "dst_offset": 0, + }, + { + "index": 46, + "zone_str": "(UTC+01:00) Windhoek", + "tz_str": "WAT-1WAST,M9.1.0,M4.1.0", + "dst_offset": 60, + }, + { + "index": 47, + "zone_str": "(UTC+02:00) Amman", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 48, + "zone_str": "(UTC+02:00) Athens, Bucharest", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 49, + "zone_str": "(UTC+02:00) Beirut", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 50, + "zone_str": "(UTC+02:00) Cairo", + "tz_str": "-2", + "dst_offset": 0, + }, + { + "index": 51, + "zone_str": "(UTC+02:00) Damascus", + "tz_str": "EET-2EEST,M3.5.5/0,M10.5.5/0", + "dst_offset": 60, + }, + { + "index": 52, + "zone_str": "(UTC+02:00) E. Europe", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 53, + "zone_str": "(UTC+02:00) Harare, Pretoria", + "tz_str": "-2", + "dst_offset": 0, + }, + { + "index": 54, + "zone_str": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 55, + "zone_str": "(UTC+02:00) Istanbul", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 56, + "zone_str": "(UTC+02:00) Jerusalem", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 57, + "zone_str": "(UTC+02:00) Kaliningrad (RTZ 1)", + "tz_str": "EET-2", + "dst_offset": 0, + }, + { + "index": 58, + "zone_str": "(UTC+02:00) Tripoli", + "tz_str": "-2", + "dst_offset": 0, + }, + { + "index": 59, + "zone_str": "(UTC+03:00) Baghdad", + "tz_str": "AST-3", + "dst_offset": 0, + }, + { + "index": 60, + "zone_str": "(UTC+03:00) Kuwait, Riyadh", + "tz_str": "AST-3", + "dst_offset": 0, + }, + { + "index": 61, + "zone_str": "(UTC+03:00) Minsk", + "tz_str": "MSK-3", + "dst_offset": 0, + }, + { + "index": 62, + "zone_str": "(UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)", + "tz_str": "MSK-3", + "dst_offset": 0, + }, + { + "index": 63, + "zone_str": "(UTC+03:00) Nairobi", + "tz_str": "-3", + "dst_offset": 0, + }, + { + "index": 64, + "zone_str": "(UTC+03:30) Tehran", + "tz_str": "AZT-3:30AZST,M3.5.0/4,M10.5.0/5", + "dst_offset": 60, + }, + { + "index": 65, + "zone_str": "(UTC+04:00) Abu Dhabi, Muscat", + "tz_str": "GST-4", + "dst_offset": 0, + }, + { + "index": 66, + "zone_str": "(UTC+04:00) Baku", + "tz_str": "AZT-4AZST,M3.5.0/4,M10.5.0/5", + "dst_offset": 60, + }, + { + "index": 67, + "zone_str": "(UTC+04:00) Izhevsk, Samara (RTZ 3)", + "tz_str": "SAMT-4", + "dst_offset": 0, + }, + { + "index": 68, + "zone_str": "(UTC+04:00) Port Louis", + "tz_str": "-4", + "dst_offset": 0, + }, + { + "index": 69, + "zone_str": "(UTC+04:00) Tbilisi", + "tz_str": "GET-4", + "dst_offset": 0, + }, + { + "index": 70, + "zone_str": "(UTC+04:00) Yerevan", + "tz_str": "AMT-4", + "dst_offset": 0, + }, + { + "index": 71, + "zone_str": "(UTC+04:30) Kabul", + "tz_str": "AFT-4:30", + "dst_offset": 0, + }, + { + "index": 72, + "zone_str": "(UTC+05:00) Ashgabat, Tashkent", + "tz_str": "TMT-5", + "dst_offset": 0, + }, + { + "index": 73, + "zone_str": "(UTC+05:00) Ekaterinburg (RTZ 4)", + "tz_str": "YEKT-5", + "dst_offset": 0, + }, + { + "index": 74, + "zone_str": "(UTC+05:00) Islamabad, Karachi", + "tz_str": "PKT-5", + "dst_offset": 0, + }, + { + "index": 75, + "zone_str": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "tz_str": "IST-5:30", + "dst_offset": 0, + }, + { + "index": 76, + "zone_str": "(UTC+05:30) Sri Jayawardenepura", + "tz_str": "IST-5:30", + "dst_offset": 0, + }, + { + "index": 77, + "zone_str": "(UTC+05:45) Kathmandu", + "tz_str": "NPT-5:45", + "dst_offset": 0, + }, + { + "index": 78, + "zone_str": "(UTC+06:00) Astana", + "tz_str": "-6", + "dst_offset": 0, + }, + { + "index": 79, + "zone_str": "(UTC+06:00) Dhaka", + "tz_str": "BDT-6", + "dst_offset": 0, + }, + { + "index": 80, + "zone_str": "(UTC+06:00) Novosibirsk (RTZ 5)", + "tz_str": "NOVT-6", + "dst_offset": 0, + }, + { + "index": 81, + "zone_str": "(UTC+06:30) Yangon (Rangoon)", + "tz_str": "MMT-6:30", + "dst_offset": 0, + }, + { + "index": 82, + "zone_str": "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "tz_str": "ICT-7", + "dst_offset": 0, + }, + { + "index": 83, + "zone_str": "(UTC+07:00) Krasnoyarsk (RTZ 6)", + "tz_str": "KRAT-7", + "dst_offset": 0, + }, + { + "index": 84, + "zone_str": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "tz_str": "CST-8", + "dst_offset": 0, + }, + { + "index": 85, + "zone_str": "(UTC+08:00) Irkutsk (RTZ 7)", + "tz_str": "IRKT-8", + "dst_offset": 0, + }, + { + "index": 86, + "zone_str": "(UTC+08:00) Kuala Lumpur, Singapore", + "tz_str": "MYT-8", + "dst_offset": 0, + }, + { + "index": 87, + "zone_str": "(UTC+08:00) Perth", + "tz_str": "-8", + "dst_offset": 0, + }, + { + "index": 88, + "zone_str": "(UTC+08:00) Taipei", + "tz_str": "CST-8", + "dst_offset": 0, + }, + { + "index": 89, + "zone_str": "(UTC+08:00) Ulaanbaatar", + "tz_str": "-8", + "dst_offset": 0, + }, + { + "index": 90, + "zone_str": "(UTC+09:00) Osaka, Sapporo, Tokyo", + "tz_str": "JST-9", + "dst_offset": 0, + }, + { + "index": 91, + "zone_str": "(UTC+09:00) Seoul", + "tz_str": "KST-9", + "dst_offset": 0, + }, + { + "index": 92, + "zone_str": "(UTC+09:00) Yakutsk (RTZ 8)", + "tz_str": "YAKT-9", + "dst_offset": 0, + }, + { + "index": 93, + "zone_str": "(UTC+09:30) Adelaide", + "tz_str": "ACST-9:30ACDT,M10.1.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 94, + "zone_str": "(UTC+09:30) Darwin", + "tz_str": "ACST-9:30", + "dst_offset": 0, + }, + { + "index": 95, + "zone_str": "(UTC+10:00) Brisbane", + "tz_str": "-10", + "dst_offset": 0, + }, + { + "index": 96, + "zone_str": "(UTC+10:00) Canberra, Melbourne, Sydney", + "tz_str": "AEST-10AEDT,M10.1.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 97, + "zone_str": "(UTC+10:00) Guam, Port Moresby", + "tz_str": "ChST-10", + "dst_offset": 0, + }, + { + "index": 98, + "zone_str": "(UTC+10:00) Hobart", + "tz_str": "AEST-10AEDT,M10.1.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 99, + "zone_str": "(UTC+10:00) Magadan", + "tz_str": "MAGT-10", + "dst_offset": 0, + }, + { + "index": 100, + "zone_str": "(UTC+10:00) Vladivostok, Magadan (RTZ 9)", + "tz_str": "VLAT-10", + "dst_offset": 0, + }, + { + "index": 101, + "zone_str": "(UTC+11:00) Chokurdakh (RTZ 10)", + "tz_str": "-11", + "dst_offset": 0, + }, + { + "index": 102, + "zone_str": "(UTC+11:00) Solomon Is., New Caledonia", + "tz_str": "SBT-11", + "dst_offset": 0, + }, + { + "index": 103, + "zone_str": "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky (RTZ 11)", + "tz_str": "ANAT-12", + "dst_offset": 0, + }, + { + "index": 104, + "zone_str": "(UTC+12:00) Auckland, Wellington", + "tz_str": "NZST-12NZDT,M9.5.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 105, + "zone_str": "(UTC+12:00) Coordinated Universal Time+12", + "tz_str": "-12", + "dst_offset": 0, + }, + { + "index": 106, + "zone_str": "(UTC+12:00) Fiji", + "tz_str": "NZST-12NZDT,M9.5.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 107, + "zone_str": "(UTC+13:00) Nuku'alofa", + "tz_str": "TKT-13", + "dst_offset": 0, + }, + { + "index": 108, + "zone_str": "(UTC+13:00) Samoa", + "tz_str": "WSST-13WSDT,M9.5.0/3,M4.1.0/4", + "dst_offset": 60, + }, + { + "index": 109, + "zone_str": "(UTC+14:00) Kiritimati Island", + "tz_str": "LINT-14", + "dst_offset": 0, + }, + ] + for item in timezones: + echo( + f"Index: {item['index']:3}\tName: {item['zone_str']:65}\tRule: {item['tz_str']}" + ) + return + if index: + return await dev.modules["time"].set_timezone(index) @cli.command() From d90bf197608763923312d0dce260d5f1c437f1c6 Mon Sep 17 00:00:00 2001 From: yparitcher Date: Sun, 27 Aug 2023 00:53:43 -0400 Subject: [PATCH 17/17] move tz info to time module --- kasa/cli.py | 669 +------------------------------------------ kasa/modules/time.py | 667 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 671 insertions(+), 665 deletions(-) diff --git a/kasa/cli.py b/kasa/cli.py index feb5247d4..9d878b89c 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -578,676 +578,15 @@ async def set_timezone(dev, list, index): pass --list to see valid timezones """ + time = dev.modules["time"] if list: - timezones = [ - { - "index": 0, - "zone_str": "(UTC-12:00) International Date Line West", - "tz_str": "12", - "dst_offset": 0, - }, - { - "index": 1, - "zone_str": "(UTC-11:00) Coordinated Universal Time-11", - "tz_str": "11", - "dst_offset": 0, - }, - { - "index": 2, - "zone_str": "(UTC-10:00) Hawaii", - "tz_str": "HST10", - "dst_offset": 0, - }, - { - "index": 3, - "zone_str": "(UTC-09:00) Alaska", - "tz_str": "AKST9AKDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 4, - "zone_str": "(UTC-08:00) Baja California", - "tz_str": "PST8PDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 5, - "zone_str": "(UTC-08:00) Pacific Standard Time (US & Canada)", - "tz_str": "PST8", - "dst_offset": 0, - }, - { - "index": 6, - "zone_str": "(UTC-08:00) Pacific Daylight Time (US & Canada)", - "tz_str": "PST8PDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 7, - "zone_str": "(UTC-07:00) Arizona", - "tz_str": "MST7", - "dst_offset": 0, - }, - { - "index": 8, - "zone_str": "(UTC-07:00) Chihuahua, La Paz, Mazatlan", - "tz_str": "MST7MDT,M4.1.0,M10.5.0", - "dst_offset": 60, - }, - { - "index": 9, - "zone_str": "(UTC-07:00) Mountain Standard Time (US & Canada)", - "tz_str": "MST7", - "dst_offset": 0, - }, - { - "index": 10, - "zone_str": "(UTC-07:00) Mountain Daylight Time (US & Canada)", - "tz_str": "MST7MDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 11, - "zone_str": "(UTC-06:00) Central America", - "tz_str": "CST6", - "dst_offset": 0, - }, - { - "index": 12, - "zone_str": "(UTC-06:00) Central Standard Time (US & Canada)", - "tz_str": "CST6", - "dst_offset": 0, - }, - { - "index": 13, - "zone_str": "(UTC-06:00) Central Daylight Time (US & Canada)", - "tz_str": "CST6CDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 14, - "zone_str": "(UTC-06:00) Guadalajara, Mexico City, Monterrey", - "tz_str": "CST6CDT,M4.1.0,M10.5.0", - "dst_offset": 60, - }, - { - "index": 15, - "zone_str": "(UTC-06:00) Saskatchewan", - "tz_str": "6", - "dst_offset": 0, - }, - { - "index": 16, - "zone_str": "(UTC-05:00) Bogota, Lima, Quito, Rio Branco", - "tz_str": "COT5", - "dst_offset": 0, - }, - { - "index": 17, - "zone_str": "(UTC-05:00) Eastern Standard Time (US & Canada)", - "tz_str": "EST5", - "dst_offset": 0, - }, - { - "index": 18, - "zone_str": "(UTC-05:00) Eastern Daylight Time (US & Canada)", - "tz_str": "EST5EDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 19, - "zone_str": "(UTC-05:00) Indiana (East)", - "tz_str": "EST5EDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 20, - "zone_str": "(UTC-04:30) Caracas", - "tz_str": "VET4:30", - "dst_offset": 0, - }, - { - "index": 21, - "zone_str": "(UTC-04:00) Asuncion", - "tz_str": "PYT4PYST,M10.1.0/0,M3.4.0/0", - "dst_offset": 60, - }, - { - "index": 22, - "zone_str": "(UTC-04:00) Atlantic Standard Time (Canada)", - "tz_str": "AST4", - "dst_offset": 0, - }, - { - "index": 23, - "zone_str": "(UTC-04:00) Atlantic Daylight Time (Canada)", - "tz_str": "AST4ADT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 24, - "zone_str": "(UTC-04:00) Cuiaba", - "tz_str": "AMT4AMST,M10.3.0/0,M2.3.0/0", - "dst_offset": 60, - }, - { - "index": 25, - "zone_str": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", - "tz_str": "BOT4", - "dst_offset": 0, - }, - { - "index": 26, - "zone_str": "(UTC-04:00) Santiago", - "tz_str": "AMT4AMST,M10.3.0/0,M2.3.0/0", - "dst_offset": 60, - }, - { - "index": 27, - "zone_str": "(UTC-03:30) Newfoundland", - "tz_str": "NST3:30NDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 28, - "zone_str": "(UTC-03:00) Brasilia", - "tz_str": "BRT3BRST,M10.3.0/0,M2.3.0/0", - "dst_offset": 60, - }, - { - "index": 29, - "zone_str": "(UTC-03:00) Buenos Aires", - "tz_str": "3", - "dst_offset": 0, - }, - { - "index": 30, - "zone_str": "(UTC-03:00) Cayenne, Fortaleza", - "tz_str": "3", - "dst_offset": 0, - }, - { - "index": 31, - "zone_str": "(UTC-03:00) Greenland", - "tz_str": "PMST3PMDT,M3.2.0,M11.1.0", - "dst_offset": 60, - }, - { - "index": 32, - "zone_str": "(UTC-03:00) Montevideo", - "tz_str": "UYT3UYST,M10.1.0,M3.2.0", - "dst_offset": 60, - }, - { - "index": 33, - "zone_str": "(UTC-03:00) Salvador", - "tz_str": "3", - "dst_offset": 0, - }, - { - "index": 34, - "zone_str": "(UTC-02:00) Coordinated Universal Time-02", - "tz_str": "2", - "dst_offset": 0, - }, - { - "index": 35, - "zone_str": "(UTC-01:00) Azores", - "tz_str": "AZOT1AZOST,M3.5.0/0,M10.5.0/1", - "dst_offset": 60, - }, - { - "index": 36, - "zone_str": "(UTC-01:00) Cabo Verde Is.", - "tz_str": "CVT1", - "dst_offset": 0, - }, - { - "index": 37, - "zone_str": "(UTC) Casablanca", - "tz_str": "WET0WEST,M3.5.0,M10.5.0/3", - "dst_offset": 60, - }, - { - "index": 38, - "zone_str": "(UTC) Coordinated Universal Time", - "tz_str": "GMT0", - "dst_offset": 0, - }, - { - "index": 39, - "zone_str": "(UTC) Dublin, Edinburgh, Lisbon, London", - "tz_str": "GMT0BST,M3.5.0/1,M10.5.0", - "dst_offset": 60, - }, - { - "index": 40, - "zone_str": "(UTC) Monrovia, Reykjavik", - "tz_str": "GMT0", - "dst_offset": 0, - }, - { - "index": 41, - "zone_str": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", - "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", - "dst_offset": 60, - }, - { - "index": 42, - "zone_str": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", - "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", - "dst_offset": 60, - }, - { - "index": 43, - "zone_str": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", - "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", - "dst_offset": 60, - }, - { - "index": 44, - "zone_str": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", - "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", - "dst_offset": 60, - }, - { - "index": 45, - "zone_str": "(UTC+01:00) West Central Africa", - "tz_str": "WAT-1", - "dst_offset": 0, - }, - { - "index": 46, - "zone_str": "(UTC+01:00) Windhoek", - "tz_str": "WAT-1WAST,M9.1.0,M4.1.0", - "dst_offset": 60, - }, - { - "index": 47, - "zone_str": "(UTC+02:00) Amman", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 48, - "zone_str": "(UTC+02:00) Athens, Bucharest", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 49, - "zone_str": "(UTC+02:00) Beirut", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 50, - "zone_str": "(UTC+02:00) Cairo", - "tz_str": "-2", - "dst_offset": 0, - }, - { - "index": 51, - "zone_str": "(UTC+02:00) Damascus", - "tz_str": "EET-2EEST,M3.5.5/0,M10.5.5/0", - "dst_offset": 60, - }, - { - "index": 52, - "zone_str": "(UTC+02:00) E. Europe", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 53, - "zone_str": "(UTC+02:00) Harare, Pretoria", - "tz_str": "-2", - "dst_offset": 0, - }, - { - "index": 54, - "zone_str": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 55, - "zone_str": "(UTC+02:00) Istanbul", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 56, - "zone_str": "(UTC+02:00) Jerusalem", - "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", - "dst_offset": 60, - }, - { - "index": 57, - "zone_str": "(UTC+02:00) Kaliningrad (RTZ 1)", - "tz_str": "EET-2", - "dst_offset": 0, - }, - { - "index": 58, - "zone_str": "(UTC+02:00) Tripoli", - "tz_str": "-2", - "dst_offset": 0, - }, - { - "index": 59, - "zone_str": "(UTC+03:00) Baghdad", - "tz_str": "AST-3", - "dst_offset": 0, - }, - { - "index": 60, - "zone_str": "(UTC+03:00) Kuwait, Riyadh", - "tz_str": "AST-3", - "dst_offset": 0, - }, - { - "index": 61, - "zone_str": "(UTC+03:00) Minsk", - "tz_str": "MSK-3", - "dst_offset": 0, - }, - { - "index": 62, - "zone_str": "(UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)", - "tz_str": "MSK-3", - "dst_offset": 0, - }, - { - "index": 63, - "zone_str": "(UTC+03:00) Nairobi", - "tz_str": "-3", - "dst_offset": 0, - }, - { - "index": 64, - "zone_str": "(UTC+03:30) Tehran", - "tz_str": "AZT-3:30AZST,M3.5.0/4,M10.5.0/5", - "dst_offset": 60, - }, - { - "index": 65, - "zone_str": "(UTC+04:00) Abu Dhabi, Muscat", - "tz_str": "GST-4", - "dst_offset": 0, - }, - { - "index": 66, - "zone_str": "(UTC+04:00) Baku", - "tz_str": "AZT-4AZST,M3.5.0/4,M10.5.0/5", - "dst_offset": 60, - }, - { - "index": 67, - "zone_str": "(UTC+04:00) Izhevsk, Samara (RTZ 3)", - "tz_str": "SAMT-4", - "dst_offset": 0, - }, - { - "index": 68, - "zone_str": "(UTC+04:00) Port Louis", - "tz_str": "-4", - "dst_offset": 0, - }, - { - "index": 69, - "zone_str": "(UTC+04:00) Tbilisi", - "tz_str": "GET-4", - "dst_offset": 0, - }, - { - "index": 70, - "zone_str": "(UTC+04:00) Yerevan", - "tz_str": "AMT-4", - "dst_offset": 0, - }, - { - "index": 71, - "zone_str": "(UTC+04:30) Kabul", - "tz_str": "AFT-4:30", - "dst_offset": 0, - }, - { - "index": 72, - "zone_str": "(UTC+05:00) Ashgabat, Tashkent", - "tz_str": "TMT-5", - "dst_offset": 0, - }, - { - "index": 73, - "zone_str": "(UTC+05:00) Ekaterinburg (RTZ 4)", - "tz_str": "YEKT-5", - "dst_offset": 0, - }, - { - "index": 74, - "zone_str": "(UTC+05:00) Islamabad, Karachi", - "tz_str": "PKT-5", - "dst_offset": 0, - }, - { - "index": 75, - "zone_str": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", - "tz_str": "IST-5:30", - "dst_offset": 0, - }, - { - "index": 76, - "zone_str": "(UTC+05:30) Sri Jayawardenepura", - "tz_str": "IST-5:30", - "dst_offset": 0, - }, - { - "index": 77, - "zone_str": "(UTC+05:45) Kathmandu", - "tz_str": "NPT-5:45", - "dst_offset": 0, - }, - { - "index": 78, - "zone_str": "(UTC+06:00) Astana", - "tz_str": "-6", - "dst_offset": 0, - }, - { - "index": 79, - "zone_str": "(UTC+06:00) Dhaka", - "tz_str": "BDT-6", - "dst_offset": 0, - }, - { - "index": 80, - "zone_str": "(UTC+06:00) Novosibirsk (RTZ 5)", - "tz_str": "NOVT-6", - "dst_offset": 0, - }, - { - "index": 81, - "zone_str": "(UTC+06:30) Yangon (Rangoon)", - "tz_str": "MMT-6:30", - "dst_offset": 0, - }, - { - "index": 82, - "zone_str": "(UTC+07:00) Bangkok, Hanoi, Jakarta", - "tz_str": "ICT-7", - "dst_offset": 0, - }, - { - "index": 83, - "zone_str": "(UTC+07:00) Krasnoyarsk (RTZ 6)", - "tz_str": "KRAT-7", - "dst_offset": 0, - }, - { - "index": 84, - "zone_str": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", - "tz_str": "CST-8", - "dst_offset": 0, - }, - { - "index": 85, - "zone_str": "(UTC+08:00) Irkutsk (RTZ 7)", - "tz_str": "IRKT-8", - "dst_offset": 0, - }, - { - "index": 86, - "zone_str": "(UTC+08:00) Kuala Lumpur, Singapore", - "tz_str": "MYT-8", - "dst_offset": 0, - }, - { - "index": 87, - "zone_str": "(UTC+08:00) Perth", - "tz_str": "-8", - "dst_offset": 0, - }, - { - "index": 88, - "zone_str": "(UTC+08:00) Taipei", - "tz_str": "CST-8", - "dst_offset": 0, - }, - { - "index": 89, - "zone_str": "(UTC+08:00) Ulaanbaatar", - "tz_str": "-8", - "dst_offset": 0, - }, - { - "index": 90, - "zone_str": "(UTC+09:00) Osaka, Sapporo, Tokyo", - "tz_str": "JST-9", - "dst_offset": 0, - }, - { - "index": 91, - "zone_str": "(UTC+09:00) Seoul", - "tz_str": "KST-9", - "dst_offset": 0, - }, - { - "index": 92, - "zone_str": "(UTC+09:00) Yakutsk (RTZ 8)", - "tz_str": "YAKT-9", - "dst_offset": 0, - }, - { - "index": 93, - "zone_str": "(UTC+09:30) Adelaide", - "tz_str": "ACST-9:30ACDT,M10.1.0,M4.1.0/3", - "dst_offset": 60, - }, - { - "index": 94, - "zone_str": "(UTC+09:30) Darwin", - "tz_str": "ACST-9:30", - "dst_offset": 0, - }, - { - "index": 95, - "zone_str": "(UTC+10:00) Brisbane", - "tz_str": "-10", - "dst_offset": 0, - }, - { - "index": 96, - "zone_str": "(UTC+10:00) Canberra, Melbourne, Sydney", - "tz_str": "AEST-10AEDT,M10.1.0,M4.1.0/3", - "dst_offset": 60, - }, - { - "index": 97, - "zone_str": "(UTC+10:00) Guam, Port Moresby", - "tz_str": "ChST-10", - "dst_offset": 0, - }, - { - "index": 98, - "zone_str": "(UTC+10:00) Hobart", - "tz_str": "AEST-10AEDT,M10.1.0,M4.1.0/3", - "dst_offset": 60, - }, - { - "index": 99, - "zone_str": "(UTC+10:00) Magadan", - "tz_str": "MAGT-10", - "dst_offset": 0, - }, - { - "index": 100, - "zone_str": "(UTC+10:00) Vladivostok, Magadan (RTZ 9)", - "tz_str": "VLAT-10", - "dst_offset": 0, - }, - { - "index": 101, - "zone_str": "(UTC+11:00) Chokurdakh (RTZ 10)", - "tz_str": "-11", - "dst_offset": 0, - }, - { - "index": 102, - "zone_str": "(UTC+11:00) Solomon Is., New Caledonia", - "tz_str": "SBT-11", - "dst_offset": 0, - }, - { - "index": 103, - "zone_str": "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky (RTZ 11)", - "tz_str": "ANAT-12", - "dst_offset": 0, - }, - { - "index": 104, - "zone_str": "(UTC+12:00) Auckland, Wellington", - "tz_str": "NZST-12NZDT,M9.5.0,M4.1.0/3", - "dst_offset": 60, - }, - { - "index": 105, - "zone_str": "(UTC+12:00) Coordinated Universal Time+12", - "tz_str": "-12", - "dst_offset": 0, - }, - { - "index": 106, - "zone_str": "(UTC+12:00) Fiji", - "tz_str": "NZST-12NZDT,M9.5.0,M4.1.0/3", - "dst_offset": 60, - }, - { - "index": 107, - "zone_str": "(UTC+13:00) Nuku'alofa", - "tz_str": "TKT-13", - "dst_offset": 0, - }, - { - "index": 108, - "zone_str": "(UTC+13:00) Samoa", - "tz_str": "WSST-13WSDT,M9.5.0/3,M4.1.0/4", - "dst_offset": 60, - }, - { - "index": 109, - "zone_str": "(UTC+14:00) Kiritimati Island", - "tz_str": "LINT-14", - "dst_offset": 0, - }, - ] - for item in timezones: + for timezone in time.get_timezones(): echo( - f"Index: {item['index']:3}\tName: {item['zone_str']:65}\tRule: {item['tz_str']}" + f"Index: {timezone['index']:3}\tName: {timezone['zone_str']:65}\tRule: {timezone['tz_str']}" ) return if index: - return await dev.modules["time"].set_timezone(index) + return await time.set_timezone(index) @cli.command() diff --git a/kasa/modules/time.py b/kasa/modules/time.py index aa5e45f03..faf72e5b6 100644 --- a/kasa/modules/time.py +++ b/kasa/modules/time.py @@ -4,6 +4,669 @@ from ..exceptions import SmartDeviceException from .module import Module, merge +timezones = [ + { + "index": 0, + "zone_str": "(UTC-12:00) International Date Line West", + "tz_str": "12", + "dst_offset": 0, + }, + { + "index": 1, + "zone_str": "(UTC-11:00) Coordinated Universal Time-11", + "tz_str": "11", + "dst_offset": 0, + }, + { + "index": 2, + "zone_str": "(UTC-10:00) Hawaii", + "tz_str": "HST10", + "dst_offset": 0, + }, + { + "index": 3, + "zone_str": "(UTC-09:00) Alaska", + "tz_str": "AKST9AKDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 4, + "zone_str": "(UTC-08:00) Baja California", + "tz_str": "PST8PDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 5, + "zone_str": "(UTC-08:00) Pacific Standard Time (US & Canada)", + "tz_str": "PST8", + "dst_offset": 0, + }, + { + "index": 6, + "zone_str": "(UTC-08:00) Pacific Daylight Time (US & Canada)", + "tz_str": "PST8PDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 7, + "zone_str": "(UTC-07:00) Arizona", + "tz_str": "MST7", + "dst_offset": 0, + }, + { + "index": 8, + "zone_str": "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "tz_str": "MST7MDT,M4.1.0,M10.5.0", + "dst_offset": 60, + }, + { + "index": 9, + "zone_str": "(UTC-07:00) Mountain Standard Time (US & Canada)", + "tz_str": "MST7", + "dst_offset": 0, + }, + { + "index": 10, + "zone_str": "(UTC-07:00) Mountain Daylight Time (US & Canada)", + "tz_str": "MST7MDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 11, + "zone_str": "(UTC-06:00) Central America", + "tz_str": "CST6", + "dst_offset": 0, + }, + { + "index": 12, + "zone_str": "(UTC-06:00) Central Standard Time (US & Canada)", + "tz_str": "CST6", + "dst_offset": 0, + }, + { + "index": 13, + "zone_str": "(UTC-06:00) Central Daylight Time (US & Canada)", + "tz_str": "CST6CDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 14, + "zone_str": "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + "tz_str": "CST6CDT,M4.1.0,M10.5.0", + "dst_offset": 60, + }, + { + "index": 15, + "zone_str": "(UTC-06:00) Saskatchewan", + "tz_str": "6", + "dst_offset": 0, + }, + { + "index": 16, + "zone_str": "(UTC-05:00) Bogota, Lima, Quito, Rio Branco", + "tz_str": "COT5", + "dst_offset": 0, + }, + { + "index": 17, + "zone_str": "(UTC-05:00) Eastern Standard Time (US & Canada)", + "tz_str": "EST5", + "dst_offset": 0, + }, + { + "index": 18, + "zone_str": "(UTC-05:00) Eastern Daylight Time (US & Canada)", + "tz_str": "EST5EDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 19, + "zone_str": "(UTC-05:00) Indiana (East)", + "tz_str": "EST5EDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 20, + "zone_str": "(UTC-04:30) Caracas", + "tz_str": "VET4:30", + "dst_offset": 0, + }, + { + "index": 21, + "zone_str": "(UTC-04:00) Asuncion", + "tz_str": "PYT4PYST,M10.1.0/0,M3.4.0/0", + "dst_offset": 60, + }, + { + "index": 22, + "zone_str": "(UTC-04:00) Atlantic Standard Time (Canada)", + "tz_str": "AST4", + "dst_offset": 0, + }, + { + "index": 23, + "zone_str": "(UTC-04:00) Atlantic Daylight Time (Canada)", + "tz_str": "AST4ADT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 24, + "zone_str": "(UTC-04:00) Cuiaba", + "tz_str": "AMT4AMST,M10.3.0/0,M2.3.0/0", + "dst_offset": 60, + }, + { + "index": 25, + "zone_str": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "tz_str": "BOT4", + "dst_offset": 0, + }, + { + "index": 26, + "zone_str": "(UTC-04:00) Santiago", + "tz_str": "AMT4AMST,M10.3.0/0,M2.3.0/0", + "dst_offset": 60, + }, + { + "index": 27, + "zone_str": "(UTC-03:30) Newfoundland", + "tz_str": "NST3:30NDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 28, + "zone_str": "(UTC-03:00) Brasilia", + "tz_str": "BRT3BRST,M10.3.0/0,M2.3.0/0", + "dst_offset": 60, + }, + { + "index": 29, + "zone_str": "(UTC-03:00) Buenos Aires", + "tz_str": "3", + "dst_offset": 0, + }, + { + "index": 30, + "zone_str": "(UTC-03:00) Cayenne, Fortaleza", + "tz_str": "3", + "dst_offset": 0, + }, + { + "index": 31, + "zone_str": "(UTC-03:00) Greenland", + "tz_str": "PMST3PMDT,M3.2.0,M11.1.0", + "dst_offset": 60, + }, + { + "index": 32, + "zone_str": "(UTC-03:00) Montevideo", + "tz_str": "UYT3UYST,M10.1.0,M3.2.0", + "dst_offset": 60, + }, + { + "index": 33, + "zone_str": "(UTC-03:00) Salvador", + "tz_str": "3", + "dst_offset": 0, + }, + { + "index": 34, + "zone_str": "(UTC-02:00) Coordinated Universal Time-02", + "tz_str": "2", + "dst_offset": 0, + }, + { + "index": 35, + "zone_str": "(UTC-01:00) Azores", + "tz_str": "AZOT1AZOST,M3.5.0/0,M10.5.0/1", + "dst_offset": 60, + }, + { + "index": 36, + "zone_str": "(UTC-01:00) Cabo Verde Is.", + "tz_str": "CVT1", + "dst_offset": 0, + }, + { + "index": 37, + "zone_str": "(UTC) Casablanca", + "tz_str": "WET0WEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 38, + "zone_str": "(UTC) Coordinated Universal Time", + "tz_str": "GMT0", + "dst_offset": 0, + }, + { + "index": 39, + "zone_str": "(UTC) Dublin, Edinburgh, Lisbon, London", + "tz_str": "GMT0BST,M3.5.0/1,M10.5.0", + "dst_offset": 60, + }, + { + "index": 40, + "zone_str": "(UTC) Monrovia, Reykjavik", + "tz_str": "GMT0", + "dst_offset": 0, + }, + { + "index": 41, + "zone_str": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 42, + "zone_str": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 43, + "zone_str": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 44, + "zone_str": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "tz_str": "CET-1CEST,M3.5.0,M10.5.0/3", + "dst_offset": 60, + }, + { + "index": 45, + "zone_str": "(UTC+01:00) West Central Africa", + "tz_str": "WAT-1", + "dst_offset": 0, + }, + { + "index": 46, + "zone_str": "(UTC+01:00) Windhoek", + "tz_str": "WAT-1WAST,M9.1.0,M4.1.0", + "dst_offset": 60, + }, + { + "index": 47, + "zone_str": "(UTC+02:00) Amman", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 48, + "zone_str": "(UTC+02:00) Athens, Bucharest", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 49, + "zone_str": "(UTC+02:00) Beirut", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 50, + "zone_str": "(UTC+02:00) Cairo", + "tz_str": "-2", + "dst_offset": 0, + }, + { + "index": 51, + "zone_str": "(UTC+02:00) Damascus", + "tz_str": "EET-2EEST,M3.5.5/0,M10.5.5/0", + "dst_offset": 60, + }, + { + "index": 52, + "zone_str": "(UTC+02:00) E. Europe", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 53, + "zone_str": "(UTC+02:00) Harare, Pretoria", + "tz_str": "-2", + "dst_offset": 0, + }, + { + "index": 54, + "zone_str": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 55, + "zone_str": "(UTC+02:00) Istanbul", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 56, + "zone_str": "(UTC+02:00) Jerusalem", + "tz_str": "EET-2EEST,M3.5.0/3,M10.5.0/4", + "dst_offset": 60, + }, + { + "index": 57, + "zone_str": "(UTC+02:00) Kaliningrad (RTZ 1)", + "tz_str": "EET-2", + "dst_offset": 0, + }, + { + "index": 58, + "zone_str": "(UTC+02:00) Tripoli", + "tz_str": "-2", + "dst_offset": 0, + }, + { + "index": 59, + "zone_str": "(UTC+03:00) Baghdad", + "tz_str": "AST-3", + "dst_offset": 0, + }, + { + "index": 60, + "zone_str": "(UTC+03:00) Kuwait, Riyadh", + "tz_str": "AST-3", + "dst_offset": 0, + }, + { + "index": 61, + "zone_str": "(UTC+03:00) Minsk", + "tz_str": "MSK-3", + "dst_offset": 0, + }, + { + "index": 62, + "zone_str": "(UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)", + "tz_str": "MSK-3", + "dst_offset": 0, + }, + { + "index": 63, + "zone_str": "(UTC+03:00) Nairobi", + "tz_str": "-3", + "dst_offset": 0, + }, + { + "index": 64, + "zone_str": "(UTC+03:30) Tehran", + "tz_str": "AZT-3:30AZST,M3.5.0/4,M10.5.0/5", + "dst_offset": 60, + }, + { + "index": 65, + "zone_str": "(UTC+04:00) Abu Dhabi, Muscat", + "tz_str": "GST-4", + "dst_offset": 0, + }, + { + "index": 66, + "zone_str": "(UTC+04:00) Baku", + "tz_str": "AZT-4AZST,M3.5.0/4,M10.5.0/5", + "dst_offset": 60, + }, + { + "index": 67, + "zone_str": "(UTC+04:00) Izhevsk, Samara (RTZ 3)", + "tz_str": "SAMT-4", + "dst_offset": 0, + }, + { + "index": 68, + "zone_str": "(UTC+04:00) Port Louis", + "tz_str": "-4", + "dst_offset": 0, + }, + { + "index": 69, + "zone_str": "(UTC+04:00) Tbilisi", + "tz_str": "GET-4", + "dst_offset": 0, + }, + { + "index": 70, + "zone_str": "(UTC+04:00) Yerevan", + "tz_str": "AMT-4", + "dst_offset": 0, + }, + { + "index": 71, + "zone_str": "(UTC+04:30) Kabul", + "tz_str": "AFT-4:30", + "dst_offset": 0, + }, + { + "index": 72, + "zone_str": "(UTC+05:00) Ashgabat, Tashkent", + "tz_str": "TMT-5", + "dst_offset": 0, + }, + { + "index": 73, + "zone_str": "(UTC+05:00) Ekaterinburg (RTZ 4)", + "tz_str": "YEKT-5", + "dst_offset": 0, + }, + { + "index": 74, + "zone_str": "(UTC+05:00) Islamabad, Karachi", + "tz_str": "PKT-5", + "dst_offset": 0, + }, + { + "index": 75, + "zone_str": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "tz_str": "IST-5:30", + "dst_offset": 0, + }, + { + "index": 76, + "zone_str": "(UTC+05:30) Sri Jayawardenepura", + "tz_str": "IST-5:30", + "dst_offset": 0, + }, + { + "index": 77, + "zone_str": "(UTC+05:45) Kathmandu", + "tz_str": "NPT-5:45", + "dst_offset": 0, + }, + { + "index": 78, + "zone_str": "(UTC+06:00) Astana", + "tz_str": "-6", + "dst_offset": 0, + }, + { + "index": 79, + "zone_str": "(UTC+06:00) Dhaka", + "tz_str": "BDT-6", + "dst_offset": 0, + }, + { + "index": 80, + "zone_str": "(UTC+06:00) Novosibirsk (RTZ 5)", + "tz_str": "NOVT-6", + "dst_offset": 0, + }, + { + "index": 81, + "zone_str": "(UTC+06:30) Yangon (Rangoon)", + "tz_str": "MMT-6:30", + "dst_offset": 0, + }, + { + "index": 82, + "zone_str": "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "tz_str": "ICT-7", + "dst_offset": 0, + }, + { + "index": 83, + "zone_str": "(UTC+07:00) Krasnoyarsk (RTZ 6)", + "tz_str": "KRAT-7", + "dst_offset": 0, + }, + { + "index": 84, + "zone_str": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "tz_str": "CST-8", + "dst_offset": 0, + }, + { + "index": 85, + "zone_str": "(UTC+08:00) Irkutsk (RTZ 7)", + "tz_str": "IRKT-8", + "dst_offset": 0, + }, + { + "index": 86, + "zone_str": "(UTC+08:00) Kuala Lumpur, Singapore", + "tz_str": "MYT-8", + "dst_offset": 0, + }, + { + "index": 87, + "zone_str": "(UTC+08:00) Perth", + "tz_str": "-8", + "dst_offset": 0, + }, + { + "index": 88, + "zone_str": "(UTC+08:00) Taipei", + "tz_str": "CST-8", + "dst_offset": 0, + }, + { + "index": 89, + "zone_str": "(UTC+08:00) Ulaanbaatar", + "tz_str": "-8", + "dst_offset": 0, + }, + { + "index": 90, + "zone_str": "(UTC+09:00) Osaka, Sapporo, Tokyo", + "tz_str": "JST-9", + "dst_offset": 0, + }, + { + "index": 91, + "zone_str": "(UTC+09:00) Seoul", + "tz_str": "KST-9", + "dst_offset": 0, + }, + { + "index": 92, + "zone_str": "(UTC+09:00) Yakutsk (RTZ 8)", + "tz_str": "YAKT-9", + "dst_offset": 0, + }, + { + "index": 93, + "zone_str": "(UTC+09:30) Adelaide", + "tz_str": "ACST-9:30ACDT,M10.1.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 94, + "zone_str": "(UTC+09:30) Darwin", + "tz_str": "ACST-9:30", + "dst_offset": 0, + }, + { + "index": 95, + "zone_str": "(UTC+10:00) Brisbane", + "tz_str": "-10", + "dst_offset": 0, + }, + { + "index": 96, + "zone_str": "(UTC+10:00) Canberra, Melbourne, Sydney", + "tz_str": "AEST-10AEDT,M10.1.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 97, + "zone_str": "(UTC+10:00) Guam, Port Moresby", + "tz_str": "ChST-10", + "dst_offset": 0, + }, + { + "index": 98, + "zone_str": "(UTC+10:00) Hobart", + "tz_str": "AEST-10AEDT,M10.1.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 99, + "zone_str": "(UTC+10:00) Magadan", + "tz_str": "MAGT-10", + "dst_offset": 0, + }, + { + "index": 100, + "zone_str": "(UTC+10:00) Vladivostok, Magadan (RTZ 9)", + "tz_str": "VLAT-10", + "dst_offset": 0, + }, + { + "index": 101, + "zone_str": "(UTC+11:00) Chokurdakh (RTZ 10)", + "tz_str": "-11", + "dst_offset": 0, + }, + { + "index": 102, + "zone_str": "(UTC+11:00) Solomon Is., New Caledonia", + "tz_str": "SBT-11", + "dst_offset": 0, + }, + { + "index": 103, + "zone_str": "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky (RTZ 11)", + "tz_str": "ANAT-12", + "dst_offset": 0, + }, + { + "index": 104, + "zone_str": "(UTC+12:00) Auckland, Wellington", + "tz_str": "NZST-12NZDT,M9.5.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 105, + "zone_str": "(UTC+12:00) Coordinated Universal Time+12", + "tz_str": "-12", + "dst_offset": 0, + }, + { + "index": 106, + "zone_str": "(UTC+12:00) Fiji", + "tz_str": "NZST-12NZDT,M9.5.0,M4.1.0/3", + "dst_offset": 60, + }, + { + "index": 107, + "zone_str": "(UTC+13:00) Nuku'alofa", + "tz_str": "TKT-13", + "dst_offset": 0, + }, + { + "index": 108, + "zone_str": "(UTC+13:00) Samoa", + "tz_str": "WSST-13WSDT,M9.5.0/3,M4.1.0/4", + "dst_offset": 60, + }, + { + "index": 109, + "zone_str": "(UTC+14:00) Kiritimati Island", + "tz_str": "LINT-14", + "dst_offset": 0, + }, +] + class Time(Module): """Implements the timezone settings.""" @@ -53,6 +716,10 @@ async def get_timezone(self): """Request timezone information from the device.""" return await self.call("get_timezone") + def get_timezones(self): + """Return allowed timezones.""" + return timezones + async def set_timezone(self, tz_index): """Request timezone information from the device.""" return await self.call("set_timezone", {"index": tz_index})