Tom IT

Belkin Wemo plug & shellscript automated control

A client who uses paxton door access control for their gym wanted to have their TV switch on when a customer enters, and switch off after 1 hour. I bought a Belkin WeMo Switch and found a shellscript that can switch the wemo on and off (original script.)

For this I created a C# console application in combination with the paxton sdk that fetches the last time a user entered the premises, and it will write the desired state of the TV power switch to a simple txt file (ON or OFF):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Paxton.Net2.OemClientLibrary;
using System.Xml.Linq;
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;

namespace ConsoleApplication2
{
    class Program
    {
        private const int REMOTE_PORT = 8025;
        private const string REMOTE_HOST = "192.168.2.2";
        private OemClient _net2Client = new OemClient(REMOTE_HOST, REMOTE_PORT);
        private static string switchFile = @"C:\cygwin64\home\user\switch.txt";
       
        static void Main(string[] args)
        {
            Program main = new Program();
            main.startUp();
            System.Environment.Exit(0);
        }
        public int startUp()
        {

            bool res = AuthenticateUser("OEM Client", "password");
            if (res != true)
            {
                Log("Authentication failed, exiting application");
                return 1;
            }
            Log("Authentication success");

            IEvents events = _net2Client.ViewEvents(1, "EventType = 20", "EventId desc");
          
            IEventView evt = events.EventsList()[events.EventsList().Keys.ElementAt(events.EventsList().Count - 1)];
           
              
                
            Log(evt.EventType + " " + evt.EventTypeDescription + " " + evt.EventTime + " " +evt.EventDate+" "+evt.EventDescription+ " " +evt.Username+ " " + evt.UserId);

            double lastAccess = DateTimeToUnixTimestamp(stringToDateTime(evt.EventDate + " " + evt.EventTime));
            double currentTime = DateTimeToUnixTimestamp(DateTime.Now);
            Log(lastAccess.ToString());
            Log(currentTime.ToString());

            //Longer than an hour? switch off
            if(Math.Round(currentTime - lastAccess) > 3600)
            {
                File.WriteAllText(switchFile, "OFF");
            }
            else
            {
                File.WriteAllText(switchFile, "ON");
            }

            return 1;

        }

        private DateTime stringToDateTime(string date)
        {
            // Date strings are interpreted according to the current culture. 
            // If the culture is en-US, this is interpreted as "January 8, 2008",
            // but if the user's computer is fr-FR, this is interpreted as "August 1, 2008" 

            DateTime dt = Convert.ToDateTime(date);

            return dt;
        }
        public static double DateTimeToUnixTimestamp(DateTime dateTime)
        {
            return (TimeZoneInfo.ConvertTimeToUtc(dateTime) - new DateTime(1970, 1, 1)).TotalSeconds;
        }

        /**
        * Authenticate user
        * For some reason we can't authenticate with username password, only with userId Password..
        * So we need to get the userId and Authenticate with it..
        **/
        private bool AuthenticateUser(string userName, string password)
        {
            IOperators operators = _net2Client.GetListOfOperators();
            Dictionary<int, string> operatorsList = operators.UsersDictionary();
            foreach (int userID in operatorsList.Keys)
            {
                if (operatorsList[userID] == userName)
                {
                    Dictionary<string, int> methodList = _net2Client.AuthenticateUser(userID, password);
                    return (methodList != null);
                }
            }
            return false;
        }

        private void Log(string logMessage)
        {
            Console.WriteLine(logMessage);
            Console.WriteLine("--------------------");

        }
    }
}

This application is scheduled every few minutes, after wich a shell script is  called that will switch the tv to the desired state, the shellscript:

#!/bin/sh
#
# WeMo Control Script
#
#

IP=192.168.2.21
#switch.txt contains ON or OFF
COMMAND=`cat ~/switch.txt`
PORT=0

#Do a quick port test (1 of 4 is used)
for PTEST in 49152 49153 49154 49155
do
PORTTEST=$(curl -s -m 3 $IP:$PTEST | grep "404")                      
if [ "$PORTTEST" != "" ]
then
PORT=$PTEST
break
fi
done    
if [ $PORT = 0 ]
then
echo "Cannot find a port"
exit
fi
#get the state	 first, so we can decide if we need to switch at all or TV already has desired state
STATE=$(curl -0 -A '' -X POST -H 'Accept: ' -H 'Content-type: text/xml; charset="utf-8"' -H "SOAPACTION: \"urn:Belkin:service:basicevent:1#GetBinaryState\"" --data '<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetBinaryState xmlns:u="urn:Belkin:service:basicevent:1"><BinaryState>1</BinaryState></u:GetBinaryState></s:Body></s:Envelope>' -s http://$IP:$PORT/upnp/control/basicevent1 | 
grep "<BinaryState"  | cut -d">" -f2 | cut -d "<" -f1 | sed 's/0/OFF/g' | sed 's/1/ON/g')

	if [ $COMMAND = "ON" ] && [ $STATE != "ON" ]

		then

			curl -0 -A '' -X POST -H 'Accept: ' -H 'Content-type: text/xml; charset="utf-8"' -H "SOAPACTION: \"urn:Belkin:service:basicevent:1#SetBinaryState\"" --data '<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetBinaryState xmlns:u="urn:Belkin:service:basicevent:1"><BinaryState>1</BinaryState></u:SetBinaryState></s:Body></s:Envelope>' -s http://$IP:$PORT/upnp/control/basicevent1 |
grep "<BinaryState"  | cut -d">" -f2 | cut -d "<" -f1

	elif [ $COMMAND = "OFF" ] && [ $STATE != "OFF" ]

		then

			curl -0 -A '' -X POST -H 'Accept: ' -H 'Content-type: text/xml; charset="utf-8"' -H "SOAPACTION: \"urn:Belkin:service:basicevent:1#SetBinaryState\"" --data '<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetBinaryState xmlns:u="urn:Belkin:service:basicevent:1"><BinaryState>0</BinaryState></u:SetBinaryState></s:Body></s:Envelope>' -s http://$IP:$PORT/upnp/control/basicevent1 |
grep "<BinaryState"  | cut -d">" -f2 | cut -d "<" -f1
	else

		echo "No change in state"
		echo ""
		echo ""

	fi

 

Add Comment