Toon (eneco) integration with Home Assistant

@opdoffer the crash is expected. The session is being disconnected. That is what i am referring to as “automatic reauthentication” in the above post. I have added debugging looking into how to detect the de authentication and re request it transparently. This will take a few days as i need to wait for it to happen. I will fix it though i guess by next week and then we are golden.

If anyone on this thread has solar installed and wishes to contribute please raise your hand.

Hey guys, just committed everything to master and deleted the separate smart plug branch. Looks like we need some additional work on reauthentication. Could you not reauthenticate every 50th update? That’s a small overhead and should be well within the apparent session limit? I don’t mind waiting a few extra days though. There’s work to be done before we can submit, like testing with Tox and polishing up the documentation::

So if I understand correct the crash should not occur with your latest commit (without the smart plug). I can test that. If there’s anything I can help with, let me now.

Ok I tried it but got an error so I thought maybe it’s because I don’t have the latest HASS version so I upgraded to the latest version, but still I get this error:
17-04-25 22:32:33 ERROR (MainThread) [homeassistant.loader] Unable to find component toon
17-04-25 22:32:33 ERROR (MainThread) [homeassistant.setup] Setup failed for toon: Component not found.

I put
toon:
etc.
in the configuration.yaml, that’s the right place yes?
any idea how I can get it working?

I have a hassbian installation and I created the custom_components folder (it didn’t exist) in here “/home/homeassistant/.homeassistant/config” and created the subfolders climate, sensor and switch etc.

@PuckStar, create the custom_componente folder in /home/homeassistant/.homeassistant. Not in config

1 Like

I installed it as well. No errors here. Please recheck your config and paths. There should be a typo somewhere. Also note the correct toon.py is located in (I made the same mistake earlier):

docker
\config\custom_components\toon.py
\config\custom_components\climate\toon.py
\config\custom_components\sensor\toon.py
\config\custom_components\switch\toon.py

or hassbian
.homeassistant/custom_components\toon.py
.homeassistant/custom_components\climate\toon.py
.homeassistant/custom_components\sensor\toon.py
.homeassistant/custom_components\switch\toon.py

so you have to place 4 files in 4 folders. Mind the file in the root of custom_components

1 Like

Ok I put it there and now toonlib was indeed automatically installed :).

However in the hass log I get this:

17-04-25 23:05:36 ERROR (MainThread) [homeassistant.setup] Error during setup of component toon
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.4/site-packages/homeassistant/setup.py", line 192, in _async_setup_component
    None, component.setup, hass, processed_config)
  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 "/home/homeassistant/.homeassistant/custom_components/toon.py", line 34, in setup
    config['toon']['password'])
  File "/home/homeassistant/.homeassistant/custom_components/toon.py", line 62, in __init__
    self.update()
  File "/home/homeassistant/.homeassistant/custom_components/toon.py", line 66, in update
    self.data['power_current'] = self.toon.power.value
  File "/home/homeassistant/.homeassistant/deps/toonlib/toonlib.py", line 237, in power
    power = self._state['powerUsage']
  File "/home/homeassistant/.homeassistant/deps/cachetools/__init__.py", line 46, in wrapper
    v = func(*args, **kwargs)
  File "/home/homeassistant/.homeassistant/deps/toonlib/toonlib.py", line 174, in _state
    raise IncompleteResponse(state)

[edit] last record removed because it may contain sensitive data.
if needed for troubleshooting send me a PM and I can provide the record.

@costas and @krocat, you two deserve a big applause so far. I have tested and so far everything is working: state changes and manual input. I also use that in automation and scenes and works fine as well. And if tomorrow it doesn’t crash, I’m even more happy.

:clap::clap:

Good work guys and many thanks!!

1 Like

@puckstar you entered your credentials in configuration.yaml? like:

toon:
username: !secret toon_username
password: !secret toon_password

yep, and the fact that I see my custom named hue lights in the last long record gives me the impression that logging in also worked well.

it also shows the current temp and the set temp correctly in that record:
realSetpoint’: 1950,
‘currentTemp’: 1924

@krocat this is the incomplete respons from the webservice right? That should disappear within the next 5 or 10 minutes when a complete retrieval is successfull? Im I right?

