Followup: Automating with Ubqiuiti mPower

In my previous post, I talked about how to setup SSH Key authentication and symlinking the relay device so you could easily automate or script how to turn on/off/restart devices.  In this post, I wanted to show you one way in which this could be utliized.

I used shell scripting (on the mPower) and a PHP script running on another (internal) webserver to do this.  This is assuming you already have some experience in scripting (bash, sh, and knowledge of PHP).  You will need to have a webserver (apache,nginx,lighttpd, etc.) set up and configured on how to serve PHP content. I don’t go into this on this post.

I’ll first dazzle you with the end result:

This website uses CSS (bootstrap), html and PHP to render the page.  It utilizes an (additional) SSH key for the webserver to use to log in passwordlessly to the mPower Switch and call the shell script on there.  You can use the shell script by itself or with SSH calls as well.

Replace the bolded and italicized portions below to fit your environment.  The path to your SSH should be readable by the user that’s running the PHP script.  I actually changed the user’s shell (temporarily) to do a ssh-keygen -t rsa.  Also, the variables (e.g. wireless, retropi, etc.) should match the symlinks that you created in the previous post.

power.php

<?php
$path = "/var/etc/persistent/$device";
$ip = "10.0.100.1";
function getStatus() {
 $cmd="/usr/bin/ssh -q -oStrictHostKeyChecking=no -i /path/to/your/ssh_key ubnt@" . $GLOBALS['ip'] . " " . $GLOBALS['path'] . "/power.sh status";
 $out = Array();
 exec($cmd,$out,$retVal);
 if($retVal) {
 echo "<center><h3>Error retrieving status</h3></center>";
 print_r($out);
 exit(1);
 }
 echo "<table>\n";
 echo "<tr><th>Device</th><th>Status</th></tr>\n";
 foreach ($out as $value) {
 $output = explode(" ",$value);
 echo "<tr><td>$output[0]</td><td>$output[1]</td></tr>";
 }
 echo "</table>\n";
}
function deviceAction($device,$action) {
 $out = Array();
 $cmd="/usr/bin/ssh -q -oStrictHostKeyChecking=no -i /path/to/your/ssh_key ubnt@" . $GLOBALS['ip'] . " " . $GLOBALS['path'] . "/power.sh " . $device . " " . $action . " 2>&1";
 exec($cmd,$out,$retVal);
 if($retval) {
 echo "Error with SSH call<br>\n";
 print_r($out);
 echo "<br>";
 }
 echo "<h3>Called SSH command to do action \"$action\" on <b>$device</b></h3><br>\n";

}
echo "<center>";
if ($_POST["action"] == "off" || $_POST["action"] == "on" || $_POST["action"] == "cycle" ) {
 $action = $_POST["action"];
}
if ($_POST["device"] == "xfinity" || $_POST["device"] == "wireless" || $_POST["device"] == "retropi" || $_POST["device"] == "modem" ) {
 $device = $_POST["device"];
}

if (isset($device) && isset($action) && ($device !== "") && ($action !== "")) {
 deviceAction($device,$action);
} else {
 echo "<h3>Please select a device and action</h3>";
}
echo "</center>";
echo "<html>\n";
echo <<< HEAD

<head>
<link href="css/bootstrap.min.css" rel="stylesheet">\n</head>
<style>
.dropbtn {
 background-color: #4CAF50;
 color: white;
 padding: 16px;
 font-size: 16px;
 border: none;
 cursor: pointer;
}

.dropdown {
 position: relative;
 display: inline-block;
}

.dropdown-content {
 display: none;
 position: absolute;
 background-color: #f9f9f9;
 min-width: 160px;
 box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
 z-index: 1;
}

.dropdown-content a {
 color: black;
 padding: 12px 16px;
 text-decoration: none;
 display: block;
}

