External link towards OpenHAB (item)

I’m using pushover messages to be informed when OpenHAB isn’t in the right state.

Example:
Our ‘House Mode’ should be away if all our cell phones (=ping) aren’t home for 20 minutes. Today, OpenHAB send us a little message to inform us kindly that the House Mode is still ‘Active’, and it should be ‘Away’.
This works very nice, and each time, it’s ‘Ohhh, right…’ :wink:

I would like to send now a kind of link in the message that enable us easily to activate this quickly. This to avoid to open the app, search the right place, enable…

Example:
This is friendly reminder that your House is still fully activated. Click here to secure it.

Is there way to change this from the outside world, without the UI?
Of course with the necessary security and so.
And url like http://mypublicip/basicui/item=HouseMode&status=Away&user=Me&pwd=verySecure ?

Here is the problem. Is it going to be more of an inconvenience to enter in your myopenhab.org username and password once you click on that link or is it going to be more of an inconvenience to open the app and browse to the correct Item to manually toggle.

To me, it is clearly more inconvenient to have to type in my long email address and password than it is to navigate my sitemap in the app.

Because you need to change the state of an Item we can’t really use the REST API because that requires a POST or a PUT. Just clicking on a link like that will create a GET request.

However, it’s a bit of a hack, but you can install the ClassicUI and use the old style OH 1.x REST call (I don’t remember how it works off the top of my head but think it is documented on the old wiki). Or you can create an HTML file and use and XMLHttpRequest to make the request to the OH REST API as desired. You can see an example of how to do that in OAuth2 using just OH Rules and myopenhab.org.

OK, First attempt. :wink:

@rlkoshak,
Not sure if I understand your remark about REST v1. Seems that REST is working for my case with curl? With a small workaround maybe. See below…

On a seperate webserver (with php), I’ve got:

  • /var/www/html/ModeAway.php
?php
echo "House is in now in Mode Away.<br>";
$message=shell_exec("/var/www/html/scripts/ModeAway.sh 2>&1");
print_r($message);
?>
  • /var/www/html/scripts/ModeAway.sh
#!/bin/bash                                                                                                                                                                                                                    
curl -s -X POST --header "Content-Type: text/plain" --header "Accept: application/json" -d "AWAY" "http://SERVERIP/rest/items/HouseMode"  

When I open the php page (ModeAway.php), it seems to trigger the status nicely.

For the security, I’m still thinking what to do. Your example (OAuth2) seems a lot of work.
I was thinking of building a kind of ‘time-out’. Maybe in the same rule where I check the presence of phones, I can add something that enables the webpage publicly for 5 minutes or so?

ps Not sure if I can (=should) run this on the OH server itself? I Don’t think that it has PHP on it today… And I’m not sure if it’s a good idea to install this?

My purpose in posting that link was primarily for you to look at the HTML page.

To implement you ModeAway.php using just an HTML file that can be served by OH through myopenhab.org it’s simple enough:

<!DOCTYPE html>
<html>
	<head>
		<title>Mode Away</title>
	</head>
<script>
// Change these values to your Item and the state you want to send when this page is loaded.

var item = 'HouseMode'
var code = "AWAY"

document.write("Preparing to update " + item + " with " + code)

var xhr = new XMLHttpRequest();
xhr.open('POST', "https://myopenhab.org/rest/items/"+item);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.setRequestHeader("Accept", "application/json");
xhr.onreadystatechange = function() {
	if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
		document.write("Received  " + code);
	}
	else if(xhr.status != 200) {
		document.write("Error in callback: " + xhr.status + " " + xhr.responseText);
	}
}
xhr.send(code)

document.write("Sent " + code + "...");

</script>

</html>

No need for a separate server. No need for PHP. No need for external scripts. And since you are not passing arguments as part of the URL, you don’t need all that JavaScript up front to parse out the arguments. If we assume this is saved to modeaway.html and placed in the html folder of your OH conf you would activate the command to your HouseMode Item by accessing https://myopenhab.org/static/modeaway.html from your browser or from an app.

And for security this goes through myopenhab.org so you have all the same security that you have now.

Seems like a win.

And you can make it smarter if you want/need to. For example, if we add back the argument parser, you can pass the Item and the state as arguments and make the HTML generic.

