Switch type in HTTP binding not updating status

I am using openHAB 4.0.3 as openHABian in a RasPi 4.

Using the HTTP binding for a connection with a Rademacher HomePilot, I found something strange about the “switch” type. Generally, there are various relay actuators in the Rademacher range, and their API access is “the usual stuff”: One current-status variable, one command for on, one for off. So far, so simple.

These switches have different sources to be operated from - automatization, manual interaction, etc. One way, among others, should of course be via the OH GUI and the OH rules. Therefore, it would be extremely useful if OH does not only issue commands and internally stores the last one, but also actively reads the current “real” status of the switch - something I would have expected as “so normal” to be of course existing already, but I found it to be different - at least from my observations.

It seems like the status of the switch is only read after a command was issued, but not on the configured regular timebase of the binding.
The status of the switch in the API is “0” for off and “100” for on, by the way. So a transformation is needed.

I tested this with three different configurations.

  1. Just read the status as a standalone string variable.
  - id: Schalter_NL_Flur_2_Status
    channelTypeUID: http:string
    label: Schalter Nachtlicht Flur 2 Status
    description: null
    configuration:
      mode: READWRITE
      escapedUrl: false
      stateExtension: /v4/devices
      stateTransformation: JSONPATH:$.devices[?(@.did==<myDID>)].statusesMap.Position∩JS:SwitchToStr.js

with SwitchToStr.js transformation looking as such:

(function(x){
    try{
        if (x == 0) {
            return ("OFF");
        }
        return ("ON");
    } catch(e) {
        return null;
    }
})(input)

Result: works like a charm, it updates with the parametrized sampling rate and displays “ON” or “OFF” according to the real state. No matter from which source the relay is actuated.

  1. Proof-check: what happens if I apply it as the current state of the actual switch type with the commands already configured, but the state yet without a transformation:
  - id: Schalter_NL_Flur_2
    channelTypeUID: http:switch
    label: Schalter Nachtlicht Flur 2
    description: null
    configuration:
      onValue: '{"name":"TURN_ON_CMD"}'
      mode: READWRITE
      stateExtension: /v4/devices
      offValue: '{"name":"TURN_OFF_CMD"}'
      escapedUrl: false
      stateTransformation: JSONPATH:$.devices[?(@.did==<myDID>)].statusesMap.Position
      commandExtension: /devices/<myDID>

Result: The commands work like a charm, I can use the OH GUI to turn the switch on and off. The status of the switch is displayed “as previously commanded” for some seconds, then it changes to UNDEF. Well, all as expected.

  1. Do the real thing. Same as (2), but with status transformation. Note that the stateTransformation and stateExtension are identical to (1) except the JS filename.
  - id: Schalter_NL_Flur_2
    channelTypeUID: http:switch
    label: Schalter Nachtlicht Flur 2
    description: null
    configuration:
      onValue: '{"name":"TURN_ON_CMD"}'
      mode: READWRITE
      stateExtension: /v4/devices
      offValue: '{"name":"TURN_OFF_CMD"}'
      escapedUrl: false
      stateTransformation: JSONPATH:$.devices[?(@.did==<myDID>)].statusesMap.Position∩JS:toSwitch.js
      commandExtension: /devices/<myDID>

with toSwitch.js looking as such (note that this is identical to SwitchToStr.js except the return values):

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

Result: Command / Control working perfectly as before in (2). Status is displayed “as previously commanded” and stays like this. Woo-hoo, works, even the transformation, I thought. :wink:

Until I commanded the switch from outside OH and changed its state.
I ran two channels in parallel, just to be sure, the “only-string-status” as described in (1) and the configuration as a switch type in (3).
The string channel reacted as expected and updated its state. The log showed the INFO for the value change.
The switch channel never changed. No errors, no warning, nothing in the log. And exactly that’s what I don’t understand and would be grateful for help. :slight_smile:

(yes, I tried several times even with different switches. I waited several multiples of the update rate. I rebooted several times. It stayed all as described…)

All transforms operate on Strings and are expected to return Strings. Since "0" ~== 0. That can be part of the problem. Also, you don’t have OnOffType available unless you import it from @runtime or import the class yourself. That is probably throwing an exception so this transformation always returns null and suppressing the error message.

(function(x){
  return (x == "0") ? "ON" : "OFF";
})(input)

Or if you must have the try/catch, at least add some logging.

(function(x){
  try {
    return (x == "0") ? "ON" : "OFF";
  } catch(e) {
    console.error('toSwitch.js encountered an error: ' + e);
    return null;
  }
})(input)

Note, a JS Transform in OH 4 has everything that would normally be available in a rule (except for event) but nothing that isn’t normally available in a rule (e.g. OnOffType).

You see nothing in the logs because you catch the error and silently return null which OH treats as “ignore”.

1 Like

Thanks a lot for so many hints! :slight_smile:
(I could have gotten the idea that OH might ignore “catch” myself…) :wink:
With this, I get the error that it does not know the OnOffType.

I just checked the rest of it. We’re getting closer but are not there yet. This is what I used for way more detailed logs for toSwitch.js:

