Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend schedule handling cli support #501

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

yparitcher
Copy link

@yparitcher yparitcher commented Aug 25, 2023

Some improvements for the schedule command.

A draft for now, I plan on adding rule edit support, please give feedback

Fixes: #265
Fixes: #436

Based on the commands in the Thesis linked in that issue.
Tested on a EP10

@yparitcher yparitcher marked this pull request as draft August 25, 2023 03:01
@codecov-commenter
Copy link

codecov-commenter commented Aug 25, 2023

Codecov Report

Patch coverage: 72.97% and project coverage change: -1.47% ⚠️

Comparison is base (24da24e) 79.59% compared to head (d90bf19) 78.13%.
Report is 1 commits behind head on master.

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #501      +/-   ##
==========================================
- Coverage   79.59%   78.13%   -1.47%     
==========================================
  Files          26       26              
  Lines        1960     2108     +148     
  Branches      602      673      +71     
==========================================
+ Hits         1560     1647      +87     
- Misses        359      419      +60     
- Partials       41       42       +1     
Files Changed Coverage Δ
kasa/cli.py 54.87% <58.33%> (-1.69%) ⬇️
kasa/modules/time.py 86.20% <60.00%> (-5.46%) ⬇️
kasa/modules/rulemodule.py 86.66% <93.61%> (+4.05%) ⬆️
kasa/modules/__init__.py 100.00% <100.00%> (ø)
kasa/modules/antitheft.py 100.00% <100.00%> (ø)
kasa/modules/countdown.py 100.00% <100.00%> (ø)
kasa/modules/schedule.py 100.00% <100.00%> (ø)
kasa/smartbulb.py 92.38% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@rytilahti rytilahti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @yparitcher! I added some initial review comments below.

@@ -630,18 +631,113 @@ async def schedule(dev):

@schedule.command(name="list")
@pass_dev
@click.option("--json", is_flag=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsonifying is handled on the cli automatically for the return value, so there should be no need for special handling.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way i get the actual json that is passed to the device, not the python rule wrapped in json

$ kasa --host 192.168.0.xxx --type plug schedule list
id='B9A82B5BA5AB6F6DA4277429A226D632' name='7 Off 11 On' enable=<EnabledOption.Enabled: 1> wday=[1, 1, 1, 1, 1, 1, 1] repeat=<EnabledOption.Enabled: 1> sact=<Action.TurnOff: 0> stime_opt=<TimeOption.Enabled: 0> smin=420 eact=<Action.TurnOn: 1> etime_opt=<TimeOption.Enabled: 0> emin=660 s_light=None

$ kasa --host 192.168.0.xxx --type plug --json schedule list
id='B9A82B5BA5AB6F6DA4277429A226D632' name='7 Off 11 On' enable=<EnabledOption.Enabled: 1> wday=[1, 1, 1, 1, 1, 1, 1] repeat=<EnabledOption.Enabled: 1> sact=<Action.TurnOff: 0> stime_opt=<TimeOption.Enabled: 0> smin=420 eact=<Action.TurnOn: 1> etime_opt=<TimeOption.Enabled: 0> emin=660 s_light=None
[
    "id='B9A82B5BA5AB6F6DA4277429A226D632' name='7 Off 11 On' enable=<EnabledOption.Enabled: 1> wday=[1, 1, 1, 1, 1, 1, 1] repeat=<EnabledOption.Enabled: 1> sact=<Action.TurnOff: 0> stime_opt=<TimeOption.Enabled: 0> smin=420 eact=<Action.TurnOn: 1> etime_opt=<TimeOption.Enabled: 0> emin=660 s_light=None"
]

$ kasa --host 192.168.0.xxx --type plug schedule list --json
{"id": "B9A82B5BA5AB6F6DA4277429A226D632", "name": "7 Off 11 On", "enable": 1, "wday": [1, 1, 1, 1, 1, 1, 1], "repeat": 1, "sact": 0, "stime_opt": 0, "smin": 420, "eact": 1, "etime_opt": 0, "emin": 660, "s_light": null}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be fixed separately then (I think the proper way would be extending the json_formatter_cb by defining a serializer for pydantic BaseModel), but let's do that in a separate PR.

kasa/modules/rulemodule.py Outdated Show resolved Hide resolved
kasa/cli.py Outdated Show resolved Hide resolved
kasa/cli.py Outdated
Comment on lines 664 to 670
@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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should modiy the Rule to have more user-friendly field names (using alias) and add some documentation on what input values they accept.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the names (If you better ones please comment), the doc still needs to be done.

Is there a way to pass the pydatic info to click? for example TimeOption

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a direct answer to that, sorry. I suppose generic support for all pydantic models is not that easy, but one can use manually inherit from click.ParamType to perform the conversion.

if name is not None:
rule_to_edit.name = name
if enable is not None:
rule_to_edit.enable = 1 if enable else 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pydantic should handle the conversion just fine as long as the types are correct, so there should be no need for manual conversions here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want that only the user specified options should override the existing rule fields, however if the user does not specify a flag we get a None value that i don't want to pass to pydantic to overwrite the field. If there is a better way to do this with click & pydantic please let me know. (I am not too familiar with either of them)

@rytilahti rytilahti added the enhancement New feature or request label Aug 26, 2023
@rytilahti rytilahti changed the title Schedule Extend schedule handling cli support Aug 26, 2023
@yparitcher
Copy link
Author

As i do not have bulbs, I did not implement bulb specific functionality, but i did leave the scaffolding for someone else to do it.

@yparitcher
Copy link
Author

I redid the rule inheritance a bit. not sure if there is a better way

@yparitcher yparitcher marked this pull request as ready for review August 27, 2023 04:01
Copy link
Member

@rytilahti rytilahti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that you extend the time module to support timezone handling, could you please move that into its own PR to keep it easier to review? I'll try to find some time soon to take another look at this, alas, I won't be able to test this until some point next month.

sact: Optional[Action]
stime_opt: TimeOption
smin: int
sact: Optional[Action] = Field(alias="start_action")
Copy link
Member

@rytilahti rytilahti Aug 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sact: Optional[Action] = Field(alias="start_action")
start_action: Optional[Action] = Field(alias="sact")

This is wrong way around, no? Basically, the alias allows using a nicer name for the field name itself, reading (and serializing?) in this case from/to a json field called sact.

@yparitcher
Copy link
Author

I don't have much time to work on this (it was a bit driveby, as it now work for me locally). But i hope to eventually split out the changes into separate PRs. Anyone is also welcome to fixup this PR if wanted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for setting the timezone Set schedules?
3 participants