TPLink HS110 smart plug configuration help/error

Hi all,

I’m trying to get home assistant to see a HS110 TPLink smart plug with power monitoring. Home assistant is running on a Synology NAS, currently on version 0.52.1.

My configuration is:

switch:

  • platform: tplink
    host: 192.168.1.180
    name: tplinkhs110

The IP address is correct (responds to pings) and I can see/control it from the TPLink app. I get the following in the log though:

2017-10-30 23:41:38 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
File “/usr/local/lib/python3.6/asyncio/tasks.py”, line 182, in _step
result = coro.throw(exc)
File “/usr/src/app/homeassistant/helpers/entity_component.py”, line 381, in async_process_entity
new_entity, self, update_before_add=update_before_add
File “/usr/src/app/homeassistant/helpers/entity_component.py”, line 212, in async_add_entity
yield from self.hass.async_add_job(entity.update)
File “/usr/local/lib/python3.6/asyncio/futures.py”, line 332, in iter
yield self # This tells Task to wait for completion.
File “/usr/local/lib/python3.6/asyncio/tasks.py”, line 250, in _wakeup
future.result()
File “/usr/local/lib/python3.6/asyncio/futures.py”, line 245, in result
raise self._exception
File “/usr/local/lib/python3.6/concurrent/futures/thread.py”, line 55, in run
result = self.fn(*self.args, **self.kwargs)
File “/usr/src/app/homeassistant/components/switch/tplink.py”, line 95, in update
= “%.1f W” % emeter_readings[“power”]
KeyError: ‘power’

Any help would be much appreciated!

Can you try unplugging and plugging the socket back in and restarting homeassistant. If this doesn’t work can you upgrade hass to the latest version. Maybe for some reason you got the newer pip package which is not API compatible?

I have the same issue, or what looks to be very similar. This is with an HS110 and hassio 0.57.3 I’ve unplugged/re-plugged the switch and restarted the pi host and I get the error message shown below.

Any thoughts appreciated

2017-11-15 18:52:13 ERROR (MainThread) [homeassistant.components.switch] Error on device update!
Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/homeassistant/helpers/entity_component.py”, line 216, in async_add_entity
yield from entity.async_device_update(warning=False)
File “/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py”, line 309, in async_device_update
yield from self.hass.async_add_job(self.update)
File “/usr/lib/python3.6/asyncio/futures.py”, line 331, in iter
yield self # This tells Task to wait for completion.
File “/usr/lib/python3.6/asyncio/tasks.py”, line 244, in _wakeup
future.result()
File “/usr/lib/python3.6/asyncio/futures.py”, line 244, in result
raise self._exception
File “/usr/lib/python3.6/concurrent/futures/thread.py”, line 55, in run
result = self.fn(*self.args, **self.kwargs)
File “/usr/lib/python3.6/site-packages/homeassistant/components/switch/tplink.py”, line 90, in update
= “%.1f W” % emeter_readings[“power”]
KeyError: ‘power’

I have one and it works fine, but I’m on Python 3.5.2/Ubuntu 16.04 Server LTS. If it’s any lead to a solution ?

Thanks for that - perhaps this issue is more to do with hassio. I’m glad it works on another platform. I’m a bit too committed to home assistant on Pi to switch to another platform. I have found that IFTTT works with the switch OK, so integration with that might be one option, although I really wanted to keep all my home automation away from the cloud.

I did think about multiple HA instances but as this isn’t supported any more, I didn’t want to do that either.

I shall be patient though …

I chose this one because it doesn’t need any external access. I set it up in a dedicated WiFi SSID/VLAN that can only communicate with the VLAN where the HA server is. Works great !
I’m expecting some Broadlink plugs too, I guess they will offer the same, except for the consumption statistics.

The error comes in a place where it tries to retrieve the statistics. Right after this block, this kind of error (missing value) is caught in the code :

        emeter_statics = self.smartplug.get_emeter_daily()
        try:
            self._emeter_params[ATTR_DAILY_CONSUMPTION] \
                = "%.2f kW" % emeter_statics[int(time.strftime("%e"))]
        except KeyError:
            # device returned no daily history
            pass

I would suggest that you add the try/except KeyError for each value (line 89 and following):

try:    
     self._emeter_params[ATTR_CURRENT_CONSUMPTION] \
         = "%.1f W" % emeter_readings["power"]
except KeyError:
    pass
try:    
     self._emeter_params[ATTR_TOTAL_CONSUMPTION] \
         = "%.2f kW" % emeter_readings["total"]
except KeyError:
    pass
try:    
     self._emeter_params[ATTR_VOLTAGE] \
except KeyError:
    pass
try:    
         = "%.2f V" % emeter_readings["voltage"]
except KeyError:
    pass
try:    
     self._emeter_params[ATTR_CURRENT] \
         = "%.1f A" % emeter_readings["current"]
