Skip to content
Merged
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 82 additions & 6 deletions homeassistant/components/switch/wemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
https://home-assistant.io/components/switch.wemo/
"""
import logging
from datetime import datetime, timedelta

from homeassistant.components.switch import SwitchDevice
from homeassistant.const import (
Expand All @@ -20,6 +21,16 @@
ATTR_CURRENT_STATE_DETAIL = 'state_detail'
ATTR_COFFEMAKER_MODE = "coffeemaker_mode"

# Wemo Insight
ATTR_POWER_CURRENT_W = 'power_current_w'
# ATTR_POWER_AVG_W = 'power_average_w'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required?

ATTR_POWER_TODAY_MW_MIN = 'power_today_mW_min'
ATTR_POWER_TOTAL_MW_MIN = 'power_total_mW_min'
ATTR_ON_FOR_TIME = 'on_time_most_recent'
ATTR_ON_TODAY_TIME = 'on_time_today'
ATTR_ON_TOTAL_TIME = 'on_time_total'
ATTR_POWER_THRESHOLD = 'power_threshold_w'

MAKER_SWITCH_MOMENTARY = "momentary"
MAKER_SWITCH_TOGGLE = "toggle"

Expand Down Expand Up @@ -109,23 +120,88 @@ def device_state_attributes(self):

if self.insight_params or (self.coffeemaker_mode is not None):
attr[ATTR_CURRENT_STATE_DETAIL] = self.detail_state
attr[ATTR_POWER_CURRENT_W] = self.power_current_watt
# attr[ATTR_POWER_AVG_W] = self.power_average_watt
attr[ATTR_POWER_TODAY_MW_MIN] = self.power_today_mw_min
attr[ATTR_POWER_TOTAL_MW_MIN] = self.power_total_mw_min
attr[ATTR_ON_FOR_TIME] = self.on_for
attr[ATTR_ON_TODAY_TIME] = self.on_today
attr[ATTR_ON_TOTAL_TIME] = self.on_total
attr[ATTR_POWER_THRESHOLD] = self.power_threshold

if self.coffeemaker_mode is not None:
attr[ATTR_COFFEMAKER_MODE] = self.coffeemaker_mode

return attr

# @property

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not needed, was from originally when that method was currrent_power_mwh

def _current_power_mw(self):
"""Current power usage in mW."""
if self.insight_params:
try:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of try … catch, use self.insight_param.get('current_power')

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guess I could do if self.insight_params and self.insight_param.get('current_power'):, guessing the original code if self.insight_params condition because non-Insight switches don't have those attribs.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly right.

return self.insight_params['currentpower']
except KeyError:
return None

@property
def power_current_watt(self):
"""Current power usage in W."""
if self.insight_params:
try:
return self._current_power_mw() / 1000
except TypeError:
return None

@property

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are somethings properties and other methods ? Also, why are they properties/method to begin with and not just all part of device_state_attributes ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Started out cutting and pasting what was there (I'm not a python guy, nor do I know HA components)... If we don't need the methods, I can just load everything into the state attribs assignments.

def power_threshold(self):
"""Threshold of W at which Insight will indicate it's load is ON."""
if self.insight_params:
return self.insight_params['powerthreshold'] / 1000

@staticmethod
def as_uptime(_seconds):
"""Format seconds into uptime string in the format: 00d 00h 00m 00s."""
uptime = datetime(1, 1, 1) + timedelta(seconds=_seconds)
return "{:0>2d}d {:0>2d}h {:0>2d}m {:0>2d}s".format(uptime.day-1,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the timedelta object directly? It supports days, hours etc https://docs.python.org/3/library/datetime.html#datetime.timedelta

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm probably doing something stupid (python noob), but when I try that I get this:

>>> from datetime import datetime, timedelta
>>> uptime = timedelta(days=0,seconds=86401,hours=0,minutes=0)
>>> print ("{:0>2d}d {:0>2d}h {:0>2d}m {:0>2d}s".format(uptime.days, uptime.hours, uptime.minutes, uptime.seconds))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'datetime.timedelta' object has no attribute 'hours'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh you're right, I was wrong. Looks like timedelta converts it all to seconds.

uptime.hour,
uptime.minute,
uptime.second)

@property
def on_for(self):
"""On time in seconds."""
if self.insight_params:
return WemoSwitch.as_uptime(self.insight_params['onfor'])

@property
def on_today(self):
"""On time in seconds."""
if self.insight_params:
return WemoSwitch.as_uptime(self.insight_params['ontoday'])

@property
def on_total(self):
"""On time in seconds."""
if self.insight_params:
return WemoSwitch.as_uptime(self.insight_params['ontotal'])

@property
def current_power_mwh(self):
"""Current power usage in mWh."""
def power_total_mw_min(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't just rename overrides of official properties. Please check out the switch ABC and see what is supported and what is not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Insight returns average milliwatt power consumed for each minute. So for 12W it will increment this value by 12,000 each minute. So it's mW/min.

mWh is average milliwatts per hour... The Insight doesn't provide that.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point I hope to refactor some of the HA power/energy code - but this requires changing some of the base components properties - and any other components that override then.

Until then I think you need to leave the official properties as they are - and adddevice_state_properties for the correct / new attributes.

"""Total of average mW per minute."""
if self.insight_params:
return self.insight_params['currentpower']
try:
return self.insight_params['totalmw']
except KeyError:
return None

@property
def today_power_mw(self):
"""Today total power usage in mW."""
def power_today_mw_min(self):
"""Total consumption today in mW per minute."""
if self.insight_params:
return self.insight_params['todaymw']
try:
return self.insight_params['todaymw']
except KeyError:
return None

@property
def detail_state(self):
Expand Down