.dropdown-content a:hover {background-color: #f1f1f1}

.dropdown:hover .dropdown-content {
 display: block;
}

.dropdown:hover .dropbtn {
 background-color: #3e8e41;
}
table {
 font-family: arial, sans-serif;
 border-collapse: collapse;
 width: 100%;
}

td, th {
 border: 1px solid #dddddd;
 text-align: left;
 padding: 8px;
}

tr:nth-child(even) {
 background-color: #dddddd;
}
</style>
</head>
HEAD;
echo "<body>\n";
echo <<< EOB
<br><br>
<center>
<form name="Master" action="" method="post">
<h3>
 <label class="radio-inline">
 <input type="radio" name="device" id="device" value="wireless">Wireless
 </label>
 <label class="radio-inline">
 <input type="radio" name="device" id="device" value="xfinity">Xfinity
 </label>
 <label class="radio-inline">
 <input type="radio" name="device" id="device" value="modem">Modem
 </label>
 <label class="radio-inline">
 <input type="radio" name="device" id="device" value="retropi">RetroPi
 </label>
</h3>
<br>
<div class="dropdown">
 <select id="action" name="action" class="dropbtn">Dropdown</button>
 <div class="dropdown-content">
 <option selected value="">Select an Action</option>
 <option value="cycle">Restart</option>
 <option value="off">Turn Off</option>
 <option value="on">Turn On</option>
 </select>
 </div>
</div>
<br>
<br>
<input type="submit" name="send"/>
</form>
</center>
EOB;
getStatus();
echo "</body></html>\n";
?>

Copy and paste should probably work fine for the above file (Make sure you replace the bolded and italicized text with your environment’s information!). For this next one, I highly recommend copy and pasting it locally and then SCP’ing it over to the mPower. The tab/text formatting gets all screwy in vi; even with :set paste set. Also, make sure to set the permissions of power.sh to executable (chmod +x power.sh or chmod 0700 power.sh) and the PHP file will need to be read and executed by the web service process user.

/var/etc/persistent/power.sh

#!/usr/bin/sh
# Steve Rosenstein 2017 steve@steverosenstein.us

PATH="/var/etc/persistent";
DEVICES="xfinity wireless modem retropi"

status() {
for DEVICE in $DEVICES;
do
 STATUS=$(/usr/bin/cat $PATH/$DEVICE)
 if [ $STATUS == "0" ]
 then
 OUTPUT="off"
 elif [ $STATUS == "1" ]
 then
 OUTPUT="on"
 else
 OUTPUT="unknown"
 fi
 echo $DEVICE $OUTPUT
done
}

usage() {
 echo "$0 <device> [off|on|cycle|restart|status] or $0 status";
 echo "Please enter one of the following possible devices to restart:";
 echo ${DEVICES};
 exit 0;
}

action() {
 DEVICE=$1
 ACTION=$2
 case $ACTION in
 off)
 echo "Turning off ${DEVICE}"
 echo "0" > ${PATH}/${DEVICE};
 ;;
 on) 
 echo "Turning on ${DEVICE}"
 echo "1" > ${PATH}/${DEVICE};
 ;;
 cycle|restart) 
 echo "Turning ${DEVICE} off and then back on"
 echo "0" > ${PATH}/${DEVICE};
 /usr/bin/sleep 2;
 echo "1" > ${PATH}/${DEVICE};
 ;;
 status)
 STATUS=$(/usr/bin/cat ${PATH}/${DEVICE});
 if [ ${STATUS} == "0" ]
 then
 OUTPUT="off";
 elif [ ${STATUS} == "1" ]
 then
 OUTPUT="on";
 else 
 OUTPUT="unknown";
 fi 
 echo "$DEVICE $OUTPUT";
 ;;



*)
 echo "Invalid action selected."
 usage
 ;;
 esac
}
if [ $# == "1" ] && [ "$1" == "status" ]
then
 status;
 exit;
fi

if [ $# != "2" ]
then
 usage;
 exit 1;
else
 DEVICE=$1;
 ACTION=$2
fi
case $DEVICE in 
 retropi)
 action retropi $ACTION;
 ;;
 xfinity)
 action xfinity $ACTION;
 ;;
 wireless)
 action wireless $ACTION;
 ;;
 modem)
 action modem $ACTION;
 ;;
 *)
 usage
 ;;
esac

For the CSS file you should be able to just grab the CSS from here.  You just need to make sure that the bootstrap.min.css is in a directory called “css” in the root of your web directory.  Also make sure they are all readable, and the directory is executable, for the user that runs the web process.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.