Premise Premise WebClient Protocol documentation

Motorola Premise

ckindel

Member
Hey Premise lovers - 
 
When I built my custom Windows Phone front end app for my Premise installation I did so using the REST like protocol that SYSConnector (the Premise ActiveX Control) uses. I got a little help from JImSpr in how this protocol worked and figured the rest out.
 
Last night, for some strange reason, I decided to actually take the time to document this protocol as far as I could.
 
In my app, which still works beautifully, I don't make use of subscriptions. I poll. I did so because it wasn't clear how subscriptions worked, and the use-cases in the app don't really require a lot of real-time updates. But now that I've taken the time to document this I can see exactly how they work and I think you will too. The trick is whatever client you write will have to talk HTTP directly over your own socket and can't use a higher level HTTP client library.
 
In any case, here you go:  I am happy to take pull requests on this if anyone has additional details.
 
https://github.com/tig/Premise
 
I plan on adding some sample code (in C#) when I get a chance.
 
Cheers!
 
https://github.com/tig/Premise/tree/master/PremiseWebClient
 

Premise WebClient .NET Client Library Project
Copyright © 2013 Kindel Systems
This project includes the following:
  • Premise WebClient .NET Client Library - A .NET library that should make it easy to build .NET apps that talk to Premise. Fully supports subscriptions so polling is not needed.
  • pr - A simple command line tool that makes it easy to exercise the client library.
Premise WebClient .NET Client Library
A .NET library for accessing Premise from .NET.
The Premise WebClient .NET Client Library makes it easy to build .NET apps that talk to Premise. It supports the entire Premise WebClient Protocol including subscriptions so polling is not needed. See README.md in that project for more details.
The client is written in C# 4.5 (Visual Studio 2012) and the library is built as .NET Portable Class Library (PCL) so it should work on ASP.NET, Windows Phone 7/8, Windows 8, Android (Xamarin), and iOS (Xamarin).

Installation
To add the PremiseWebClient library to your .NET, Windows Phone, or Windows 8 project use NuGet.
From the command line:
PM> Install-Package PremiseWebClient -Pre
Or use "Manage NuGet Packages" in Visual Studio.

Example Usage
This example illustrates connecting to a device (a light in my home office). It shows subscribing to both the Brightness properties and shows setting properties.
// Setup server connection
_server.Host = host;
_server.Port = port;
_server.Username = username;
_server.Password = password;

// Turn on subscriptions (optional if you don't want them)
await _server.StartSubscriptionsAsync();

// FastMode is off by default
_server.FastMode = true;

// Create a local object representing a server object
PremiseObject deskButton = new PremiseObject("sys://Home/Downstairs/Office/Keypad/Button_Desk");

// Create event handler to receive subscription notifications when the value of a
// property on this object changes on the server
deskButton.PropertyChanged += (sender, args) => {
// Note
var val = ((PremiseObject)sender)[PremiseProperty.NameFromItem(args.PropertyName)];
Console.WriteLine("{0}: {1} = {2}", ((PremiseObject)sender).Location, PremiseProperty.NameFromItem(args.PropertyName), val);
};

// Identify what properties you care about. In this case we care about 'Description'
// 'Status', and 'Trigger' because this is a keypad button.
// You can provide hints as to their types so that the library can coerce
// types between .NET and Premise.
await deskButton.AddPropertyAsync("Description", PremiseProperty.PremiseType.TypePercent);

// Notice for 'Status' we set the last parameter to true. This subscribes to
// changes. If you don't set this to true (or separately call "SubscribeToProperty"
// the property will not be subscribed by default. But the property will
// get updated from the server initially.
await deskButton.AddPropertyAsync("Status", PremiseProperty.PremiseType.TypeBoolean, true);

await deskButton.AddPropertyAsync("Trigger", PremiseProperty.PremiseType.TypeBoolean);

// Use array syntax to access the properties.
Console.WriteLine("deskButton Status is {0}", deskbutton["Status"]);

// From code you can trigger a Premise momentary property just by setting
// it to true
deskButton["Trigger"] = true;

// However, PremiseLib supports XAML Commands which make wiring up buttons in
// UI easy. Use the syntax "<name>Command" in your XAML or code and PremiseLib
// will automatically set the property to true under the covers.
deskButton["TriggerCommand"].Execute(null);
Example of setting properties in code.
PremiseObject entryLight = new PremiseObject("sys://Home/Upstairs/EntryLight");
await entryLight.AddPropertyAsync("Brightness", PremiseProperty.PremiseType.TypePercent, true);
entryLight["Brightness"] = entryLight["Brightness"] - .15;

// The preceding line will cause the Brightness property to change on the client. This
// will cause the value to get sent to the server.
// This will then result in a subscription update back to the client.
// Therefore the property change notification be called at least twice (once for when we
// changed the value locally and once when the server notified us).
// In some cases, the client will get multiple updates because the underlying driver
// in Premise rounds the value (Lutron does this).

// Note we can use Premise type syntax because PremiseProperty knows how to
// coerce for PremiseTypePercent types.
entryLight["Brightness"] = "33%";
This example shows how you would create an ObservableCollection that could be easily consumed by a XAML based application on Windows 8 or Windows Phone.
...
await PremiseServer.Instance.StartSubscriptionsAsync();

PremiseObject o1 = new PremiseObject("sys://Home/Downstairs/Office/Keypad/Button_Desk");
await o1.AddPropertyAsync("Description", PremiseProperty.PremiseType.TypeText);
await o1.AddPropertyAsync("Status", PremiseProperty.PremiseType.TypeBoolean, true);
await o1.AddPropertyAsync("Trigger", PremiseProperty.PremiseType.TypeBoolean);

PremiseObject o2 = new PremiseObject("sys://Home/Downstairs/Office/Keypad/Button_Workshop");
await o2.AddPropertyAsync("Description", PremiseProperty.PremiseType.TypeText);
await o2.AddPropertyAsync("Status", PremiseProperty.PremiseType.TypeBoolean, true);
await o2.AddPropertyAsync("Trigger", PremiseProperty.PremiseType.TypeBoolean);

KeypadButtons = new ObservableCollection<PremiseObject> {
(PremiseObject) o1,
(PremiseObject) o2
};
foreach (PremiseObject l in KeypadButtons) {
l.PropertyChanged += (s, a) => Debug.WriteLine("MVM: {0}: {1} = {2}",
((PremiseObject) s).Location,
a.PropertyName,
((PremiseObject) s)[a.PropertyName]);

}
}

