Scott Hanselman

Podcast Update with Guest Spots and a New Show - October 2012

October 30, '12 Comments [5] Posted in Podcast
Sponsored By

I've been on a podcasting kick lately. Not for any particular reason, but a number of things have come together that have found me as a guest on a number of podcasts. I've also had the good fortune to have a number of great guests on Hanselminutes lately.

Lots of folks who listen to podcasts are doing it while commuting. I hope you enjoy these additional podcasts and perhaps they'll edutain you during your daily commute.

I hope you take a few minutes and download a few of these shows.


imageStackExchange Podcast #35

Just last week my buddy Joel Spolsky had me on the 35th episode of the new StackExchange Podcast. I've complained about podcasts that are "just talk" before and brought my prejudice to Joel's show, but we have so much fun just beating each other up that I have to admit defeat. Not ever podcast has to be dense with information and content - and this episode is no exception. ;)

I hope they'll have me back soon.


ratchetandthegeeksquareAnnouncing - Ratchet and The Geek #1

Just a few days ago I launched my third podcast as a collaboration with my good friend Luvvie. Luvvie is a social media consultant and popular humor blogger that I've known for years. We've been kicking around the idea of a podcast since early this Spring. We have such fun when we call each other on the phone, why don't we start recording our calls? (and adding a little structure.)

Luvvie has blogging, social media and marketing expertise, while I'm a coder and teacher. We both like the same music, pop culture, TV shows, movies, gadget and technology so we have mashed it all together into Ratchet and The Geek.

We'll be doing the show late late on Thursday nights every two weeks.


image

Fanboy Radio #616

I've been REALLY getting into Digital Comics via Comixology over the last year and blogged about it in some detail (with animated gifs!) and earlier this year I was a guest on an episode of Fanboy Radio.

Fanboy Radio (or 'FbR') is a radio talk show all about pop culture and entertainment from the fan's perspective. It's also broadcast on the radio in Fort Worth, Texas.

We had a great chat, covering the rise of digital comics, Comixology, GuidedView technology and lots more. The guys were a lot of fun and it was an opportunity for me to geek out about something that isn't programming or computers. (I DO have other interests, you know.)


imageSimple Mobile Review (SMRPodcast) #136

Last month I was on Simple Mobile Review at the invitation of Chris Ashley. We talked about phones and NFC technology and if it will ever take off. We discussed the new iPhone 5 and teased Robb for sticking with his BlackBerry.

It was a great time and we spent a bunch of time teasing each other, which is an important part of any good podcast.


dramaThis Developer's Life - Drama

Some of you may have missed the most recent episode of This Developer's Life from last month. Rob and I asked ourselves where does drama come from? How do we react to it? How much drama can be created by simple semicolon? We explore The Great JavaScript Semicolon Affair with guests like

  • Peter Cooper Friendly publisher, programmer and author
  • Derick Bailey Consultant and aspiring microprenuer
  • H. Alan Stevens Father, Geek & Speaker
  • Dave Ward Software developer focusing on jQuery and web application usability.
  • Sara Chipps Just a girl, standing in front of a compiler, asking it to love her.
  • Tenderlove When I'm not trimming my beard, I'm hanging out with my lady.

This Developer's Life is sponsored out of kindness by the epic win that is DevExpress.


Hansel-Minutes-LogoHanselminutes Podcast Rollup

If I may be so bold as to say Hanselminutes has been pretty good lately. I've had some great guests - many suggested by listeners! - and some great conversations. Here's just this month:

This week's show has a special offer for listeners from DNSimple, my DNS service of choice. Four months free at http://dnsimple.com/hm. Did you miss one of these shows perhaps? Why not subscribe now so you don't miss another show?


Sponsor: Big thanks to this week's sponsor. Check them out, it's a great program, I've done it and spoken to actual live humans who help you get started writing an app! Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today. Your Idea. Your App. 30 Days.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Cloud-Controlled Remote Pan Tilt Zoom Camera API for a Logitech BCC950 Camera with Azure and SignalR

October 23, '12 Comments [33] Posted in Hardware | Lync | Open Source | Remote Work
Sponsored By

