Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/skykettle-ha.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-07-15 12:24:07 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-07-15 12:24:07 +0300
commit1b2f7314e6fae14ff301ece7763269c17d113ed3 (patch)
tree97c9ee43b5d7b3d2cad213f7c4086357e2697b8d
parent2f03dbc403370863b8a851c38262dd06f1bbbd53 (diff)
Model specific methods
-rw-r--r--custom_components/skykettle/light.py1
-rw-r--r--custom_components/skykettle/skykettle.py192
-rw-r--r--custom_components/skykettle/water_heater.py17
3 files changed, 140 insertions, 70 deletions
diff --git a/custom_components/skykettle/light.py b/custom_components/skykettle/light.py
index b42e3b6..368dfd5 100644
--- a/custom_components/skykettle/light.py
+++ b/custom_components/skykettle/light.py
@@ -112,6 +112,7 @@ class KettleLight(LightEntity):
@property
def available(self):
+ if self.kettle.model_code != 1: return False # Not sure
if self.light_type == LIGHT_GAME:
return self.kettle.available
else:
diff --git a/custom_components/skykettle/skykettle.py b/custom_components/skykettle/skykettle.py
index 2f48a99..595a720 100644
--- a/custom_components/skykettle/skykettle.py
+++ b/custom_components/skykettle/skykettle.py
@@ -75,6 +75,7 @@ class SkyKettle():
"temp_high", "unknown2", "r_high", "g_high", "b_high"])
Status = namedtuple("Status", ["mode", "target_temp", "sound_enabled", "current_temp",
"color_interval", "is_on", "boil_time"])
+ StatusSimple = namedtuple("StatusSimple", ["mode", "target_temp", "is_on", "current_temp"])
Stats = namedtuple("Stats", ["ontime", "energy_wh", "heater_on_count", "user_on_count"])
FreshWaterInfo = namedtuple("FreshWaterInfo", ["is_on", "unknown1", "water_freshness_hours"])
@@ -86,8 +87,7 @@ class SkyKettle():
self.model_code = SkyKettle.SUPPORTED_DEVICES[model]
_LOGGER.debug(f"Kettle model code: {self.model_code}")
else:
- self.model_code = 1
- _LOGGER.warn(f"Unknown kettle model")
+ raise SkyKettleError("Unknown kettle model")
@abstractmethod
async def command(self, command, params=[]):
@@ -117,111 +117,165 @@ class SkyKettle():
_LOGGER.debug(f"Turned off")
async def set_main_mode(self, mode, target_temp = 0, boil_time = 0):
- data = pack("BxBxxxxxxxxxxBxx", int(mode), int(target_temp), int(0x80 + boil_time))
+ if self.model_code in [0]:
+ data = pack("BxBx", int(mode), int(target_temp))
+ elif self.model_code in [1, 2]:
+ data = pack("BxBxxxxxxxxxxBxx", int(mode), int(target_temp), int(0x80 + boil_time))
r = await self.command(SkyKettle.COMMAND_SET_MAIN_MODE, data)
if r[0] != 1: raise SkyKettleError("can't set mode")
_LOGGER.debug(f"Mode set: mode={mode} ({SkyKettle.MODE_NAMES[mode]}), target_temp={target_temp}, boil_time={boil_time}")
async def get_status(self):
r = await self.command(SkyKettle.COMMAND_GET_STATUS)
- status = SkyKettle.Status(*unpack("<BxBx?BHBxxxxBxx", r))
- status = status._replace(
- is_on = status.is_on == 2,
- boil_time = status.boil_time - 0x80
- )
+ if self.model_code in [0]:
+ # Old models
+ mode, target_temp, is_on, current_temp = unpack("<BxBxxxxxBxBxxxxx", r)
+ status = Status(mode=mode,
+ target_temp=target_temp,
+ is_on=is_on==2,
+ current_temp=current_temp,
+ sound_enabled=None,
+ boil_time=None,
+ color_interval=None)
+ elif self.model_code in [1, 2]:
+ # New models
+ status = SkyKettle.Status(*unpack("<BxBx?BHBxxxxBxx", r))
+ status = status._replace(
+ is_on = status.is_on == 2,
+ boil_time = status.boil_time - 0x80
+ )
_LOGGER.debug(f"Status: mode={status.mode} ({SkyKettle.MODE_NAMES[status.mode]}), is_on={status.is_on}, "+
f"target_temp={status.target_temp}, current_temp={status.current_temp}, sound_enabled={status.sound_enabled}, "+
f"color_interval={status.color_interval}, boil_time={status.boil_time}")
return status
async def sync_time(self):
- t = time.localtime()
- offset = calendar.timegm(t) - calendar.timegm(time.gmtime(time.mktime(t)))
- now = int(time.time())
- data = pack("<ii", now, offset)
- r = await self.command(SkyKettle.COMMAND_SYNC_TIME, data)
- # r = await self.command(SkyKettle.COMMAND_SYNC_TIME,
- # list(now.to_bytes(4, byteorder='little')) +
- # list(offset.to_bytes(4, byteorder='little', signed=True)))
- if r[0] != 0: raise SkyKettleError("can't sync time")
- _LOGGER.debug(f"Writed time={now} ({datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S')}), offset={offset} (GMT{offset/60/60:+.2f})")
+ if self.model_code in [1, 2]:
+ t = time.localtime()
+ offset = calendar.timegm(t) - calendar.timegm(time.gmtime(time.mktime(t)))
+ now = int(time.time())
+ data = pack("<ii", now, offset)
+ r = await self.command(SkyKettle.COMMAND_SYNC_TIME, data)
+ if r[0] != 0: raise SkyKettleError("can't sync time")
+ _LOGGER.debug(f"Writed time={now} ({datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S')}), offset={offset} (GMT{offset/60/60:+.2f})")
+ else:
+ _LOGGER.debug(f"sync_time is not supported by this model")
async def get_time(self):
- r = await self.command(SkyKettle.COMMAND_GET_TIME)
- t, offset = unpack("<ii", r)
- _LOGGER.debug(f"time={t} ({datetime.fromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S')}), offset={offset} (GMT{offset/60/60:+.2f})")
- return t, offset
+ if self.model_code in [1, 2]:
+ r = await self.command(SkyKettle.COMMAND_GET_TIME)
+ t, offset = unpack("<ii", r)
+ _LOGGER.debug(f"time={t} ({datetime.fromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S')}), offset={offset} (GMT{offset/60/60:+.2f})")
+ return t, offset
+ else:
+ _LOGGER.debug(f"get_time is not supported by this model")
async def set_lamp_auto_off_hours(self, hours):
- data = pack("<H", int(hours))
- r = await self.command(SkyKettle.COMMAND_SET_AUTO_OFF_HOURS, data)
- if r[0] != 0: raise SkyKettleError("can't set lamp auto off hours")
- _LOGGER.debug(f"Updated lamp auto off hours={hours}")
+ if self.model_code in [1]: # Not sure
+ data = pack("<H", int(hours))
+ r = await self.command(SkyKettle.COMMAND_SET_AUTO_OFF_HOURS, data)
+ if r[0] != 0: raise SkyKettleError("can't set lamp auto off hours")
+ _LOGGER.debug(f"Updated lamp auto off hours={hours}")
+ else:
+ _LOGGER.debug(f"set_lamp_auto_off_hours is not supported by this model")
async def get_lamp_auto_off_hours(self):
- r = await self.command(SkyKettle.COMMAND_GET_AUTO_OFF_HOURS)
- hours, = unpack("<H", r)
- _LOGGER.debug(f"Lamp auto off hours={hours}")
- return hours
+ if self.model_code in [1]: # Not sure
+ r = await self.command(SkyKettle.COMMAND_GET_AUTO_OFF_HOURS)
+ hours, = unpack("<H", r)
+ _LOGGER.debug(f"Lamp auto off hours={hours}")
+ return hours
+ else:
+ _LOGGER.debug(f"get_lamp_auto_off_hours is not supported by this model")
async def get_colors(self, light_type):
- r = await self.command(SkyKettle.COMMAND_GET_COLORS, [light_type])
- colors_set = SkyKettle.ColorsSet(*unpack("BBBBBBBBBBBBBBBB", r))
- _LOGGER.debug(f"{colors_set}")
- return colors_set
+ if self.model_code in [1]: # Not sure
+ r = await self.command(SkyKettle.COMMAND_GET_COLORS, [light_type])
+ colors_set = SkyKettle.ColorsSet(*unpack("BBBBBBBBBBBBBBBB", r))
+ _LOGGER.debug(f"{colors_set}")
+ return colors_set
+ else:
+ _LOGGER.debug(f"get_colors is not supported by this model")
async def set_colors(self, colors_set):
- data = pack("BBBBBBBBBBBBBBBB", *colors_set)
- r = await self.command(SkyKettle.COMMAND_SET_COLORS, data)
- if r[0] != 0: raise SkyKettleError("can't set colors")
- _LOGGER.debug(f"Updated colors set: {colors_set}")
+ if self.model_code in [1]: # Not sure
+ data = pack("BBBBBBBBBBBBBBBB", *colors_set)
+ r = await self.command(SkyKettle.COMMAND_SET_COLORS, data)
+ if r[0] != 0: raise SkyKettleError("can't set colors")
+ _LOGGER.debug(f"Updated colors set: {colors_set}")
+ else:
+ _LOGGER.debug(f"set_colors is not supported by this model")
async def commit(self):
- r = await self.command(SkyKettle.COMMAND_COMMIT_SETTINGS)
- if r[0] != 1: raise SkyKettleError("can't commit settings")
- _LOGGER.debug(f"Settings commited")
+ if self.model_code in [1]: # Not sure
+ r = await self.command(SkyKettle.COMMAND_COMMIT_SETTINGS)
+ if r[0] != 1: raise SkyKettleError("can't commit settings")
+ _LOGGER.debug(f"Settings commited")
+ else:
+ _LOGGER.debug(f"commit is not supported by this model")
async def set_lamp_color_interval(self, secs):
- data = pack("<H", int(secs))
- r = await self.command(SkyKettle.COMMAND_SET_COLOR_INTERVAL, data)
- if r[0] != 0: raise SkyKettleError("can't set lamp color change interval")
- _LOGGER.debug(f"Updated lamp color interval secs={secs}")
+ if self.model_code in [1]: # Not sure
+ data = pack("<H", int(secs))
+ r = await self.command(SkyKettle.COMMAND_SET_COLOR_INTERVAL, data)
+ if r[0] != 0: raise SkyKettleError("can't set lamp color change interval")
+ _LOGGER.debug(f"Updated lamp color interval secs={secs}")
+ else:
+ _LOGGER.debug(f"set_lamp_color_interval is not supported by this model")
async def impulse_color(self, r, g, b, brightness=0xff, interval=0):
- data = pack("<BBBBH", r, g, b, brightness, interval)
- r = await self.command(SkyKettle.COMMAND_IMPULSE_COLOR, data)
- if r[0] != 1: raise SkyKettleError("can't fire color impulse")
- _LOGGER.debug(f"Impulse! r={r}, g={g}, b={b}, brightness={brightness}, interval={interval}")
+ if self.model_code in [1]: # Not sure
+ data = pack("<BBBBH", r, g, b, brightness, interval)
+ r = await self.command(SkyKettle.COMMAND_IMPULSE_COLOR, data)
+ if r[0] != 1: raise SkyKettleError("can't fire color impulse")
+ _LOGGER.debug(f"Impulse! r={r}, g={g}, b={b}, brightness={brightness}, interval={interval}")
+ else:
+ _LOGGER.debug(f"impulse_color is not supported by this model")
async def set_light_switch(self, light_type, on):
- data = pack("BB?", light_type, light_type, on)
- r = await self.command(SkyKettle.COMMAND_SET_LIGHT_SWITCH, data)
- if r[0] != 0: raise SkyKettleError("can't switch light")
- _LOGGER.debug(f"Light with type={light_type} ({SkyKettle.LIGHT_NAMES[light_type]}) switched {'on' if on else 'off'}")
+ if self.model_code in [1, 2]:
+ data = pack("BB?", light_type, light_type, on)
+ r = await self.command(SkyKettle.COMMAND_SET_LIGHT_SWITCH, data)
+ if r[0] != 0: raise SkyKettleError("can't switch light")
+ _LOGGER.debug(f"Light with type={light_type} ({SkyKettle.LIGHT_NAMES[light_type]}) switched {'on' if on else 'off'}")
+ else:
+ _LOGGER.debug(f"set_light_switch is not supported by this model")
async def get_light_switch(self, light_type):
- data = pack("B", light_type)
- r = await self.command(SkyKettle.COMMAND_GET_LIGHT_SWITCH, data)
- is_on, = unpack("xx?xx", r)
- _LOGGER.debug(f"Light with type={light_type} ({SkyKettle.LIGHT_NAMES[light_type]}) is {'on' if is_on else 'off'}")
- return is_on
+ if self.model_code in [1, 2]:
+ data = pack("B", light_type)
+ r = await self.command(SkyKettle.COMMAND_GET_LIGHT_SWITCH, data)
+ is_on, = unpack("xx?xx", r)
+ _LOGGER.debug(f"Light with type={light_type} ({SkyKettle.LIGHT_NAMES[light_type]}) is {'on' if is_on else 'off'}")
+ return is_on
+ else:
+ _LOGGER.debug(f"get_light_switch is not supported by this model")
async def set_sound(self, on):
- data = pack("?", on)
- r = await self.command(SkyKettle.COMMAND_SET_SOUND, data)
- if r[0] != 1: raise SkyKettleError("can't switch sound")
- _LOGGER.debug(f"Sound switched {'on' if on else 'off'}")
+ if self.model_code in [1, 2]: # Not sure
+ data = pack("?", on)
+ r = await self.command(SkyKettle.COMMAND_SET_SOUND, data)
+ if r[0] != 1: raise SkyKettleError("can't switch sound")
+ _LOGGER.debug(f"Sound switched {'on' if on else 'off'}")
+ else:
+ _LOGGER.debug(f"set_sound is not supported by this model")
async def set_fresh_water(self, on, unknown1=48):
- data = pack("<x?Hxxxxxxxxxxxx", on, int(unknown1))
- r = await self.command(SkyKettle.COMMAND_SET_FRESH_WATER, data)
- _LOGGER.debug(f"Fresh water notification switched {'on' if on else 'off'}")
+ if self.model_code in [1]: # Not sure
+ data = pack("<x?Hxxxxxxxxxxxx", on, int(unknown1))
+ r = await self.command(SkyKettle.COMMAND_SET_FRESH_WATER, data)
+ _LOGGER.debug(f"Fresh water notification switched {'on' if on else 'off'}")
+ else:
+ _LOGGER.debug(f"set_fresh_water is not supported by this model")
async def get_fresh_water(self):
- r = await self.command(SkyKettle.COMMAND_GET_FRESH_WATER, [0x00])
- info = SkyKettle.FreshWaterInfo(*unpack("<x?HHxxxxxxxxxx", r))
- _LOGGER.debug(f"Fresh water notification is {'on' if info.is_on else 'off'}, unknown1={info.unknown1}, water_freshness_hours={info.water_freshness_hours}")
- return info
+ if self.model_code in [1]: # Not sure
+ r = await self.command(SkyKettle.COMMAND_GET_FRESH_WATER, [0x00])
+ info = SkyKettle.FreshWaterInfo(*unpack("<x?HHxxxxxxxxxx", r))
+ _LOGGER.debug(f"Fresh water notification is {'on' if info.is_on else 'off'}, unknown1={info.unknown1}, water_freshness_hours={info.water_freshness_hours}")
+ return info
+ else:
+ _LOGGER.debug(f"get_fresh_water is not supported by this model")
async def get_stats(self):
r1 = await self.command(SkyKettle.COMMAND_GET_STATS1, [0x00])
diff --git a/custom_components/skykettle/water_heater.py b/custom_components/skykettle/water_heater.py
index 966db86..84c36d6 100644
--- a/custom_components/skykettle/water_heater.py
+++ b/custom_components/skykettle/water_heater.py
@@ -93,7 +93,22 @@ class SkyWaterHeater(WaterHeaterEntity):
@property
def operation_list(self):
- return [STATE_OFF] + list(SkyKettle.MODE_NAMES.values())
+ if self.kettle.model_code == 1: # Not sure
+ return [
+ STATE_OFF,
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_HEAT],
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_BOIL],
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_BOIL_HEAT],
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_LAMP],
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_GAME]
+ ]
+ else:
+ return [
+ STATE_OFF,
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_HEAT],
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_BOIL],
+ SkyKettle.MODE_NAMES[SkyKettle.MODE_BOIL_HEAT]
+ ]
@property
def extra_state_attributes(self):