-
Notifications
You must be signed in to change notification settings - Fork 47
Refactoring for new Auth #94
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
Closed
Closed
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
b49ae90
First go at integrating new way of creating a token
little-quokka 9da12ac
Call /userinfo in login
little-quokka ea89dd5
Fix login call ... special thanks to @heldchen (a true hero ... no pu…
little-quokka 89429ad
updating from quokkas branch
danielcherubini eaff330
Refactored with auth.py
danielcherubini 61301ca
Fixes refresh token issue
danielcherubini 6223314
Cleaning up
danielcherubini de2869e
Add PanasonicSession with improved token handling and error checking.
little-quokka 9e8f524
better login flow
danielcherubini 03cf97c
More cleanup
danielcherubini fdca27f
Working
danielcherubini dd07276
Formatting fixes
danielcherubini 3f5ec2b
Rewrite of auth.py
danielcherubini 9c632ed
Ensure that with each API call the token is tested and potentially up…
little-quokka 4d06824
Improved error handling; Crack open token to check expiry; Move excep…
little-quokka caebec3
Update default token file name to allow this to be run on windows as …
little-quokka 5e3f9d1
Fix low hanging fruit of issues reported by pylint (moved from score …
little-quokka c3f39d1
Make contents of pcomfortcloud/ a library and use pcomfortcloud.py as…
little-quokka f9c9555
Merge branch 'master' of https://github.com/little-quokka/python-pana…
danielcherubini a47d074
Revert "Merge branch 'master' of https://github.com/little-quokka/pyt…
danielcherubini fa02514
Revert "Integrate recent changes from little-quokka/python-panasonic-…
danielcherubini 1a4baa7
Merge pull request #2 from danielcherubini/revert-1-master
danielcherubini 0fdd24a
adding from little-quokka's branch
danielcherubini 3919864
linting
danielcherubini 87afbd2
Merge pull request #3 from danielcherubini/little-quokka
danielcherubini 3cd4989
Uses automatic app version
danielcherubini 7ed3c5e
cleaning out app version code from apiclient
danielcherubini 329f112
Commenting out the auto app verison update call, and adding comments why
danielcherubini 50d5030
Moving Appversion to gist
danielcherubini 91409a9
Updating app version scraper
danielcherubini 965b1ec
Adding @heldchen's fixes for the 404s
danielcherubini 81eae60
fixing issue with method
danielcherubini e1024ad
Renaming panasonicsession.py back to session.py
danielcherubini 93c0b44
Small cleanups
danielcherubini 4eb30d1
removing aiohttp from requirements.txt
danielcherubini 977f943
Fixing bad import
danielcherubini cf3bebc
fixes issue with app version
danielcherubini ddcd6fc
adding more controlflow around appversion
danielcherubini fea9970
Fixes string issue thanks @heldchen
danielcherubini f2cb4bc
Updating README.md
danielcherubini 572f7f0
Making Token optional
danielcherubini 0e2c839
Removing Optional Token from README.md
danielcherubini 3c9d178
Lowercasing the headers
danielcherubini a333c5f
updating the fallback
danielcherubini File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,4 +103,7 @@ venv.bak/ | |
| # mypy | ||
| .mypy_cache/ | ||
|
|
||
| .vscode | ||
| .vscode | ||
| .idea | ||
|
|
||
| token.json | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,301 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| """ Command line interface for Panasonic Comfort Cloud """ | ||
| from pcomfortcloud import __main__ | ||
| __main__.main() | ||
| import argparse | ||
| import os | ||
| import json | ||
| from enum import Enum | ||
|
|
||
| import pcomfortcloud | ||
|
|
||
|
|
||
| def print_result(obj, indent=0): | ||
| for key in obj: | ||
| value = obj[key] | ||
|
|
||
| if isinstance(value, dict): | ||
| print(" "*indent + key) | ||
| print_result(value, indent + 4) | ||
| elif isinstance(value, Enum): | ||
| print( | ||
| " "*indent + "{0: <{width}}: {1}".format(key, value.name, width=25-indent)) | ||
| elif isinstance(value, list): | ||
| print(" "*indent + "{0: <{width}}:".format(key, width=25-indent)) | ||
| for elt in value: | ||
| print_result(elt, indent + 4) | ||
| print("") | ||
| else: | ||
| print(" "*indent + | ||
| "{0: <{width}}: {1}".format(key, value, width=25-indent)) | ||
|
|
||
|
|
||
| def str2bool(boolean_string_value): | ||
| if boolean_string_value.lower() in ('yes', 'true', 't', 'y', '1'): | ||
| return True | ||
| if boolean_string_value.lower() in ('no', 'false', 'f', 'n', '0'): | ||
| return False | ||
| raise argparse.ArgumentTypeError('Boolean value expected.') | ||
|
|
||
|
|
||
| def main(): | ||
| """ Start pcomfortcloud Comfort Cloud command line """ | ||
|
|
||
| parser = argparse.ArgumentParser( | ||
| description='Read or change status of pcomfortcloud Climate devices') | ||
|
|
||
| parser.add_argument( | ||
| 'username', | ||
| help='Username for pcomfortcloud Comfort Cloud') | ||
|
|
||
| parser.add_argument( | ||
| 'password', | ||
| help='Password for pcomfortcloud Comfort Cloud') | ||
|
|
||
| parser.add_argument( | ||
| '-t', '--token', | ||
| help='File to store token in', | ||
| default='token.json') | ||
|
|
||
| parser.add_argument( | ||
| '-r', '--raw', | ||
| help='Raw dump of response', | ||
| type=str2bool, nargs='?', const=True, | ||
| default=False) | ||
|
|
||
| commandparser = parser.add_subparsers( | ||
| help='commands', | ||
| dest='command') | ||
|
|
||
| commandparser.add_parser( | ||
| 'list', | ||
| help="Get a list of all devices") | ||
|
|
||
| get_parser = commandparser.add_parser( | ||
| 'get', | ||
| help="Get status of a device") | ||
|
|
||
| get_parser.add_argument( | ||
| dest='device', | ||
| type=int, | ||
| help='Device number #') | ||
|
|
||
| set_parser = commandparser.add_parser( | ||
| 'set', | ||
| help="Set status of a device") | ||
|
|
||
| set_parser.add_argument( | ||
| dest='device', | ||
| type=int, | ||
| help='Device number #' | ||
| ) | ||
|
|
||
| set_parser.add_argument( | ||
| '-p', '--power', | ||
| choices=[ | ||
| pcomfortcloud.constants.Power.On.name, | ||
| pcomfortcloud.constants.Power.Off.name], | ||
| help='Power mode') | ||
|
|
||
| set_parser.add_argument( | ||
| '-t', '--temperature', | ||
| type=float, | ||
| help="Temperature") | ||
|
|
||
| set_parser.add_argument( | ||
| '-f', '--fanSpeed', | ||
| choices=[ | ||
| pcomfortcloud.constants.FanSpeed.Auto.name, | ||
| pcomfortcloud.constants.FanSpeed.Low.name, | ||
| pcomfortcloud.constants.FanSpeed.LowMid.name, | ||
| pcomfortcloud.constants.FanSpeed.Mid.name, | ||
| pcomfortcloud.constants.FanSpeed.HighMid.name, | ||
| pcomfortcloud.constants.FanSpeed.High.name], | ||
| help='Fan speed') | ||
|
|
||
| set_parser.add_argument( | ||
| '-m', '--mode', | ||
| choices=[ | ||
| pcomfortcloud.constants.OperationMode.Auto.name, | ||
| pcomfortcloud.constants.OperationMode.Cool.name, | ||
| pcomfortcloud.constants.OperationMode.Dry.name, | ||
| pcomfortcloud.constants.OperationMode.Heat.name, | ||
| pcomfortcloud.constants.OperationMode.Fan.name], | ||
| help='Operation mode') | ||
|
|
||
| set_parser.add_argument( | ||
| '-e', '--eco', | ||
| choices=[ | ||
| pcomfortcloud.constants.EcoMode.Auto.name, | ||
| pcomfortcloud.constants.EcoMode.Quiet.name, | ||
| pcomfortcloud.constants.EcoMode.Powerful.name], | ||
| help='Eco mode') | ||
|
|
||
| set_parser.add_argument( | ||
| '-n', '--nanoe', | ||
| choices=[ | ||
| pcomfortcloud.constants.NanoeMode.On.name, | ||
| pcomfortcloud.constants.NanoeMode.Off.name, | ||
| pcomfortcloud.constants.NanoeMode.ModeG.name, | ||
| pcomfortcloud.constants.NanoeMode.All.name], | ||
| help='Nanoe mode') | ||
|
|
||
| # set_parser.add_argument( | ||
| # '--airswingauto', | ||
| # choices=[ | ||
| # pcomfortcloud.constants.AirSwingAutoMode.Disabled.name, | ||
| # pcomfortcloud.constants.AirSwingAutoMode.AirSwingLR.name, | ||
| # pcomfortcloud.constants.AirSwingAutoMode.AirSwingUD.name, | ||
| # pcomfortcloud.constants.AirSwingAutoMode.Both.name], | ||
| # help='Automation of air swing') | ||
|
|
||
| set_parser.add_argument( | ||
| '-y', '--airSwingVertical', | ||
| choices=[ | ||
| pcomfortcloud.constants.AirSwingUD.Auto.name, | ||
| pcomfortcloud.constants.AirSwingUD.Down.name, | ||
| pcomfortcloud.constants.AirSwingUD.DownMid.name, | ||
| pcomfortcloud.constants.AirSwingUD.Mid.name, | ||
| pcomfortcloud.constants.AirSwingUD.UpMid.name, | ||
| pcomfortcloud.constants.AirSwingUD.Up.name], | ||
| help='Vertical position of the air swing') | ||
|
|
||
| set_parser.add_argument( | ||
| '-x', '--airSwingHorizontal', | ||
| choices=[ | ||
| pcomfortcloud.constants.AirSwingLR.Auto.name, | ||
| pcomfortcloud.constants.AirSwingLR.Left.name, | ||
| pcomfortcloud.constants.AirSwingLR.LeftMid.name, | ||
| pcomfortcloud.constants.AirSwingLR.Mid.name, | ||
| pcomfortcloud.constants.AirSwingLR.RightMid.name, | ||
| pcomfortcloud.constants.AirSwingLR.Right.name], | ||
| help='Horizontal position of the air swing') | ||
|
|
||
| dump_parser = commandparser.add_parser( | ||
| 'dump', | ||
| help="Dump data of a device") | ||
|
|
||
| dump_parser.add_argument( | ||
| dest='device', | ||
| type=int, | ||
| help='Device number 1-x') | ||
|
|
||
| history_parser = commandparser.add_parser( | ||
| 'history', | ||
| help="Dump history of a device") | ||
|
|
||
| history_parser.add_argument( | ||
| dest='device', | ||
| type=int, | ||
| help='Device number 1-x') | ||
|
|
||
| history_parser.add_argument( | ||
| dest='mode', | ||
| type=str, | ||
| help='mode (Day, Week, Month, Year)') | ||
|
|
||
| history_parser.add_argument( | ||
| dest='date', | ||
| type=str, | ||
| help='date of day like 20190807') | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| if os.path.isfile(args.token): | ||
| with open(args.token, "r") as token_file: | ||
| json_token = json.load(token_file) | ||
| else: | ||
| json_token = None | ||
|
|
||
| session = pcomfortcloud.ApiClient( | ||
| args.username, | ||
| args.password, | ||
| json_token, | ||
| args.raw) | ||
|
|
||
| session.start_session() | ||
| json_token = session.get_token() | ||
|
|
||
| with open(args.token, "w") as token_file: | ||
| json.dump(json_token, token_file, indent=4) | ||
|
|
||
| try: | ||
| if args.command == 'list': | ||
| print("list of devices and its device id (1-x)") | ||
| for idx, device in enumerate(session.get_devices()): | ||
| if idx > 0: | ||
| print('') | ||
|
|
||
| print("device #{}".format(idx + 1)) | ||
| print_result(device, 4) | ||
|
|
||
| if args.command == 'get': | ||
| if int(args.device) <= 0 or int(args.device) > len(session.get_devices()): | ||
| raise Exception("device not found, acceptable device id is from {} to {}".format( | ||
| 1, len(session.get_devices()))) | ||
|
|
||
| device = session.get_devices()[int(args.device) - 1] | ||
| print("reading from device '{}' ({})".format( | ||
| device['name'], device['id'])) | ||
|
|
||
| print_result(session.get_device(device['id'])) | ||
|
|
||
| if args.command == 'set': | ||
| if int(args.device) <= 0 or int(args.device) > len(session.get_devices()): | ||
| raise Exception("device not found, acceptable device id is from {} to {}".format( | ||
| 1, len(session.get_devices()))) | ||
|
|
||
| device = session.get_devices()[int(args.device) - 1] | ||
| print("writing to device '{}' ({})".format( | ||
| device['name'], device['id'])) | ||
|
|
||
| kwargs = {} | ||
|
|
||
| if args.power is not None: | ||
| kwargs['power'] = pcomfortcloud.constants.Power[args.power] | ||
|
|
||
| if args.temperature is not None: | ||
| kwargs['temperature'] = args.temperature | ||
|
|
||
| if args.fanSpeed is not None: | ||
| kwargs['fanSpeed'] = pcomfortcloud.constants.FanSpeed[args.fanSpeed] | ||
|
|
||
| if args.mode is not None: | ||
| kwargs['mode'] = pcomfortcloud.constants.OperationMode[args.mode] | ||
|
|
||
| if args.eco is not None: | ||
| kwargs['eco'] = pcomfortcloud.constants.EcoMode[args.eco] | ||
|
|
||
| if args.nanoe is not None: | ||
| kwargs['nanoe'] = pcomfortcloud.constants.NanoeMode[args.nanoe] | ||
|
|
||
| if args.airSwingHorizontal is not None: | ||
| kwargs['airSwingHorizontal'] = pcomfortcloud.constants.AirSwingLR[args.airSwingHorizontal] | ||
|
|
||
| if args.airSwingVertical is not None: | ||
| kwargs['airSwingVertical'] = pcomfortcloud.constants.AirSwingUD[args.airSwingVertical] | ||
|
|
||
| session.set_device(device['id'], **kwargs) | ||
|
|
||
| if args.command == 'dump': | ||
| if int(args.device) <= 0 or int(args.device) > len(session.get_devices()): | ||
| raise Exception("device not found, acceptable device id is from {} to {}".format( | ||
| 1, len(session.get_devices()))) | ||
|
|
||
| device = session.get_devices()[int(args.device) - 1] | ||
|
|
||
| print_result(session.dump(device['id'])) | ||
|
|
||
| if args.command == 'history': | ||
| if int(args.device) <= 0 or int(args.device) > len(session.get_devices()): | ||
| raise Exception("device not found, acceptable device id is from {} to {}".format( | ||
| 1, len(session.get_devices()))) | ||
|
|
||
| device = session.get_devices()[int(args.device) - 1] | ||
|
|
||
| print_result(session.history(device['id'], args.mode, args.date)) | ||
|
|
||
| except pcomfortcloud.ResponseError as ex: | ||
| print(ex) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is main.py deleted and moved into this file? Is there any specific reason for that?