I like my giant blog post titles. Nyah.

Logitech BCC950 ConferenceCam, HD 1080p Video at 30 fps, 78deg. Field of View, USB 2.0 CompliantAs a remote worker for almost 5 years now, I live in video conferences. I feel really strongly about the power of seeing someone's face rather than just being a voice on a scratchy speaker phone. I've build an AutoAnswer Kiosk for Lync with some friends that you can get for free at http://lyncautoanswer.com (and read about the code here), I've got a BusyLight so the kids know I'm on a call, and the Holy Grail for the last few years has been a reliable Pan Tilt Zoom camera that I could control remotely.

Related Reading

A few years ago I super-glued a LifeCam camera to an Eagletron TrackerPod and build a web interface to it. I wanted to do this on the cheap as I can't afford (and my boss is into) a $1500 Panasonic IP Camera.

The Solution...er, the Problem

I have found my camera and built my solution. The Logitech BCC950 Conference Cam is the best balance between cost and quality and it's got Pan Tilt and (digital) Zoom functionality. The Zoom is less interesting to me than the motorized Pan Tilt.

Let's think about the constraints.

  • A Logitech BCC950 PTZ camera is installed on a Windows machine in my office in Seattle.
  • I'm anywhere. I'm usually in Portland but could be in a hotel.
    • I may or may not be VPN'ed into work. This means I want to be able to communicate with the camera across networks, traverse NATs and generally not worry about being able to connect.
  • I want to be able to control the camera in a number of ways, Web API, whatever, but ideally with cool buttons that are (or look) integrated with my corporate instant messaging system.

There's three interesting parts here, then.

  1. Can I even control the camera's PTZ functions programmatically?
  2. Can I relay messages across networks to the camera?
  3. Can I make a slick client interface easily?

Let's figure them out one at a time.

Can I even control the camera's PTZ functions programmatically?

I looked all over and googled my brains out trying to find an API to talk to the Logitech camera. I emailed the Logitech people and they folks me that the camera would respond to DirectShow APIs. This means I can control the camera without any drivers!

MSDN showed me PROPSETID_VIDCAP_CAMERACONTROL which has an enumeration that includes things like:

This lead me to this seven year old DirectShow .NET library that wraps the hardest parts of the DirectShow COM API. There's a little utility called GraphEdt.exe (GraphEdit) that you can get in the Windows SDK that lets you look at all the DirectShow-y things and devices and filters on your system.

GraphEdit

This utility let me control the camera's Zoom but Pan and Tilt were grayed out! Why?

GraphEdit showing Pan and Tilt grayed out

Turns out that this Logitech Camera supports only relative Pan and Tilt, not absolute. Whatever code that creates this Properties dialog was never updated to support a relative pan and tilt but the API supports it via KSPROPERTY_CAMERACONTROL_PAN_RELATIVE!

That means I can send a start message quickly followed by a stop message to pan. It's not super exact, but it should work.

Here's the C# code for my move() method. Note the scandalous Thread.Sleep call.

private void MoveInternal(KSProperties.CameraControlFeature axis, int value)
{
// Create and prepare data structures
var control = new KSProperties.KSPROPERTY_CAMERACONTROL_S();

IntPtr controlData = Marshal.AllocCoTaskMem(Marshal.SizeOf(control));
IntPtr instData = Marshal.AllocCoTaskMem(Marshal.SizeOf(control.Instance));

control.Instance.Value = value;

//TODO: Fix for Absolute
control.Instance.Flags = (int)CameraControlFlags.Relative;

Marshal.StructureToPtr(control, controlData, true);
Marshal.StructureToPtr(control.Instance, instData, true);
var hr2 = _ksPropertySet.Set(PROPSETID_VIDCAP_CAMERACONTROL, (int)axis,
instData, Marshal.SizeOf(control.Instance), controlData, Marshal.SizeOf(control));

//TODO: It's a DC motor, no better way?
Thread.Sleep(20);

control.Instance.Value = 0; //STOP!
control.Instance.Flags = (int)CameraControlFlags.Relative;

Marshal.StructureToPtr(control, controlData, true);
Marshal.StructureToPtr(control.Instance, instData, true);
var hr3 = _ksPropertySet.Set(PROPSETID_VIDCAP_CAMERACONTROL, (int)axis,
instData, Marshal.SizeOf(control.Instance), controlData, Marshal.SizeOf(control));

if (controlData != IntPtr.Zero) { Marshal.FreeCoTaskMem(controlData); }
if (instData != IntPtr.Zero) { Marshal.FreeCoTaskMem(instData); }
}

All the code for this PTZDevice wrapper is here. Once that library was working, creating a little console app to move the camera around with a keyboard was trivial.

var p = PTZDevice.GetDevice(ConfigurationManager.AppSettings["DeviceName"], PTZType.Relative);
while (true)
{
ConsoleKeyInfo info = Console.ReadKey();
if (info.Key == ConsoleKey.LeftArrow)
{
p.Move(-1, 0);
}
else if (info.Key == ConsoleKey.RightArrow)
{
p.Move(1, 0);
}
else if (info.Key == ConsoleKey.UpArrow)
{
p.Move(0, 1);
}
else if (info.Key == ConsoleKey.DownArrow)
{
p.Move(0, -1);
}
else if (info.Key == ConsoleKey.Home)
{
p.Zoom(1);
}
else if (info.Key == ConsoleKey.End)
{
p.Zoom(-1);
}
}

Also easy was a simple WebAPI. (I put the name of the camera to look for in a config file in both these cases.)

[HttpPost]
public void Move(int x, int y)
{
var p = PTZDevice.GetDevice(ConfigurationManager.AppSettings["DeviceName"], PTZType.Relative);
p.Move(x,y);
}

[HttpPost]
public void Zoom(int value)
{
var p = PTZDevice.GetDevice(ConfigurationManager.AppSettings["DeviceName"], PTZType.Relative);
p.Zoom(value);
}

At this point I've got the camera moving LOCALLY. Next, I mail it to Damian (my office buddy) in Seattle and he hooks it up to my office computer. But I need something to control it running on THAT machine...and talking to what?

Can I relay messages across networks to the camera?

Here's the architecture. Since I can't talk point to point via TCP between wherever I am and wherever the camera is, I need a relay. I could use a Service Bus Relay which would be great for something larger but I wanted to see if I could make something even simpler. I'd like to use HTTP since it's, well, it's HTTP.

A Diagram showing my laptop talksk via SignalR through Azure to the camera in Seattle

Since Azure lets me have 10 free websites and automatically supports SSL via a wildcard cert for sites at the *.azurewebsites.net domain, it was perfect for what I needed. I want to use SSL because it's the best way to guarantee that my traffic not be affected by corporate proxy servers.

There's three parts. Let's start in the middle. What's the Relay look like? I'm going to use SignalR because it will let me not only call methods easily and asynchronously but, more importantly, it will abstract away the connection details from me. I'm looking to relay messages over a psuedo-persistent connection. 

So what's the code look like for a complex relay system like this? ;)

using System;
using SignalR.Hubs;

namespace PTZSignalRRelay
{
public class RelayHub : Hub
{
public void Move(int x, int y, string groupName)
{
Clients[groupName].Move(x, y); //test
}

public void Zoom(int value, string groupName)
{
Clients[groupName].Zoom(value);
}

public void JoinRelay(string groupName)
{
Groups.Add(Context.ConnectionId, groupName);
}
}
}

Crazy, eh? That's it. Clients call JoinRelay with a name. The name is the name of the computer with the camera attached. (More on this later) This means that this single relay can handle effectively any number of clients. When a client calls to Relay with a message and group name, the relay then broadcasts to clients that have that group name.

Can I make a slick client interface easily?

I created a super basic WPF app that's just a transparent window with buttons. In fact, the background isn't white or black, it's transparent. It's a SolidColorBrush that is all but invisible. It's not totally transparent or I wouldn't be able to grab it with the mouse!

<SolidColorBrush x:Key="NotQuiteTransparent" Color="#01000000"></SolidColorBrush>

The buttons use the .NET SignalR library and call it like this.

HubConnection connection = null;
IHubProxy proxy = null;
string remoteGroup;
string url;

private void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}

private async void MoveClick(object sender, RoutedEventArgs e)
{
var ui = sender as Control;
Point p = Point.Parse(ui.Tag.ToString());
await proxy.Invoke("Move", p.X, p.Y, remoteGroup);
}

private async void ZoomClick(object sender, RoutedEventArgs e)
{
var ui = sender as Control;
int z = int.Parse(ui.Tag.ToString());
await proxy.Invoke("Zoom", z, remoteGroup);
}

private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
url = ConfigurationManager.AppSettings["relayServerUrl"];
remoteGroup = ConfigurationManager.AppSettings["remoteGroup"];
connection = new HubConnection(url);
proxy = connection.CreateProxy("RelayHub");
await connection.Start();
await proxy.Invoke("JoinRelay", remoteGroup);
}

The client app just needs to know the name of the computer with the camera it wants to control. That's the "GroupName" or in this case, from the client side, the "RemoteGroup." Then it knows the Relay Server URL, like https://foofooserver.azurewebsites.net. The .NET client uses async and await to make the calls non-blocking so the UI remains responsive.

Here's a bunch of traffic going through the Relay while I was testing it this afternoon, as seen by the Azure Dashboard.

Traffic as shown in a graph on the Azure Dashboard

The client calls the Relay and the Relay broadcasts to connected clients. The Remote Camera Listener responds to the calls. We get the machine name, join the relay and setup two methods that will respond to Move and Zoom.

The only hard thing we ran into (Thanks David Fowler!) was that the calls to the DirectShow API actually have to be on a UI thread rather than a background thread, so we have to get the current SynchronizationContext and post our messages with it. This results in a little indirection but it's not too hard to read. Note the comments.

private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var deviceName = ConfigurationManager.AppSettings["DeviceName"];
device = PTZDevice.GetDevice(deviceName, PTZType.Relative);

url = ConfigurationManager.AppSettings["relayServerUrl"];
remoteGroup = Environment.MachineName; //They have to hardcode the group, but for us it's our machine name
connection = new HubConnection(url);
proxy = connection.CreateProxy("RelayHub");

//Can't do this here because DirectShow has to be on the UI thread!
// This would cause an obscure COM casting error with no clue what's up. So, um, ya.
//proxy.On<int, int>("Move",(x,y) => device.Move(x, y));
//proxy.On<int>("Zoom", (z) => device.Zoom(z));

magic = SynchronizationContext.Current;

proxy.On<int, int>("Move", (x, y) => {
//Toss this over the fence from this background thread to the UI thread
magic.Post((_) => {
Log(String.Format("Move({0},{1})", x,y));
device.Move(x, y);
}, null);
});

proxy.On<int>("Zoom", (z) => {
magic.Post((_) =>
{
Log(String.Format("Zoom({0})", z));
device.Zoom(z);
}, null);
});

try {
await connection.Start();
Log("After connection.Start()");
await proxy.Invoke("JoinRelay", remoteGroup);
Log("After JoinRelay");
}
catch (Exception pants) {
var foo = (WebException)pants.GetBaseException();
StreamReader r = new StreamReader(foo.Response.GetResponseStream());
string yousuck = r.ReadToEnd();
Log(yousuck);
throw;
}
}

It All Works Together

Now I've got all the parts. Buttons that call a Relay that then call back - through NAT and networks - to the Remote Camera Listener which uses the Camera library to move it.

It's ALIVE and it's awesome

It works like a champ. And, because the buttons are transparent, I can put them over the Lync window and pretend it's all integrated.

TODO: I'm hoping that someone who knows more about Windows Internals will volunteer to create some code that will automatically move the buttons as the Lync Window moves and position them over the video window in the corner. Ahem.

The buttons look integrated. But they aren't.The buttons look integrated. But they aren't.

You can set this up yourself, but I haven't gotten around to making an install or anything. If you have a Logitech BCC950 you are welcome to use my Relay until it costs me something. There's a preliminary download up here so you'd only need the Listener on one side and the Buttons on the other. No drivers are needed since we're using DirectShow itself.

This was great fun, and more importantly, I use this PanTiltZoom System ever day and it makes my life better. The best was that I was able to do the whole thing in C#. From client UI to cloud-based relay to device control to COM wrapper, it was all C#. It makes me feel very empowered as a .NET developer to be able to make systems like this with a minimal amount of code.

Lync Developer Resources

Related Links


Sponsor: Big thanks to this week's sponsor. Check them out, it's a great program, I've done it and spoken to actual live humans who help you get started writing an app! Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today. Your Idea. Your App. 30 Days.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Instapaper delivered to your Kindle changes how you consume web content - Plus IFTTT, blogs and more

October 18, '12 Comments [29] Posted in Reviews
Sponsored By

I've talked about Instapaper before when I tease folks of having 42 tabs open.

Instapaper - Google Chrome

Remember that "open in new tab" rarely means "read it later." It usually means "use up memory and let this page run in the background until eventually declare tab-bankruptcy and close them all."

Kindle Instapaper Photo by Joshua Kaufman via Flickr under CC BY-SA 2.0 http://www.flickr.com/photos/joshuakaufman/5020686891/So if Open In New Tab doesn't mean Read Later, what does? Why, READ LATER does! This gets even better when you combine a Read Later tool like Instapaper with an Amazon Kindle like my new Kindle Paperwhite (I reviewed the Paperwhite last week.)

Inserting a Kindle into your Life's Workflow

Here's the idea. You get a bunch of links that flow through your life all week long. These are often in the form of what I call "long-form reading." Hackernews links, NYTimes studys, academic papers, etc. Some folks make bookmarks, have folders called "Links" on their desktops, or email themselves links.

I have these websites, papers and interesting links rolled up and delivered automatically to my Kindle every week. Think about how amazing that is and how it can change your relationship with content on the web. The stress and urgency (and open tabs) are gone. I am naturally and organically creating a personalized book for weekend reading.

I have a bookmarklet from Instapaper that says "Read Later" on my browser toolbar. I've put it in every browser I use, even Mobile Safari. I've also logged into Instapaper from all my social apps so that I can Read Later from my iPhone Twitter Client for example. You'd be surprised how many apps support Instapaper once you start looking for this.

Workflow Flow Chart - sorry if you are blind. There's text about this soon.What this means it is that Instapaper is ready and waiting for me in every location where an interesting piece of long-form reading could present itself. I don't stress, I click Read Later and the document is shipped off to Instapaper.

I even made a flowchart a few years back. You can get more details on that in my blog post Two Must-Have Tools for a More Readable Web.

Instapaper delivered to your Kindle

So you're building a queue of links that is sent to Instapaper. Perhaps you've tried this  before but then never visited the Instapaper App or Website. This is a common complaint and why I like document delivery to the Kindle. I use my Kindle all the time so I appreciate a "no clicks required" workflow. If books show up on my Kindle I'll read them.

Just visit http://www.instapaper.com/user/kindle once you've got an Instapaper account and put in your Kindle's email address. Did you know every Kindle has one? It's either something@free.kindle.com for free WiFi delivery or just something@kindle.com for 3G delivery with a small fee. I use the free one. You can find out your Kindle's Email Address here under Personal Document Settings.

The key is to allow your Kindle to receive email from the unique Instapaper email address. It's a whitelist.

image

Then, back over in the Instapaper Settings, I set a delivery time if at least 5 things are in the "book":

image

Pulling Links and Content from other Locations with IFTTT

Perhaps you pull your content from elsewhere, or you Like things on Facebook, put them in Dropbox, email them to a special address or something else. You can use If This Then That as the social workflow glue to route those links to Instapaper - and ultimately to your Kindle!

For example, I also use the Delicious social bookmarking service to hold things I want to save. But, I also want to read them and I don't want to stop using Delicious just because I use Instapaper. Instead, I use an IFTTT Recipe to  take newly bookmarked things and send them to Instapaper (and my Kindle!) as well.

Here's my Delicious to Kindle Recipe. You can make any recipe you want to pull links from wherever you find them and send them into your long-form reading queue.

image

