I have been busy developing for Windows 8 for a while now. Until Microsoft releases a WinRT “Surface” device (October?) I thought it would be nice to be able to test my apps transitions between ApplicationViewState.
I have an accelerometer in my .Net Gadgeteer kit…and a wifi module…hmm.
What I built is a gadget that exposes JSON formatted accelerometer data via a web service. Any Windows 8 (WinRT) applications can consume this service. There are a few details to getting this to work. I will briefly go over the main things to be aware of here. I will post the entire project later.
Here is what it looks like tacked on my laptop:
Across the top (from left to right): OLED Display, SEEED Studio Accelerometer, GHI Spider board, Wifi module
Across the Bottom: power module, battery pack.
On the table is a ClearWire wifi router.
Here are some of the main things to be aware of:
Time Series Graph
I added a OLED Display because it was very handy to have a time series graph to display the x,y,z axis’ for troubleshooting.
Here is the code for the graph:
public class GraphHelper
{
uint currentX;
uint MaxX;
uint _y;
uint _GraphHeight = 10;
Gadgeteer.Modules.Seeed.OledDisplay _display;
public GraphHelper(uint y, Gadgeteer.Modules.Seeed.OledDisplay display )
{
_y = y;
_display = display;
currentX = 0;
MaxX = _display.Width;
Clear();
}
private void Clear()
{
_display.SimpleGraphics.DisplayRectangle(Gadgeteer.Color.Gray, 1, Gadgeteer.Color.White, 0, _y, _display.Width, _GraphHeight);
}
float _maxG=1;
public void AddDataPoint(float range)
{
//check if new values are larger than we expected.
//I assume the range is between 1 and -1.
//If the range is larger then we need to adjust.
if (System.Math.Abs((int)System.Math.Ceiling(range)) > _maxG)
_maxG = range;
//shift all values to positive range.
//TODO: fix variable names...
float rangeNorm = range + _maxG;
float integral = _GraphHeight / _maxG;
rangeNorm = rangeNorm * integral;
rangeNorm -= _GraphHeight;
rangeNorm += _y + (float)(_GraphHeight * 0.5);
if(currentX==0)
Clear();
if ( rangeNorm < _y)
rangeNorm = _y;
if(rangeNorm > (_y + _GraphHeight))
rangeNorm = _y + _GraphHeight;
if (currentX <= MaxX)
{
_display.SimpleGraphics.SetPixel(Gadgeteer.Color.Green, currentX++, (uint)System.Math.Ceiling((uint)System.Math.Ceiling(rangeNorm)));
}
else
{
currentX = 0;
}
}
Here is how you would call its c’tor to put a graph halfway down the screen (display_height/2=64)and plot a point :
this.graphX = new GraphHelper(64, _display ); graphX.AddDataPoint( (float) averagedAcceleration.X );
Windows 8 Capabilities Panel in Visual Studio 12
Pay attention to the Capabilites tab in the Package.appxmanifest. I had enabled “Internet(Client)” and thought I was good to go. No so. There is also a “Home or Work Networking” capability. For connections to resources on a LAN you need to enable this.
Reactive Extensions for .Net are Very Cool
In my Win8 application I needed to call the sensor service on a timer. There are many ways I could have done this. I wanted a quick and easy solution that would work with the async nature of WinRT development and I knew for certain that this code would be not in a production system…ever. This isn’t to say RX .Net isn’t production worthy, just that this usage of a timer is probably not optimal for production but is great for demo code.
var fivePerSecond = Observable.Interval(TimeSpan.FromMilliseconds(200))
.ObserveOnDispatcher()
.Subscribe(num =>
{
Get_Sensor_Data();
});
Every 200 ms this will call Get_Sensor_Data()…which then calls MoveCube() here:
HttpResponseMessage response = await rootPage.httpClient.GetAsync("http://192.168.1.10");
await Helpers.MoveCube(response, renderer);
Page.NotifyUser.Text = "Completed";
And finally, we get to the MoveCube()…
internal static class Helpers
{
internal static async Task MoveCube(HttpResponseMessage response, DxRenderer.Cube cube)
{
string responseBodyAsText;
responseBodyAsText = await response.Content.ReadAsStringAsync();
JsonValue value = JsonValue.Parse(responseBodyAsText);
var c = value.GetObject();
string sx = (c["Accel"] as JsonValue).GetObject()["x"].GetString();
string sy = (c["Accel"] as JsonValue).GetObject()["y"].GetString();
float.TryParse(sx, out cube.X);
float.TryParse(sy, out cube.Y);
}
}
SharpDX is DirectX for C#
Finally, Jose Fajardo, who has published some very useful demos of SharpDX, provided the starting point for the Win8 cube rotation via accelerometer. I wasn’t able to get the SharpDX demos that come with SharpDX to run. But I was able to get Jose’s samples working. So thanks Jose! SharpDX is the only way I know of to do DirectX in WinRT apps using C#.



