GadgetReactor / pyHS100

Python Library to control TPLink Switch (HS100 / HS110)
Other
409 stars 128 forks source link

New firmware breaks the energy meter #103

Closed kirichkov closed 6 years ago

kirichkov commented 6 years ago

As per this post it appears there’s a firmware 2.0 for the switches and it returns different keys for the emeter.

The keys appear to now include also the SI unit they return:

{‘total_wh’: 2, ‘voltage_mv’: 240645, ‘current_ma’: 22, ‘power_mw’: 0}
rytilahti commented 6 years ago

This is about a new hardware generation I think (looks like tplink's DE page offers v1 and v2 help: http://www.tp-link.de/download/HS110.html).

bremor commented 6 years ago

I can't code, but I have the HS110 which is experiencing this problem if you need someone to assist with testing or collecting output, etc.

rytilahti commented 6 years ago

We need the output from pyhs100 emeter and pyhs100 sysinfo (mask the longitude & latitude, IDs if you want).

bremor commented 6 years ago

I'm very new to this - I have hass.io installed, does this mean I don't have access to command line? Otherwise, could you please tell me how I can run those commands.?

kirichkov commented 6 years ago

I saw v3 on a TP-Link regional site as well! It includes a 1A USB output, same as V2 I think.

rytilahti commented 6 years ago

I think we could use the hardware version for detecting this change and adapting accordingly?

kirichkov commented 6 years ago

That might be possible, but it might also be the case that the old hardware revisions get the firmware update at some point in time.

iceymanz commented 6 years ago

I saw the request for output from the new version. So to that end: I have this device: http://static.tp-link.com/HS110(AU)_1.0-F_1484718874096p.jpg

Another new firmware bug: emeter and sysinfo crash with the following traceback if you do not specify --ip (--plug doesnt seem to matter)

== Emeter == Current state: {'voltage_mv': 248540, 'power_mw': 1312, 'total_wh': 4, 'current_ma': 30}

Traceback (most recent call last): File "/srv/homeassistant/bin/pyhs100", line 11, in sys.exit(cli()) File "/srv/homeassistant/lib/python3.4/site-packages/click/core.py", line 722, in call return self.main(args, kwargs) File "/srv/homeassistant/lib/python3.4/site-packages/click/core.py", line 697, in main rv = self.invoke(ctx) File "/srv/homeassistant/lib/python3.4/site-packages/click/core.py", line 1066, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/srv/homeassistant/lib/python3.4/site-packages/click/core.py", line 895, in invoke return ctx.invoke(self.callback, ctx.params) File "/srv/homeassistant/lib/python3.4/site-packages/click/core.py", line 535, in invoke return callback(args, **kwargs) File "/srv/homeassistant/lib/python3.4/site-packages/click/decorators.py", line 63, in new_func % object_type.name) RuntimeError: Managed to invoke callback without a context object of type 'SmartDevice' existing

sysinfo

== System info == {'active_mode': 'none', 'alias': 'Tplink Test', 'dev_name': 'Smart Wi-Fi Plug With Energy Monitoring', 'deviceId': '80062952E2F3D9461CFB91FF21B7868F194F627A', 'feature': 'TIM:ENE', 'fwId': '00000000000000000000000000000000', 'hwId': 'A28C8BB92AFCB6CAFB83A8C00145F7E2', 'hw_ver': '2.0', 'icon_hash': '', 'latitude_i': -xxxxx, 'led_off': 0, 'longitude_i': xxxxx, 'mac': '70:4F:57:xx:xx:xx', 'model': 'HS110(AU)', 'oemId': '6480C2101948463DC65D7009CAECDECC', 'on_time': 0, 'relay_state': 0, 'rssi': -70, 'sw_ver': '1.5.2 Build 171201 Rel.084625', 'type': 'IOT.SMARTPLUGSWITCH', 'updating': 0}

emeter output:

Current state: {'voltage_mv': 246520, 'power_mw': 258401, 'current_ma': 3104, 'total_wh': 387}

I can generate any other output as necessary.

iceymanz commented 6 years ago

Hello, is anyone working on this currently? Can I provide any samples, tests or examples to assist?

rytilahti commented 6 years ago

So, I propose that we create a container giving access to both types of keys (to keep API intact), and doing conversions where necessary (e.g. when accessing 'power_mw' on older firmwares, we just convert 'power' when it's accessed). Unfortunately I have no time to work on this at the moment, so if someone wants to step up and do the legwork, it would be great.

rytilahti commented 6 years ago

I just commited the initial fix for this issue, it would be nice if someone could try it out. This applies only to fetching the current consumption, reading of historical data is still broken for the time being.

I simply added a dict-based container which implements conversion based on the wanted key, that is, the existing keys keep working on also on the devices running newer firmwares without any changes.

dmshimself commented 6 years ago

With HA 0.62.1 I replaced the file and the error moves to the following:

Error while setting up platform tplink Traceback (most recent call last): File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py", line 189, in _async_setup_platform SLOW_SETUP_MAX_WAIT, loop=self.hass.loop) File "/usr/lib/python3.5/asyncio/tasks.py", line 400, in wait_for return fut.result() File "/usr/lib/python3.5/asyncio/futures.py", line 293, 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 "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/switch/tplink.py", line 38, in setup_platform from pyHS100 import SmartPlug File "/srv/homeassistant/lib/python3.5/site-packages/pyHS100/init.py", line 17, in from .smartplug import SmartPlug File "/srv/homeassistant/lib/python3.5/site-packages/pyHS100/smartplug.py", line 8, in from .. import SmartPlug, SmartDeviceException ValueError: attempted relative import beyond top-level package

craigcarps commented 6 years ago

I'm running HA 0.62.1 with TP-Link HS110(AU) Hardware Version 2.0 & Firmware Version 1.0.10 and I can confirm the component is still broken, below is the output my home-assistant.log file:

2018-02-06 19:25:58 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[0] }}) 2018-02-06 19:25:58 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[1] }}) 2018-02-06 19:26:16 ERROR (MainThread) [homeassistant.components.switch] tplink: Error on device update! Traceback (most recent call last): File "/srv/homeassistant/lib/python3.4/site-packages/homeassistant/helpers/entity_component.py", line 397, in _async_add_entity yield from entity.async_device_update(warning=False) File "/srv/homeassistant/lib/python3.4/site-packages/homeassistant/helpers/entity.py", line 308, in async_device_update yield from self.hass.async_add_job(self.update) File "/usr/lib/python3.4/asyncio/futures.py", line 388, in iter yield self # This tells Task to wait for completion. File "/usr/lib/python3.4/asyncio/tasks.py", line 286, in _wakeup value = future.result() File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result raise self._exception File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run result = self.fn(*self.args, **self.kwargs) File "/srv/homeassistant/lib/python3.4/site-packages/homeassistant/components/switch/tplink.py", line 105, in update = "{:.2f}".format(emeter_readings["power"]) KeyError: 'power' 2018-02-06 19:26:29 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[0] }}) 2018-02-06 19:26:29 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[1] }}) 2018-02-06 19:27:00 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[1] }}) 2018-02-06 19:27:00 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[0] }}) 2018-02-06 19:27:31 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[1] }}) 2018-02-06 19:27:31 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[0] }}) 2018-02-06 19:28:02 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[0] }}) 2018-02-06 19:28:02 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'dict object' has no attribute 'sn' (value: {"result":2}, template: {{ value_json.sn[1] }})