You can even have blogs - like this one! - sent automatically to your Kindle via Instapaper with an IFTTT recipe like this:

image

The possibilities are endless.

Conclusion

It can't be overstated how useful this is if you have a Kindle. Rather than opening "guilt-tabs" that you'll never read, have them delivered to yourself in a way that will encourage you TO READ THEM!

If your system isn't working for you, change it. If you already have a system that works, well, great job making it all the way to the end of this blog post!

For more personal productivity ideas watch my video on Scaling Yourself and visit the Productivity section of this blog.


This Week's Sponsor: Your Idea. Your App. 30 Days. Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

How to call WinRT APIs in Windows 8 from C# Desktop Applications - WinRT Diagram

October 12, '12 Comments [28] Posted in Win8 | Windows Client
Sponsored By

I was trying to access some of the sensors that are built into this Intel Ultrabook that runs Windows 8. However, while there's support for Location Sensors built into the .NET 4 libraries on Windows 7 and up, I want to access the complete Sensor and Location Platform that is built into Windows 8 itself. Those APIs are available via COM and I could call them via COM, but calling them via the WinRT layer is so much nicer. Plus, this is kind of why WinRT exists.

This got me thinking about WinRT and what it means. I did a podcast a few months ago that really cleared things up but I've always found all the various diagrams that attempted to explain how things fit together to be WAY TOO COMPLEX.

DISCLAIMER: All diagrams are, by their nature, oversimplifications. I work on Web Stuff, not Windows Stuff, so this is all my opinion and conjecture, done on my own time. I'm not in the Windows org, I'm just a dude trying to write an app for babies.

I figure it can't be as complicated as all these diagrams. I drew this to help myself understand.

WinRT Diagram

Just like the C Language has the C Runtime that provides a bunch of supporting functions and defines a calling convention for them, so the Windows Runtime (WinRT) does for Windows and its languages. These APIs and runtime includes metadata about calling conventions that make WinRT APIs easier to call than COM.

See how in the diagram I can call any API from the .NET CLR? In the case of the Sensors APIs I want to call, while they are ultimately Win32 APIs or COM APIs, I would like to call them using the highest level calling convention available and that's the very friendly Windows RT ones.

Calling WinRT APIs from C# Desktop Applications

I like to test things using small Console Apps, but those aren't "Windows Store Applications," so am I allowed to call WinRT APIs from my Desktop or Console application?

Sure. There's actually a section of the MSDN Documentation that lists out all the WinRT APIs for Windows 8 that are able to be called from the Desktop. I can specifically check the LightSensor class itself within the documentation and make sure it's allowed to be called from Desktop applications.

LightSensor is allowed to be called from Desktop Apps

There isn't super-clear but there IS documentation on how to add WinRT references to non-Windows Store applications.

Adding a Reference to WinRT from a Desktop App

The docs say, somewhat obscurely:

In the desktop projects, the Core tab doesn’t appear by default. The user can choose to code against the Windows Runtime by opening the shortcut menu for the project node, choosing Unload Project, adding the following snippet, opening the shortcut menu for the project node again, and then choosing Reload Project. Now, when the user invokes the Reference Manager dialog box from the project, the Core tab will appear.

   <propertygroup>
    <targetplatformversion>8.0</targetplatformversion>
  </propertygroup>

I'll make a .NET 4.5 C# Console Application. I'll edit the .csproj and add the TargetPlatformVersion line. I'll select Add Reference from the context menu on the References node of Solution Explorer.

Windows Core References

I'll add a little code to check the status of the Light Sensor on my laptop:

LightSensor light = LightSensor.GetDefault();
if (light != null)
{
uint minReportInterval = light.MinimumReportInterval;
uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
light.ReportInterval = reportInterval;

light.ReadingChanged += light_ReadingChanged; //event hander
}

However, when I compile the app, I get an error on the line where I'm trying to hook up an event handler. The "+=" language sugar for adding a multicast delegate isn't working.