private ObservableCollection<PremiseObject> _KeypadButtons;
public ObservableCollection<PremiseObject> KeypadButtons {
get { return _KeypadButtons; }
set { _KeypadButtons = value; RaisePropertyChanged("KeypadButtons"); }
}
}
The corresponding XAML:
<ListBox x:Name="Lighting" ItemsSource="{Binding Path=KeypadButtons}" >
<ListBox.ItemTemplate>
<DataTemplate >
<Grid Margin="6">
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding [Description]}" VerticalAlignment="Center" Width="120" />
<TextBlock Text="{Binding [Status]}" VerticalAlignment="Center" Width="120" />
<Button Content="Trigger" Command="{Binding [TriggerCommand]}" Width="186" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The beauty of the above is that the button is automatically disabled if there is no connection to the server.

Other examples
  • pr - A command line example included in the PremiseLib project
  • PremiseMetro - a Win8/WinRT example.
What's Next?
  • Put the library on NuGet
  • Incorporate it into an Android app using Xamarin (Mono). This will suss out all cross-platform issues.
  • Build an iOS test app.
  • Re-write my Windows Phone app to use this instead of my hack-job I'm currently using.
 
Charlie,
 
Excellent job!!!!...except I do not currently have the technical skills to know how to implement what you're talking about...can you do a 'Premise subscriptions for Dummies/Chuck' version?
 
chucklyons said:
Charlie,
 
Excellent job!!!!...except I do not currently have the technical skills to know how to implement what you're talking about...can you do a 'Premise subscriptions for Dummies/Chuck' version?
 
For now, what I've built is pretty much a prototype and probably not useful to others as anything more than proof that "Yes, it is completely possible, and relatively easy, to speak the Premise WebClient protocol from any modern programming platform, including .NET."
 
What I've built is not going to directly help the implementation of browser based things like JQM, because for that we need a Javascript implementation (which I have no intention of writing). But someone else can now proceed with building the equivalent of SYSConnector in Javascript (assuming one can get Javascript to actually talk over sockets, which I understand is possible).
 
I have always hated AutomationBrowser and never really use it. JQM helps alot, but to me is just a 'backup' for when a native app can't/won't work.  
 
My plan for my .NET work is to make the core PremiseLib library that talks the protocol be a portable .NET library that can run on Windows Phone, Windows 8, Android (via Xamarin/Mono), and iOS (via Xamarin/Mono).
 
My wife uses an iPhone so I need to build a version of my native home control app I have for Windows phone for iOS...which is REALLY my motivation for doing all this.
 
Because the architecture of how PremiseLib works is fairly clean I totally plan on making my native apps open source. My Windows Phone app is a disgusting mess inside and not only would I be embarrassed for others to see the code, it would only lead to world hunger, more cancer, and probably WWIII if others started using it.  
 
