OStrama / weishaupt_modbus

This integration allows you to monitor and controll your weishaupt heatpump via modbus.
MIT License
21 stars 7 forks source link

Weishaupt Gas Heating support #43

Open dm82m opened 5 days ago

dm82m commented 5 days ago

Is your feature request related to a problem? Please describe. Hey guys, we were previously using a integration (https://github.com/erikkastelec/hass-WEM-Portal) that needs a wemportal.com paid account and then scrapes the heating data from the web portal aswell as the mobile api endpoint for the app. It worked well couple of years but now Weishaupt secured it more and is forbidding the automated data requests.

One user tested your integration and I did aswell. Even that we DO NOT HAVE bought the modbus module from Weishaupt it even works - at least half the way. So we can install the integration, it seems also to connect and shows several entities but they do not have a values.

Describe the solution you'd like It would be more than great, if you could try make the Weishaupt gas heaters also supported by your integration. If you would need local network access to the device or some modbus queries to be executed, just drop me a message.

Describe alternatives you've considered Sadly there is no alternative at the moment. So we are getting no data anymore with the old integration, there is no real solution in sight.

Additional context

image
dm82m commented 5 days ago

I did a bit more debugging and think, that your integration is not really checking for an existing endpoint. it just creates the entities and due to a missing endpoint they have no data.

cause if I use mbpoll to query the gas heating, I get no connection:

dirk.maucher@MAC-JY9QJFH75M ~ % mbpoll -m tcp -a 0 -r 100 -c 10 192.168.178.31
mbpoll 1.0-0 - ModBus(R) Master Simulator
Copyright (c) 2015-2023 Pascal JEAN, https://github.com/epsilonrt/mbpoll
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type 'mbpoll -w' for details.

mbpoll: Connection failed: Connection refused.

edit: so I would guess, that there is no modbus tcp endpoint, to get it you need to buy the modbus tcp module from weishaupt...

MadOne commented 5 days ago

Well thats interesting. Our integration checks for Connection and retrys 2 times. You should see Connection failed in the logs. Can you run this python script? https://github.com/OStrama/weishaupt_modbus/blob/main/custom_components%2Fweishaupt_modbus%2Ftest_modbus.py

You need to edit the ip in the Script

dm82m commented 5 days ago

how can I run the script within home assistant? tried to directly execute it on HA shell but throws me this:

➜  weishaupt_modbus git:(master) ✗ python test_modbus.py 
Traceback (most recent call last):
  File "/homeassistant/custom_components/weishaupt_modbus/test_modbus.py", line 1, in <module>
    import asyncio
  File "/usr/lib/python3.12/asyncio/__init__.py", line 8, in <module>
    from .base_events import *
  File "/usr/lib/python3.12/asyncio/base_events.py", line 24, in <module>
    import socket
  File "/usr/lib/python3.12/socket.py", line 55, in <module>
    import os, sys, io, selectors
  File "/usr/lib/python3.12/selectors.py", line 12, in <module>
    import select
  File "/homeassistant/custom_components/weishaupt_modbus/select.py", line 3, in <module>
    from homeassistant.config_entries import ConfigEntry
ModuleNotFoundError: No module named 'homeassistant'
MadOne commented 5 days ago

You need to run it locally

dm82m commented 5 days ago

locally on the 'homeassistant' container I get this:

Traceback (most recent call last):
  File "/config/custom_components/weishaupt_modbus/test_modbus.py", line 1, in <module>
    import asyncio
  File "/usr/local/lib/python3.12/asyncio/__init__.py", line 8, in <module>
    from .base_events import *
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 24, in <module>
    import socket
  File "/usr/local/lib/python3.12/socket.py", line 55, in <module>
    import os, sys, io, selectors
  File "/usr/local/lib/python3.12/selectors.py", line 12, in <module>
    import select
  File "/config/custom_components/weishaupt_modbus/select.py", line 3, in <module>
    from homeassistant.config_entries import ConfigEntry
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 32, in <module>
    from . import data_entry_flow, loader
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 21, in <module>
    from .core import HomeAssistant, callback
  File "/usr/src/homeassistant/homeassistant/core.py", line 96, in <module>
    from .util.async_ import (
  File "/usr/src/homeassistant/homeassistant/util/async_.py", line 5, in <module>
    from asyncio import (
ImportError: cannot import name 'AbstractEventLoop' from partially initialized module 'asyncio' (most likely due to a circular import) (/usr/local/lib/python3.12/asyncio/__init__.py)
MadOne commented 5 days ago

I ran it on my pc locally. Did not run in the ha Environment.

dm82m commented 5 days ago

okay, created a venv on my mac, installed pymodbus and started the script:

(test) dirk.maucher@MAC-JY9QJFH75M test % python test_modbus.py
/Users/dirk.maucher/Downloads/test/test_modbus.py:110: DeprecationWarning: There is no current event loop
  loop = asyncio.get_event_loop()
2024-11-17 12:10:18,606 DEBUG base:64 Connecting to 192.168.178.31:502.
2024-11-17 12:10:18,606 DEBUG transport:236 Connecting comm
2024-11-17 12:10:18,626 WARNING transport:244 Failed to connect [Errno 61] Connect call failed ('192.168.178.31', 502)
Traceback (most recent call last):
  File "/Users/dirk.maucher/Downloads/test/test_modbus.py", line 111, in <module>
    loop.run_until_complete(main())
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 721, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/Users/dirk.maucher/Downloads/test/test_modbus.py", line 72, in main
    if rr.isError():
       ^^
UnboundLocalError: cannot access local variable 'rr' where it is not associated with a value
dm82m commented 5 days ago

would say that my initial assumption was correct -> weishaupt device is not responding on port 502 - so no modbus tcp running!?

MadOne commented 5 days ago

At least there is no response. On the the heatpumps you have to enable Modus and whitelist ip / net for access. Maybe you have such an option? Some heatpumps have a local http server and a web frontend. Do you have something like this.

Fir enableing the webserver i needed the oem menu (code 21)

MrAhmalo commented 5 days ago

There is only a JSON Interface on the Weishaupt Heaters. Sadly no Modbus option in the settings.

MadOne commented 5 days ago

Perhaps we could implement the json reading. Can you perhaps share such a json?

dm82m commented 5 days ago

@MrAhmalo I enabled the json interface on my gas heating system. but I cant access it, so its not answering on all the ports I tested. the manual tells something like it should be accessible on port 80 an user/password is admin/Admin123 - have you had any success receiving json data?

MrAhmalo commented 4 days ago

@dm82m I got some interesting news. I was not able to access the JSON interface while the Heater is connected to my router. But connecting my PC via a LAN Cable directly to the heater worked. First, I did not know the new IP Address of the Heater, but http://wem-sg worked. There I saw just a simple network settings page for the heater. But using my browsers developer network inspection menu, I noticed, that the webpage accessed some JSON Endpoints.

Webpage: grafik

JSON Endpoints: grafik

Most of them were just some scripts for the webpage functionality, I think. But there was also a JSON Endpoint. (http://wem-sg/ajax/CanApiJson.json)

I was able to log in and get data via a python script, but it only responded with unreadable information. From what I understand, this JSON Endpoint is also only for the webpage functionality, but I might be wrong.

I just hope that there is some way to access the system by it.

Here is the python script I made:

import requests

# JSON URL
url = "http://wem-sg/ajax/CanApiJson.json"

# Login Data
username = "admin"
password = "Admin123"

response = requests.get(url, auth=(username, password))

data = response.json()

if response.status_code == 200:
    print(response.json())
else:
    print(f"Error: {response.status_code}")
dm82m commented 4 days ago

What answer do you get?

MadOne commented 4 days ago

I don't even get a connection. But i can login via browser: image

But with the following script i get an 404

import requests
# JSON URL
url = "http://10.10.1.225/ajax/CanApiJson.json"
# Login Data
username = "admin"
password = "Admin123"
response = requests.get(url, auth=(username, password))
print(response)

<Response [404]>

MrAhmalo commented 4 days ago

What answer do you get?

{"ID":"00000003","SRC":"SYS","CAPI":{"NN":6,"N01":{"VG":"020600250c01000100"},"N02":{"VG":"020600250c02000123"},"N03":{"VG":"020600250c0300017e"},"N04":{"VG":"020600250c040001ce"},"N05":{"VG":"020600250c05000159"},"N06":{"VG":"020600250c060001c1"}}}

MrAhmalo commented 4 days ago

@MadOne How could you log in and get this data page?

MadOne commented 4 days ago

I just open the ip in browser. (I am on an wbb heatpump)

MrAhmalo commented 4 days ago

Yeah the heaters are very different there

OStrama commented 4 days ago

Maybe, this helps a bit: https://github.com/erikkastelec/hass-WEM-Portal/issues/9 would it make sense to thest if such requests are possible directly? However, this is something completely different than the Modbus interface of the heatpumps. I'm not sure if we should merge this all together. On the other hand: One thing that I really miss on the Modbus IF is the programming of the heatpump's timer..

developer-stephan commented 4 days ago

{"ID":"00000003","SRC":"SYS","CAPI":{"NN":6,"N01":{"VG":"020600250c01000100"},"N02":{"VG":"020600250c02000123"},"N03":{"VG":"020600250c0300017e"},"N04":{"VG":"020600250c040001ce"},"N05":{"VG":"020600250c05000159"},"N06":{"VG":"020600250c060001c1"}}}

grafik

Interessante Ideen von ChatGPT

MadOne commented 3 days ago

Schaut mal hier: https://github.com/lairsdragon/nodered-weishaupt

OStrama commented 3 days ago

Yes, looks interesting. But do you think it would make sense to put this all in one integration?

MadOne commented 3 days ago

Yes i think so. There are so much possible sources (modbus, local webserver, json) and some devices share a subset of these. But not all sources deliver all information. For example modbus can not display the firmware version, the local webserver does. Some information on modbus are not correct (2.wez , IO,)

We for example could use modbus and some values of the webserver that we cant get from modbus. Modbus is fast and relieable, so a good choice for sensors. But now and then we could scrape the webserver for missing values.

The models without modbus could only use the local web scraping,

And we should not let down the guys with just a json response.

OStrama commented 2 days ago

OK, then it would make sense to enhance the class structure in a way that these other sources can be added conveniently via the item lists. Will be interesting ;-)

MadOne commented 1 day ago

I was thinking about making api_items additional to the Modbus_Items. The problem i see, is the update coordinator. We cant hammer the internal web server with so much requests as we can with modbus. I have to wait 10 sec between requests to get reliable responses. I think the best would be a second coordinator but im unsure if this is possible.

OStrama commented 1 day ago

We already have a few of them. For every device and I think sensor class a new one is created..

OStrama commented 1 day ago

I think the polling interval for the modbus items is 30 sec. For the api calls we should be able to do one call only for many entities..

MadOne commented 1 day ago

@OStrama Ah i see. Every platform creates its own coordinator. So we could easily create a coordinator for the api fetches.

@MrAhmalo Did you create a username and log in? I think this was the page i got before i created an account.