Error    1    Property, indexer, or event 
'Windows.Devices.Sensors.LightSensor.ReadingChanged'
is not supported by the language; try directly calling accessor
methods 'Windows.Devices.Sensors.LightSensor.add_ReadingChanged
(Windows.Foundation.TypedEventHandler
Windows.Devices.Sensors.LightSensorReadingChangedEventArgs>)'
or 'Windows.Devices.Sensors.LightSensor.remove_ReadingChanged
(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)'

To fix this and get the appropriate assemblies loaded within my application support calling WinRT from my Desktop Application I need to add a reference to System.Runtime and System.Runtime.InteropServices.WindowsRuntime.dll. It's in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5 on my system.

System.Runtime.InteropServices.WindowsRuntime.dll in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5

Now my app compiles. I'll even change out the delegate and make it a Anders lambda because that's fancy.

light.ReadingChanged += (s, a) =>
{
Console.WriteLine(String.Format("There was light! {0}", a.Reading.IlluminanceInLux));
};

Now I can run my little console app, sense some light and check it out in action. Here's a screenshot showing the results of me shining a light at my laptop. You can see the Ambient LightSensor picks it up and outputs to the Console.

The ambient light sensor reacting

While the tooling to make non-Windows Store applications call Windows RT applications is a little manual within Visual Studio right now, the underlying ability and runtime have work very nicely for me. Hopefully these few manual setups will turn into a checkbox at some point.

It's also nice to see the MSDN documentation includes the details about which APIs actually can be called from the Desktop and which can be called from Windows Store apps.


This week's sponsor: Your Idea. Your App. 30 Days. Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Intel Ultrabook hardware prototype - Windows 8 and the Sensor Platform

October 12, '12 Comments [9] Posted in Reviews | Win8
Sponsored By

What better time to test the Sensors in this Intel Ultrabook prototype then while in the air? I'm on a flight right now from Krakow, Poland to Munich, Germany, and I realized this was the perfect time to bring out this little 3 pound wonder. Even better because I received an email just a few days before with updated Sensor Firmware for this device.

I did an initial review of this non-production Ultrabook last month as well as an unboxing and initial impressions video on YouTube. Check the video out below. I've recently added closed-captioning.

Since that time I've been using this Ultrabook almost exclusively as my main machine, even preferring it over my giant (but super powerful) Lenovo W520. I've always been one to prefer the heavier laptop over a lighter one as long as it's got the power I need. However the i7-3667 Ivy Bridge in this system has been just fine for everything I could throw at it - even running Windows 7 and Ubuntu  in a Hyper-V virtual machine while running Visual Studio 2012 under Windows 8. My only real complain so far has been that this model I was provided for review purposes has only 4 gigs of RAM and not 8 or 12. I feel like 4gigs is a real minimum for the kinds of computing I'm doing. That said, the 160 gig Intel SSD has been so fast that I haven't really noticed the lack of memory except when pushing two VMs really hard.

Anyway, I wanted to focus on the sensors as this prototype has all the possible sensors an Ultrabook can have, the most initially interesting sensor to me being the GPS and Location Services.

You can get sensor data in a number of ways. I figured I'd try a few.

There's a Windows 8 Bing Maps Geolocation Sample you can get. It is C# and XAML and uses the Bing Map SDK. You have a little work to do in that you need to:

  • Make sure you have a version of Visual Studio that can make Windows 8 apps. There's a free Express version.
  • Get the Bing Maps SDK for Windows 8 . This just came out last week. There's JavaScript, C#, C++ andVB support.
  • Register at http://bingmapsportal.com for a free Trial key for your Windows 8 Store app.
    • Take the resulting key and put it in the XAML markup under "Credentials" of the bm:Map control.

There's also a much simpler (no map) Geolocation Sample that you can just download and run. It includes three scenarios: ongoing tracking of your position, a one time "get" of your position, and a background task that gets your position even after your application has been shutdown. As with all Windows 8-type apps you'll automatically get a permission popup when an application asks for something sensitive like your location.

The code is pretty simple, in fact. There's a Windows.Devices.Geolocation namespace with a Geolocator class. It has both PositionChanged and StatusChanged events. Since you can't physically move your device every time (although I'm flying now) you can actually run your application inside the Windows "Simulator" and effectively LIE about the location.

In the screenshot below I've taken my actual location that was reported by the physical GPS inside this Ultrabook and moved it a few thousand miles using the black menu popup from the Simulator and saw the underlying value reported change. Note the "use simulated location" checkbox. You can change between the sensor subsystem and the faked GPS values.

Running a geolocation sample in the simulator and lying about the location

Here you can see me flying over the Atlantic Ocean while on my flight.

I'm the Mayor of this part of the Atlantic

Accessing the Sensors are very easy from Windows 8 as there's now a unified Sensor and Location Platform. You don't have to sweat 3rd party drivers, just ask Windows if it knows things like brightness or location and it will tell you if it knows.

You can access at least Location Services via System.Device under .NET on Windows 7 as well. Here's a quick example Console app I did to prove it to myself:

GeoCoordinateWatcher foo = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
foo.MovementThreshold = 10;

foo.StatusChanged += (sensor, changed) =>
{
Console.WriteLine(changed.Status);
};
foo.PositionChanged += (sensor, changed) => {

Console.WriteLine(changed.Position.Timestamp.ToString("G"));
Console.WriteLine(String.Format("Location: {0}, {1}",
changed.Position.Location.Latitude.ToString("0.000"),
changed.Position.Location.Longitude.ToString("0.000")));

} ;

foo.Start();
Console.ReadLine();
foo.Stop(); //Say you're done to save batteries!

So that means Desktop apps can use System.Device.Location and Windows Store (sandboxed) apps use Microsoft.Devices.GeoLocation, as well as all the other sensors made available via WinRT. If you find WinRT confusing I'd encourage you to listen to my podcast on the topic. I had WinRT explained to me by a WinRT developer and I feel much better about it.

Also worth noting with GPS data you can get ahold of it even from inside a modern browser. Just a little bit of JavaScript:

<script>
navigator.geolocation.getCurrentPosition(
function myfunction(data) {
alert(data.coords.longitude + " " + data.coords.latitude);
});
</script>

Then your browser will warn you and ask permission, similar to this:

This site wants to track your physical location

I'd like to see all possible sensors become available to the browser, similar to the way the Firefox OS proposes to allow access to hardware from JavaScript.

Of course, within Windows 8 applications I can access any Sensor data at all - regardless of language (JS, VB, C#, C++) - with similar APIs. You instantiate the Sensor class, hook up a few events and you're set, like this LightSensor example. I can even call these WinRT APIs from Desktop Applications.

private LightSensor _lightsensor; // Our app's lightsensor object

private void ReadingChanged(object sender, LightSensorReadingChangedEventArgs e)
{
Dispatcher.InvokeAsync(CoreDispatcherPriority.Normal, (s, a) =>
{
LightSensorReading reading = (a.Context as LightSensorReadingChangedEventArgs).Reading;
txtLuxValue.Text = String.Format("{0,5:0.00}", reading.IlluminanceInLux);
}, this, e);
}

//Then, whenever you need to, just...
_lightsensor = LightSensor.GetDefault(); // Get the default light sensor object

// Assign an event handler for the ALS reading-changed event
if (_lightsensor != null)
{
// Establish the report interval for all scenarios
uint minReportInterval = _lightsensor.MinimumReportInterval;
uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
_lightsensor.ReportInterval = reportInterval;

// Establish the event handler
_lightsensor.ReadingChanged += new TypedEventHandler<LightSensor, LightSensorReadingChangedEventArgs>(ReadingChanged);
}

It's pretty straightforward. These Ultrabooks have a PILE of sensors, as you can see using the Sensor Diagnostic Tool below.

All the Sensors built into the Intel Ultrabook

The really interesting question to me is: How can we use these for games? Sure, there's the obvious utilities for dimming the screen and what not, but what kinds of really creative stuff could be done? What would a Contre Jour look like with compasses and inclinometers feeding information to the game and affecting not just active animations but subtle background ones as well?

What do YOU think? Do we need need these sensor arrays in our portable computers? Have we just not come up with the really creative uses for them?


Disclosure of Material Connection: Intel sent me this Ultrabook for free in the hope that I would review it on my blog. Regardless, I only recommend products or services I I would use and think you would find useful. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.