Judo water treatment

After I also managed to kill my working Judo water treatment integration because of updating Appdaemo to 0.15.2 i was reading and trying for 5 hours but I can’t get it back to work.
Appdaemon is starting with the follwing .log File, but there are no datas collected from my Softwell P and also there’s no Data coming into MQTT.

Here’s the log File.

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service base-addon-banner: starting

-----------------------------------------------------------
 Add-on: AppDaemon
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.15.2
 You are running the latest version of this add-on.
 System: Home Assistant OS 11.1  (amd64 / generic-x86-64)
 Home Assistant Core: 2023.11.2
 Home Assistant Supervisor: 2023.11.3
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service init-appdaemon: starting
Looking in indexes: https://pypi.org/simple, https://wheels.home-assistant.io/musllinux-index/
Requirement already satisfied: paho-mqtt in /usr/lib/python3.11/site-packages (1.6.1)
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
s6-rc: info: service init-appdaemon successfully started
s6-rc: info: service appdaemon: starting
s6-rc: info: service appdaemon successfully started
s6-rc: info: service legacy-services: starting
[00:55:04] INFO: Starting AppDaemon...
s6-rc: info: service legacy-services successfully started
2023-11-16 00:55:05.733724 INFO AppDaemon: AppDaemon Version 4.4.2 starting
2023-11-16 00:55:05.733881 INFO AppDaemon: Python version is 3.11.6
2023-11-16 00:55:05.734015 INFO AppDaemon: Configuration read from: /config/appdaemon.yaml
2023-11-16 00:55:05.734114 INFO AppDaemon: Added log: AppDaemon
2023-11-16 00:55:05.734180 INFO AppDaemon: Added log: Error
2023-11-16 00:55:05.734260 INFO AppDaemon: Added log: Access
2023-11-16 00:55:05.734353 INFO AppDaemon: Added log: Diag
2023-11-16 00:55:05.831841 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2023-11-16 00:55:05.920598 INFO HASS: HASS Plugin Initializing
2023-11-16 00:55:05.920698 WARNING HASS: ha_url not found in HASS configuration - module not initialized
2023-11-16 00:55:05.920834 INFO HASS: HASS Plugin initialization complete
2023-11-16 00:55:05.921078 INFO AppDaemon: Initializing HTTP
2023-11-16 00:55:05.921324 INFO AppDaemon: Using 'ws' for event stream
2023-11-16 00:55:05.922808 INFO AppDaemon: Starting API
2023-11-16 00:55:05.923842 INFO AppDaemon: Starting Admin Interface
2023-11-16 00:55:05.924024 INFO AppDaemon: Starting Dashboards
2023-11-16 00:55:05.930575 INFO HASS: Connected to Home Assistant 2023.11.2
2023-11-16 00:55:05.935428 INFO AppDaemon: App 'main_app' added
2023-11-16 00:55:05.936322 INFO AppDaemon: App 'hello_world' added
2023-11-16 00:55:05.936746 INFO AppDaemon: Found 2 active apps
2023-11-16 00:55:05.936904 INFO AppDaemon: Found 0 inactive apps
2023-11-16 00:55:05.937029 INFO AppDaemon: Found 0 global libraries
2023-11-16 00:55:05.937183 INFO AppDaemon: Starting Apps with 2 workers and 2 pins
2023-11-16 00:55:05.937678 INFO AppDaemon: Running on port 5050
2023-11-16 00:55:05.953583 INFO HASS: Evaluating startup conditions
2023-11-16 00:55:05.957758 INFO HASS: Startup condition met: hass state=RUNNING
2023-11-16 00:55:05.957930 INFO HASS: All startup conditions met
2023-11-16 00:55:05.976180 INFO AppDaemon: Got initial state from namespace default
2023-11-16 00:55:07.941109 INFO AppDaemon: Scheduler running in realtime
2023-11-16 00:55:07.944563 INFO AppDaemon: Adding /homeassistant/appdaemon/apps/ to module import path
2023-11-16 00:55:07.945107 INFO AppDaemon: Adding /homeassistant/appdaemon/apps/main to module import path
2023-11-16 00:55:07.950612 WARNING AppDaemon: No app description found for: /homeassistant/appdaemon/apps/main/messages_getjudo.py - ignoring
2023-11-16 00:55:07.951788 WARNING AppDaemon: No app description found for: /homeassistant/appdaemon/apps/main/config_getjudo.py - ignoring
2023-11-16 00:55:07.952882 INFO AppDaemon: Loading App Module: /homeassistant/appdaemon/apps/main/main_entity.py
2023-11-16 00:55:07.972989 WARNING AppDaemon: No app description found for: /homeassistant/appdaemon/apps/main/getjudo.py - ignoring
2023-11-16 00:55:07.973457 INFO AppDaemon: Loading app main_app using class main_loop from module main_entity
2023-11-16 00:55:07.974329 INFO AppDaemon: Calling initialize() for main_app
Lade gespeicherte Variablen
----------------------
Letzte Fehler-ID: 321363
Wasserverbrauch gestern: 0
Offset für heutigen Wasserverbrauch: 221712
Letzte Ausführung des Scripts: 15
da: 0x1
dt: 0x34
serial: 09532167a1ac
token: 0815x2
avergage regeneration interval: 0h
counter for avg-calc: 1
last regenerations count: 952
timestamp of last regeneration: 0s
Initialisierung erfolgreich!
2023-11-16 00:55:08.012375 INFO AppDaemon: App initialization complete