(function(x){
  try {
    console.info('toSwitch.js input ' + x);
        if (x == "0") {
            console.info('toSwitch.js returns OFF ');
            return ("OFF");
        }
        console.info('toSwitch.js returns ON ');
        return ("ON");
  } catch(e) {
    console.error('toSwitch.js encountered an error: ' + e);
    return null;
  }
})(input)

I see this on the console with the expected sampling rate:

2023-09-26 18:44:33.515 [INFO ] [org.openhab.automation.script       ] - toSwitch.js input 100
2023-09-26 18:44:33.517 [INFO ] [org.openhab.automation.script       ] - toSwitch.js returns ON 

or

2023-09-26 18:47:08.540 [INFO ] [org.openhab.automation.script       ] - toSwitch.js input 0
2023-09-26 18:47:08.541 [INFO ] [org.openhab.automation.script       ] - toSwitch.js returns OFF 

so the script is running. Still, this has absolutely no effect on the state of the Switch type… :frowning:

If I use the OH GUI to switch it from off to on, I get this on the console:

2023-09-26 18:48:08.555 [INFO ] [org.openhab.automation.script       ] - toSwitch.js input 0
2023-09-26 18:48:08.556 [INFO ] [org.openhab.automation.script       ] - toSwitch.js returns OFF 
2023-09-26 18:48:08.458 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Nachtlicht_Flur_2_Schalter_Nachtlicht_Flur_2_vorm_Arbeitszimmer' received command ON
2023-09-26 18:48:08.460 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'Nachtlicht_Flur_2_Schalter_Nachtlicht_Flur_2_vorm_Arbeitszimmer' predicted to become ON
2023-09-26 18:48:08.462 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Nachtlicht_Flur_2_Schalter_Nachtlicht_Flur_2_vorm_Arbeitszimmer' changed from UNDEF to ON
2023-09-26 18:48:08.559 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Nachtlicht_Flur_2_Schalter_Nachtlicht_Flur_2_vorm_Arbeitszimmer' changed from ON to UNDEF
2023-09-26 18:48:13.585 [INFO ] [org.openhab.automation.script       ] - toSwitch.js input 100
2023-09-26 18:48:13.586 [INFO ] [org.openhab.automation.script       ] - toSwitch.js returns ON 
2023-09-26 18:48:13.549 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Nachtlicht_Flur_2_Schalter_Nachtlicht_Flur_2_vorm_Arbeitszimmer_Status' changed from OFF to ON

…so you can see that the command is actually executed by the switch, the script is triggered, the separate string channel sees the change from off to on, but the switch channel quickly jumps back to UNDEF.

I have the impression that something fundamental changed here concerning what OH expects as an input. For OH 3.x I found a lot of examples with the “ON” and “OFF” strings, which I already found unfunctional before, that’s why I came up with the OnOffType… the documentation of OH 4.x is still quite sparse at this point :upside_down_face:

Probably it will work if the return value is as expected, so we’re probably quite close :wink:

Right, I explain that in my reply too.

Autoupdate will “predict” the new state of an Item based on a received command and update the Item with that prediction. Later on, when the end device (in this case the web API call) changes the binding updates the Item with the “real” state. When the device reports back new states, it’s a good idea to turn off autoupdate (metadata on the Item). This avoids that flapping.

Not really.

I think the combination of the onValue/offValue and the state transformation is causing problems. When you use those properties, they operate both ways. When you send the command ON it gets converted to {“name”:“TURN_ON_CMD”}. When {“name”:“TURN_ON_CMD”} is returned by the device it gets converted to ON before sending it to the Item, independent of the transform.

I do not know the order of operations either. It looks like it does the transform first and then applies the onValue/offValue and since those don’t match anything returned by the transform it fails and ignores the message.

1 Like

Well now I got your point - the ON and OFF statuses are the decisive element! :smiley:

I used the “talkative” version of the transformation scripts to see what actually is commanded when the switch is pressed in the GUI, and it is the values of ON and OFF status.

So I changed these statuses as such:

        Type switch : Schalter_NL_Flur_2 "Schalter Nachtlicht Flur 2 (vorm Arbeitszimmer)" [  // Relay switch  DID=1010040
            stateExtension="/v4/devices",
            stateTransformation="JSONPATH:$.devices[?(@.did==<myDID>)].statusesMap.Position",
            commandTransformation="JS:toSwitchCmd.js",
            commandExtension="/devices/<myDID>",
            onValue="100",
            offValue="0"

and set up the new toSwitchCmd.js script as such:

(function(x){
  try {
        if (x == "0") {
            return ("{\"name\":\"TURN_OFF_CMD\"}");
        }
        return ("{\"name\":\"TURN_ON_CMD\"}");
  } catch(e) {
    console.error('toSwitchCmd.js encountered an error: ' + e);
    return null;
  }
})(input)

…and guess what. IT WORKS!!! :smiley: :smiley:
Not only is the behavior of the GUI switching exactly as expected, it also changes according to external switch actuations. Thanks a lot for the good support! :+1: