royduin / home-assistant-incomfort

:fire: Intergas InComfort integration with Home Assistant
MIT License
8 stars 4 forks source link

newer lan2rf gateway needs user/password #6

Closed Revaes closed 5 years ago

Revaes commented 5 years ago

Hi Roy,

Trying to use your plugin for HA. Recently acquired the lan2rf gateway,

Web interface version: |   | 1.3
Firmware version: |   | IC3-1-ICN-V1.17
Build date: |   | Sep 17 2018 00:08:00

With me, the http://IP/data.json?heater=0 returns a 404 error. I only seem to get json returned after logging in and requesting on http://IP/protect/data.json?heater=0

This however does not work with your script. I am not a regular python user, in Domoticz I got it to work by requesting http://user:password@192.168.X.X/protect/data.json?heater=0

However, trying that here (i replaced lines after urlopen 2x) but now get the following error:

Thu Mar 28 2019 21:12:48 GMT+0100 (Midden-Europese standaardtijd)
Error while setting up platform InComfort
Traceback (most recent call last):
  File "/usr/lib/python3.5/http/client.py", line 798, in _get_hostport
    port = int(host[i+1:])
ValueError: invalid literal for int() with base 10: 'pw@192.168.X.X'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/helpers/entity_platform.py", line 128, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT, loop=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 "/home/homeassistant/.homeassistant/custom_components/InComfort/climate.py", line 44, in setup_platform
    add_devices([InComfortThermostat(name, host)])
  File "/home/homeassistant/.homeassistant/custom_components/InComfort/climate.py", line 62, in __init__
    self.update()
  File "/home/homeassistant/.homeassistant/custom_components/InComfort/climate.py", line 151, in update
    response = urlopen('http://user:pw@192.168.X.X/protect/data.json?heater=0')
  File "/usr/lib/python3.5/urllib/request.py", line 163, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.5/urllib/request.py", line 466, in open
    response = self._open(req, data)
  File "/usr/lib/python3.5/urllib/request.py", line 484, in _open
    '_open', req)
  File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.5/urllib/request.py", line 1282, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/lib/python3.5/urllib/request.py", line 1223, in do_open
    h = http_class(host, timeout=req.timeout, **http_conn_args)
  File "/usr/lib/python3.5/http/client.py", line 762, in __init__
    (self.host, self.port) = self._get_hostport(host, port)
  File "/usr/lib/python3.5/http/client.py", line 803, in _get_hostport
    raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
http.client.InvalidURL: nonnumeric port: 'pw@192.168.X.X'

It seems like is reading the semicolon as the sign that a port number is incoming.

Are you able to help?

royduin commented 5 years ago

Can't reproduce this because I don't have the authentication. I'm running web interface version 1.1 and firmware version IC3-ICN-V1.12 from March 2016. Is it possible to update somehow? Maybe we've to contact Intergas about this.

royduin commented 5 years ago

About the semicolon, maybe there is another module in Home Assistant which support the basic authentication credentials in the url so we can check how they've done it? I'm a PHP developer not a Python developer.

Revaes commented 5 years ago

I will inquire Intergas on this question.

JayOne73 commented 5 years ago

You could try to do this:

urllib.urlopen("http://username:password@host.com/path") source

More info how to setup in the thread above this answer.

royduin commented 5 years ago

If @JayOne73 suggestion is working @Revaes, let me know so I can change it for everyone and document it. But a PR is also welcome.

JayOne73 commented 5 years ago

Here is example of a component with username/password settings set in the configuration.yaml: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/kodi/media_player.py. Because I'm also using the older rf-gateway I am not able to test this.

Revaes commented 5 years ago

You could try to do this:

urllib.urlopen("http://username:password@host.com/path") source

More info how to setup in the thread above this answer.

This was acutally the first thing I tried becaused that solved mij problem in domoticz. However with python the semicolon (:) seems to indicate that a port number is given, but the part after the : is not a number. Putting it like this produces this error:

http.client.InvalidURL: nonnumeric port: 'password@192.168.X.X'

JayOne73 commented 5 years ago

Within the kodi media player there is an authentication for images which is solved as below:

        if username is not None:
            kwargs['auth'] = aiohttp.BasicAuth(username, password)
            image_auth_string = "{}:{}@".format(username, password)
        else:
            image_auth_string = ""

        http_protocol = 'https' if encryption else 'http'
        ws_protocol = 'wss' if encryption else 'ws'

        self._http_url = '{}://{}:{}/jsonrpc'.format(http_protocol, host, port)
        self._image_url = '{}://{}{}:{}/image'.format(
            http_protocol, image_auth_string, host, port)
        self._ws_url = '{}://{}:{}/jsonrpc'.format(ws_protocol, host, tcp_port)

        self._http_server = jsonrpc_async.Server(self._http_url, **kwargs)
royduin commented 5 years ago

Any updates @Revaes? Did @JayOne73 his suggestion work? What did Intergas say?

Revaes commented 5 years ago

Received an e-mail from Intergas that they do not support home domotica, and therefore have not updated the API documentation to the latest gateway firmware version.

Intergas'reply:

Wij bieden op dit moment helaas geen verdergaande ondersteuning op het gebied van Domotica richting de eindgebruiker. Dit is ook de reden dat de documentatie die u ziet niet is bijgewerkt tot de laatste firmware versie van de gateway.

I haven't yet had time to try @JayOne73 suggestions.

royduin commented 5 years ago

I've asked Intergas if it's possible to update the InComfort (so I can reproduce the problem); their reaction in Dutch:

De LAN2RF gateways kunnen niet worden voorzien van een andere firmware. Updaten is dus niet mogelijk, daar is de hardware niet voor geschikt.

De nieuwere Incomfort Basis ii gateways (Intergas artikelnummer 032004) is daar wel op voorbereid maar daadwerkelijk updaten is ook daar nog niet mogelijk. Dit zit wel in de planning bij onze ontwikkelaars maar een indicatie van wanneer dit geïmplementeerd gaat worden heb ik helaas nog niet voor u.

Pretty bad if you ask me, what if there is a vulnerability in it and someone can control it? If I find myself some free time maybe I'm going to investigate this and see if the device is secure.

furian88 commented 5 years ago

Ok, so i've been playing around a bit with the code.

i managed to the code to auto login but receiving the next error: edit: receiving different errors as i try to play around :) the below is just 1 part of my tries.

Error while setting up platform InComfort
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/homeassistant/helpers/entity_platform.py", line 126, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT, loop=hass.loop)
  File "/usr/local/lib/python3.7/asyncio/tasks.py", line 416, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/InComfort/climate.py", line 46, in setup_platform
    add_devices([InComfortThermostat(name, host)])
  File "/config/custom_components/InComfort/climate.py", line 64, in __init__
    self.update()
  File "/config/custom_components/InComfort/climate.py", line 154, in update
    string = response.read().decode('utf-8')
AttributeError: 'Response' object has no attribute 'read'

change these lines: top:

import requests

bottom:

        requests.get('http://' + self.host + '/protect/data.json?heater=0&thermostat=0&setpoint=' +
                str((min(max(temperature, 5), 30) - 5.0) * 10), auth=('admin', 'intergas'))
        self._target_temperature = temperature

    def update(self):
        """Get the latest data."""
        response = requests.get('http://' + self.host + '/protect/data.json?heater=0', auth=('admin', 'intergas'))
        string = response.read().decode('utf-8')
        self.data = json.loads(string)
Revaes commented 5 years ago

Great to hear you are making progress Furian, you are on the newer firmware as well?

I hope to get in some time next weekend to try some stuff.

@royduin It is really disturbing that updates to the firmware are not possible, especially since you cannot block trafic to the gateway because all normal phone app commands go through the Intergas servers.

furian88 commented 5 years ago

yeah its getting somewhere.. (its my first time actually doing something like this.. :) )

i am indeed using a newer firmware, mine is from September.

Web interface version:   1.3
Firmware version:   IC3-2-ICN-V1.17
Build date:   Sep 17 2018 00:08:00

current error remaining:

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/homeassistant/helpers/entity_platform.py", line 365, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/local/lib/python3.7/site-packages/homeassistant/helpers/entity.py", line 225, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/local/lib/python3.7/site-packages/homeassistant/helpers/entity.py", line 248, in _async_write_ha_state
    state = self.state
  File "/config/custom_components/InComfort/climate.py", line 70, in state
    if bool(self.data['IO'] & 8):
TypeError: string indices must be integers
furian88 commented 5 years ago

Boom! it works! (have not tried modifying the input though, but it reads the info from our CV)

i added the climate.py to this post as a .txt (modify the username/password offcourse to your own) climate.py.txt .

royduin commented 5 years ago

Awesome, great work @furian88. It would be nice if we could make this optional and configurable from the configuration.yaml, something like:

climate:
  - platform: InComfort
    name: Woonkamer
    host: 192.168.1.123
    auth: true
    username: admin
    password: intergas

Where auth defaults to false. It would be nice to get a pull request for that.

furian88 commented 5 years ago

that would be awsome indeed and should be possible i guess. i'm leaving it how it is though :) 2 much trouble getting it so far haha.

i also tried modifying the temp, this works without issues! I added the sensor as last, this also works like a charm.

royduin commented 5 years ago

I've implemented it here: https://github.com/royduin/home-assistant-incomfort/blob/auth/climate.py, can you guys @furian88 and @Revaes test this? Just add auth: true to the configuration and in case the username and password are anything other than admin and intergas you can specify them with the username and password options. To see the changes: https://github.com/royduin/home-assistant-incomfort/pull/7/files

furian88 commented 5 years ago

wow that looks a lot better then how i made it haha :)

edit: works fine for me!

royduin commented 5 years ago

Thanks for testing! Waiting for @Revaes, if it's also working for him I'll merge the PR and create a new release.

Revaes commented 5 years ago

It works llike a charm @royduin . Thank you for helping me out!

JayOne73 commented 5 years ago

Although I'm using the first edition of the gateway I also confirm that the changes has no effect on my setup so far.

royduin commented 5 years ago

Good to hear @Revaes and @JayOne73. PR is merged and a new versions is tagged.