Need help converting rest api command into RESTful Switch

I could use some help. I am trying to convert a rest api commands that works fine on the RPI command line into a RESTful Switch based on the information in the below.

Rest API command to turn ON the switch:
curl -u myusername:mypwd -X PUT -H "X-CSRF: x" --data "value=true" --digest "http://192.168.1.15/restapi/relay/outlets/5/state/"

Rest api command to turn OFF the switch:
curl -u myusername:mypwd -X PUT -H "X-CSRF: x" --data "value=false" --digest "http://192.168.1.15/restapi/relay/outlets/5/state/"

Here is the Restful Switch component that I have added to my configuration.yaml file:

switch:
  - platform: rest
    resource: http://192.168.1.15/restapi/relay/outlets/5/state/
    method: PUT
    username: myusername
    password: mypwd
    headers: "'X-CSRF: x' --data 'value='"
    body_on: '{"value": "true"}'
    body_off: '{"value": "false"}'

However when I try to validate my config file I get the following error message: Invalid config for [switch.rest]: expected a dictionary for dictionary value @ data[‘headers’]. Got “‘X-CSRF: x’ --data ‘value=’”. I know the issue is likely with how i converted the header value into the header and body on and body off statements, but I have tried multiple variations and I have not been able to get it to pass validation. I would really appreciate it if someone here who is familiar with the RESTful Switch could help me with my syntax.

I am running the latest 64-bit hass.io installation on a Raspberry Pi 3 B+

Thanks in advance for the help.

Andrew J

You’ll never get this to work with the RESTful Switch. It uses aiohttp, and aiohttp does not support digest authentication.

You should use the Command line Switch instead (using curl.)

pnburkner: You are awesome sir. Got it to work. I and tried that earlier, but I think I had my quotation marks set incorrectly. Working now with the following switch command line.

   switch:
     - platform: command_line
        switches:
          power_outlet_6:
            command_on: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=true' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
            command_off: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=false' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
            friendly_name: 'DLI Outlet 6'

The only problem I have now is that the switch does not show up as a switch, but two lightening bolts. I assume there is a way to change the switch type.

Thanks again for the prompt and helpful response.

Andrew J

I believe that’s because you’re not using the optional command_state (and possibly value_template), which is what the sensor will use to temporarily poll the status of the switch. Is there a command you can send to have the switch return its current state?

I don’t think so. Here is the link to all the rest api command for the switch:

I don’t see any options to return the state.

From that page:

Get the status of relay/outlet 1
curl -k -u admin:1234 -H “Accept:application/json” --digest https://192.168.0.100/restapi/relay/outlets/2/state/

Yeah, I just saw that myself. But how would I combine that with the command line to turn the switch on?

You need to add at least the command_state parameter to the configuration. Can you run that command (using curl) and tell me what the output is? Also, do echo $? afterwards so we can also see what the return status is from the curl command. That information will help determine whether or not you need to use value_template in addition to command_state.

yes. If I run the following command I get True if the outlet is on and False if off.

curl -k -u usrname:pwd -H "Accept:application/json" --digest "https://192.168.1.15/restapi/relay/outlets/5/state/"

So, I think you want the following:

  switch:
    - platform: command_line
      switches:
        power_outlet_6:
          command_on: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=true' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
          command_off: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=false' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
          command_state: "curl -u usrname:pwd -H 'Accept:application/json' --digest 'https://192.168.1.15/restapi/relay/outlets/5/state/'"
          value_template: "{{ value|lower }}"
          friendly_name: 'DLI Outlet 6'

Some comments…

I don’t think you need to use curl’s -k option, since the other commands work without it. I do, however, suggest adding curl’s -s option (just put it before the -u option) to all the commands. Lastly, in the value_template, the |lower part may or may not be necessary. I think you can get away without it.

Let me now how this works.

EDIT:

First, I updated the config to get the indentation right. I must have screwed it up when I copied and pasted.

Next, I believe by default this will poll the switch (i.e., send command_state) every 30 seconds. You should see this in home-assistant.log (look for “Running state command”.) If you want to change this interval, I think you can by adding scan_interval: xxx at the same indentation level as switches:. E.g.,:

  switch:
    - platform: command_line
      scan_interval:
        seconds: 10
      switches:
        power_outlet_6:
          command_on: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=true' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
          command_off: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=false' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
          command_state: "curl -u usrname:pwd -H 'Accept:application/json' --digest 'https://192.168.1.15/restapi/relay/outlets/5/state/'"
          value_template: "{{ value|lower }}"
          friendly_name: 'DLI Outlet 6'
1 Like

The first code worked - partially. It would turn the switch on, but then in HA it would return to the off position even though the switch was actually on. I am trying your latest code now. The new hass.os takes forever to restart to it takes a while to test…