rytilahti commented 6 years ago

@dmshimself I don't know what sort of setup you are running, but if you look into the source code, there is no such line in the 0.3.0 version which is used by homeassistant: https://github.com/GadgetReactor/pyHS100/blob/0.3.0/pyHS100/smartplug.py#L8 .

@craigcarps

= "{:.2f}".format(emeter_readings["power"]) KeyError: 'power'

that looks like exactly what the linked PR #107 is supposed to fix. As I have no test device and no one has reported back on that PR, it has not been merged.

craigcarps commented 6 years ago

Hi Rytilahti

I've just had a look at the fix code and it appears that 1/3 system code checks has not passed tests, so I'm assuming that is why the code hasnt been merged back into source.

https://github.com/GadgetReactor/pyHS100/pull/107

I'm happy to do any testing, but is the user testing done pre or post getting a successful push back to source? Looks like most of the code changes were done to smartdevice.py. If I manually change the modified lines in my Hassbian install is that all that is needed to test the new code? (e.g. /srv/homeassistant/lib/python3.4/site-packages/pyHS100/smartdevice.py)

Craig

rytilahti commented 6 years ago

@craigcarps it hasn't been merged because I'm waiting for someone to test it, it's just a partial fix as it doesn't touch other functionality besides the current measurement (so no monthly/weekly/daily information).