<!DOCTYPE html>
<html>
	<head>
		<title>OAuth2 Catcher</title>
	<script type="text/javascript">
	function getAllUrlParams(url) {

  // get query string from url (optional) or window
  var queryString = url ? url.split('?')[1] : window.location.search.slice(1);

  // we'll store the parameters here
  var obj = {};

  // if query string exists
  if (queryString) {

    // stuff after # is not part of query string, so get rid of it
    queryString = queryString.split('#')[0];

    // split our query string into its component parts
    var arr = queryString.split('&');

    for (var i=0; i<arr.length; i++) {
      // separate the keys and the values
      var a = arr[i].split('=');

      // in case params look like: list[]=thing1&list[]=thing2
      var paramNum = undefined;
      var paramName = a[0].replace(/\[\d*\]/, function(v) {
        paramNum = v.slice(1,-1);
        return '';
      });

      // set parameter value (use 'true' if empty)
      var paramValue = typeof(a[1])==='undefined' ? true : a[1];

      // (optional) keep case consistent
      paramName = paramName.toLowerCase();
      paramValue = paramValue.toLowerCase();

      // if parameter name already exists
      if (obj[paramName]) {
        // convert value to array (if still string)
        if (typeof obj[paramName] === 'string') {
          obj[paramName] = [obj[paramName]];
        }
        // if no array index number specified...
        if (typeof paramNum === 'undefined') {
          // put the value on the end of the array
          obj[paramName].push(paramValue);
        }
        // if array index number specified...
        else {
          // put the value at that index number
          obj[paramName][paramNum] = paramValue;
        }
      }
      // if param name doesn't exist yet, set it
      else {
        obj[paramName] = paramValue;
      }
    }
  }

  return obj;
}
	</script>
	</head>
<script>
var item = getAllUrlParams().item
var state = getAllUrlParams().state;
document.write("Preparing to update " + item + " with state " + state)

var xhr = new XMLHttpRequest();
xhr.open('POST', "https://myopenhab.org/rest/items/"+item);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.setRequestHeader("Accept", "application/json");
xhr.onreadystatechange = function() {
	if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
		document.write("Received  " + state);
	}
	else if(xhr.status != 200) {
		document.write("Error in callback: " + xhr.status + " " + xhr.responseText);
	}
}
document.write("Sent " + state + "...");
xhr.send(state)

</script>

</html>

If we save this to commanditem.html in the conf/html folder you can send a command to ANY Item by accessing https://myopenhab.org/static/commanditem.html?item=HouseMode&state=AWAY from you browser or app or whatever you are using. Again, you are going through myopenhab.org so there is no need for a separate web server and you have all the same security that you have now.

Or if you have ClassicUI installed, as described in the link above, you can access https://myopenhab.org/classicui/CMD?HouseMode=AWAY to issue commands to your Items. That is easy enough. Again, you are going through myopenhab.org so there is no need for a separate server and you have all the same security you have now.

Another alternative is you can use IFTTT Button Widgets to add single button icons on your phone’s screens to trigger these commands.

Under no circumstances should you stand up your own web server and expose it to the Internet. That is just asking to be attacked.

2 Likes

Thanks already for your support!!!
I’m really jealous at you guys when you answer things like this. You make it sounds all so easy. :wink:

I’ve just tried the commanditem.html example.
But when I run it, i’m getting an error:

http://PUBLICURL/static/commanditem.html?item=HouseMode&state=AWAY

Error in callback: 0

And I’m getting also the same error with the ModeAway.thml example.
http://PUBLICURL/static/ModeAway.html

Error in callback: 0

Guess I can’t use the publicurl of my part, but must use the myopenhab.org link? :blush:
I should investigate a bit more in myopenhab.org. Never really used it.

The line that starts with xhr.open needs to use the same base url that you used to access the page. If you didn’t use myopengab.org then you need to change the url on that line as appropriate.

It also occurs to me, why not just create one it’s more simplified HABPanel pages or sitemaps to access? This all still seems way more complexity and risk for dubious benefit.

Will test later on, don’t have access right now…

But the idea behind it all, is that I’ve got just a simple link in a pushover message to change the housemode.
So no need to open apps or so, just click and done. :wink:

Well, click the link, enter username and password, and then it gets done. :wink:

One thing to realize is when using the html files above, it is your browser that is making the web call to command the Item. There isn’t anything going on on the server side.