Note, that my current WP app is hard coded to my home. It does not dynamically generate screens from the layout in Builder. And I plan on keeping things that way, for the most part. I simply do not believe that a home-hierarchy based UI is the way to go. So, even when I build these new apps, they will only serve as guides for others.
 
Charlie,
 
This is neat work you are doing!  If you build the android version of your app, I'd be a willing beta tester.  I remember the beautiful windows phone 7 screen shots you teased us with.  It sounds like this new app your building will be very generic and open-source, how awesome is that? :)
 
Charlie,
 
You totally Rock!!!!  I was working on a .NET version of a library that exposes Premise as a set of WCF services.   You beat me to it!  Thanks!!!!!!
 
Yes, I'm on-board. I think the jqm move is heading towards the right direction, but I think there's more to do. W84's ajax is pretty cool. It probably needs some smart guys (or gals) to make it tighter than I can do right now. I am interested in hearing what would replace the hierarchical home that builder provides. It is, IMO, one of the more challenging aspects of Premise, but I am currently lost as to what something else would look like... 
 
Folks, 
 
I've made a bunch of progress on this. Here's where the currently checked in code stands:
 
  • Core library seems complete & reliable. 
  • pr.exe sample app works great
  • I've built a sample Win8/WinRT app that let me figure out the best way to ensure that subscriptions and triggers would work in XAML. I had to re-factor my original design to use array syntax for acessing properties instead of C#'s "dynamic" because Win8/XAML does not support data binding to 'dynamic' properties (a known bug that is "won't fix" by microsoft).
  • Docs are updated
I still am not ready for others to start using this because I have not done the following:
 
  • Re-factor the core library such that platform differences (e.g. stock .NET, WinRT, WIndows Phone, Mono) are isolated gracefully.
  • Built in support for authentication for subscriptions (it works fine if you don't want to use subscripitons at all, but I had to write my own HTTP client for the subscription stuff directly on sockets and have not yet implemented auth for that; I'm just testing it on my local network with auth turned off in Premise).
  • Write a Xamarin/Mono android test that proves the library will work on Android/Mono
  • Write a Windows Phone 8 test app that proves it will work with WP's version of .NET
But for now, you can go look at the docs and see some example code illustrating how it works. I'm quite proud of how elegant not only the use-code is but the actual implementation. Especially compared to my previous attempt.
 
Read all about it here:
 
https://github.com/tig/Premise/tree/master/PremiseWebClient
 
Thoughts, suggestions, questions welcome...
 
Charlie, very nice!!!!
 
I'm tired and going to bed, but I'm very excited about what you've done! (and didn't want to forget giving you some kudos! - sometime responses here are slow to appear)
 
chucklyons said:
Yes, I'm on-board. I think the jqm move is heading towards the right direction, but I think there's more to do. W84's ajax is pretty cool. It probably needs some smart guys (or gals) to make it tighter than I can do right now. I am interested in hearing what would replace the hierarchical home that builder provides. It is, IMO, one of the more challenging aspects of Premise, but I am currently lost as to what something else would look like... 
 
 
JQM polling(ajax) was just a band-aid that I thought of when I needed my android phone to work with Premise.  Native apps would work a lot better.  Running all the JavaScript is taxing on the browser, luckily tablets and smart phones have blown up since I first added JQM to Premise  :D All the work that has been done by you guys is awesome, you rock :rockon:
 
Charlie,
 
You mention in the protocol description that the built-in object methods (e.g. IsOfExplicitType) do not work.  Have you found a way to make that happen with your library?
 
This is an awesome contribution you've made!!!!!!
 
-John
 
I have verified that built-in object methods such as IsOfExplicitType are not available via the invoke method command.
 
However, it would be easy to define your own method on any class that could call IsOfExplicitType for you.
 
You could define an override of Object (or other class) that has a method CheckIsOfExplicitType(strClass)
 
method.CheckIsOfExplictType = this.IsOfExplicitType(method.strClass)
 
I tested this by adding CheckIsOfExplicitType to the Occupancy class and in my test client wrote this code:
 
string s = await _server.InvokeMethodTaskAsync("sys://Home/Downstairs/Office", "CheckIsOfExplicitType(\"sys://Schema/Home/Location\")");
Console.WriteLine("Result: {0}", s);
 
the console read "Result: -1".  -1 is the representation of true in vbscript. So it works.
 
Volunteering to test an IOS app if needed.  ^_^  My hope was to eventually write a native iPhone/iPad app (and finally put my developer subscription to use) once I finished writing drivers for all of my devices and getting everything integrated w/Premise.  Great to hear someone with much more experience is headed in the same direction! :pray:
 
Back
Top