except KeyError:
    pass

And see what happens !

Or maybe, depending on a firmware change, the names of the values have changed. What does the “emeter_readings” variable contents ?

My lack of diagnosis skills with hassio or even knowledge as to wether I can change the code in the docker hass.io uses makes me feel a tad inadequate :slight_smile: . So I have set up a unbuntu/mint box because that is easy and used the virtenv to create hass as per the install guide https://home-assistant.io/docs/installation/virtualenv/ and that gives a very similar error as below. I’ll work though your great idea on that rig and see what I can find.

Just in case though, was there a set of install instructions you went through for your rig in case I fancy trying that too?

Error on device update!
Traceback (most recent call last):
File “/home/mint/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py”, line 217, in async_add_entity
yield from entity.async_device_update(warning=False)
File “/home/mint/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity.py”, line 306, in async_device_update
yield from self.hass.async_add_job(self.update)
File “/usr/lib/python3.5/asyncio/futures.py”, line 361, in iter
yield self # This tells Task to wait for completion.
File “/usr/lib/python3.5/asyncio/tasks.py”, line 296, in _wakeup
future.result()
File “/usr/lib/python3.5/asyncio/futures.py”, line 274, in result
raise self._exception
File “/usr/lib/python3.5/concurrent/futures/thread.py”, line 55, in run
result = self.fn(*self.args, **self.kwargs)
File “/home/mint/homeassistant/lib/python3.5/site-packages/homeassistant/components/switch/tplink.py”, line 90, in update
= “%.1f W” % emeter_readings[“power”]
KeyError: ‘power’

I popped in a logging statement and I see the data returned is
emter_readings is {‘total_wh’: 2, ‘voltage_mv’: 240645, ‘current_ma’: 22, ‘power_mw’: 0}

In the code it’s using words like current rather than current_ma and so as an experiment I updated the phrases in the code to match. We now ges further and a different error appears as shown below. I’m guessing this means a further mismatch between what the code is expecting what what the HS110 api returns.

Looking at the function get_emeter_daily, I’m not sure where to add debugging, although I’m happy to try!

File “/usr/local/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py”, line 217, in async_add_entity
yield from entity.async_device_update(warning=False)
File “/usr/local/lib/python3.5/site-packages/homeassistant/helpers/entity.py”, line 306, in async_device_update
yield from self.hass.async_add_job(self.update)
File “/usr/local/lib/python3.5/asyncio/futures.py”, line 381, in iter
yield self # This tells Task to wait for completion.
File “/usr/local/lib/python3.5/asyncio/tasks.py”, line 310, in _wakeup
future.result()
File “/usr/local/lib/python3.5/asyncio/futures.py”, line 294, in result
raise self._exception
File “/usr/local/lib/python3.5/concurrent/futures/thread.py”, line 55, in run
result = self.fn(*self.args, **self.kwargs)
File “/usr/local/lib/python3.5/site-packages/homeassistant/components/switch/tplink.py”, line 110, in update
emeter_statics = self.smartplug.get_emeter_daily()
File “/home/.homeassistant/deps/lib/python3.5/site-packages/pyHS100/smartdevice.py”, line 417, in get_emeter_daily
for entry in response[‘day_list’]}
File “/home/.homeassistant/deps/lib/python3.5/site-packages/pyHS100/smartdevice.py”, line 417, in
for entry in response[‘day_list’]}

Firmware version according to the Kasa app is 1.2.10 and hardware version is 2.0

The new firmware is the reason. It apparently has changed the return values and this will require a fix in the library. I’ve already raised an issue about it.

Just to clarify - did you get your switch with firmware 2.0 or did you upgrade the firmware? So far I’ve seen only firmware 1.0.8.

Thanks for raising that issue - much appeciated. The switch came like that new. I live in NZ and bought it from a local tech store in Auckland just a few days ago. They had a whole bunch of them, so I expect they will all be the same.

Here’s what I get from mine, that is working :

get_emeter_realtime()
{‘current’: 0.025489, ‘voltage’: 238.855531, ‘total’: 0.454, ‘power’: 2.211675}

get_emeter_daily()
{1: 0.069, 2: 0.074, 3: 0.075, 4: 0.072, 5: 0.072, 6: 0.078, 7: 0.078, 8: 0.079, 9: 0.072, 10: 0.086, 11: 0.002, 12: 0, 13: 0.009, 14: 0.083, 15: 0.078, 16: 0.08, 17: 0.079, 18: 0.081, 19: 0.044}

hw_info
{‘oemId’: ‘EDITED’, ‘fwId’: ‘EDITED’, ‘hwId’: ‘EDITED’, ‘hw_ver’: ‘1.0’, ‘mac’: ‘EDITED’, ‘type’: ‘IOT.SMARTPLUGSWITCH’, ‘sw_ver’: ‘1.0.10 Build 160304 Rel.082646’, ‘dev_name’: ‘Wi-Fi Smart Plug With Energy Monitoring’}

