Integration of a Judo "i-soft plus" water-softener into openHAB

The purpose of this topic is to provide a possibility to intergrate the Judo “i-soft plus” water-softener into openHAB. The screnshot shows the relevant parameters in BasicUI used for PC and iPhone.

Am a Windows11 user and run OH 5.2.0-SNAPSHOT #5309.

The judo.items file looks like following:

Number residual_hardness_setpoint

Switch Curl_Judo_WasserstoppVentil     "Wasserstopp-Ventil"

String water_current         "Wasserverbrauch aktuell"
String water_total        "Wasser gesamt"
String water_average        "Durchschnittlicher Wasserverbrauch [%1$s l]"
String actual_quantity        "aktueller Verbrauch"
String salt_quantity        "Salzmenge [%1$s g]"
String salt_range        "Salzreichweite [%1$s Tage]"
String residual_hardness    "eingestellte Härte [%1$s °d]"
String natural_hardness        "Natürliche Härte [%1$s °d]"
String valve            "Wasserstopventilstatus"
String standby "Standby"
String vacation	"Ferienmodus"
String abstraction_time "Abstraktionszeit"
String quantity "Abnahmemenge"
String flow_rate "Durchfluss Grenzwert"    
Number rawwater            "verbrauchtes Rohwasser [%1$s l]"
Number decarbonatedwater    "verbrauchtes entkalktes Wasser [%1$s l]"

String software_version "Software Version [%1s]"
String hardware_version "Hardware Version [%1s]"
String notice_event "Event Message [%1s]"
Number service_date "Service Datum [%1s]"
String service_date_time "Service Datum [%1s]"
Number next_service_date "Nächster Service [%1s]"
String next_service_date_time "Nächster Service [%1s]"
Number actual_date "Letzte Daten [%1s]"
String actual_date_time "Letzte Daten [%1s]"

DateTime water_total_update "[%1$tm/%1$td %1$tH:%1$tM]"

In order to read out the Judo “i-soft plus” data, i run a command_judo.bat using a cron rule every 30 minutes. CURL and JQ (jQuery) commands are used in order to retrieve the required data. CURL is used to send a request to the water-softener and JQ is used to extract the desired parameter from the response string. Response string and final value are both stored within .txt files for further processsing

Cron rule:

rule "Judo i-Soft Wasserenthärter alle 30 Minuten auslesen"
	when
		Item residual_hardness_setpoint changed or
//		Item Curl_Judo_WasserstoppVentil changed or
		Time cron "0 30/60 * 1/1 * ? *"
	then
		executeCommandLine("C:\\openHAB3\\userdata\\Judo\\login_judo.bat")
		Thread.sleep(30000)
		executeCommandLine(Duration.ofSeconds(180), "C:\\openHAB3\\userdata\\Judo\\command_judo.bat")
end

This also requires to pull a token for each login using the login_judo.bat:

cd..
cd C:\openHAB3\userdata\Judo
curl -o token_string.txt "https://192.168.1.123:8124?group=register&command=login&msgnumber=2&name=login&user=XXXXXX&password=YYYYYY&role=customer" --insecure
Timeout /T 5
jq -r ".token" token_string.txt > token.txt
Timeout /T 3
set /p TOKEN=< token.txt
echo %TOKEN%
curl -o connect_string.txt "https://192.168.1.123:8124?group=register&command=connect&msgnumber=5&token=%TOKEN%&parameter=i-soft+plus&serial+number=193902" --insecure
Timeout /T 3
jq -r ".status" connect_string.txt > status.txt
set /p STATUS=< status.txt
echo %STATUS%

The content of the command_judo.bat file is:

cd..
cd C:\openHAB3\userdata\Judo
set /p TOKEN=< token.txt
echo %TOKEN%

curl -o natural_hardness_string.txt "https://192.168.1.123:8124?group=info&command=natural+hardness&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" natural_hardness_string.txt > natural_hardness.txt
Timeout /T 2
set /p NATURAL_HARDNESS=< natural_hardness.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%NATURAL_HARDNESS%" "http://192.168.1.137:8080/rest/items/natural_hardness"

curl -o residual_hardness_string.txt "https://192.168.1.123:8124?group=settings&command=residual+hardness&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" residual_hardness_string.txt > residual_hardness.txt
Timeout /T 2
set /p RESIDUAL_HARDNESS=< residual_hardness.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%RESIDUAL_HARDNESS%" "http://192.168.1.137:8080/rest/items/residual_hardness"

