The Weekly Source Code 57 -Controlling an Eagletron TrackerPod with C# 4, ASP.NET MVC and jQuery
I have a 42" HDTV in Seattle that's hooked up all the time as an "Embodied Social Proxy." It's a portal between the Microsoft Redmond campus and my house here in Oregon. I've blogged about Embodied Social Proxies before as well as shot video of one for Channel 9. It's called the "HanselCart" around work, although recently it's stopped being a cart and now it's a whole office that folks in Building 42 can drop by and see me, er, the Virtual Me.
One of the things that hasn't been 100% smooth is that while the LifeCam Cinema HD 720p is a nice camera, I can't MOVE it. I have to ask folks to move it for me, which is a slight irritant.
I'm getting ready to head up to Seattle for a meeting. While I was packing I found this TrackerPod motorized WebCam pan/tilt/zoom in my junk closet. I must have purchased it a long time ago and forgotten. I drilled a hole into the metal base of the LifeCam Cinema HD and superglued it while half-threading it on the TrackerPod's standard tripod-style male screw.
It's late, but I figured it I was going up to Seattle tomorrow, maybe I could hack something together quickly with this device and take it with me. There's a Custom Programming API page on the TrackerPod site with a TrackerPod COM Client.
This is what I built in action:
Here's how I did it in 40 minutes. First, I made a new ASP.NET MVC 3 web project, keeping the default template. This is quick and dirty, right?
Yes, I used a <TABLE>, sue me.
Here's the complete Razor View. I knew that I'd want a bunch of buttons to move the camera, and I assumed I would use jQuery to make an AJAX to the server side running ASP.NET MVC. I'm using the latest jQuery 1.4.4 and I'm getting it from the updated Microsoft cookieless CDN (Content Delivery Network.)
Rather than making a complex switch statement for the different buttons or different event handlers, I decided to use arbitrary HTML5 data attributes. Each INPUT Button has attributes like data-xvalue and data-yvalue.
There's one Click() handler hooked up to all Buttons. It gets the values of those data attributes, then POSTs the data to the Move method of the Home Controller.
@{
View.Title = "Home Page";
}
<script src="•http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.4.min.js"
type="text/javascript"></script>
<table border="0">
<tr>
<td></td><td>
<input type="button" value=" up " name="up"
data-xvalue="0" data-yvalue="-10" data-method="0" />
</td><td></td>
</tr>
<tr>
<td>
<input type="button" value="left" name="left"
data-xvalue="10" data-yvalue="0" data-method="0" />
</td>
<td>
<input type="button" value="home" name="home"
data-xvalue="0" data-yvalue="0" data-method="1" />
</td>
<td>
<input type="button" value="right" name="right"
data-xvalue="-10" data-yvalue="0"
data-method="0" />
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="button" value="down" name="down"
data-xvalue="0" data-yvalue="10" data-method="0" />
</td>
<td>
</td>
</tr>
</table>
<script type="text/javascript">
//<![CDATA[
$(document).ready(function () {
$('input').click(function (event) {
var target = event.target;
x = $(target).data('xvalue');
y = $(target).data('yvalue');
m = $(target).data('method');
$.post("/Home/Move", { x: x, y: y, method: m });
}
);
});
//]]>
</script>
In the Home Controller, there's a method called Move(int x, int y, int method) where method is the way to move the camera - relative is 0 or absolute is 1. That's part of the camera's calling convention.
using TRACKERPOD_DUAL_COMLib;
namespace TrackerPodWeb.Controllers
{
public class HomeController : Controller
{
private dynamic cam = MvcApplication.myCameraInstance;
[HttpPost]
public void Move(int x, int y, int method)
{
cam.x = x;
cam.y = y;
cam.move_method = method;
cam.move();
}
public ActionResult Index()
{
return View();
}
}
}
See that dynamic object? That was the part that blew me away. I'm so used to COM Interop being a freaking nightmare from .NET that I spent most of the time messing with COM Interfaces and Type Libraries and exceptions when I realized that C# 4 was supposed to fix all that.
Like I've been saying about Razor - "stop thinking about syntax and just use it." - the same applies to COM interop in .NET 4 (Remember that the Visual Basic guys have have this nice experience for years...that's why VB is such a popular business automation language.)
Just use the dynamic keyword and start calling COM methods. Seriously, it just worked. I was copy/pasting code from the TrackerCam's VB6 (yes Visual Basic 6) samples into C#4 and other than a few semicolons, it was working directly!
Here's my Web Application's startup code:
public static dynamic myCameraInstance { get; set; }
protected void Application_Start()
{
//snip the MVC init stuff...
myCameraInstance = new TrackerPod();
myCameraInstance.app_name = "hanselcam";
myCameraInstance.initialize();
}
Here I hang on to the COM object for the camera as a poor man's singleton for use elsewhere. I should probably put guard-code around this to make sure it doesn't disappear or something but it's working so far. It should be a proper singleton I think.
Then I use that instance in my HomeController and call the COM methods in Move(). ASP.NET MVC takes care of the binding from jQuery to the Action Method, and .NET 4, C# and the DLR take care of the call into the COM TrackerCam stuff.
HTML5+jQuery -> ASP.NET MVC -> C# 4 dynamic keyword -> DLR COM Binder -> COM Library = It just works.
There's some HTML5 attributes, five lines of JS here and basically four lines of COM interop on my Move() method.
Now I'll be able to control my Seattle WebCam from Oregon. I may make it so I can control it from the Office Communicator Lync chat client or something. It'd also be nice if someone wrapped up the TrackerPod as a nice C# library and put it on CodePlex.
I'll add that to my ToDo list, or perhaps you will, Dear Reader. ;)
Related Links
- VIDEO: Hanselminutes on 9: Embodied Social Proxies (and Remote Video Heads!) with Microsoft Research
- YOUTUBE VIDEO: Embodied Social Proxy: Connecting Hub-and-Satellite Teams
- Virtual Camaraderie - A Persistent Video "Portal" for the Remote Worker
- Buy a TrackerCam
- Full Disclosure: I took a second just now and got an affiliate code for a TrackerCam because it was easy to use this camera. I bought the TrackerPod mount myself years and found it in my closet tonight. I don't know anyone at Eagletron.
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.



About Newsletter