From f127fce93f184f36e224dff471950ced0342275d Mon Sep 17 00:00:00 2001 From: Meatballs1 Date: Wed, 20 Mar 2024 11:56:52 +0000 Subject: [PATCH] Cleanup error checking and exceptions --- HCDevice.py | 64 +++++++++++++++++++++++++---------------------------- hc2mqtt | 37 +++++++++++++++++-------------- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/HCDevice.py b/HCDevice.py index d8835b2..4945042 100755 --- a/HCDevice.py +++ b/HCDevice.py @@ -95,25 +95,20 @@ class HCDevice: # Based on PR submitted https://github.com/Skons/hcpy/pull/1 def test_program_data(self, data): if "program" not in data: - raise Exception("{self.name}. Message data invalid, no program specified.") + raise TypeError("Message data invalid, no program specified.") - if isinstance(data["program"], str): - try: - data["program"] = int(data["program"]) - except Exception: - raise Exception( - "{self.name}. Message data invalid, UID in 'program' must be an integer." - ) - elif isinstance(data["program"], int) is False: - raise Exception( - "{self.name}. Message data invalid. UID in 'program' must be an integer." + + if isinstance(data["program"],int) is False: + raise TypeError( + f"Message data invalid, UID in 'program' must be an integer." ) + # devices.json stores UID as string uid = str(data["program"]) if uid not in self.features: - raise Exception( - f"{self.name}. Unable to configure appliance. Program UID {uid} is not valid" - "for this device." + raise ValueError( + f"Unable to configure appliance. Program UID {uid} is not valid" + " for this device." ) feature = self.features[uid] @@ -121,34 +116,34 @@ class HCDevice: # Hood is Cooking.Common.Program.{name} # May also be in the format BSH.Common.Program.Favorite.001 if ".Program." not in feature["name"]: - raise Exception( - f"{self.name}. Unable to configure appliance. Program UID {uid} is not a valid" - "program." + raise ValueError( + f"Unable to configure appliance. Program UID {uid} is not a valid" + f" program - {feature['name']}." ) if "options" in data: for option_uid in data["options"]: if str(option_uid) not in self.features: - raise Exception( - f"{self.name}. Unable to configure appliance. Option UID {uid} is not" - "valid for this device." + raise ValueError( + f"Unable to configure appliance. Option UID {uid} is not" + " valid for this device." ) # Test the feature of an appliance agains a data object def test_feature(self, data): if "uid" not in data: - raise Exception("{self.name}. Unable to configure appliance. UID is required.") + raise Exception("Unable to configure appliance. UID is required.") if isinstance(data["uid"], int) is False: - raise Exception("{self.name}. Unable to configure appliance. UID must be an integer.") + raise Exception("Unable to configure appliance. UID must be an integer.") if "value" not in data: - raise Exception("{self.name}. Unable to configure appliance. Value is required.") + raise Exception("Unable to configure appliance. Value is required.") # Check if the uid is present for this appliance uid = str(data["uid"]) if uid not in self.features: - raise Exception(f"{self.name}. Unable to configure appliance. UID {uid} is not valid.") + raise Exception(f"Unable to configure appliance. UID {uid} is not valid.") feature = self.features[uid] @@ -156,14 +151,14 @@ class HCDevice: print(now(), self.name, f"Processing feature {feature['name']} with uid {uid}") if "access" not in feature: raise Exception( - f"{self.name}. Unable to configure appliance." + "Unable to configure appliance. " f"Feature {feature['name']} with uid {uid} does not have access." ) access = feature["access"].lower() if access != "readwrite" and access != "writeonly": raise Exception( - f"{self.name}. Unable to configure appliance." + "Unable to configure appliance. " f"Feature {feature['name']} with uid {uid} has got access {feature['access']}." ) @@ -171,7 +166,7 @@ class HCDevice: if "values" in feature: if isinstance(data["value"], int) is False: raise Exception( - f"Unable to configure appliance. The value {data['value']} must be an integer." + f"Unable to configure appliance. The value {data['value']} must be an integer. " f"Allowed values are {feature['values']}." ) value = str(data["value"]) @@ -179,9 +174,9 @@ class HCDevice: # but always seem to be an integer. An integer must be provided if value not in feature["values"]: raise Exception( - f"{self.name}. Unable to configure appliance." - f"Value {data['value']} is not a valid value." - f"Allowed values are {feature['values']}." + "Unable to configure appliance. " + f"Value {data['value']} is not a valid value. " + f"Allowed values are {feature['values']}. " ) if "min" in feature: @@ -193,8 +188,8 @@ class HCDevice: or data["value"] > max ): raise Exception( - f"{self.name}. Unable to configure appliance." - f"Value {data['value']} is not a valid value." + "Unable to configure appliance. " + f"Value {data['value']} is not a valid value. " f"The value must be an integer in the range {min} and {max}." ) @@ -238,13 +233,14 @@ class HCDevice: if data is not None: if action == "POST": - if "resource" == "/ro/values": + if resource == "/ro/values": # Raises exceptions on failure self.test_feature(data) - elif "resource" == "/ro/activeProgram": + elif resource == "/ro/activeProgram": # Raises exception on failure self.test_program_data(data) + msg["data"] = [data] try: diff --git a/hc2mqtt b/hc2mqtt index 6cbad0a..9886921 100755 --- a/hc2mqtt +++ b/hc2mqtt @@ -88,27 +88,32 @@ dev = {} def client_connect(client, device, mqtt_topic): def on_message(client, userdata, msg): - print(msg.topic) mqtt_state = msg.payload.decode() mqtt_topic = msg.topic.split("/") - print(now(), f"received mqtt message {mqtt_state}") - - if len(mqtt_topic) >= 2: - device_name = mqtt_topic[-2] - topic = mqtt_topic[-1] - else: - raise Exception(f"Invalid mqtt topic {msg.topic}") - + print(now(), f"{msg.topic} received mqtt message {mqtt_state}") + try: - msg = json.loads(mqtt_state) - if topic == "set" and "uid" in msg: - dev[device_name].get("/ro/values", 1, "POST", msg) - elif topic == "activeProgram": - dev[device_name].get("/ro/activeProgram", 1, "POST", msg) + if len(mqtt_topic) >= 2: + device_name = mqtt_topic[-2] + topic = mqtt_topic[-1] else: - raise Exception(f"Payload {msg} is not correctly formatted") + raise Exception(f"Invalid mqtt topic {msg.topic}.") + + try: + msg = json.loads(mqtt_state) + except ValueError as e: + raise ValueError(f"Invalid JSON in message: {mqtt_state}.") from e + + if topic == "set": + resource = "/ro/values" + elif topic == "activeProgram": + resource = "/ro/activeProgram" + else: + raise Exception(f"Payload topic {topic} is unknown.") + + dev[device_name].get(resource, 1, "POST", msg) except Exception as e: - print("ERROR", e, file=sys.stderr) + print(now(), device_name, "ERROR", e, file=sys.stderr) host = device["host"] device_topics = topics