To test you can either change the files manually or just simply install the branch with this command: pip install -U git+https://github.com/rytilahti/pyHS100.git@emeter_for_new_firmwares

dmshimself commented 6 years ago

@rytilahti - I'm using raspberian with a virtualenv setup as described here: https://home-assistant.io/docs/installation/raspberry-pi/

@craigcarps thanks for the steer on how to put this fix in properly. Just to be on the safe side, I reinstall 0.62.1 using :

pip install homeassistant==0.62.1 and then used your very handy command line to install the branch and rebooted. I now get the following if that helps.:

tplink: Error on device update! Traceback (most recent call last): File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py", line 397, in _async_add_entity yield from entity.async_device_update(warning=False) File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity.py", line 308, in async_device_update yield from self.hass.async_add_job(self.update) File "/usr/lib/python3.5/asyncio/futures.py", line 380, in iter yield self # This tells Task to wait for completion. File "/usr/lib/python3.5/asyncio/tasks.py", line 304, in _wakeup future.result() File "/usr/lib/python3.5/asyncio/futures.py", line 293, 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 "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/switch/tplink.py", line 113, in update emeter_statics = self.smartplug.get_emeter_daily() File "/srv/homeassistant/lib/python3.5/site-packages/pyHS100/smartdevice.py", line 449, in get_emeter_daily for entry in response['day_list']} File "/srv/homeassistant/lib/python3.5/site-packages/pyHS100/smartdevice.py", line 449, in for entry in response['day_list']} KeyError: 'energy'

rytilahti commented 6 years ago

@dmshimself only get_emeter_realtime is affected by that PR at the moment, could you please paste the output of pyhs100 emeter to see if the emeter values themselves are now fine?

dmshimself commented 6 years ago

Sure thing ...

No host name given, trying discovery.. Discovering devices for 3 seconds == My Smart Plug - HS110(AU) == Device state: ON Host/IP: 192.168.17.209 LED state: True On since: 2018-02-09 18:35:16.298092 == Generic information == Time: 2018-02-09 18:46:02 Hardware: 2.0 Software: 1.5.2 Build 171201 Rel.084625 MAC (rssi): 70:4F:57:FF:9D:D5 (-47) Location: {'longitude':xxx, 'latitude': -yyy} == Emeter == Current state: {'power_mw': 283233130, 'current_ma': 291751, 'total_wh': -1, 'voltage_mv': 970801}

Traceback (most recent call last): File "/srv/homeassistant/bin/pyhs100", line 11, in load_entry_point('pyHS100==0.3.0', 'console_scripts', 'pyhs100')() File "/srv/homeassistant/lib/python3.5/site-packages/click/core.py", line 722, in call return self.main(args, kwargs) File "/srv/homeassistant/lib/python3.5/site-packages/click/core.py", line 697, in main rv = self.invoke(ctx) File "/srv/homeassistant/lib/python3.5/site-packages/click/core.py", line 1066, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/srv/homeassistant/lib/python3.5/site-packages/click/core.py", line 895, in invoke return ctx.invoke(self.callback, ctx.params) File "/srv/homeassistant/lib/python3.5/site-packages/click/core.py", line 535, in invoke return callback(args, **kwargs) File "/srv/homeassistant/lib/python3.5/site-packages/click/decorators.py", line 63, in new_func % object_type.name) RuntimeError: Managed to invoke callback without a context object of type 'SmartDevice' existing (homeassistant) homeassistant@home-bob:/srv/homeassistant $