curl -o water_total_string.txt "https://192.168.1.123:8124?group=consumption&command=water+total&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" water_total_string.txt > water_total.txt
Timeout /T 2
set /p WATER_TOTAL=< water_total.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%WATER_TOTAL%" "http://192.168.1.137:8080/rest/items/water_total"

curl -o water_current_string.txt "https://192.168.1.123:8124?group=consumption&command=water+current&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" water_current_string.txt > water_current.txt
Timeout /T 2
set /p WATER_CURRENT=< water_current.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%WATER_CURRENT%" "http://192.168.1.137:8080/rest/items/water_current"

curl -o water_average_string.txt "https://192.168.1.123:8124?group=consumption&command=water+average&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" water_average_string.txt > water_average.txt
Timeout /T 2
set /p WATER_AVERAGE=< water_average.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%WATER_AVERAGE%" "http://192.168.1.137:8080/rest/items/water_average"

curl -o salt_quantity_string.txt "https://192.168.1.123:8124?group=consumption&command=salt+quantity&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" salt_quantity_string.txt > salt_quantity.txt
Timeout /T 2
set /p SALT_QUANTITY=< salt_quantity.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%SALT_QUANTITY%" "http://192.168.1.137:8080/rest/items/salt_quantity"

curl -o salt_range_string.txt "https://192.168.1.123:8124?group=consumption&command=salt+range&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" salt_range_string.txt > salt_range.txt
Timeout /T 2
set /p SALT_RANGE=< salt_range.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%SALT_RANGE%" "http://192.168.1.137:8080/rest/items/salt_range"

curl -o standby_string.txt "https://192.168.1.123:8124?group=waterstop&command=standby&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" standby_string.txt > standby.txt
Timeout /T 2
set /p STANDBY=< standby.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%STANDBY%" "http://192.168.1.137:8080/rest/items/standby"

curl -o vacation_string.txt "https://192.168.1.123:8124?group=waterstop&command=vacation&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" vacation_string.txt > vacation.txt
Timeout /T 2
set /p VACATION=< vacation.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%VACATION%" "http://192.168.1.137:8080/rest/items/vacation"

curl -o valve_string.txt "https://192.168.1.123:8124?group=waterstop&command=valve&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" valve_string.txt > valve.txt
Timeout /T 2
set /p VALVE=< valve.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%VALVE%" "http://192.168.1.137:8080/rest/items/valve"

curl -o flowrate_string.txt "https://192.168.1.123:8124?group=waterstop&command=flow+rate&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" flowrate_string.txt > flowrate.txt
Timeout /T 2
set /p FLOWRATE=< flowrate.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%FLOWRATE%" "http://192.168.1.137:8080/rest/items/flow_rate"

curl -o quantity_string.txt "https://192.168.1.123:8124?group=waterstop&command=quantity&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" quantity_string.txt > quantity.txt
Timeout /T 2
set /p QUANTITY=< quantity.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%QUANTITY%" "http://192.168.1.137:8080/rest/items/quantity"

curl -o abstraction_time_string.txt "https://192.168.1.123:8124?group=waterstop&command=abstraction+time&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" abstraction_time_string.txt > abstraction_time.txt
Timeout /T 2
set /p ABSTRACTIONTIME=< abstraction_time.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%ABSTRACTIONTIME%" "http://192.168.1.137:8080/rest/items/abstraction_time"

curl -o actual_quantity_string.txt "https://192.168.1.123:8124?group=consumption&command=actual+quantity&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" actual_quantity_string.txt > actual_quantity.txt
Timeout /T 2
set /p ACTUALQUANTITY=< actual_quantity.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%ACTUALQUANTITY%" "http://192.168.1.137:8080/rest/items/actual_quantity"

curl -o software_version_string.txt "https://192.168.1.123:8124?group=version&command=software+version&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" software_version_string.txt > software_version.txt
Timeout /T 2
set /p SOFTWAREVERSION=< software_version.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%SOFTWAREVERSION%" "http://192.168.1.137:8080/rest/items/software_version"

curl -o hardware_version_string.txt "https://192.168.1.123:8124?group=version&command=hardware+version&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" hardware_version_string.txt > hardware_version.txt
Timeout /T 2
set /p HARDWAREVERSION=< hardware_version.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%HARDWAREVERSION%" "http://192.168.1.137:8080/rest/items/hardware_version"

curl -o notice_event_string.txt "https://192.168.1.123:8124?group=register&command=notice+of+event&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" notice_event_string.txt > notice_event.txt
Timeout /T 2
set /p NOTICEOFEVENT=< notice_event.txt
Timeout /T 2
curl -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "%NOTICEOFEVENT%" "http://192.168.1.137:8080/rest/items/notice_event"