Trying Hennings Link ( 2. April) + my token is showing me the actual data from the Softwell.

Any ideas for me??

@gohakn

I can only say that my log looks the same but after “INFO AppDaemon: App initialization complete” it continues with

2023-11-15 18:54:30.353526 INFO AppDaemon: App initialization complete
Verbunden mit MQTT Broker...
Topics wurden abonniert...
Autoconfigs wurden gesendet...

So maybe you should check your MQTT settings again if everything is correct there?

If you tinkered with the files too much you could try replacing them with the originals from Github, make the 0.15.2 “adjustments”, insert your login data and try if it works then.

I am a newbie but eventually I managed to read the values in home assistant using the connectivity module…

sensor:

  # Judo i-soft safe+ sensors
  # in Case of more than 1 byte response we have to reorder to get little endian byte values
  - platform: rest
    name: "Hardness setpoint"
    unique_id: judo_hardness_setpoint
    resource: http://192.168.188.86/api/rest/5100
    method: GET
    authentication: basic
    username: "admin"
    password: "Connectivity"
    # 2 byte response
    value_template: "{{ (value_json.data[2:4] + value_json.data[0:2]) | int(base=16) }}"

  # Water consumed
  - platform: rest
    name: "Water consumed"
    unique_id: judo_water_consumed
    resource: http://192.168.188.86/api/rest/2800
    method: GET
    authentication: basic
    username: "admin"
    password: "Connectivity"
    # 4 byte response
    value_template: "{{((value_json.data[6:8] + 
                        value_json.data[4:6] + 
                        value_json.data[2:4] + 
                        value_json.data[0:2]) | int(base=16) )/1000}}"
    unit_of_measurement: m³
  - platform: rest
    name: "Soft Water consumed"
    unique_id: judo_soft_water_consumed
    resource: http://192.168.188.86/api/rest/2900
    method: GET
    authentication: basic
    username: "admin"
    password: "Connectivity"
    # 4 byte response
    value_template: "{{((value_json.data[6:8] + 
                        value_json.data[4:6] + 
                        value_json.data[2:4] + 
                        value_json.data[0:2]) | int(base=16) )/1000}}"
    unit_of_measurement: m³ 

I am absolutely sure, there is a better way to convert the byte values. But it works.

Of course, a real integration will be much more nicer

2 Likes

Please Test
http://192.168.188.86/api/rest/2900
http://192.168.188.86/api/rest/2800

Edit: Sorry the „2800“ and „2900“ you use :v:

:beers: 4 U & me…

Just one digit from the MQTT Portnumber was wrong…

2023-11-16 20:47:29.775829 INFO AppDaemon: App initialization complete
Verbunden mit MQTT Broker...
Topics wurden abonniert...
Autoconfigs wurden gesendet...
1 Like

Hey, I saw you solved that problem with the new update. My problem is similar - I did all from post of mike4001, but my appdaemon is in a always restart loop… message is that:

