Skip to content

Commit

Permalink
Add log message for XML payload (issue #681)
Browse files Browse the repository at this point in the history
  • Loading branch information
ollo69 committed Jan 28, 2024
1 parent ce4a107 commit 5effd57
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 21 deletions.
7 changes: 0 additions & 7 deletions custom_components/smartthinq_sensors/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,6 @@ class ThinQBinarySensorEntityDescription(BinarySensorEntityDescription):
icon_on="mdi:account-lock",
entity_registry_enabled_default=False,
),
ThinQBinarySensorEntityDescription(
key=WashDeviceFeatures.DOORCLOSE,
name="Door close",
icon="mdi:alpha-o-box-outline",
icon_on="mdi:alpha-c-box",
entity_registry_enabled_default=False,
),
ThinQBinarySensorEntityDescription(
key=WashDeviceFeatures.DOORLOCK,
name="Door lock",
Expand Down
1 change: 0 additions & 1 deletion custom_components/smartthinq_sensors/wideq/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ class WashDeviceFeatures(StrEnum):
DELAYSTART = "delay_start"
DETERGENT = "detergent"
DETERGENTLOW = "detergent_low"
DOORCLOSE = "door_close"
DOORLOCK = "door_lock"
DOOROPEN = "door_open"
DRYLEVEL = "dry_level"
Expand Down
17 changes: 12 additions & 5 deletions custom_components/smartthinq_sensors/wideq/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -1030,20 +1030,27 @@ def lookup_bit_enum(self, key):

# exception because doorlock bit
# is not inside the model enum
if key == "DoorLock" and ret_val is None:
if str_val == "1":
door_locks = {"DoorLock": "1", "doorLock": "DOORLOCK_ON"}
if ret_val is None and key in door_locks:
if self.is_info_v2 and not str_val:
return None
if str_val == door_locks[key]:
return LABEL_BIT_ON
return LABEL_BIT_OFF

return ret_val

def lookup_bit(self, key):
def lookup_bit(self, key, invert=False):
"""Lookup bit value for a specific key of type enum."""
enum_val = self.lookup_bit_enum(key)
if enum_val is None:
return None
bit_val = LOCAL_LANG_PACK.get(enum_val, StateOptions.OFF)
if bit_val == StateOptions.ON:
bit_val = LOCAL_LANG_PACK.get(enum_val)
if not bit_val:
return StateOptions.OFF
if not invert:
return bit_val
if bit_val == StateOptions.OFF:
return StateOptions.ON
return StateOptions.OFF

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
WashDeviceFeatures.DAMPDRYBEEP: ["DampDryBeep", "dampDryBeep"],
WashDeviceFeatures.DETERGENT: ["DetergentStatus", "ezDetergentState"],
WashDeviceFeatures.DETERGENTLOW: ["DetergentRemaining", "detergentRemaining"],
WashDeviceFeatures.DOORCLOSE: ["DoorClose", "doorClose"],
WashDeviceFeatures.DOOROPEN: ["DoorClose", "doorClose"],
WashDeviceFeatures.DOORLOCK: ["DoorLock", "doorLock"],
WashDeviceFeatures.HANDIRON: ["HandIron", "handIron"],
WashDeviceFeatures.MEDICRINSE: ["MedicRinse", "medicRinse"],
Expand All @@ -57,6 +57,8 @@
WashDeviceFeatures.TURBOWASH: ["TurboWash", "turboWash"],
}

INVERTED_BITS = [WashDeviceFeatures.DOOROPEN]

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -651,7 +653,8 @@ def _update_bit_features(self):
"""Update features related to bit status."""
index = 1 if self.is_info_v2 else 0
for feature, keys in BIT_FEATURES.items():
status = self.lookup_bit(self._getkeys(keys[index]))
invert = feature in INVERTED_BITS
status = self.lookup_bit(self._getkeys(keys[index]), invert)
self._update_feature(feature, status, False)

def _update_features(self):
Expand Down
49 changes: 43 additions & 6 deletions custom_components/smartthinq_sensors/wideq/model_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from collections import namedtuple
from copy import deepcopy
import json
import logging
from numbers import Number

from .const import BIT_OFF, BIT_ON
Expand All @@ -18,6 +19,8 @@
TYPE_REFERENCE = "reference"
TYPE_STRING = "string"

_LOGGER = logging.getLogger(__name__)


EnumValue = namedtuple("EnumValue", ["options"])
RangeValue = namedtuple("RangeValue", ["min", "max", "step"])
Expand Down Expand Up @@ -178,6 +181,11 @@ def decode_monitor(self, data):
def decode_snapshot(self, data, key):
"""Decode status data."""

@property
def monitor_type(self) -> str | None:
"""Return used monitor type."""
return None


class ModelInfoV1(ModelInfo):
"""A description of a device model's capabilities for type V1."""
Expand All @@ -190,6 +198,7 @@ def is_valid_model_data(model_data: dict) -> bool:
def __init__(self, data):
"""Initialize the class."""
super().__init__(data)
self._monitor_type = None
self._bit_keys = {}

@property
Expand Down Expand Up @@ -344,15 +353,27 @@ def get_control_cmd(self, cmd_key, ctrl_key=None):
control["cmd"] = ctrl_key
return control

@property
def monitor_type(self) -> str | None:
"""Return used monitor type."""
if self._monitor_type is None:
self._monitor_type = self._data["Monitoring"]["type"]
return self._monitor_type

@property
def byte_monitor_data(self):
"""Check that type of monitoring is BINARY(BYTE)."""
return self._data["Monitoring"]["type"] == "BINARY(BYTE)"
return self.monitor_type == "BINARY(BYTE)"

@property
def hex_monitor_data(self):
"""Check that type of monitoring is BINARY(HEX)."""
return self._data["Monitoring"]["type"] == "BINARY(HEX)"
return self.monitor_type == "BINARY(HEX)"

@property
def xml_monitor_data(self):
"""Check that type of monitoring is XML."""
return self.monitor_type == "XML"

def decode_monitor_byte(self, data):
"""Decode binary byte encoded status data."""
Expand Down Expand Up @@ -388,9 +409,23 @@ def decode_monitor_hex(self, data):
return decoded

@staticmethod
def decode_monitor_json(data):
def decode_monitor_xml(data):
"""Decode a xml that encodes status data."""
_LOGGER.warning("Received XML data from device: %s", data)
return None

@staticmethod
def decode_monitor_json(data, mon_type):
"""Decode a bytestring that encodes JSON status data."""
return json.loads(data.decode("utf8"))
try:
return json.loads(data.decode("utf8"))
except json.JSONDecodeError:
_LOGGER.warning(
"Received data with invalid format from device. Type: %s - Data: %s",
mon_type,
data,
)
return None

def decode_monitor(self, data):
"""Decode status data."""
Expand All @@ -399,7 +434,9 @@ def decode_monitor(self, data):
return self.decode_monitor_byte(data)
if self.hex_monitor_data:
return self.decode_monitor_hex(data)
return self.decode_monitor_json(data)
if self.xml_monitor_data:
return self.decode_monitor_xml(data)
return self.decode_monitor_json(data, self.monitor_type)

@staticmethod
def _get_current_temp_key(key: str, data):
Expand All @@ -421,7 +458,7 @@ def _get_current_temp_key(key: str, data):

def decode_snapshot(self, data, key):
"""Decode status data."""
if self._data["Monitoring"]["type"] != "THINQ2":
if self.monitor_type != "THINQ2":
return {}

if key and key not in data:
Expand Down

0 comments on commit 5effd57

Please sign in to comment.