Unfortunately, I still have the same issue. With the scan_interval added it will turn the switch on, but then in ha the switch returns to the off position and stays there. So turning on the switch work (yeah), but now I just need to get ha to see that it is on and keep the switch in the on position.

I think the problem is with the value_template. Unless that results in exactly “true” (after first being changed to all lower case), then it will update the switch’s state as off.

So, can you run the curl command (curl -u usrname:pwd -H 'Accept:application/json' --digest 'https://192.168.1.15/restapi/relay/outlets/5/state/') again from the OS command line, and let me know the exact output?

EDIT: Actually, I’m starting to think that command_state (at least) may need curl’s -s option.

Here is what I get from the command line for the state command:

core-ssh:~# curl -k -u username:pwd -H "Accept:application/json" --digest "https://192.168.1.15/restapi/relay/outlets/5/state/"
truecore-ssh:~#

note that it I run without the “-k”, I get the following error message:

curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Edit:

If it helps. Here is what I get when the switch is off.

core-ssh:~# curl -k -u andjones132:K3yOKAckOZ56 -H "Accept:application/json" --digest "https://192.168.1.15/restapi/relay/outletstate/"
falsecore-ssh:~#

SUCCESS!!! By adding the “-k” back to the command_state line it works now. It stays in the on position when switched on. Now I can switch it on and off without any issues. This is my latest code:

  - platform: command_line
    scan_interval:
      seconds: 10
    switches:
      power_outlet_6:
        command_on: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=true' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
        command_off: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=false' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
        command_state: "curl -k -u username:pwd -H 'Accept:application/json' --digest 'https://192.168.1.15/restapi/relay/outlets/5/state/'"
        value_template: "{{ value|lower }}"
        friendly_name: 'DLI Outlet 6'

Edit: I got so excited I forgot to remove my real user name and password…

2 Likes

Ok, thanks. Hmm, interesting about the -k switch. I would have thought your other commands (to turn the switch on and off) would have failed without -k. Oh well. So -k is necessary.

So I really think -s is also necessary. curl behaves differently when run at the command line and via a script or something. In the latter case it may be outputting a progress bar, which will mess up the output. So, definitely add -s.

So now we have:

  switch:
    - platform: command_line
      scan_interval:
        seconds: 10
      switches:
        power_outlet_6:
          command_on: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=true' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
          command_off: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=false' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
          command_state: "curl -s -k -u usrname:pwd -H 'Accept:application/json' --digest 'https://192.168.1.15/restapi/relay/outlets/5/state/'"
          value_template: "{{ value }}"
          friendly_name: 'DLI Outlet 6'

BTW, the |lower is definitely not needed because I can see in the code the output is converted to lower case before evaluating the template.

Nice! So apparently -s isn’t needed after all. Weird that command_on and command_off would workout with -k.

EDIT:

You should be able to remove the |lower part of the value_template.

GLAD IT’S FINALLY WORKING! :smile:

Thank you sooooooooo much pn. I really appreciate the help. I have been banging my head against the wall for weeks trying to get this working. I originally tried using the DigitalLoggers component, but could never get it to work. It would just give a bunch of errors in the log each time I restarted. Using these Curl commands seemed like the next best option, but was struggling to get them to work as I have never had to use this component before. I really appreciate the help and guidance.

All the best.

Edit: I will try a few different variations like adding the -s and removing the “|lower” and seeing if it makes any difference.

Andrew J

Glad to help!

The -s option makes curl “silent”, meaning only output data returned. If it’s working without -s, then adding it probably won’t do much. Removing |lower shouldn’t make any noticeable difference, although it will make it slightly more efficient (no sense converting a string to lower case when it already is. :wink:)

Just a quick follow up and one more question if I may.

I added the -s to the command_state and removed the “|lower” from the value_template and it is working great. It does seem a bit less laggy now.

One last question. Is there anyway to move my username and password to my !secret file and include the reference in the command lines for on, off, and state? I tried using several string concatenation options like “+” and “&&”, but none would pass validations. I guess it might be possible to move the entire command lines to the secrets file, but as I have a number of these switches to setup that would quickly become a pain. Is there a straight forward way of substituting in the !secret passcode in the command line strings?

switch:
  - platform: command_line
    scan_interval:
      seconds: 10
    switches:
      dli_power_outlet_6:
        command_on: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=true' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
        command_off: "curl -u username:pwd -X PUT -H 'X-CSRF: x' --data 'value=false' --digest 'http://192.168.1.15/restapi/relay/outlets/5/state/'"
        command_state: "curl -s -k -u username:pwd -H 'Accept:application/json' --digest 'https://192.168.1.15/restapi/relay/outlets/5/state/'"
        value_template: "{{ value }}"
        friendly_name: 'Outlet 6 - Not in Use

Thanks again.

Andrew J

1 Like