2023-11-17 14:09:40.063332 INFO AppDaemon: Loading App Module: /config/apps/hello.py
2023-11-17 14:09:40.139565 WARNING AppDaemon: No app description found for: /config/apps/main/config_getjudo.py - ignoring
2023-11-17 14:09:40.140508 INFO AppDaemon: Loading App Module: /config/apps/main/main_entity.py
2023-11-17 14:09:40.142952 WARNING AppDaemon: No app description found for: /config/apps/main/getjudo.py - ignoring
2023-11-17 14:09:40.143807 WARNING AppDaemon: No app description found for: /config/apps/main/messages_getjudo.py - ignoring
2023-11-17 14:09:40.144558 INFO AppDaemon: Loading app hello_world using class HelloWorld from module hello
2023-11-17 14:09:40.146293 INFO AppDaemon: Loading app main_app using class main_loop from module main_entity
2023-11-17 14:09:40.148361 INFO AppDaemon: Calling initialize() for hello_world
2023-11-17 14:09:40.255483 INFO hello_world: Hello from AppDaemon
2023-11-17 14:09:40.256611 INFO hello_world: You are now ready to run Apps!
2023-11-17 14:09:40.257561 INFO AppDaemon: Calling initialize() for main_app
Lade gespeicherte Variablen
----------------------
['Scriptfehler - Laden der Variablen aus Datei fehlgeschlagen in Zeile: 362', FileNotFoundError(2, 'No such file or directory')]
['Beende Script. Schwerwiegender Fehler in Zeile: 384', FileNotFoundError(2, 'No such file or directory')]
Verbunden mit MQTT Broker...
Topics wurden abonniert...
Autoconfigs wurden gesendet...
[14:09:40] INFO: Service AppDaemon exited with code 0 (by signal 0)
[14:09:41] INFO: Starting AppDaemon..

During all the tryings getting Judo back to life I did a lot of different things ending up ( like you) with a Appdaemon starting in a loop.

I followed “convicte’s” post GitHub and after correcting my wrong mqtt settings it’s working again.

Maybe this can help you too.

Thanks for the link - now I did a lot of new setup of some steps - it is working

Hey there,
I just came across your Judo implementation and wanted to give it a try. I implemented the AppDaemon way, and can connect to Judo API and also the script seems to initialize properly.
Output from AppDaemon.log:

2024-02-14 09:25:44.904945 INFO AppDaemon: Calling initialize() for main_app
Lade gespeicherte Variablen
----------------------
Letzte Fehler-ID: 458852
Wasserverbrauch gestern: 125
Offset für heutigen Wasserverbrauch: 368611
Letzte Ausführung des Scripts: 14
da: 0x1
dt: 0x33
serial: XXXXXXXX
token: XXXXXXXXXXX
avergage regeneration interval: 0h
counter for avg-calc: 1
last regenerations count: 733
timestamp of last regeneration: 1707885177s
Softwater prop. since Regeneration: 237.53L
Hardwater prop. since Regeneration: 131.153L
Initialisierung erfolgreich!
2024-02-14 09:25:44.961946 INFO AppDaemon: App initialization complete
Verbunden mit MQTT Broker...
Topics wurden abonniert...
Autoconfigs wurden gesendet...

The problem is, that no devices/entities are created in Homeassistant for MQTT. I checked the Mosquitto broker addon logs and can see successful client logins as soon as I start the AppDaemon config.

Secondly, it seems the app is hanging somewhere as I just get the initial log output, but no subsequent updates. So seems like the main_loop is not executed every 20 seconds.
I also ran the script from VScode commandline with same behavior. Initial polling suceeds, then no further updates.

Does anyone have an idea how to proceed troubleshooting?
Thanks much for your ideas.
Best Sebastian

Hi,

I am quite new to Home Assistant so please forgive me if I ask silly questions :slight_smile:

I have installed AppDaemon as HomeAssistant Addon, however there doesn’t appear the “app” folder to which I should copy the files for the Judo integration. If I manually create such a folder and copy the files, nothing happens either. And shouldn’t there be a link somewhere in the configuration.yaml file?

I have also tried to install AppDaemon directly on the Unraid NAS level and copy the files into the app folder there, but this doesn’t help either. In the “State” tab, a compile error for the main_loop is mentioned.

Can somebody please help me how to implement it correctly? Thank you very much in advance!

thanks for this solution! I successfully managed to get it to work again…
However I did not have to carry out the final step:

if RUN_IN_APPDEAMON == True:
TEMP_FILE = “/config/apps/main/temp_getjudo.pkl”

I simply had no “main” folder within …\apps.…
This just as a feedback from my side.
Again: Thanks for providing this step by step solution. Much appreciated!
Best, Frank

Hi @andromedavpn

I’m trying to get my Judo ZEWA i-safe filt api linked into HA. Used your code as a template and it workes great. However, some data isn’t pulling properly or at all. For example the daily water usage isn’t being pulled.

  - platform: rest 
    method: GET
    resource: http://192.168.0.133/api/rest/FB00{{ '%02X' % now().day }}{{ '%02X' % now().month }}{{ '%04X' % now().year }}
    name: "Wasserverbrauch heute"
    unique_id: judo_zewa_i-safe_filt_wasserverbrauch-heute
    authentication: basic
    username: "admin"
    password: "Connectivity"

The URL should be correct based on Judo’s documentation. And if I hard-code the variable part of the URL (which always inserts the current date) it also does not work. .So I do not think the problem is in the variable part of the url.

Any ideas? Thanks!!

