diff --git a/.gitignore b/.gitignore index 30b574f..61ca52b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ __pycache__ logos/@eaDir/ logos/Thumbs.db *.bac +examples/rootCA.VIMAR.crt +examples/credentials.cfg diff --git a/README.md b/README.md index d2486b1..74d4631 100755 --- a/README.md +++ b/README.md @@ -168,9 +168,13 @@ You can use the vimarlink library in the command line like this: python3.9 -m pip install async_timeout homeassistant # see examples cd examples -# edit example.py and add your credentials -# run the example script, which will turn on and off the first light it will find -python3.9 example.py +# copy credentials.cfg.dist to credentials.cfg and add your credentials +# run the example script - print help +python3.9 example.py -h +# run the example script - list all lights +python3.9 example.py --platform lights +# run the example script - change a specific cover to open +python3.9 example.py --platform covers --device 721 --status "up/down" --value 0 ``` ## contribution diff --git a/custom_components/vimar/manifest.json b/custom_components/vimar/manifest.json index c8efffc..1331164 100755 --- a/custom_components/vimar/manifest.json +++ b/custom_components/vimar/manifest.json @@ -6,6 +6,6 @@ "dependencies": [], "config_flow": false, "codeowners": ["@h4de5"], - "version": "2021.5.2", + "version": "2021.5.3", "iot_class": "local_polling" } diff --git a/custom_components/vimar/vimarlink/vimarlink.py b/custom_components/vimar/vimarlink/vimarlink.py index e02dd4e..c7c285e 100755 --- a/custom_components/vimar/vimarlink/vimarlink.py +++ b/custom_components/vimar/vimarlink/vimarlink.py @@ -312,7 +312,7 @@ def get_room_devices(self, devices={}, start: int = None, limit: int = None): if VimarLink._room_ids is None: return None - start, limit = self._sanitaze_limits(start, limit) + start, limit = self._sanitize_limits(start, limit) _LOGGER.debug("get_room_devices started - from %d to %d", start, start + limit) @@ -341,7 +341,7 @@ def get_remote_devices(self, devices={}, start: int = None, limit: int = None): if len(devices) == 0: _LOGGER.debug("get_remote_devices started - from %d to %d", start, start + limit) - start, limit = self._sanitaze_limits(start, limit) + start, limit = self._sanitize_limits(start, limit) select = """SELECT '' AS room_ids, o2.id AS object_id, o2.name AS object_name, o2.VALUES_TYPE AS object_type, o2.NAME AS object_name, o2.VALUES_TYPE AS object_type, @@ -355,7 +355,7 @@ def get_remote_devices(self, devices={}, start: int = None, limit: int = None): return self._generate_device_list(select, devices) - def _sanitaze_limits(self, start: int, limit: int): + def _sanitize_limits(self, start: int, limit: int): """Check for sane values in start and limit.""" # upper limit is hardcoded - too many results will kill webserver if limit is None or limit > MAX_ROWS_PER_REQUEST or limit <= 0: diff --git a/examples/credentials.cfg.dist b/examples/credentials.cfg.dist new file mode 100755 index 0000000..f35d38f --- /dev/null +++ b/examples/credentials.cfg.dist @@ -0,0 +1,9 @@ +; CHANGE YOUR CREDENTIALS HERE +[webserver] +schema=https +host=192.168.0.100 +port=443 +username=admin +password=password +certificate=rootCA.VIMAR.crt +timeout=5 \ No newline at end of file diff --git a/examples/example.py b/examples/example.py index 959074e..9bc83b4 100755 --- a/examples/example.py +++ b/examples/example.py @@ -2,7 +2,8 @@ # import async_timeout import os import sys -import time +import configparser +import argparse # those imports only work in that directory # this will be easier to use, as soon as we have a separate python package @@ -20,74 +21,101 @@ "sensors": 'sensor', } -# initialize credentials -# CHANGE YOUR CREDENTIALS HERE -schema = 'https' -host = '192.168.0.100' -port = 443 -username = 'admin' -password = 'password' -certificate = 'rootCA.VIMAR.crt' -timeout = 5 - -# setup link to vimar web server -vimarconnection = VimarLink(schema, host, port, username, password, certificate, timeout) - -# if certificate is not available, download it -if os.path.isfile(certificate) is False: - vimarconnection.install_certificate() - -# initialize project -vimarproject = VimarProject(vimarconnection) - -# try to login -try: - valid_login = vimarconnection.check_login() -except BaseException as err: - print("Login Exception: %s" % err) - valid_login = False - -if (not valid_login): - print("Login failed") - exit(1) - -# load all devices and device status -vimarproject.update() - -# check all available device types -for device_type, platform in AVAILABLE_PLATFORMS.items(): - device_count = vimarproject.platform_exists(device_type) - if device_count: - print("load platform %s with %d %s" % (platform, device_count, device_type)) - -# get all lights -lights = vimarproject.get_by_device_type("lights") - -# list all lights and their status -for device_id, device in lights.items(): - print(device_id, "-", device["object_name"], "available status:", list(device["status"].keys())) - -# SELECT YOUR OWN DEVICE ID FROM THE LIST ABOVE -test_device_id = "704" - -# if the default device_id is not available turn on the first found light -if (test_device_id not in lights): - test_device_id = list(lights)[0] - -if ("on/off" not in lights[test_device_id]["status"]): - print("given device does not support 'on/off' status - available:", list(lights[test_device_id]["status"].keys())) - exit(1) - -# get optionals parameter for given status name -optionals = vimarconnection.get_optionals_param("on/off") - -# change a single status to on -print("Turn on device", test_device_id, "-", lights[test_device_id]["object_name"]) -vimarconnection.set_device_status(lights[test_device_id]["status"]["on/off"]["status_id"], '1', optionals) - -# wait 2 seconds -time.sleep(2) - -# change a single status to off again -print("Turn off device", test_device_id, "-", lights[test_device_id]["object_name"]) -vimarconnection.set_device_status(lights[test_device_id]["status"]["on/off"]["status_id"], '0', optionals) + +def main(): + + parser = argparse.ArgumentParser(description='Command line client for controlling a vimar webserver') + parser.add_argument('-c', '--config', type=str, default="credentials.cfg", dest="configpath", help="Path to your credentials settings") + parser.add_argument('-p', '--platform', type=str, dest="platform", help="Must be one of: lights, covers, switches, climates, media_players, scenes or sensors") + # parser.add_argument('-l', '--list', action='store_true', dest="list", help="List all available devices found in the given platform") + parser.add_argument('-d', '--device', type=int, dest="device_id", help="ID of the device you want to change") + parser.add_argument('-s', '--status', type=str, dest="status_name", help="Status that you want to change") + parser.add_argument('-v', '--value', type=str, dest="target_value", help="Change status to the given value") + args = parser.parse_args() + + if os.path.isfile("credentials.cfg") is False: + print("credentials not found - please rename credentials.cfg.dist to credentials.cfg and adapt the settings.") + exit(1) + + # read credentials from config files + config = configparser.ConfigParser() + config.read(args.configpath) + config.sections() + + # setup link to vimar web server + vimarconnection = VimarLink( + config['webserver']['schema'], + config['webserver']['host'], + int(config['webserver']['port']), + config['webserver']['username'], + config['webserver']['password'], + config['webserver']['certificate'], + int(config['webserver']['timeout'])) + + # if certificate is not available, download it + if os.path.isfile(config['webserver']['certificate']) is False: + vimarconnection.install_certificate() + + # initialize project + vimarproject = VimarProject(vimarconnection) + + # try to login + try: + valid_login = vimarconnection.check_login() + except BaseException as err: + print("Login Exception: %s" % err) + valid_login = False + if (not valid_login): + print("Login failed") + exit(1) + + # load all devices and device status + vimarproject.update() + + # check all available platforms + if args.platform is None: + for device_type, platform in AVAILABLE_PLATFORMS.items(): + device_count = vimarproject.platform_exists(device_type) + if device_count: + print("found platform %s with %d %s" % (platform, device_count, device_type)) + exit(0) + + # get all devices + devices = vimarproject.get_by_device_type(args.platform) + + if not devices: + print("No devices found for platform:", args.platform) + exit(1) + + # list all available devices for given platform + if not args.device_id: + # list all lights and their status + for device_id, device in devices.items(): + print(device_id, "-", device["object_name"], "available status:", list(device["status"].keys())) + exit(0) + + # show single device + if args.device_id: + args.device_id = str(args.device_id) + # if the default device_id is not available turn on the first found light + if args.device_id not in devices: + print("No device found with id:", args.device_id, "in platform", args.platform) + exit(1) + + statusdict = devices.get(args.device_id)["status"] + print(args.device_id, "-", devices.get(args.device_id)["object_name"], "available status:", [key + ": " + value['status_value'] for key, value in statusdict.items()]) + + if args.status_name: + if args.status_name not in devices[args.device_id]["status"]: + print("given device does not support '", args.status_name, "' status") + exit(1) + + optionals = vimarconnection.get_optionals_param(args.status_name) + + if args.target_value: + print("Setting", args.status_name, "to", args.target_value) + vimarconnection.set_device_status(statusdict[args.status_name]["status_id"], args.target_value, optionals) + + +if __name__ == "__main__": + main() \ No newline at end of file