rytilahti commented 6 years ago

I just added the conversions for get_emeter_daily() and get_emeter_monthly(), so it should work now. Please test and report back, so we can get this merged and a new version published!

dmshimself commented 6 years ago

Sure thing I'd be happy to do that with some guidance - I'm running a standard virtual environment, so if you can point me at a way to apply to that, I'd be more than happy to do it.

austomaton commented 6 years ago

Hi,

Looks good with the new firmware:

get_sysinfo() {'sw_ver': '1.5.2 Build 171201 Rel.084625', 'hw_ver': '2.0', 'type': 'IOT.SMARTPLUGSWITCH', 'model': 'HS110(AU)', 'mac': 'B0:4E:26:76:0F:5D', 'dev_name': 'Smart Wi-Fi Plug With Energy Monitoring', 'alias': 'Fan', 'relay_state': 1, 'on_time': 34313, 'active_mode': 'schedule', 'feature': 'TIM:ENE', 'updating': 0, 'icon_hash': '', 'rssi': -57, 'led_off': 1, 'longitude_i': xxx, 'latitude_i': xxx, 'hwId': 'A28C8BB92AFCB6CAFB83A8C00145F7E2', 'fwId': '00000000000000000000000000000000', 'deviceId': '80067E7562B122BAF002596BDFC6D580198A0D2B', 'oemId': '6480C2101948463DC65D7009CAECDECC'}

get_emeter_realtime() {'voltage_mv': 243343, 'current_ma': 25, 'power_mw': 1304, 'total_wh': 1223}

get_emeter_daily() {1: 0.014, 2: 0.013, 3: 0.014, 4: 0.013, 5: 0.013, 6: 0.014, 7: 0.013, 8: 0.013, 9: 0.013, 10: 0.015, 11: 0.013, 12: 0.013, 13: 0.014, 14: 0.013, 15: 0.013, 16: 0.014, 17: 0.013, 18: 0.014, 19: 0.013, 20: 0.013, 21: 0.013, 22: 0.014, 23: 0.013, 24: 0.013, 25: 0.013, 26: 0.014, 27: 0.013, 28: 0.009}

get_emeter_daily(kwh = False) {1: 14, 2: 13, 3: 14, 4: 13, 5: 13, 6: 14, 7: 13, 8: 13, 9: 13, 10: 15, 11: 13, 12: 13, 13: 14, 14: 13, 15: 13, 16: 14, 17: 13, 18: 14, 19: 13, 20: 13, 21: 13, 22: 14, 23: 13, 24: 13, 25: 13, 26: 14, 27: 13, 28: 9}

get_emeter_monthly() {3: 0.394, 2: 0.069, 4: 0.391, 5: 0.37}

get_emeter_monthly(kwh = False) {3: 394, 2: 69, 4: 391, 5: 370}

Let me know if there is anything else you need me to test - thanks.

rytilahti commented 6 years ago

@dmshimself you can install the branch with pip install git+https://github.com/rytilahti/pyHS100.git@emeter_for_new_firmwares

@austomaton thanks, great to hear that. I hope I'll hear also from some people using mixed setups, but hopefully we'll have a new release during the next week & getting the homeassistant versions also bumped soon enough.

dmshimself commented 6 years ago

Cheers. I'm getting the following message when I try the install

pyHS100 requires Python '>=3.4' but the running Python is 2.7.13

I'm guessing this is because the 0.68.1 build I'm using hasn't updated itself to more recent versions of python. I know there are manual methods to upgrade, but I'm hoping this will be done as part of a new version at some point.

rytilahti commented 6 years ago

@dmshimself you are not probably running it inside your virtualenv of your installation, as homeassistant does not work with python2 either..

Anyway, I'm hoping we can get this fixed for homeassistant 0.70.1 or for 0.71 at latest.

