Rademacher Homepilot (DuoFern) via http-Binding

Great, thanks !! It works now.

Christian

P.S.
For everybody, don’t do my mistake and install the Nashorn Javascript Version - this doesn’t work.

1 Like

Hi, thanks for these detailed descriptions!

While I am currently setting up openHAB 4.0.3 (openHABian on a Raspi 4 / 8GB) for my first time, I have quite some experience with scripting and smart home, maybe that’s why the roller shutter code as well as the evironmental sensor (UWS) worked within a day :smile:

For controlling our floor heating, I have several Rademacher 9485 wall thermostats / controllers installed.
API-wise (when looking at the JSON code the HomePilot (or smarthome-box, as it’s called since the last update) these guys look very similar to the radiator thermostats from the example - not too surprising I guess.

Correct me if I’m wrong, but the code of the example only reads the values (actual and setpoint temperature etc.) from the thermostat, it is not able to actually set values - or is it?

Did anyone already try to implement setting temperature values or activating one of the thermostat’s temperature presets? I would be curious to know! :slight_smile: :wink:

1 Like

Hi @Hundertvolt1 Nico,
thanks for your feedback and I am happy to hear that roller shutters are working for you.

Yes, you are right.
I also have some thermostats and would like to send commands from openHAB - but I didn’t had the time to implement it yet. I guess when it gets colder outside I will have more “pressure” to work on it :crazy_face:.
If you are faster we would be happy if you could share your code for sending commands to thermostats.

best, Kai

Worth a try, if I find time myself :smiley:

What item type would you suggest for the temperature setting?

I was totally surprised that openhab does not yet seem to natively have an item concept for thermostat controllers (as for e. g. dimmers and rollershutters). Or was I blindfolded?

Ideally it should provide a mixture between rollershutter and dimmer as commands - UpDown, Decimal, Refresh. I am thinking of a nice slider on the GUI which has adjustable upper and lower limits, the Rademacher devices have a range between 4 and 40 degrees, as far as I know.

Or is there a nice way to do so “just” using number:dimension?

for the position of a rollershutter we used number format in items file. So I assume for thermostats that should be fine too.

The current position of my Rademacher thermostats are readable and shown in openHAB from 40-280 (that seems to be the temperature deviced by 10 → 4,0°C - 28,0°C).
Position 40 means 4°C.

Reading of the current status is already possible, just the commandTransformation part is still missing:

Type number : Thermostat_Position [
   stateExtension="/v4/devices/55",
   stateTransformation="JSONPATH:$.device.statusesMap.Position",
   commandTransformation="JS:ThermostatPositionJSON.js", <-- this is still missing
   commandExtension="/devices/55"

When we check the device via http://homePilot-IP/v4/devices/55 I can see:

statusesMap	
   Manuellbetrieb	0
   Position	        40
   acttemperatur	212
visible	true
deviceNumber	    "35003xxx"
uid	                "e10xxx"
voiceControlledBy	""
origin	            "HomePilot"
batteryStatus	    28
batteryLow	        false
posMin	            40
posMax	            280
sceneConfig	
   0	            "DIRECT_FUNCTION_CMD"
   1	            "TARGET_TEMPERATURE_CFG"
   2	            "AUTO_MODE_CFG"

Means to me the new ThermostatPositionJSON.js (which you will work on :innocent:) need some adjustments. Instead of “GOTO_POS_CMD” (in RollerShutterPositionJSON.js) there need to be “TARGET_TEMPERATURE_CFG”, right?

RollerShutterPositionJSON.js:

(function(position){
    try{
        var obj = {name: "GOTO_POS_CMD", value: parseInt(position)};
        return (JSON.stringify(obj));
    } catch(e) {
        return null;
    }
})(input)

That need to be tested.

and during this conversation with @Hundertvolt1 I obviously solved it. My thermostat is now controllable with OH.
You need to send the target temperature (instead of the position) to the thermostat.

I try to summarize again:

item (in director /items):

Number Thermostat  "Thermostat"  {channel="http:url:HomePilot1:Thermostat"}

Things (in directory /things)

(...)
Type number : Thermostat [
   stateExtension="/v4/devices/55",
   stateTransformation="JSONPATH:$.device.statusesMap.Position",
   commandTransformation="JS:ThermostatJSON.js",
   commandExtension="/devices/55"

ThermostatJSON.js (in directory /transform)

(function(position){
    try{
        var obj = {name: "TARGET_TEMPERATURE_CFG", value: parseInt(position)};
        return (JSON.stringify(obj));
    } catch(e) {
        return null;
    }
})(input)

rule (in directory /rule)

(...)
Thermostat.sendCommand(19)     // =  19,0°C 

→ Rademacher thermostat can be controlled via openHAB too.
Does this work for you as well, @Hundertvolt1 ?

Haha, way too cool :smiley: thanks a lot already!

Have to try this as soon as possible. I’ll keep you updated!

Just one remark from looking at it - maybe the parseInt needs to be a bit adapted as the thermostats don’t just work in integer, but in 0.5deg increments.

Hey @April_Wexler,

I more or less copy-pasted your suggestions and did the adaptation to my system and can confirm it’s working fine for at least one of my wall thermo controllers. :smiley: :+1:

Somewhat funny that the sensor readings are formatted in degrees * 10 while the commands are “just” degrees. I wonder how a “half degree” (e.g. 20.5) may be commanded to the device, that was my thought in the previous post already…

Nevertheless, thanks for the really quick response and for making it work!!

On my course to make things work…

One more small question about switches. Also got tons of them installed :sweat_smile:
In your example (“Kueche_Abzugshaube”) I only see the command implementation, seems like there is no actual value reading so far.

I suppose a stateExtension and a stateTransformation are required here… in my HomePilot, I found the values at the usual places and tried an implementation:

       Type switch : Ventilator_Waschraum "Ventilator Waschraum" [  // Relay switch  DID=1010***
            stateExtension="/v4/devices/1010***",
            stateTransformation="JSONPATH:$.device.statusesMap.Position",
            commandExtension="/devices/1010***", //
            onValue="{\"name\":\"TURN_ON_CMD\"}",
            offValue="{\"name\":\"TURN_OFF_CMD\"}"
        ]

but so far this does not work correctly and I am getting an “UNDEF” as current status.
The values of statusesMap.Position is “0” for off and “100” for on. I hoped that OH would interpret 0 as off and >0 as on, but obviously it expects something else :wink:
Grateful for a little hint ^

Same as for shutters there are two things needed (at least it is working with that in my OH).
Reason is that the Status is a number, and the command is a switch:

Type switch : Abzugshaube [
      mode="WRITEONLY",
      commandExtension="/devices/27",
      onValue="{\"name\":\"TURN_ON_CMD\"}",
      offValue="{\"name\":\"TURN_OFF_CMD\"}"
      ]
Type number : AbzugshaubeStatus [
      stateExtension="/v4/devices/27",
      stateTransformation="JSONPATH:$.device.statusesMap.Position",
      commandTransformation="JS:RollerShutterPositionJSON.js",
      commandExtension="/devices/27"
      ]

I can see in my openHAB Log that Status changes from 0 (off) to 100 (on).
You are right, the commandTransformation is not working as it should for the hood in kitchen (German: “Abzugshaube”).
But for me it was still ok just to see status 0 or 100 - and can use that staus in rules.
Log:

2023-09-18 11:20:20.138 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AbzugshaubeStatus' changed from 0 to 100

Yes, the type (switch) and the 0 / 100 scheme are not compatible as such.
I think it should not be a real issue to convert the 0 / 100 thing into whatever the switch type needs, is it?

The only thing I did not find out is exactly what the switch type actually expects for the status (number in another range, boolean, string (with a certain content)…)

Do you by any chance know this or where I could find this information? Then it should be easy to write a script :wink:

Well… productive evening. :star_struck:

Maybe this is also interesting for you - I changed the ThermostatJSON.js in such a way that you can set values in 0.5 step quantization and it guarantees that any numerical input is put into this scheme:

(function(position){
    try{
        var obj = {name: "TARGET_TEMPERATURE_CFG", value: (Math.round(2.0 * parseFloat(position)) * 0.5)};
        return (JSON.stringify(obj));
    } catch(e) {
        return null;
    }
})(input)

Next thing which makes the values look nicer - currently, the Rademacher thermostat devices output the desired and actual measurement value in integer “degrees * 10”, which looks awkward in the GUI and makes value comparisons look strange. I solved this with concatenated transformations - the Thing definition:

        Type number : Heizung_Arbeitszimmer_Istwert "Heizung Arbeitszimmer Istwert" [   //DID=<myDID>
            stateExtension="/v4/devices/<myDID>",
            stateTransformation="JSONPATH:$.device.statusesMap.acttemperatur∩JS:toDegrees.js"
        ]
        Type number : Heizung_Arbeitszimmer_Sollwert "Heizung Arbeitszimmer Sollwert" [
            stateExtension="/v4/devices/<myDID>",
            stateTransformation="JSONPATH:$.device.statusesMap.Position∩JS:toDegrees.js",
            commandTransformation="JS:ThermostatJSON.js",
            commandExtension="/devices/<myDID>"
        ]

and with the toDegrees.js as such:

(function(x){
    try{
        return (x * 0.1).toFixed(1);
    } catch(e) {
        return null;
    }
})(input)

and, tadaa, we have degrees Celsius with one decimal place allover :smiley:

1 Like

Now, last for today, a partial success with the fan relay.

I finally found the definition of the on / off status here.

So I took the switch Thing and added a transformation as such:

       Type switch : Ventilator_Waschraum "Ventilator Waschraum" [  // Relay switch  DID=<myDID>
            stateExtension="/v4/devices/<myDID>",
            stateTransformation="JSONPATH:$.device.statusesMap.Position∩JS:toSwitch.js",
            commandExtension="/devices/<myDID>", //
            onValue="{\"name\":\"TURN_ON_CMD\"}",
            offValue="{\"name\":\"TURN_OFF_CMD\"}"
        ]

under the assumption that this will integrate the status and the control element into ONE thing.

The script toSwitch.js goes as such:

(function(x){
    try{
        if (x == 0) {
            return (OnOffType.from(false));
        }
        return ((OnOffType.from(true)));
    } catch(e) {
        return null;
    }
})(input)

…which works because the enum is automatically imported in the openHAB scope :partying_face:

I see that it’s working because in difference to before, the GUI element stays in the state I switch (instead of jumping back to UNDEF after one or two seconds), and there are no errors in the console log.

BUT: the switch state seems not to be updated with a regular interval, but only each time the switch element in the GUI is manually actuated, and only in this case there is a console log about a changed state. (Just to be sure I tried it without the concatenated transformation, which did not change anything about the updating behavior, but brought back the UNDEF state).

This is, uhm, not very nice, because I am using the internal timer function (“Treppenhausfunktion”) of the actuator, which automatically switches it off after 15 minutes. And OH would never notice this. :stuck_out_tongue_closed_eyes:

In two separate Things as suggested before this is not an issue, well, but this would again decouple the OH internal switch state variable from the real hardware, so no real win.

Now already being so close, I would be very happy to hear if anyone has an idea of how to convince OH to update the switch status on a regular poll (as all the other statuses…)

1 Like

thanks for that great work! I will check (and copy it to my OH) next weekend :slight_smile:

Hi, looking forward to your test results :slight_smile:

One more very important thing to note, especially if you have a very “full” Homepilot / smarthomebox.
If many values are requested from many locations (e.g. updating the set-point values of thermostats, which all have individual local URLs, and as they can change anytime triggered by different sources it absolutely makes sense to keep them up to date), the GET requests quickly get lost and end up in a timeout, as the Homepilot is simply overloaded.

I tried IOBroker some time before, and it happened there as well. Even in the documentation of their adapter, they claim to have some reading intervals hardcoded (!) there. :scream: No changes possible.

And they are updating any value of the HomePilot, so gigatons of requests in my case (80+ physical devices and 200+ virtual devices).
Actually, this disqualified IOBroker for my Homepilot.

Here, the “delay” setting in the Thing definition at the very beginning does the magic.

Thing http:url:HomePilot "HomePilot" [
    baseURL="http://192.168.85.5/",  //your HomePilot IP
    authMode="BASIC",
    ignoreSSLErrors="true",
    refresh=5,
    commandMethod="PUT",
    stateMethod="GET",
    contentType="application/json",
    timeout=3000,
    bufferSize=2048,
    delay=100
] 

Note the “delay=100” at the end. 100ms were just a first guess, probably you could even go shorter, but at least with this, the number of HTTP timeouts dropped from several hundred per minute to zero. Without any other drawbacks noted so far. :smiley:

One more “goodie” to go: The Thing definition for Rademacher Window and Door Contacts (9431).

        Type string : Fensterkontakt_Arbeitszimmer "Fensterkontakt Arbeitszimmer"[
        stateExtension="/v4/devices?devtype=Sensor",
        stateTransformation="JSONPATH:$.meters[?(@.did==<myDID>)].readings.contact_state"
        ]
        Type number : Fensterkontakt_Arbeitszimmer_Batt "Fensterkontakt Arbeitszimmer Batteriestatus"[
        stateExtension="/v4/devices?devtype=Sensor",
        stateTransformation="JSONPATH:$.meters[?(@.did==<myDID>)].batteryStatus"
        ]

This gives you the battery status (number 0…100) and the opening status as string with possible values “closed”, “tilted” and “open” (all lowercase).

Hi again :slight_smile:
I still have issues with timing - Although I have “only” 52 different stateExtensions at the moment, I get the error that 133 channels take way too long to refresh. I posted this here in another topic. Yet, I don’t know how it counts 133 channels. The channel count is over 250, the stateExtensions 52, as mentioned (but still growing). I have the impression that something is a bit awkward with the caching… but maybe my fault at another place. Help is appreciated :slight_smile:

Anyhow, maybe another kind of handling the issue with less HTTP requests.
I found that in addition to

http://<HomePilotIP>/v4/devices?devtype=Sensor

there is the address

http://<HomePilotIP>/v4/devices?devtype=Actuator
http://<HomePilotIP>/v4/devices?devtype=Scene
http://<HomePilotIP>/v4/devices?devtype=Trigger

Update
I thought this would be working as I found devtype=Actuator in various other forums.
Actually, meanwhile I found that only devtype=Sensor really yields a different result. Anything else, e.g. just http://<HomePilotIP>/v4/devices or even http://<HomePilotIP>/v4/devices?devtype=Foo has the same response from HomePilot. Unless somebody knows something else.

Nevertheless, this does not change what I mentioned before - requesting http://<HomePilotIP>/v4/devices gives you an overview of all actuators states, including setpoint and measurement values of the thermostats and seems to be very useful!

I just tried reading everything from http://<HomePilotIP>/v4/devices for a thermostat.
Generally it works, therefore having the potential of saving many HTTP requests for individual sensors.

        Type number : Heizung_Arbeitszimmer_Istwert "Heizung Arbeitszimmer Istwert" [   //DID=<myDID>
            //stateExtension="/v4/devices/<myDID>",
            //stateTransformation="JSONPATH:$.device.statusesMap.acttemperatur∩JS:toDegrees.js"
            stateExtension="/v4/devices",
            stateTransformation="JSONPATH:$.devices[?(@.did==<myDID>)].statusesMap.acttemperatur∩JS:toDegrees.js"

reading the actual value works great.

        Type number : Heizung_Arbeitszimmer_Sollwert "Heizung Arbeitszimmer Sollwert" [
            // stateExtension="/v4/devices/<myDID>",
            // stateTransformation="JSONPATH:$.device.statusesMap.Position∩JS:toDegrees.js",
            stateExtension="/v4/devices",
            stateTransformation="JSONPATH:$.devices[?(@.did==<myDID>)].statusesMap.Position∩JS:toDegrees.js"
            commandTransformation="JS:ThermostatJSON.js",
            commandExtension="/devices/<myDID>"
        ]

This is the previous (commented and known-working) and the current configuration. Unfortunately, I encountered a problem I knew before from the switches (see here) - it seems like if the stateExtension is different from the commandExtension, the state is no longer updated, at least unless a command is being sent. But no regular updates anymore.

I can’t imagine that this is intended, so either I did something wrong (help appreciated :slight_smile: ) or it may be worth investigating the OH code there :wink: