IPS und Windows Mobile 8.x

Hallo zusammen,

ich weiß es gibt keine App und es wird wohl auch keine geben. Ich bekomme allerdings beruflich/privat ein Windows Phone (Lumia 925) und möchte natürlich zumindest meine Beregnung und ein paar Werte kontrollieren und auch schalten

Nun weiß ich es gibt JSON-RPC als Schnittstelle, mir der man wohl eine Verbindung aufbauen, Werte lesen und auch ändern kann.

Gibt es noch eine andere Lösung?

Gibt es jemand der Kenntnisse hat wie man in Windows Mobile Phone 8 (Visual Studio) so eine Kommunikation aufbauen kann? Ich würde dann versuchen, zumindest rudmentär, darauf aufbauend eine kleine App zu basteln.

Ich habe schon viel gesucht, aber den Weg für eine Umsetzung nicht gefunden…

Hallo!

Zuerstmal muss ich etwas klugsch**en: Es heisst natürlich Windows Phone 8. :slight_smile:

Um Daten von IPS ins Telefon zu bekommen nutze ich Push-Raw-Nachrichten mit einem Skript aus dem Internet:

/**
*Windows Phone 7 Push Notification in php by Rudy HUYN
**/
final class WindowsPhonePushDelay
{

const Immediate=0;
const In450Sec=10;
const In900Sec=20;

 private function __construct(){}
}

class WindowsPhonePushNotification
{
    private $notif_url = '';

    function WindowsPhonePushNotification($notif_url)
    {
        $this->notif_url = $notif_url;
    }


	/**
	* Toast notifications are system-wide notifications that do not disrupt the user workflow or require intervention to resolve. They are displayed at the top of the screen for ten seconds before disappearing. If the toast notification is tapped, the application that sent the toast notification will launch. A toast notification can be dismissed with a flick.
	* Two text elements of a toast notification can be updated:
	* Title. A bolded string that displays immediately after the application icon.
	* Sub-title. A non-bolded string that displays immediately after the Title.
	*/
    public function push_toast($title, $subtitle, $param, $delay = WindowsPhonePushDelay::Immediate, $message_id=NULL)
    {
        $msg =	"<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
				"<wp:Notification xmlns:wp=\"WPNotification\">" .
				"<wp:Toast>" .
				"<wp:Text1>".htmlspecialchars($title)."</wp:Text1>" .
				"<wp:Text2>".htmlspecialchars($subtitle)."</wp:Text2>" .
				"<wp:Param>$param</wp:Param>" .
				"</wp:Toast>" .
				"</wp:Notification>";

        return $this->push('toast',$delay+2,$message_id, $msg);
    }

	/**
	*A Tile displays in the Start screen if the end user has pinned it. Three elements of the Tile can be updated:
	*@background_url : You can use a local resource or remote resource for the background image of a Tile.
	*@title : The Title must fit a single line of text and should not be wider than the actual Tile. If this value is not set, the already-existing Title will display in the Tile.
	*@count. an integer value from 1 to 99. If not set in the push notification or set to any other integer value, the current Count value will continue to display.
	*/
    public function push_tile($widebackcontent, $widebackbackground_url, $widebackground_url, $smallbackground_url, $background_url, $title, $count, $backbackground_url, $backtitle, $backcontent, $delay = WindowsPhonePushDelay::Immediate,$message_id=NULL)
    {
        $msg = 	"<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
				"<wp:Notification xmlns:wp=\"WPNotification\"  Version=\"2.0\">" .
				"<wp:Tile Template=\"FlipTile\">" .
				"<wp:SmallBackgroundImage Action=\"Update\">".htmlspecialchars($smallbackground_url)."</wp:SmallBackgroundImage>" .
    			"<wp:WideBackgroundImage Action=\"Update\">".htmlspecialchars($widebackground_url)."</wp:WideBackgroundImage>" .
    			"<wp:WideBackBackgroundImage Action=\"Update\">".htmlspecialchars($widebackbackground_url)."</wp:WideBackBackgroundImage>" .
    			"<wp:WideBackContent Action=\"Update\">$widebackcontent</wp:WideBackContent>" .

				"<wp:BackgroundImage Action=\"Update\">".htmlspecialchars($background_url)."</wp:BackgroundImage>" .
				"<wp:Count Action=\"Update\">$count</wp:Count>" .
				"<wp:Title Action=\"Update\">".htmlspecialchars($title)."</wp:Title>" .
				"<wp:BackBackgroundImage Action=\"Update\">".htmlspecialchars($backbackground_url)."</wp:BackBackgroundImage>" .
				"<wp:BackTitle Action=\"Update\">".htmlspecialchars($backtitle)."</wp:BackTitle>" .
				"<wp:BackContent Action=\"Update\">".htmlspecialchars($backcontent)."</wp:BackContent>" .
				"</wp:Tile>" .
				"</wp:Notification>";

	return $this->push('token',$delay+1, $message_id,$msg);
    }


        public function clear_tile($widebackcontent, $widebackbackground_url, $widebackground_url, $smallbackground_url, $background_url, $title, $count, $backbackground_url, $backtitle, $backcontent, $delay = WindowsPhonePushDelay::Immediate,$message_id=NULL)
    {
        $msg = 	"<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
				"<wp:Notification xmlns:wp=\"WPNotification\"  Version=\"2.0\">" .
				"<wp:Tile Template=\"FlipTile\">" .
				"<wp:SmallBackgroundImage Action=\"Update\">".htmlspecialchars($smallbackground_url)."</wp:SmallBackgroundImage>" .
    			"<wp:WideBackgroundImage Action=\"Update\">".htmlspecialchars($widebackground_url)."</wp:WideBackgroundImage>" .
    			"<wp:WideBackBackgroundImage Action=\"Clear\"></wp:WideBackBackgroundImage>" .
    			"<wp:WideBackContent  Action=\"Clear\"></wp:WideBackContent>" .

				"<wp:BackgroundImage Action=\"Update\">".htmlspecialchars($background_url)."</wp:BackgroundImage>" .
				"<wp:Count Action=\"Update\">$count</wp:Count>" .
				"<wp:Title Action=\"Update\">".htmlspecialchars($title)."</wp:Title>" .
				"<wp:BackBackgroundImage Action=\"Update\">".htmlspecialchars($backbackground_url)."</wp:BackBackgroundImage>" .
				"<wp:BackTitle Action=\"Clear\"></wp:BackTitle>" .
				"<wp:BackContent Action=\"Clear\"></wp:BackContent>" .
				"</wp:Tile>" .
				"</wp:Notification>";

	return $this->push('token',$delay+1, $message_id,$msg);
    }


	/**
	* If you do not wish to update the Tile or send a toast notification, you can instead send raw information to your application using a raw notification. If your application is not currently running, the raw notification is discarded on the Microsoft Push Notification Service and is not delivered to the device. The payload of a raw notification has a maximum size of 1 KB.
	*/
    public function push_raw($data, $delay = WindowsPhonePushDelay::Immediate,$message_id=NULL)
    {
        return $this->push(NULL,$delay+3,$message_id, $data);
    }


	/**
	*@target : type of notification
	*@delay : immediate, in 450sec or in 900sec
	*@message_id : The optional custom header X-MessageID uniquely identifies a notification message. If it is present, the same value is returned in the notification response. It must be a string that contains a UUID
	*/
    private function push($target,$delay,$message_id,$msg)
    {


		$sendedheaders=  array(
                            'Content-Type: text/xml',
                            'Accept: application/*',
							"X-NotificationClass: $delay"
                            );
		if($message_id!=NULL)
		$sendedheaders[]="X-MessageID: $message_id";
		if($target!=NULL)
		$sendedheaders[]="X-WindowsPhone-Target:$target";


		$req = curl_init();
        curl_setopt($req, CURLOPT_HEADER, true);
		curl_setopt($req, CURLOPT_HTTPHEADER,$sendedheaders);
        curl_setopt($req, CURLOPT_POST, true);
        curl_setopt($req, CURLOPT_POSTFIELDS, $msg);
        curl_setopt($req, CURLOPT_URL, $this->notif_url);
        curl_setopt($req, CURLOPT_RETURNTRANSFER, 1);
		$response = curl_exec($req);
		curl_close($req);

		$result=array();
		foreach(explode("
",$response) as $line)
		{
		$tab=explode(":",$line,2);
		if(count($tab)==2)
			$result[$tab[0]]=trim($tab[1]);
		}
		print_r($result);
     }
}



function umlaute_ersetzen($text){
$such_array  = array ('ä', 'ö', 'ü', 'ß');
$ersetzen_array = array ('ae', 'oe', 'ue', 'ss');
$neuer_text  = str_replace($such_array, $ersetzen_array, $text);
return $neuer_text;
}

Der Aufruf der Funktion erfolgt dann z.B. über:

	$notif=new WindowsPhonePushNotification($uri);
	$notif->push_raw($RawData);

Der URI wird im Telefon automatisch registriert und muss zu IP-Symcon übertragen werden, die Variable $RawData enthält dann den zu sendenden String der in der Telefon App nach dem Empfang aufbereitet werden kann. Bei mir wird der String z.B. so zusammen gesetzt:

$RawData = "IPSDaten=$Zeit;
IPSEGLicht=$IPSEGLicht;
.
.
.
";

In der Windows Phone App muss dann eben der PushChannel eingerichtet werden:

            // Holds the push channel that is created or found.
            HttpNotificationChannel pushChannel;
            // The name of our push channel.
            string channelName = "ToastChannel";


               this.Unloaded += new RoutedEventHandler(MainPage_Unloaded);


               pushChannel = new HttpNotificationChannel(channelName);

                // Register for all the events before attempting to open the channel.
                pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
                pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
                pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
                // Register for this notification only if you need to receive the notifications while your application is running.
                pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);

                pushChannel.Open();

                try
                { 
                // Bind this new channel for toast events.
                pushChannel.BindToShellTile();
//                MessageBox.Show(String.Format("pushChannel.BindToShellTile() erfolgreich"));
                }
                catch { }
                try
                {
                pushChannel.BindToShellToast();
//                MessageBox.Show(String.Format("pushChannel.BindToShellToast() erfolgreich"));
                }
                catch { }

Damit man die URI im IP-Symcon hat muss diese übertragen werden:

        void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {

            Dispatcher.BeginInvoke(() =>
            {
                // Display the new URI for testing purposes.   Normally, the URI would be passed back to your web service at this point.
                System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());
                URI = e.ChannelUri.ToString();
                settings["Uri"] = e.ChannelUri.ToString();
                settings.Save();
                postData1 = "Uri";
                postData2 = e.ChannelUri.ToString();
                SendPost();
//                MessageBox.Show(String.Format("Channel Uri upgedated {0}", e.ChannelUri.ToString()));
            });
        }

Dazu kommt noch der Abschnitt in dem die empfangenen Push-Raw-Daten verarbeitet werden sollen:


        //Aktionen beim Empfang von Push Raw Nachricht 
        void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
        {


            using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))
            {
                message = reader.ReadToEnd();
            }


//            Dispatcher.BeginInvoke(() => MessageBox.Show(String.Format("Update erhalten um {0}: {1}", DateTime.Now.ToShortTimeString(),message)));

        try
        {
            if (message.StartsWith("IPSDaten"))
            {
                string[] stringSeparators = new string[] { ";" };
                string[] Temp = message.Split(stringSeparators, StringSplitOptions.None);
                foreach (string n in Temp)
                {
                        string[] stringSeparators2 = new string[] { "=" };
                        string[] Temp2 = n.Split(stringSeparators2, StringSplitOptions.None);

                        if (Temp2[0].StartsWith("
"))
                        {
                            Temp2[0] = Temp2[0].Replace("
", "");
                        } 
                        if (Temp2[1] =="")
                        {
                            //settings[Temp2[0]] = 0;
                            Temp2[1] = Temp2[1].Replace("", "0");
                            //Dispatcher.BeginInvoke(() => MessageBox.Show(String.Format("n0:n1 in Temp2: {0} = false", Temp2[0])));
                        }
                        else
                        {
                            settings[Temp2[0]] = Temp2[1];
                            //Dispatcher.BeginInvoke(() => MessageBox.Show(String.Format("n0:n1 in Temp2: {0} = {1}", Temp2[0], Temp2[1])));
                        }
                        settings.Save();
                        
                  }

                
            }

        }
        catch { }

Die Empfangenen Daten speichere ich im IsolatedStorage, also noch

using System.IO.IsolatedStorage; 

und

IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

hinzufügen.

Die Daten vom Telefon werden bei mir über einen HttpWebRequest vom Telefon an IP-Symcon gesendet:

        //Daten an IP-Symcon übergeben
        void SendPost()
        {
            var url = "http://***.php";

            // Create the web request object
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.Method = "POST";
            webRequest.ContentType = "application/x-www-form-urlencoded";

            // Start the request
            webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
        }

        void GetRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
            // End the stream request operation
            Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);

            // Create the post data
            string postData = "param1=" + postData1 + "&" + "param2=" + postData2 + "&" + "param3=" + postData3 + "&" + "param4=" + postData4 + "&" + "param6=" + postData6;


            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Add the post data to the web request
            postStream.Write(byteArray, 0, byteArray.Length);
            postStream.Close();

            // Start the web request
            webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
        }

        void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            try
            {
                HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
                HttpWebResponse response;

                // End the get response operation
                response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
                Stream streamResponse = response.GetResponseStream();
                StreamReader streamReader = new StreamReader(streamResponse);
                var Response = streamReader.ReadToEnd();
                streamResponse.Close();
                streamReader.Close();
                response.Close();

            }
            catch (WebException e)
            {
                // Error treatment
                // ...
            }
        }

Damit der Webrequest die Daten an IP-Symcon übergeben kann habe ich unter Webfront eine PHP-Datei mit folgendem Inhalt erstellt:

<title>WPPushdienst</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="stylesheet" type="text/css" href="../webfront.css" />

<?php
  SetValueString(12345 ,$_REQUEST['param1']);
  SetValueString(12345 ,$_REQUEST['param2']);
  SetValueString(12345 ,$_REQUEST['param3']);
  SetValueString(12345 ,$_REQUEST['param4']);
  SetValueString(12345 ,$_REQUEST['param5']);
  SetValueString(12345 ,$_REQUEST['param6']);
?>

<HEAD></HEAD>

Im Großen und Ganzen wäre dass schon alles.
Da ich mit den Codeschnipseln noch ein bisschen mehr mache könnte man das Projekt je nach Bedarf noch etwas einschrumpfen.
Die Übertragung der Daten könnte man natürlich auch mittels JSON umsetzen, habe mich aber vorerst für den normalen Webrequest mit Parameterübergabe entschieden.
Da WP8 im Moment nur sehr eingeschränkt VPN unterstützt funktioniert die Lösung natürlich nur im lokalen Netzwerk oder wenn man die IP-Symcon-Webfront-Ports auf dem Router weiterleitet. Da das ein Sicherheitsrisiko ist möchte ich dies hier nicht empfehlen. Wenn es für WP8 bald auch Plugins für VPN über SSL/SSTP gibt und auto-triggered VPN wird das ganze wieder interessanter.

Ich hoffe ich konnte einen Anstoss zur Umsetzung geben, da ich selbst kein sehr erfahrener Programmierer bin freue ich mich auch über Verbesserungsvorschläge.

Gruß
Strichcode

Hallo Strichcode,
Hast Du schon auf WP 8.1 aktualisiert.
Dann könntest du das mit dem VPN evtl. Schon nutzen.
Es gibt dann im Store VPN SSL Apps z.B. von Checkpoint und Sonicwall.
Bin insgesamt mit dem Upgrade ganz zufrieden. Es läuft stabil auf meinem Ativ und hat ein paar nette neue Features. Lediglich die Akkulaufzeit ist ca. 10-20% schlechter.

Sent from my GT-I8750 using Tapatalk

Habe auch auf WP8.1 upgedated, im Moment weiss ich aber noch von niemandem der dass VPN mit SSTP zum Windows Server 2012 R2 hingekriegt hätte, da fehlt es wohl noch an den richtigen Plugins. Ansonsten bin ich auch soweit zufrieden. Ist hier aber wohl eher Off-Topic…

Stimmt, wäre nur interessant mit ner WP8 IPS App. Hatte such mal was angefangen aber leider zu wenig Zeit…

Sent from my GT-I8750 using Tapatalk