dmshimself commented 6 years ago

Your were quite right - many thanks In case it helps, I took out anything in my custom_components folder, upgraded to 0.69.1 from 0.68.1, applied your change and restarted. I get the following displayed:

tplink: Error on device update!
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_platform.py", line 244, in _async_add_entity
    await entity.async_device_update(warning=False)
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity.py", line 327, in async_device_update
    yield from self.hass.async_add_job(self.update)
  File "/usr/lib/python3.5/asyncio/futures.py", line 380, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 304, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, 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 "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/switch/tplink.py", line 108, in update
    = "{:.2f}".format(emeter_readings["power"])
KeyError: 'power'
rytilahti commented 6 years ago

Are you definitely sure that you did run the command inside the correct virtualenv? That's the same old error that would happen when the fix is not in place.

dmshimself commented 6 years ago

I did an upgrade as in pip3 install --upgrade homeassistant pip3 install git+https://github.com/rytilahti/pyHS100.git@emeter_for_new_firmwares

and got the same result, but when I change applying the patch to be pip install --upgrade git+https://github.com/rytilahti/pyHS100.git@emeter_for_new_firmwares

then it bust into life, hurrah. The voltage shows 970.0, the current power w shows 283233.13 and the current a shows 291.75, so those look a bit off, but I can turn the switch on and off just fine which is a great result, many thanks.

insajd commented 6 years ago

Hello, I executed command that dmshimself has written, but my HS110 still doesn't seem to work. HA v 0.70 after this doesn't even try to load tplink. Executing

$ pyhs100 sysinfo
No host name given, trying discovery..
Discovering devices for 3 seconds
== Skateboard - HS110(EU) ==
Device state: ON
Host/IP: 192.168.4.16
On since: 2018-05-31 18:33:22.626473
LED state: True
== Generic information ==
Time:         2018-05-31 19:10:27
Hardware:     2.0
Software:     1.5.2 Build 180130 Rel.085820
MAC (rssi):   AC:84:C6:3B:xx:xx (-33)
Location:     {'longitude': xx, 'latitude': xx}
== Emeter ==
Current state: {'current_ma': 574, 'voltage_mv': 237888, 'power_mw': 84160, 'total_wh': 51}

Traceback (most recent call last):
  File "/home/homeassistant/hass/bin/pyhs100", line 11, in <module>
    sys.exit(cli())
  File "/home/homeassistant/hass/lib/python3.5/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/home/homeassistant/hass/lib/python3.5/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/home/homeassistant/hass/lib/python3.5/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/homeassistant/hass/lib/python3.5/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/homeassistant/hass/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/home/homeassistant/hass/lib/python3.5/site-packages/click/decorators.py", line 63, in new_func
    % object_type.__name__)
RuntimeError: Managed to invoke callback without a context object of type 'SmartDevice' existing

Can somebody suggest what I can do to make it work?

michaelblight commented 6 years ago

Is this included in 0.70.1? I just upgraded and am getting the same error. I originally installed HA last weeekend (yes, newbie) using the method from hasscasts which sets it up inside docker inside VirtualBox. I've not used docker before so I don't know how to apply the update to just pyHS100, which is why I was waiting for 0.70.1. I'm happy to test if somebody nurse me along.

UPDATE: I have installed portainer and logged into the homeassistant container as root (can't login as ha?), but when I try pip3 install --upgrade git+https://github.com/rytilahti/pyHS100.git@emeter_for_new_firmwares I get "no such file or directory 'git'", so clearly I have no idea what I'm doing. I would have thought I should log in as ha, but it says its not in the passwd file.

insajd commented 6 years ago

previusly I wrote that that branch didn't work for me, but I took all files manually from https://github.com/rytilahti/pyHS100/tree/emeter_for_new_firmwares/pyHS100, overwritten local files in HA for pyHS100, and it actually does work with TS110 👍

jtitley commented 6 years ago

Click the above link. As @insajd said, overwrite the two files with the versions in this commit. This will fix the issue until the next release.