curl -o service_date_string.txt "https://192.168.1.123:8124?group=contract&command=service+date&msgnumber=1&token=%TOKEN%" --insecure
Timeout /T 4
jq -r ".data" service_date_string.txt > service_date.txt
Timeout /T 2
jq -r ".tftStarted" service_date_string.txt > actual_date.txt
Timeout /T 2
powershell ".\Epoch_Datetime.ps1"

The last line executes a Windows Powershell file Epoch_Datetime.ps1 in order to convert the service date from Epoch to Datetime:

$EPOCH=Get-Content -PATH .\service_date.txt
$EPOCH_ms=[int]"$EPOCH"*1000
$NEXTSERVICEDATE=$EPOCH_ms+31536000000
$response = Invoke-RestMethod 'http://192.168.1.137:8080/rest/items/service_date' -Method Post -Body $EPOCH_ms -ContentType 'text/plain'
$response2 = Invoke-RestMethod 'http://192.168.1.137:8080/rest/items/next_service_date' -Method Post -Body $NEXTSERVICEDATE -ContentType 'text/plain'
$EPOCHA_ms=Get-Content -PATH .\actual_date.txt
$response3 = Invoke-RestMethod 'http://192.168.1.137:8080/rest/items/actual_date' -Method Post -Body $EPOCHA_ms -ContentType 'text/plain'
EXIT

Extra functions are to open and close the water valve by execution of the following batch files.

watervalve_open.bat:

cd..
cd C:\openHAB3\userdata\Judo
curl -o token_string.txt "https://192.168.1.123:8124?group=register&command=login&msgnumber=2&name=login&user=XXXXXX&password=YYYYYY&role=customer" --insecure
Timeout /T 5
jq -r ".token" token_string.txt > token.txt
Timeout /T 3
set /p TOKEN=< token.txt
echo %TOKEN%
curl -o connect_string.txt "https://192.168.1.123:8124?group=register&command=connect&msgnumber=5&token=%TOKEN%&parameter=i-soft+plus&serial+number=193902" --insecure
Timeout /T 3
jq -r ".status" connect_string.txt > status.txt
set /p STATUS=< status.txt
echo %STATUS%

curl -i "https://192.168.1.123:8124/?group=waterstop&command=valve&msgnumber=1&token=%TOKEN%&parameter=open" --insecure

watervalve_close.bat:

cd..
cd C:\openHAB3\userdata\Judo
curl -o token_string.txt "https://192.168.1.123:8124?group=register&command=login&msgnumber=2&name=login&user=XXXXXX&password=YYYYYY&role=customer" --insecure
Timeout /T 5
jq -r ".token" token_string.txt > token.txt
Timeout /T 3
set /p TOKEN=< token.txt
echo %TOKEN%
curl -o connect_string.txt "https://192.168.1.123:8124?group=register&command=connect&msgnumber=5&token=%TOKEN%&parameter=i-soft+plus&serial+number=193902" --insecure
Timeout /T 3
jq -r ".status" connect_string.txt > status.txt
set /p STATUS=< status.txt
echo %STATUS%

curl -i "https://192.168.1.123:8124/?group=waterstop&command=valve&msgnumber=1&token=%TOKEN%&parameter=close" --insecure

Rules to run these 2 batch files:

rule "Judo i-Soft Wasserstopp-Ventil OPEN"
	when
		Item Curl_Judo_WasserstoppVentil received command ON
	then
		executeCommandLine("C:\\openHAB3\\userdata\\Judo\\watervalve_open.bat")
		Thread.sleep(2000)
end

rule "Update Zustand Judo i-Soft Wasserstopp-Ventil OPENED"
	when
		Item Curl_Judo_WasserstoppVentil received command ON
	then
		postUpdate(valve, "Opened")
end

rule "Judo i-Soft Wasserstopp-Ventil CLOSE"
	when
		Item Curl_Judo_WasserstoppVentil received command OFF
	then
		executeCommandLine("C:\\openHAB3\\userdata\\Judo\\watervalve_close.bat")
		Thread.sleep(2000)
end

rule "Update Zustand Judo i-Soft Wasserstopp-Ventil CLOSED"
	when
		Item Curl_Judo_WasserstoppVentil received command OFF
	then
		postUpdate(valve, "Closed")
end

It is not a very comfortable way to read out the machine parameters but its running here very reliably since a couple of years and is independend from openHAB versions and upgrades.

I hope, that it might help other users.

1 Like