I use this integration since a couple of weeks. Today I notices that sometimes the total water percentage switches for some seconds (not a complete minute) to zero (see picture).

In the protocol I can not find any suspicious entries.

Anyone an idea what the problem could be?

This is most likely a server-side issue.

And the integration does not filter it out …

I made a template sensor to avoid seeing this in my graphs

{% if float(states(‘sensor.judo_isoftsaveplus_haus_gesamtwasserverbrauch’)) > 10 %}
{{ states(‘sensor.judo_isoftsaveplus_haus_gesamtwasserverbrauch’) }}
{% endif %}

could you finde a solution?

Hi I am new here tow and struggling a little bit where to copy and include your yaml solution. Coud you give me a hint. I add all to the template.yaml besides others and get an error. A wrote a new one and put it to includes and ist doesnt work

You have to put it into the configuration.yaml.

Make sure that you only have one instance of “sensor:” Then you can add as many “- platform: rest” as you like.

Hello, this is an awesome possibility to connect Judo i-Soft Save + to Home Assistant. For me the AppDaemon solution was running for almost half a year without any issues. Since some days I cannot get it back to work. Following errors


Checking the getjudo.py all seems fine and correct.

In my browser I can access the JSON data with the link, of course replacing with correct token. I tried already other python requests. All the same error.
Does anyone have the same issue? Anyone an idea? Thanks in advance for any hints.

Hi,

I have the same problems since some days.

[‘Scriptfehler - Judo-login fehlgeschlagen in Zeile: 294’, JSONDecodeError(‘Expecting value: line 1 column 1 (char 0)’)]

The code seems to working correct. bit the request within phyton leads to a empty return.
login_response = http.request(‘GET’, f"https://www.myjudo.eu/interface/?group=register&command=login&name=login&user={username}&password={pwmd5}&nohash=Service&role=customer")

same request in browser showes the correct json.

Update: I found the solution

The judo-server now needs header information to answer correctly.

In getjudo.py codefile change following code:

add at declaration (beginning):

import requests

def judo_login(username, password):

headers = {
    'Connection': 'keep-alive',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}
login_response = requests.get(f"https://www.myjudo.eu/interface/?group=register&command=login&name=login&user={username}&password={pwmd5}&nohash=Service&role=customer", headers=headers)
#login_response = http.request('GET', f"https://www.myjudo.eu/interface/?group=register&command=login&name=login&user={username}&password={pwmd5}&nohash=Service&role=customer")
#login_response_json = json.loads(login_response.data)
login_response_json = login_response.json()

def send_command(index, data):

headers = {
    'Connection': 'keep-alive',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}
cmd_response = requests.get(f"https://www.myjudo.eu/interface/?group=register&command=login&name=login&user={username}&password={pwmd5}&nohash=Service&role=customer", headers=headers)
cmd_response_json = cmd_response.json()
#cmd_response = http.request('GET', f"https://www.myjudo.eu/interface/?token={mydata.token}&group=register&command=write%20data&serial_number={mydata.serial}&dt={mydata.dt}&index={index}&data={data}&da={mydata.da}&role=customer")
#cmd_response_json = json.loads(cmd_response.data)

def main():

headers = {
    'Connection': 'keep-alive',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}
response = requests.get(f"https://www.myjudo.eu/interface/?token={mydata.token}&group=register&command=get%20device%20data", headers=headers)
response_json = response.json()
#response = http.request('GET',f"https://www.myjudo.eu/interface/?token={mydata.token}&group=register&command=get%20device%20data")
#response_json = json.loads(response.data)
headers = {
    'Connection': 'keep-alive',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}
error_response = requests.get(f"https://myjudo.eu/interface/?token={mydata.token}&group=register&command=get%20error%20messages", headers=headers)
error_response_json = error_response.json()
#error_response = http.request('GET',f"https://myjudo.eu/interface/?token={mydata.token}&group=register&command=get%20error%20messages")
#error_response_json = json.loads(error_response.data)

Dear Stefan,

do you have (maybe) a copy-paste mistake in the above def send_command(index, data)?

Should your

cmd_response = requests.get(f"https://www.myjudo.eu/interface/?group=register&command=login&name=login&user={username}&password={pwmd5}&nohash=Service&role=customer", headers=headers)

not rather read

cmd_response = requests.get(f"https://www.myjudo.eu/interface/?token={mydata.token}&group=register&command=write%20data&serial_number={mydata.serial}&dt={mydata.dt}&index={index}&data={data}&da={mydata.da}&role=customer", headers=headers)

There was also a “false” blank in the line. With the suggested change implemented it is working again.

Thank you for the support
Andreas

1 Like