So firmware 1.10, received like this, it’s an european model (FR plug) I got from Amazon.de.

Mine is an HS110(AU) apparently. I’ve noticed in the past that some manufacturers make first shipments of new stuff to this end of the world first. The cynic in me says that’s because if they break things, there aren’t so many people here to complain :slight_smile: If you happen to use the TP-LINK KASA app, does it show you a firmware update is available?

I have the same HS110(AU) that I just purchased from PB Tech in Auckland. Hardware version 2.0 and Firmware 1.2.10 our of the box. I have the same problem using Home Assistance 0.57.3.

snap - got mine from the same place

You can try that :wink: : tplink_custom.py
(save it as tplink.py, put it in <configuration dir>/custom_component/switch)

Quick fix, I supposed the modification is only adding ‘_<unit>’ after the keyword, so it now works for both firmware.
Not so quick : since the unit changed, I had to take that to return correct values…
Obviously I could only try it doesn’t break the old firmware…

Here is the part changed :

        if self.smartplug.has_emeter:
            emeter_readings = self.smartplug.get_emeter_realtime()
            for value in emeter_readings :
                try :
                    name, unit = value.split("_",1)
                    div = 100
                except ValueError:
                    name = value.split("_",1)[0]
                    div = 1
                if name == "power":
                    self._emeter_params[ATTR_CURRENT_CONSUMPTION] \
                        = "%.1f W" % (float(emeter_readings[value])/div)
                if name == "total":
                    self._emeter_params[ATTR_TOTAL_CONSUMPTION] \
                        = "%.2f kW" % (float(emeter_readings[value])/div)
                if name == "voltage":
                    self._emeter_params[ATTR_VOLTAGE] \
                        = "%.2f V" % (float(emeter_readings[value])/div)
                if name == "current":
                    self._emeter_params[ATTR_CURRENT] \
                        = "%.1f A" % (float(emeter_readings[value])/div)

That is really appreciated and I’ve popped the change into place (into custom_components with an s). In the log I can now see other warnings/errors. I’m not sure of what needs to be added to get_emeter_daily to pull out anything useful that might help with analysing that, but I’m certainly happy to give it a try!

Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/homeassistant/helpers/entity_component.py”, line 216, in async_add_entity
yield from entity.async_device_update(warning=False)
File “/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py”, line 309, in async_device_update
yield from self.hass.async_add_job(self.update)
File “/usr/lib/python3.6/asyncio/futures.py”, line 331, in iter
yield self # This tells Task to wait for completion.
File “/usr/lib/python3.6/asyncio/tasks.py”, line 244, in _wakeup
future.result()
File “/usr/lib/python3.6/asyncio/futures.py”, line 244, in result
raise self._exception
File “/usr/lib/python3.6/concurrent/futures/thread.py”, line 55, in run
result = self.fn(*self.args, **self.kwargs)
File “/config/custom_components/switch/tplink.py”, line 108, in update
emeter_statics = self.smartplug.get_emeter_daily()
File “/usr/lib/python3.6/site-packages/pyHS100/smartdevice.py”, line 417, in get_emeter_daily
for entry in response[‘day_list’]}
File “/usr/lib/python3.6/site-packages/pyHS100/smartdevice.py”, line 417, in
for entry in response[‘day_list’]}
KeyError: ‘energy’

It’s in the underlaying lib and I didn’t look at it before. Funny thing is that it already has a (partial) support of the unit put in the name of the sensor :

 if self.emeter_units:
    key = 'energy_wh'
else:
    key = 'energy'

This emeter_units boolean is only used twice and it is set to false in the smartdevice.py. It’s set to “true” in the pyHS100.py file, for the smartbulb init. So for the HS110, it remains to “false” though I guess the day list might come with an “energy_wh” answer with your firmware ??

I can’t test this, but if you set the smartplug.emeter_units to True before line 108, it could use the correct keyword in the library and then work.
I modified the custom component in this aim, and so it works with both firmwares, but I’m not at home and my device HS110 doesn’t connect to wifi since this morning, I’m not sure it hasn’t some error in it (added lines 92 and 96 to set the boolean depending on the returned keys from first call) : tplink.py

Anyway, it now appears that the nice and clean fix is in the pyHS100 library : set the emeter_units boolean depending on the firmware.

The tplink.py now has the 1 line mod shown below, if I have read the intention right:

            self.emeter_units = True
            emeter_statics = self.smartplug.get_emeter_daily()
            try:

The error message remains much the same as in:
Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/homeassistant/helpers/entity_component.py”, line 216, in async_add_entity
yield from entity.async_device_update(warning=False)
File “/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py”, line 309, in async_device_update
yield from self.hass.async_add_job(self.update)
File “/usr/lib/python3.6/asyncio/futures.py”, line 331, in iter
yield self # This tells Task to wait for completion.
File “/usr/lib/python3.6/asyncio/tasks.py”, line 244, in _wakeup
future.result()
File “/usr/lib/python3.6/asyncio/futures.py”, line 244, in result
raise self._exception
File “/usr/lib/python3.6/concurrent/futures/thread.py”, line 55, in run
result = self.fn(*self.args, **self.kwargs)
File “/config/custom_components/switch/tplink.py”, line 109, in update
emeter_statics = self.smartplug.get_emeter_daily()
File “/usr/lib/python3.6/site-packages/pyHS100/smartdevice.py”, line 417, in get_emeter_daily
for entry in response[‘day_list’]}
File “/usr/lib/python3.6/site-packages/pyHS100/smartdevice.py”, line 417, in
for entry in response[‘day_list’]}
KeyError: 'energy

Yes exactly the test I thought about.
Is your trace complete, because I expected “KeyError: ‘energy_wh’” at least.
If it is, shows that the boolean isn’t passed to the library, I can’t explain why. Also the smartplug object throws a KEY_ERROR exception, which should be caught in the ‘update’ method and the device should work, except for the long term stats not populated ?
Otherwise, it’s that the new firmware returns something else, beyond “energy” and 'energy_wh" for the long term statistics ?

Here’s what I get from the “old” firmware :

$ python -i tplink.py
>>> from pyHS100 import SmartPlug
>>> smart = SmartPlug(‘<your IP address’)
>>> smart
<SmartPlug at 192.168.7.60 (Prise_1), is_on: True - dev specific: {‘On since’: datetime.datetime(2017, 11, 22, 20, 4, 41, 296103), ‘LED state’: True}>

>>> smart.sys_info
defaultdict(<function SmartDevice.sys_info.<locals>.<lambda> at 0x7f46fe487510>, {'model': 'HS110(FR)', 'hw_ver': '1.0', 'type': 'IOT.SMARTPLUGSWITCH', 'on_time': 66583, 'hwId': 'EDITED', 'updating': 0, 'alias': 'Prise_1', 'icon_hash': '', 'latitude': EDITED, 'sw_ver': '1.0.10 Build 160304 Rel.082646', 'deviceId': 'EDITED', 'led_off': 0, 'longitude': EDITED, 'mac': 'EDITED', 'active_mode': 'schedule', 'rssi': -74, 'fwId': 'EDITED', 'oemId': 'EDITED', 'dev_name': 'Wi-Fi Smart Plug With Energy Monitoring', 'feature': 'TIM:ENE', 'relay_state': 1})
>>> smart._query_helper(smart.emeter_type, "get_daystat",{'month': 11, 'year': 2017})
{'day_list': [{'day': 1, 'energy': 0.069, 'month': 11, 'year': 2017}, {'day': 2, 'energy': 0.074, 'month': 11, 'year': 2017}, {'day': 3, 'energy': 0.075, 'month': 11, 'year': 2017}, {'day': 4, 'energy': 0.072, 'month': 11, 'year': 2017}, {'day': 5, 'energy': 0.072, 'month': 11, 'year': 2017}, {'day': 6, 'energy': 0.078, 'month': 11, 'year': 2017}, {'day': 7, 'energy': 0.078, 'month': 11, 'year': 2017}, {'day': 8, 'energy': 0.079, 'month': 11, 'year': 2017}, {'day': 9, 'energy': 0.072, 'month': 11, 'year': 2017}, {'day': 10, 'energy': 0.086, 'month': 11, 'year': 2017}, {'day': 11, 'energy': 0.002, 'month': 11, 'year': 2017}, {'day': 12, 'energy': 0, 'month': 11, 'year': 2017}, {'day': 13, 'energy': 0.009, 'month': 11, 'year': 2017}, {'day': 14, 'energy': 0.083, 'month': 11, 'year': 2017}, {'day': 15, 'energy': 0.078, 'month': 11, 'year': 2017}, {'day': 16, 'energy': 0.08, 'month': 11, 'year': 2017}, {'day': 17, 'energy': 0.079, 'month': 11, 'year': 2017}, {'day': 18, 'energy': 0.081, 'month': 11, 'year': 2017}, {'day': 19, 'energy': 0.084, 'month': 11, 'year': 2017}, {'day': 20, 'energy': 0.087, 'month': 11, 'year': 2017}, {'day': 21, 'energy': 0.084, 'month': 11, 'year': 2017}, {'day': 22, 'energy': 0.076, 'month': 11, 'year': 2017}, {'day': 23, 'energy': 0.045, 'month': 11, 'year': 2017}]}