@PuckStar, you probably need one more restart from HA and it should all work fine. The API is inconsistent in its response and sometimes does not supply all the information. To answer @opdoffer’s question: I’m not sure if the component will auto-recover from an incomplete exception. I think we should probably look into making the component more resilient. I’d hate to put a component out there with the instruction that if you get an error in the log, you need to restart HA.

@costas, what I’ve found so far is that when I get the incomplete response exception, my climate device fails to initiate. In an earlier response, you said that you would populate the cached data with whatever you get back from the API. I find it strange that the component would then fail to initialize. In Puckstar’s error, I see activeState, currentTemperature and currentSetpoint, that should be enough to get the climate device up, wouldn’t you agree? Any thoughts on why it would fail?

Good morning all!
I am very happy to see this thread picking up!

First things first! @opdoffer thank you very much for you kind words and I am sorry to disappoint you but it will definitely crash as I have not solved the deauthentication issue, still waiting debug from my testing platform. Not to worry it will happen but will probably take a week or so.

@krocat and @PuckStar about the IncompleteResponse exception. Some explanations on how it works and how to solve it.

So upon access of any attributes of the object the state tries to be updated. The api as said numerous times is inconsistent in both responses and sequence so it sends parts of the full state in random (as it appears) order. So i try three times and update the state by updating with whatever info i get on each call. I expect these
required_keys = (‘deviceStatusInfo’,
‘gasUsage’,
‘powerUsage’,
‘thermostatInfo’,
‘thermostatStates’)
and if any of them are not in I raise the exception. That would only happen of we don’t get the full information on the first call because after that it only overwrites values on the state with ones retrieved so if the api did not respond with some value there is the previous one in the state and that gets served. That was the history of it.

Solution:
Since we are not interested in the absolute validity of data but with the proper instantiation of the object and its longevity I will instantiate the object with a default state and remove the exception all together. If the api does not provide some value on the first call we will get the default value for that attribute. I will zero out counter values and None everything else so the HA component would not have to change. If anyone has any objections on this please speak now, or forever hold your piece :slight_smile:

@krokat It just dawned on me that we already have values for solar so we could make a sensor for it. In our case it would just be zeroed out. The relevant keys are :
‘maxSolar’: 0,
‘valueProduced’: 0,
‘valueSolar’: 0

So we could make a sensor that would only initialize if the valueSolar is not 0. Thoughts?
What we do miss is the smoke detector. So anyone on this thread with a smoke detector would you like to help out?

@PuckStar I would suggest you remove the log since there are some info there that could be considered personal if you have these kind of sensibilities.

Thanks @costas, that makes perfect sense. I was thinking we should add some configuration items in the configure.yaml for people to choose whether they want gas or solar. Not everyone has solar (yet) and homes on city heating etc. won’t have gas. Perhaps that might be better, right? If we don’t initialize the components (because of an incomplete response) the component has no way to recover once the data does start flowing in, or is that not what you mean?

Yeah sadly if the initial response is incomplete there is no way to know wether the info will be provided further on. From my testing i saw that the initial request provides the bulk of the info and all subsequent ones just small bits and pieces. It is very probable that there is some state kept server side based on the uuid that only updates values that have changed. I have added the default initialization but i will keep the exception in. We would only get the exception if anyone has tempered with the default dict so its just a safety measure now. I will push soon a new version.
As for the configuration items sure I am all for it. I just think that it would be even better if the components got created based on their existence without needed configuration. Like we do with the plugs. If you have them, they show up, if not meh…

What i mean is that we get the response whether the item exists or not. so there is a ‘smokeDetectors’: {}, in my state so we could dynamically identify the existence and not require configuration making it an easier process.

I also just saw the deviceConfigInfo where we can see wether a device is locked for switching or not. I will update the library with that too. How can we make the switch disabled if the device is locked on the component @krocat ?

@krocat version 0.3.0 handles the initialization of the state so we won’t get the exception any more. @PuckStar could you please check with that version?
This version also adds a .can_toggle boolean for lights and plugs so we could use that to disable the switch if its false. Any clue on how to do that in the component @krocat?